#!/usr/bin/env bash set -euo pipefail # setup_deploy_and_checkout.sh # Usage: # GITHUB_API_TOKEN=ghp_xxx ./scripts/setup_deploy_and_checkout.sh [deploy-key-path] [backup-base] # Example: # GITHUB_API_TOKEN=... ./scripts/setup_deploy_and_checkout.sh 6e8cf6f83ab6bf596c9db6fa30069a58819f068f /root/.ssh/github_deploy_key /root/server-untracked-backup COMMIT="${1:-6e8cf6f83ab6bf596c9db6fa30069a58819f068f}" KEY_PATH="${2:-/root/.ssh/github_deploy_key}" BACKUP_BASE="${3:-/root/server-untracked-backup}" BRANCH="${4:-main}" GITHUB_REPO="aborayan2022/SaaS-PDF" GITHUB_API_TOKEN="${GITHUB_API_TOKEN:-}" RUN_LOAD_TEST="${RUN_LOAD_TEST:-false}" HEALTH_URL="${HEALTH_URL:-http://127.0.0.1:5000/api/health}" echo "Starting deploy helper: commit=$COMMIT key=$KEY_PATH backup=$BACKUP_BASE" if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then echo "Error: please run this script from inside the repository root." >&2 exit 1 fi ROOT_DIR="$(git rev-parse --show-toplevel)" cd "$ROOT_DIR" # 1) Generate deploy key if missing if [ ! -f "$KEY_PATH" ]; then echo "Generating SSH deploy key at $KEY_PATH" mkdir -p "$(dirname "$KEY_PATH")" ssh-keygen -t ed25519 -f "$KEY_PATH" -N "" -C "deploy-$(hostname)-$(date +%Y%m%d%H%M%S)" chmod 600 "$KEY_PATH" chmod 644 "${KEY_PATH}.pub" else echo "Deploy key already exists at $KEY_PATH" fi echo echo "----- PUBLIC KEY (add this to your GitHub repo Settings → Deploy keys) -----" cat "${KEY_PATH}.pub" echo # 2) Optionally add the key to GitHub via API if token provided if [ -n "$GITHUB_API_TOKEN" ]; then echo "Attempting to add deploy key to GitHub via API..." PUBKEY=$(cat "${KEY_PATH}.pub") TITLE="deploy-$(hostname)-$(date +%Y%m%d%H%M%S)" # Create JSON payload safely PAYLOAD=$(printf '{"title":"%s","key":"%s","read_only":false}' "$TITLE" "$PUBKEY") HTTP_CODE=$(curl -s -o /tmp/_gh_deploy_resp.json -w "%{http_code}" \ -X POST "https://api.github.com/repos/${GITHUB_REPO}/keys" \ -H "Authorization: token ${GITHUB_API_TOKEN}" \ -H "Content-Type: application/json" \ -d "$PAYLOAD") if [ "$HTTP_CODE" = "201" ]; then echo "Deploy key added to repo ${GITHUB_REPO}." else echo "GitHub API returned $HTTP_CODE. Response:" cat /tmp/_gh_deploy_resp.json || true echo "If the response indicates 'key is already in use' or similar, you can ignore. Otherwise add the public key manually in the repository settings." fi rm -f /tmp/_gh_deploy_resp.json fi # 3) Ensure ssh config uses this key for github.com SSH_CONFIG="/root/.ssh/config" mkdir -p /root/.ssh chmod 700 /root/.ssh if ! grep -q "Host github.com" "$SSH_CONFIG" 2>/dev/null; then echo "Adding SSH config entry for github.com -> identityfile $KEY_PATH" cat >> "$SSH_CONFIG" <&2 else if echo "$ORIGIN_URL" | grep -q "^https://github.com/"; then echo "Changing origin from HTTPS to SSH" git remote set-url origin git@github.com:${GITHUB_REPO}.git else echo "Origin is: $ORIGIN_URL" fi fi # 5) Move conflicting untracked files (use backup script if present) if [ -f "./scripts/backup_and_pull.sh" ]; then echo "Using scripts/backup_and_pull.sh to back up conflicting untracked files and pull." chmod +x ./scripts/backup_and_pull.sh ./scripts/backup_and_pull.sh "$BRANCH" "$BACKUP_BASE" else echo "No backup script found. Doing minimal safe backup of untracked files that exist in origin/branch." TMP_UNTRACKED=$(mktemp) TMP_ORIGIN=$(mktemp) TMP_CONFLICTS=$(mktemp) git ls-files --others --exclude-standard > "$TMP_UNTRACKED" git fetch origin "$BRANCH" --quiet || true git ls-tree -r --name-only origin/"$BRANCH" > "$TMP_ORIGIN" 2>/dev/null || true grep -Fx -f "$TMP_UNTRACKED" "$TMP_ORIGIN" > "$TMP_CONFLICTS" || true if [ -s "$TMP_CONFLICTS" ]; then echo "The following untracked local files conflict with origin/$BRANCH:" cat "$TMP_CONFLICTS" TS=$(date +%Y%m%d%H%M%S) BACKUP_DIR="${BACKUP_BASE}-${TS}" mkdir -p "$BACKUP_DIR" while IFS= read -r f; do if [ -e "$f" ]; then mkdir -p "$(dirname "$BACKUP_DIR/$f")" mv -v -- "$f" "$BACKUP_DIR/$f" fi done < "$TMP_CONFLICTS" echo "Files moved to $BACKUP_DIR" else echo "No conflicting untracked files found. Proceeding to pull." fi rm -f "$TMP_UNTRACKED" "$TMP_ORIGIN" "$TMP_CONFLICTS" git pull origin "$BRANCH" || true fi # 6) Fetch and checkout the requested commit echo "Fetching all remotes and tags" git fetch --all --tags --prune if git rev-parse --verify "$COMMIT" >/dev/null 2>&1; then echo "Commit $COMMIT exists locally. Checking out (detached HEAD)." git checkout -f "$COMMIT" else echo "Commit $COMMIT not present locally. Attempting to fetch from origin." git fetch origin "$COMMIT" --depth=1 || true if git rev-parse --verify "$COMMIT" >/dev/null 2>&1; then git checkout -f "$COMMIT" else echo "Failed to find commit $COMMIT after fetch. Exiting." >&2 exit 1 fi fi # Create/update lightweight branch pointer for convenience BRNAME="deployed-${COMMIT:0:8}" echo "Updating branch pointer $BRNAME -> $COMMIT" git branch -f "$BRNAME" "$COMMIT" || true # 7) Restart services (docker-compose aware) if command -v docker >/dev/null 2>&1; then echo "Restarting docker compose services (up -d --build)" if docker compose version >/dev/null 2>&1; then docker compose up -d --build --remove-orphans docker compose ps --all elif docker-compose version >/dev/null 2>&1; then docker-compose up -d --build --remove-orphans docker-compose ps --all else echo "Docker CLI present but unable to run compose. Please restart services manually." >&2 fi else echo "Docker not found. If you're not using docker, restart your service manager (systemd, supervisor, etc.) as needed." >&2 fi # 8) Simple health check echo "Waiting 6s for services to become ready..." sleep 6 if command -v curl >/dev/null 2>&1; then echo "Health check: $HEALTH_URL" if curl -sS -f "$HEALTH_URL" -o /tmp/_health.json; then echo "Health OK:" cat /tmp/_health.json else echo "Health endpoint failed or returned error. Check container logs." fi fi # 9) Optional quick load test (disabled by default) if [ "$RUN_LOAD_TEST" = "true" ]; then echo "Starting quick load test (1000 requests, concurrency 50) against $HEALTH_URL" if command -v hey >/dev/null 2>&1; then hey -n 1000 -c 50 "$HEALTH_URL" elif command -v ab >/dev/null 2>&1; then ab -n 1000 -c 50 "$HEALTH_URL" else echo "Load-testing tools not installed. Install 'hey' or 'ab' and re-run with RUN_LOAD_TEST=true to enable." >&2 fi fi echo "Done. If you added the public key manually in GitHub, re-run the script (or run ./scripts/backup_and_pull.sh and then checkout the commit) if needed."