diff --git a/deploy/sync-mirror.sh b/deploy/sync-mirror.sh index bd04e98..15c9cdd 100755 --- a/deploy/sync-mirror.sh +++ b/deploy/sync-mirror.sh @@ -367,6 +367,27 @@ print(json.dumps({'chat_id': sys.argv[4], 'text': msg, 'parse_mode': 'HTML'})) REPO_TAG="main" log "Starting sync cycle" +# Step 0: self-heal any gh-pr-* PR rows missing github_pr. +# Runs FIRST — before per-repo work (branch-mirror loop, auto-create-PR block). +# Recovers from races/transient failures in Step 4.5's one-shot link UPDATE. +# Idempotent: SELECT empty when clean, zero-cost path. Same SELECT/UPDATE +# heals historical orphans (PR 4066 picked up on first cron tick post-deploy) +# and future races on subsequent ticks. The branch name encodes the GitHub PR +# number deterministically (gh-pr-{N}/...) so no API call is required. +if [ -f "$PIPELINE_DB" ]; then + sqlite3 -separator '|' "$PIPELINE_DB" \ + "SELECT number, branch FROM prs WHERE branch LIKE 'gh-pr-%' AND github_pr IS NULL;" \ + 2>/dev/null | while IFS='|' read -r pr_num branch; do + gh_pr_num=$(echo "$branch" | sed -n 's|^gh-pr-\([0-9]*\)/.*|\1|p') + [ -z "$gh_pr_num" ] && continue + if sqlite3 "$PIPELINE_DB" \ + "UPDATE prs SET github_pr = $gh_pr_num, source_channel = 'github' WHERE number = $pr_num;" \ + 2>/dev/null; then + log "self-heal: linked Forgejo PR #$pr_num -> GitHub PR #$gh_pr_num" + fi + done +fi + for entry in "${MIRROR_REPOS[@]}"; do # Read the 4 fields. `read` splits on $IFS (whitespace) by default. read -r forgejo_repo github_repo bare_path mode <<< "$entry"