Reviewer Bot Reconcile #42
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Reviewer Bot Reconcile | |
| on: | |
| workflow_run: | |
| workflows: ["Reviewer Bot"] | |
| types: [completed] | |
| permissions: | |
| issues: write | |
| pull-requests: write | |
| contents: read | |
| actions: read | |
| env: | |
| STATE_ISSUE_NUMBER: "314" | |
| jobs: | |
| reconcile: | |
| if: ${{ github.event.workflow_run.event == 'pull_request_review' && github.event.workflow_run.conclusion == 'success' }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v6 | |
| - name: Download reconcile context artifact | |
| uses: actions/download-artifact@v5 | |
| with: | |
| name: reviewer-bot-reconcile-context-${{ github.event.workflow_run.id }} | |
| run-id: ${{ github.event.workflow_run.id }} | |
| repository: ${{ github.repository }} | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| path: ${{ runner.temp }}/reviewer-bot | |
| - name: Validate reconcile context artifact | |
| env: | |
| RECONCILE_CONTEXT_PATH: ${{ runner.temp }}/reviewer-bot/reconcile-context.json | |
| EXPECTED_WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }} | |
| EXPECTED_WORKFLOW_RUN_HEAD_SHA: ${{ github.event.workflow_run.head_sha }} | |
| run: | | |
| if [ ! -f "${RECONCILE_CONTEXT_PATH}" ]; then | |
| echo "Missing reconcile context artifact at ${RECONCILE_CONTEXT_PATH}" >&2 | |
| exit 1 | |
| fi | |
| uv run python - <<'PY' | |
| import json | |
| import os | |
| import sys | |
| from pathlib import Path | |
| path = Path(os.environ["RECONCILE_CONTEXT_PATH"]) | |
| try: | |
| payload = json.loads(path.read_text(encoding="utf-8")) | |
| except (OSError, json.JSONDecodeError) as exc: | |
| print(f"Failed to parse reconcile context artifact JSON: {exc}", file=sys.stderr) | |
| raise SystemExit(1) | |
| if not isinstance(payload, dict): | |
| print("Reconcile context artifact must be a JSON object", file=sys.stderr) | |
| raise SystemExit(1) | |
| required_fields = ( | |
| "schema_version", | |
| "event_name", | |
| "event_action", | |
| "pr_number", | |
| "head_sha", | |
| "source_run_id", | |
| ) | |
| missing = [field for field in required_fields if field not in payload] | |
| if missing: | |
| print( | |
| "Reconcile context artifact missing required fields: " + ", ".join(missing), | |
| file=sys.stderr, | |
| ) | |
| raise SystemExit(1) | |
| if payload["schema_version"] != 1: | |
| print("Unsupported reconcile context schema_version", file=sys.stderr) | |
| raise SystemExit(1) | |
| if payload["event_name"] != "pull_request_review": | |
| print("Reconcile context event_name mismatch", file=sys.stderr) | |
| raise SystemExit(1) | |
| if payload["event_action"] != "submitted": | |
| print("Reconcile context event_action mismatch", file=sys.stderr) | |
| raise SystemExit(1) | |
| pr_number = payload["pr_number"] | |
| if not isinstance(pr_number, int) or pr_number <= 0: | |
| print("Reconcile context pr_number must be a positive integer", file=sys.stderr) | |
| raise SystemExit(1) | |
| artifact_head_sha = payload["head_sha"] | |
| if not isinstance(artifact_head_sha, str) or not artifact_head_sha.strip(): | |
| print("Reconcile context head_sha must be a non-empty string", file=sys.stderr) | |
| raise SystemExit(1) | |
| artifact_head_sha = artifact_head_sha.strip() | |
| source_run_id = payload["source_run_id"] | |
| if not isinstance(source_run_id, int) or source_run_id <= 0: | |
| print("Reconcile context source_run_id must be a positive integer", file=sys.stderr) | |
| raise SystemExit(1) | |
| expected_run_id = int(os.environ["EXPECTED_WORKFLOW_RUN_ID"]) | |
| if source_run_id != expected_run_id: | |
| print("Reconcile context source_run_id does not match triggering run id", file=sys.stderr) | |
| raise SystemExit(1) | |
| expected_head_sha = os.environ["EXPECTED_WORKFLOW_RUN_HEAD_SHA"].strip() | |
| if not expected_head_sha: | |
| print("Missing expected workflow_run head SHA", file=sys.stderr) | |
| raise SystemExit(1) | |
| if artifact_head_sha != expected_head_sha: | |
| print("Reconcile context head_sha does not match workflow_run head_sha", file=sys.stderr) | |
| raise SystemExit(1) | |
| github_env = os.environ.get("GITHUB_ENV") | |
| if not github_env: | |
| print("GITHUB_ENV is not available", file=sys.stderr) | |
| raise SystemExit(1) | |
| with open(github_env, "a", encoding="utf-8") as env_file: | |
| env_file.write(f"WORKFLOW_RUN_RECONCILE_PR_NUMBER={pr_number}\n") | |
| env_file.write(f"WORKFLOW_RUN_RECONCILE_HEAD_SHA={artifact_head_sha}\n") | |
| PY | |
| - name: Run reviewer bot reconcile | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| STATE_ISSUE_NUMBER: ${{ env.STATE_ISSUE_NUMBER }} | |
| EVENT_NAME: workflow_run | |
| EVENT_ACTION: ${{ github.event.action }} | |
| WORKFLOW_RUN_EVENT: ${{ github.event.workflow_run.event }} | |
| WORKFLOW_RUN_HEAD_SHA: ${{ github.event.workflow_run.head_sha }} | |
| REPO_OWNER: ${{ github.repository_owner }} | |
| REPO_NAME: ${{ github.event.repository.name }} | |
| run: | | |
| uv run python scripts/reviewer_bot.py |