Repository navigation
Dependabot Alert Sweep #30
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
| # Dependabot alert sweep (#2233), the alert-consuming half of #2229. | |
| # | |
| # Dependabot's SECURITY-update PRs are turned off for this repo; its ALERTS are | |
| # left on. Those are two independent settings, and this workflow depends on the | |
| # split: it reads the alerts and turns them into ordinary board-tracked issues, | |
| # so the fix is written by hand against `v2/main` like any other work. | |
| # | |
| # alert -> this sweep -> issue (labeled, milestoned, boarded) -> maintainer PR -> v2/main | |
| # | |
| # It is a SCHEDULE, not an event handler, because there is no `dependabot_alert` | |
| # workflow trigger — that is a webhook event only. Daily is deliberate: with | |
| # security PRs off there is no mergeable-against-`main` artifact and no window to | |
| # race, so the merge guard #2060 needed has no analogue here. What replaces it is | |
| # a precondition inside the script: `automated-security-fixes` is a repo SETTING | |
| # and can be switched back on from the UI without a commit, so the sweep reads it | |
| # back and fails loudly on an explicit `enabled: true`. That read needs a | |
| # permission `GITHUB_TOKEN` cannot hold, so with the default token it reports | |
| # UNVERIFIED instead — see the token notes below; it is a conditional guard, not | |
| # an invariant. | |
| # | |
| # ⚠️ GitHub computes the dependency graph, and therefore every alert, from the | |
| # DEFAULT branch (`main`), while we ship from `v2/main`. Two consequences: | |
| # | |
| # * An alert is re-checked against `v2/main`'s own lockfile before an issue is | |
| # filed — hence the `ref: v2/main` checkout below. An alert whose vulnerable | |
| # range no longer matches is already fixed on the branch we ship from and is | |
| # waiting on a milestone merge to close, so it is skipped silently. | |
| # * A vulnerable dependency introduced on `v2/main` and not yet merged to | |
| # `main` produces NO alert at all. No approach that consumes GitHub's alerts | |
| # avoids that. The release-time `npm audit --audit-level=high` report from | |
| # #2231 is a second signal that partially covers it — at release time only; | |
| # running that same report over `v2/main`'s lockfiles on a schedule would | |
| # close it fully and is a separable follow-up. | |
| # | |
| # `vulnerability-alerts: read` is the one non-default permission, and | |
| # `GITHUB_TOKEN` supports it — no PAT is needed to read the alerts themselves. | |
| # Two side steps are outside its reach, and `PROJECT_TOKEN` is what covers them | |
| # when it exists: | |
| # | |
| # * Writing the board card, since board #28 is an ORG project | |
| # (`organization projects: write`). Absent, the issue is still filed labeled | |
| # and milestoned and the next `/issue-triage` sweep boards it. | |
| # * Reading back `automated-security-fixes`, which needs `administration: read` | |
| # — a permission `permissions:` has no key for, so `GITHUB_TOKEN` can never | |
| # have it. Absent, that assertion is reported as UNVERIFIED rather than | |
| # failing the run; an explicit `enabled: true` still fails it. | |
| # | |
| # Nothing the sweep exists to do is skipped for want of that secret. | |
| # | |
| # The version-update half of #2229 is the sibling `dependency-refresh.yml`. | |
| name: Dependabot Alert Sweep | |
| on: | |
| schedule: | |
| - cron: "17 6 * * *" # 06:17 UTC daily; alerts are not minute-sensitive | |
| workflow_dispatch: | |
| # The marker check is a read-before-write, not an atomic one, and nothing stops | |
| # a `workflow_dispatch` from landing on top of the scheduled run. Two overlapping | |
| # runs would both see no open issue and both file one, which is the exact | |
| # duplicate this sweep's whole idempotency design exists to prevent (Copilot). | |
| # `cancel-in-progress: false` because the queued run must WAIT and then re-read | |
| # the state the first run wrote — cancelling it would drop a sweep instead. | |
| concurrency: | |
| group: dependabot-alert-sweep | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| issues: write | |
| vulnerability-alerts: read | |
| jobs: | |
| alert-sweep: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout v2/main | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| ref: v2/main | |
| - name: Setup Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: "22.x" | |
| cache: "npm" | |
| # Root install only, and no lifecycle scripts. The sweep's one dependency | |
| # is `semver`; it reads every lockfile as JSON and never needs a client's | |
| # tree on disk, so the postinstall cascade into `clients/*` that | |
| # `dependency-refresh.yml` genuinely needs (it shells out to | |
| # `npm outdated` in each) would be minutes of nothing here. | |
| - name: Install root dependencies | |
| run: npm ci --ignore-scripts | |
| - name: Run the Dependabot alert sweep | |
| run: node scripts/dependabot-alerts.mjs | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| # Optional: an org-project PAT with `organization projects: write`. | |
| # Absent, the issue is filed unboarded and triage picks it up. | |
| PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }} |