#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" TARGET="${UPLOAD_TARGET:-ibl_tentarapelajar}" REMOTE_HOST="${UPLOAD_REMOTE_HOST:-10.9.20.31}" REMOTE_USER="${UPLOAD_REMOTE_USER:-one}" REMOTE_PATH="${UPLOAD_REMOTE_PATH:-/home/one/project/one/one-api-lab/}" PRIVATE_KEY_PATH="${UPLOAD_PRIVATE_KEY_PATH:-/Users/fajrihardhitamurti/id_rsa}" MODE="commit" REF="HEAD" DRY_RUN=0 usage() { cat <<'EOF' Usage: upload_ibl_committed_files.sh [commit|range] [REF] [--dry-run] Modes: commit [REF] Upload added/copied/modified files from one commit (default: HEAD) range [A..B] Upload added/copied/modified files from a git revision range Examples: ./upload-ibl ./upload-ibl commit HEAD ./upload-ibl range HEAD~3..HEAD ./upload-ibl --dry-run EOF } log() { printf '[upload-ibl] %s\n' "$*" } fail() { printf '[upload-ibl] %s\n' "$*" >&2 exit 1 } while [[ $# -gt 0 ]]; do case "$1" in commit|range) MODE="$1" shift if [[ $# -gt 0 ]] && [[ "$1" != --* ]]; then REF="$1" shift fi ;; --dry-run) DRY_RUN=1 shift ;; -h|--help) usage exit 0 ;; *) fail "Unknown argument: $1" ;; esac done git -C "$ROOT_DIR" rev-parse --is-inside-work-tree >/dev/null 2>&1 || fail "Not inside a git worktree" [[ -f "$PRIVATE_KEY_PATH" ]] || fail "Private key not found: $PRIVATE_KEY_PATH" tmpdir="$(mktemp -d)" trap 'rm -rf "$tmpdir"' EXIT changed_list="$tmpdir/changed-files.txt" skipped_list="$tmpdir/skipped-files.txt" case "$MODE" in commit) git -C "$ROOT_DIR" rev-parse --verify "$REF^{commit}" >/dev/null 2>&1 || fail "Invalid commit ref: $REF" git -C "$ROOT_DIR" diff-tree --no-commit-id --root --diff-filter=ACM --name-only -r "$REF" > "$changed_list" git -C "$ROOT_DIR" diff-tree --no-commit-id --root --diff-filter=DR --summary -r "$REF" > "$skipped_list" || true ;; range) git -C "$ROOT_DIR" rev-parse --verify "${REF##*..}^{commit}" >/dev/null 2>&1 || fail "Invalid range end: $REF" git -C "$ROOT_DIR" diff --diff-filter=ACM --name-only "$REF" > "$changed_list" git -C "$ROOT_DIR" diff --diff-filter=DR --summary "$REF" > "$skipped_list" || true ;; *) fail "Unknown mode: $MODE" ;; esac if [[ ! -s "$changed_list" ]]; then log "No added/copied/modified files found for $MODE $REF" if [[ -s "$skipped_list" ]]; then log "Skipped delete/rename changes:" sed 's/^/[upload-ibl] /' "$skipped_list" fi exit 0 fi changed_paths=() while IFS= read -r path; do [[ -n "$path" ]] || continue case "$path" in graphify-out/*) continue ;; esac changed_paths+=("$path") done < "$changed_list" if [[ "${#changed_paths[@]}" -eq 0 ]]; then log "No deployable files found for $MODE $REF" exit 0 fi log "Uploading ${#changed_paths[@]} path(s) from $MODE $REF to $TARGET" rsync_opts=(-az --progress --human-readable --relative --exclude='.git/' --exclude='.DS_Store') if [[ "$DRY_RUN" -eq 1 ]]; then rsync_opts+=(--dry-run) fi SSH_CMD="ssh -i $PRIVATE_KEY_PATH -o BatchMode=yes -o StrictHostKeyChecking=accept-new" destination="${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH%/}/" pushd "$ROOT_DIR" >/dev/null if rsync "${rsync_opts[@]}" -e "$SSH_CMD" "${changed_paths[@]}" "$destination"; then log "Done: $TARGET" else fail "Upload failed: $TARGET" fi popd >/dev/null if [[ -s "$skipped_list" ]]; then log "Skipped delete/rename changes:" sed 's/^/[upload-ibl] /' "$skipped_list" fi