name: PR Walkthrough Reconcile # A description edit must be able to repair a stale callout without starting # the model-backed generation workflow or executing pull request code. on: pull_request_target: types: [edited] permissions: {} concurrency: group: pr-walkthrough-reconcile-${{ github.event.pull_request.number }} cancel-in-progress: true jobs: pr-walkthrough-reconcile: if: > vars.PR_WALKTHROUGH_ENABLED == 'true' && github.event_name == 'pull_request_target' && github.event.action == 'edited' && github.event.pull_request.draft == false && ( github.event.pull_request.head.repo.full_name == github.repository || ( github.event.pull_request.head.repo.full_name != github.repository && ( contains(github.event.pull_request.labels.*.name, 'safe-to-review') || (vars.CLAUDE_REVIEW_ALLOWLIST != '' && contains(fromJSON(vars.CLAUDE_REVIEW_ALLOWLIST), github.event.pull_request.user.login)) ) ) ) runs-on: ubuntu-latest timeout-minutes: 5 concurrency: group: pr-description-${{ github.event.pull_request.number }} cancel-in-progress: false permissions: contents: read pull-requests: write steps: - name: Checkout trusted reconciliation helper uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 with: ref: ${{ github.workflow_sha }} fetch-depth: 1 persist-credentials: false - name: Repair stale walkthrough callout env: GH_TOKEN: ${{ github.token }} TRUSTED_SHA: ${{ github.workflow_sha }} HEAD_SHA: ${{ github.event.pull_request.head.sha }} PR_NUMBER: ${{ github.event.pull_request.number }} WALKTHROUGH_BASE_URL: https://walkthrough.kandev.ai run: | set -euo pipefail test "$(git rev-parse HEAD)" = "$TRUSTED_SHA" test -f scripts/pr-walkthrough-pr-body test "$PR_NUMBER" -gt 0 [[ "$HEAD_SHA" =~ ^[0-9a-f]{40}$ ]] SHORT_HEAD_SHA="${HEAD_SHA:0:12}" PUBLIC_URL="${WALKTHROUGH_BASE_URL%/}/pr/${PR_NUMBER}/${SHORT_HEAD_SHA}.html" RESPONSE_META_PATH=pr-walkthrough-public.response PUBLIC_HTML_PATH=pr-walkthrough-public.html if ! curl --fail --silent --show-error --location --max-time 30 \ --retry 3 --retry-all-errors --retry-delay 2 --retry-max-time 30 \ --output "$PUBLIC_HTML_PATH" \ --write-out '%{http_code}\t%{content_type}\t%{url_effective}' \ > "$RESPONSE_META_PATH" \ "$PUBLIC_URL"; then echo "Canonical walkthrough is not publicly available; skipping repair." >> "$GITHUB_STEP_SUMMARY" exit 0 fi IFS=$'\t' read -r response_status response_content_type response_effective_url < "$RESPONSE_META_PATH" if [ "$response_status" != "200" ] || [ "$response_effective_url" != "$PUBLIC_URL" ] || ! printf '%s\n' "$response_content_type" | grep -Eiq '^text/html(;|[[:space:]]|$)' || ! test -s "$PUBLIC_HTML_PATH"; then echo "Canonical walkthrough did not return a non-empty HTML response; skipping repair." >> "$GITHUB_STEP_SUMMARY" exit 0 fi for attempt in 1 2 3; do rm -f \ pr-response.json \ pr-latest-response.json \ pr-verified-response.json \ pr-update.json \ pr-verify-update.json \ pr-body-before \ pr-body-latest \ pr-body-expected \ pr-body-verified if ! gh api "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}" > pr-response.json || ! python3 -c 'import json; json.load(open("pr-response.json", encoding="utf-8"))'; then if [ "$attempt" -eq 3 ]; then echo "Unable to fetch the pull request description." >&2 exit 1 fi sleep 2 continue fi set +e python3 scripts/pr-walkthrough-pr-body \ --github-response pr-response.json \ --output pr-update.json \ --url "$PUBLIC_URL" \ --pr-number "$PR_NUMBER" \ --head-sha "$HEAD_SHA" \ --require-existing update_status=$? set -e if [ "$update_status" -eq 4 ]; then echo "No existing walkthrough callout found; skipping repair." >> "$GITHUB_STEP_SUMMARY" exit 0 fi if [ "$update_status" -eq 3 ]; then echo "PR description already links the canonical walkthrough." >> "$GITHUB_STEP_SUMMARY" exit 0 fi if [ "$update_status" -ne 0 ]; then echo "Existing walkthrough markers are malformed; refusing to rewrite the PR description." >&2 exit 1 fi jq -j '.body // ""' pr-update.json > pr-body-expected jq -j '.body // ""' pr-response.json > pr-body-before if ! gh api "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}" > pr-latest-response.json || ! python3 -c 'import json; json.load(open("pr-latest-response.json", encoding="utf-8"))'; then if [ "$attempt" -eq 3 ]; then echo "Unable to refresh the pull request description." >&2 exit 1 fi sleep 2 continue fi current_head_sha="$(jq -r '.head.sha // ""' pr-latest-response.json)" if [ "$current_head_sha" != "$HEAD_SHA" ]; then echo "PR head advanced to ${current_head_sha}; skipping stale repair." >> "$GITHUB_STEP_SUMMARY" exit 0 fi jq -j '.body // ""' pr-latest-response.json > pr-body-latest if ! cmp -- pr-body-before pr-body-latest; then echo "Pull request description changed before repair PATCH; retrying." >&2 sleep 2 continue fi if ! gh api --method PATCH \ "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}" \ --input pr-update.json \ --silent; then if [ "$attempt" -eq 3 ]; then echo "Unable to repair the pull request description." >&2 exit 1 fi sleep 2 continue fi if ! gh api "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}" > pr-verified-response.json || ! python3 -c 'import json; json.load(open("pr-verified-response.json", encoding="utf-8"))'; then if [ "$attempt" -eq 3 ]; then echo "Unable to verify the repaired pull request description." >&2 exit 1 fi sleep 2 continue fi verified_head_sha="$(jq -r '.head.sha // ""' pr-verified-response.json)" if [ "$verified_head_sha" != "$HEAD_SHA" ]; then echo "PR head advanced to ${verified_head_sha}; skipping stale repair." >> "$GITHUB_STEP_SUMMARY" exit 0 fi jq -j '.body // ""' pr-verified-response.json > pr-body-verified if ! cmp -- pr-body-expected pr-body-verified; then if [ "$attempt" -eq 3 ]; then echo "Pull request description changed before repair readback verification." >&2 exit 1 fi echo "Pull request description changed after repair PATCH; retrying." >&2 sleep 2 continue fi set +e python3 scripts/pr-walkthrough-pr-body \ --github-response pr-verified-response.json \ --output pr-verify-update.json \ --url "$PUBLIC_URL" \ --pr-number "$PR_NUMBER" \ --head-sha "$HEAD_SHA" \ --require-existing verify_status=$? set -e if [ "$verify_status" -eq 3 ]; then echo "Repaired the stale walkthrough link in the PR description." >> "$GITHUB_STEP_SUMMARY" exit 0 fi if [ "$attempt" -eq 3 ]; then echo "Pull request description readback did not contain the canonical walkthrough." >&2 exit 1 fi echo "Pull request description readback changed; retrying repair." >&2 sleep 2 done echo "Pull request description repair did not converge." >&2 exit 1