Auto-merge OpenAPI description update PRs - #6993
Conversation
|
Added a hard-fail Preflight step that runs before anything else, per review feedback. Both credentials are now verified up front instead of failing opaquely mid-run. Merge token. Probes
This matters because Chatterbox. Posts a real message to Also added a Two real bugs surfaced while testing the new code:
Validation. Token probe exercised against live API across all four branches (unset / valid / bad credentials / valid-token-but-unreadable-repo), each reporting correctly. HTTP classifier verified against live |
There was a problem hiding this comment.
Pull request overview
Adds automation to merge current bot-generated OpenAPI updates and close superseded PRs.
Changes:
- Selects and validates the latest OpenAPI 3.0/3.1 PRs.
- Scans for potential breaking changes before merging.
- Pushes merges, closes older PRs, and sends failure alerts.
Show a summary per file
| File | Description |
|---|---|
.github/workflows/auto-merge-openapi-updates.yml |
Implements the scheduled auto-merge workflow. |
Review details
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
- Files reviewed: 1/1 changed files
- Comments generated: 7
- Review effort level: Balanced
| code=$(curl --silent --output /dev/null --write-out '%{http_code}' \ | ||
| --max-time 20 \ | ||
| -u "${CHATTERBOX_TOKEN}:" \ | ||
| "${CHATTERBOX_URL%/}/topics/%23api-platform" \ | ||
| --data ':white_check_mark: OpenAPI auto-merge preflight: chatterbox route is alive.' \ |
| superseded=$(jq -r \ | ||
| --argjson keep30 "${pr_30:-0}" \ | ||
| --argjson keep31 "${pr_31:-0}" \ | ||
| '[.[].number | select(. != $keep30 and . != $keep31)] | join(" ")' \ | ||
| <<<"$open_prs") |
| # Removed top-level path key, e.g. ` "/repos/{owner}/{repo}":` | ||
| paths=$(count '^- "/') | ||
| # Removed enum member, e.g. ` - archived` | ||
| enums=$(count '^-[[:space:]]+- [A-Za-z0-9_.-]+$') |
| [ -n "$ref" ] || continue | ||
|
|
||
| git fetch --no-tags --filter=blob:none origin "$ref":"refs/remotes/origin/$ref" | ||
| diff=$(git diff "$base...origin/$ref" -- "$file" || true) |
| for pair in "$PR_30:$REF_30" "$PR_31:$REF_31"; do | ||
| pr="${pair%%:*}"; ref="${pair#*:}" | ||
| [ -n "$pr" ] && [ -n "$ref" ] || continue | ||
| git fetch --no-tags origin "$ref":"refs/remotes/origin/$ref" --filter=blob:none |
| if: >- | ||
| steps.preflight.outcome == 'success' && | ||
| (failure() || steps.breaking.outputs.status == 'breaking') |
| permissions: | ||
| contents: write | ||
| pull-requests: write |
|
Aligned the breaking-change gate with the team's own definition and added the release-notes summary, per the first-responder runbook comparison. 1. Semantic breaking-change detection (replaces the grep heuristics)The previous scan caught 3 of the 9 breaking changes listed in Replaced with
Note the opposing directions on Cost is acceptable: parsing the 9.8 MB Validation. Against the real #6989 diff: 0 findings (no false positives), and an identical-file control also yields 0. Then each of the 10 rules was exercised by mutating a real description and confirming that rule - and only that rule - fires. That test caught a bug in my own test harness: the first 2. Change summary posted before merge
The scanner already computes exactly this, so the workflow now posts operation/schema counts, added operations, and any breaking findings as a PR comment before merging. This should make release-note prep better than the status quo, where the step is skipped in practice. 3. Alignment with the FR runbookThis automates step 6 ( Companion PR github/api-platform#9851 updates Still a gap
|
|
Converting to draft so we can work through how to detect locks for GHES releases |
|
Added GHES release-candidate freeze detection. The signalThe key observation is that step 1 of the sequence is what creates the evidence here. Setting That gives a detector needing no cross-repo polling, no Slack integration, and no manual state:
It is also self-clearing: once the version is on Note the 3.21 row: the descriptions landed 18 minutes before the docs RC merged. That is the entire freeze window, and it is why this is evaluated on every run rather than cached. Two signals1. New GHES version (automatic). Compares 2. Behaviour when frozenMerging, closing superseded PRs, and the breaking-change scan are all gated. The workflow posts a notice on the affected PRs explaining why it's holding and pings A freeze is reported as a distinct Validation
Companion doc update in github/api-platform#9851 covers the sequence, the detection, and the manual override. |
What
Adds
.github/workflows/auto-merge-openapi-updates.yml, which auto-merges the newest opengithub-openapi-bot"Update OpenAPI 3.x Descriptions" PRs and closes the older superseded ones.Merging these by hand is pure toil: they are machine-generated from
github/github, they are effectively never reviewed, and they stack up. There are 34 superseded PRs open right now.How it works
Runs every 2 hours (plus
workflow_dispatch, which supports adry_runinput):Lint OpenAPI 3.0 releasesandLint OpenAPI 3.1 releasesonly.api.github.com.yamlfor removed path keys, enum values, and schema definitions. Any hit skips the merge and pings#api-platform.gitand pushes tomain.#api-platformon failure or breaking-change detection only. Success is silent.Design notes
Why
gitinstead of the merge API / native auto-merge. These PRs are 100K+ lines across 64+ files.PUT /pulls/{n}/mergereturns 502/504,GET /pulls/{n}/filesreturns 422 "diff taking too long", andGET /pulls/{n}reportschanged_files: 0. Native auto-merge is also disabled on this repo (allow_auto_merge: false) and would depend on that same API. Localgit merge+pushis the only thing that works, which matches the existing manual runbook.Why the repo size is not a problem. Checkout uses
filter: blob:none, so the ~4.6 GB of history is not downloaded; blobs are fetched lazily only for the files actually touched.Why CodeQL is excluded from the gate. The CodeQL failures on these PRs are
timed_out, not findings. Code scanning here is default setup scanning only theactionslanguage, which is unrelated to YAML description changes, and it is not a required check onmain(required_status_checks.contextsis empty), so it is not gating merges today either. Excluding it is an explicit allowlist decision rather than a bypass.Token. Uses the existing (currently unused)
OPENAPI_MERGE_TOKENsecret, falling back togithub.token. Note that pushes made withGITHUB_TOKENdo not trigger downstream workflows, soOPENAPI_MERGE_TOKENis the intended path.Validation
runblock passesbash -n.Suggested rollout
Merge, then run
workflow_dispatchwithdry_run: trueonce to confirm selection in-situ before letting the schedule take over.Note
Left as a draft for a human to review and mark ready.