Repository navigation
feat(coderabbit-config): validate .coderabbit.yaml so a broken config… #1
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: Bump coderabbit-config-validate callers | |
| # When the coderabbit-config-validate reusable workflow (or the checker + vendored | |
| # schema behind it) is updated on main, open a SHA-bump PR in every repo that pins | |
| # a caller against it. PRs are opened by Cloud Code Bot so they are easy to filter | |
| # and merge. | |
| # | |
| # This is a thin entrypoint over the shared bumper at | |
| # .github/bump-callers/bump-callers.sh — the same script drives every other fleet. | |
| # Keeping ONE implementation is deliberate: a forked copy is how other shared | |
| # machinery in the org has drifted. The entrypoints differ only in their | |
| # path-filter trigger and the parameters passed below. (They stay separate rather | |
| # than one matrix because their triggers differ — a cursor-review.yml change must | |
| # not spuriously bump these callers, and vice versa.) | |
| # | |
| # This fleet matters more than most for the SCHEMA, not the workflow file: the | |
| # vendored schema.v2.json is what every consumer is graded against, and it moves | |
| # on its own schedule via refresh-coderabbit-schema.yml. Without this fleet a | |
| # refreshed schema would sit on main while every pinned caller kept validating | |
| # against a months-old copy — the exact vendoring-rots failure the refresh job | |
| # exists to prevent, reintroduced one layer down. | |
| # | |
| # The caller list is NOT hardcoded here. This repo is PUBLIC (workflow file and | |
| # Actions run logs are both publicly viewable), and most callers are private, so | |
| # their names must never appear in this file or its logs. The list lives in the | |
| # repo-level Actions SECRET `CODERABBIT_CONFIG_CALLERS` as a JSON array of | |
| # {"repo","file","label"} objects, same shape as the other fleets' rosters. | |
| # | |
| # A SECRET, not a variable (BE-6472): the roster reaches the script through the | |
| # step's `env:` below, and Actions prints that env block BEFORE the step runs — so | |
| # a variable's raw value would be published in this public repo's run log ahead of | |
| # any masking the script could do. A secret is runner-masked everywhere, that dump | |
| # included. `bump-callers.sh` still `::add-mask::`es every repo name before IT | |
| # echoes anything: Actions masks the roster as ONE exact string, not each name | |
| # inside it, so a name echoed on its own would otherwise print in the clear. | |
| # | |
| # The roster is seeded EMPTY, so `ALLOW_EMPTY: "true"` below: this fleet grows as | |
| # callers land (v1 wires one repo; the rest follow), and an empty list is a clean | |
| # no-op rather than an error. Flip it to "false" once the fleet has live callers — | |
| # at that point an empty roster is a bug, and a silent clean exit would leave every | |
| # caller pinned to a stale checker with nothing red anywhere to say so. | |
| # | |
| # Update flow — adding/removing a caller needs NO public commit: | |
| # jq -c . callers.json | gh secret set CODERABBIT_CONFIG_CALLERS --repo Comfy-Org/github-workflows | |
| # Keep the canonical callers.json in a PRIVATE infra/ops repo so roster edits have | |
| # a reviewed source of truth; the org audit log records each edit. (The specific | |
| # home repo is intentionally not named here — this file is public.) | |
| # | |
| # Recovery note: GitHub evaluates a `paths:` filter against only the first 300 | |
| # changed files of a push, so a change here buried in a larger main push can | |
| # create NO run at all. `workflow_dispatch` above is the recovery — run it once | |
| # from main and the fleet catches up. Run it once when this fleet first lands, | |
| # too: landing a fleet does not touch the reusable it watches, so its own merge | |
| # matches no path filter and fires no run. | |
| on: | |
| workflow_dispatch: {} # allow on-demand runs (e.g. to re-bump callers) | |
| push: | |
| branches: [main] | |
| paths: | |
| - .github/workflows/coderabbit-config-validate.yml | |
| - .github/coderabbit-config/** | |
| permissions: | |
| contents: read | |
| # Serialize runs of this fleet. The bumper pushes to a STABLE branch | |
| # (ci/bump-coderabbit-config-validate) shared across runs, so two overlapping runs | |
| # (a rapid second main push, or a push racing a manual re-run) would force-reset | |
| # that branch and race the PR update — an older run finishing last could leave the | |
| # committed diff pinned to a stale SHA. cancel-in-progress: false lets the running | |
| # bump finish; GitHub keeps only the newest pending run, so the latest SHA always | |
| # wins (BE-3882). | |
| concurrency: | |
| group: bump-coderabbit-config-callers | |
| cancel-in-progress: false | |
| jobs: | |
| bump: | |
| # Guard against a workflow_dispatch run from a non-main ref: github.sha is the | |
| # tip of whatever ref was selected, and the bumper force-resets a stable shared | |
| # branch — a manual run from an older ref would pin every caller to a stale SHA | |
| # (and run this job's script, with the App token minted below, from an | |
| # unreviewed commit). The push trigger is already main-only, so this only ever | |
| # skips stray manual runs. | |
| if: github.ref == 'refs/heads/main' | |
| runs-on: ubuntu-latest | |
| # The job is a bounded loop of `git`/`gh` network calls, plus the preflight's | |
| # deepening fetch; nothing here should take minutes. Without this a hung call | |
| # would hold a runner for the default 6 hours (and, via the serializing | |
| # concurrency group above, block every later bump behind it). | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| # The shared staleness/decommission guard — one implementation for every | |
| # fleet, documented in .github/bump-callers/README.md "Preflight". It decides | |
| # whether this run is a stale re-run (a later commit already touched the | |
| # watched surface and has its own run) or the surface has been | |
| # decommissioned, and emits the SHA the bump below pins. | |
| # WATCHED/WATCHED_ASSETS are LITERAL paths, never the `paths:` globs, and | |
| # must cover EVERY entry in this fleet's filter above: the re-point only pins | |
| # callers to a tip whose watched content it compared, so widen these inputs | |
| # in the same change if you ever widen that filter. | |
| - name: Preflight (staleness / decommission guard) | |
| id: preflight | |
| env: | |
| NEW_SHA: ${{ github.sha }} | |
| WATCHED: .github/workflows/coderabbit-config-validate.yml | |
| WATCHED_ASSETS: .github/coderabbit-config | |
| run: bash .github/bump-callers/preflight.sh | |
| - name: Generate Cloud Code Bot token | |
| # Stale run or decommissioned surface — don't mint an org-wide write token | |
| # for a job that is about to bump nothing. | |
| if: steps.preflight.outputs.proceed == 'true' | |
| uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1.12.0 — pinned: see dependabot.yml ignore (v2+ breaks cross-repo `owner:` token scoping) | |
| id: token | |
| with: | |
| app-id: ${{ vars.APP_ID }} | |
| private-key: ${{ secrets.CLOUD_CODE_BOT_PRIVATE_KEY }} | |
| # `owner:` with no `repositories:` is deliberate and cannot be narrowed: | |
| # the caller list is a runtime secret (see the header), so the repos this | |
| # token must reach are not knowable at authoring time — and naming them | |
| # here would leak private caller names into a public file. The | |
| # PERMISSIONS can be narrowed without naming anything, so they are: the | |
| # bumper commits the rewritten caller file (contents), opens or updates | |
| # the bump PR (pull-requests), and stamps the caller's label through the | |
| # issues API (issues). | |
| owner: Comfy-Org | |
| permission-contents: write | |
| permission-pull-requests: write | |
| permission-issues: write | |
| - name: Bump SHA in caller repos | |
| # Stale run or decommissioned surface — nothing to bump. | |
| if: steps.preflight.outputs.proceed == 'true' | |
| env: | |
| GH_TOKEN: ${{ steps.token.outputs.token }} | |
| # NOT github.sha: when main moved on but the watched surface is | |
| # unchanged, the preflight re-points this run at the verified tip, and | |
| # reading github.sha here would silently discard that re-point. | |
| NEW_SHA: ${{ steps.preflight.outputs.new_sha }} | |
| # Names the roster to fix in an error message. It is a SECRET, not a | |
| # variable; the env key keeps the fleets' historical name so every | |
| # entrypoint and the shared script stay in step. | |
| VAR_NAME: CODERABBIT_CONFIG_CALLERS | |
| TAG: coderabbit-config-validate | |
| WORKFLOW_FILE: coderabbit-config-validate.yml | |
| # An empty roster — `[]`, or a secret nobody has set — is a clean no-op | |
| # here, not an error. See the header for when to flip this. | |
| ALLOW_EMPTY: "true" | |
| # JSON array of {"repo","file","label"} — see the header comment for the | |
| # update flow. Kept in a repo-level SECRET (not this file, and not a | |
| # variable) so private caller names never land in this public repo — nor, | |
| # since a secret is masked in the step's env dump too, in its run logs. | |
| CALLERS_JSON: ${{ secrets.CODERABBIT_CONFIG_CALLERS }} | |
| run: bash .github/bump-callers/bump-callers.sh |