diff --git a/.github/workflows/ci-lib-changelog-emitter.yml b/.github/workflows/ci-lib-changelog-emitter.yml index 3a483bfb..7be67e33 100644 --- a/.github/workflows/ci-lib-changelog-emitter.yml +++ b/.github/workflows/ci-lib-changelog-emitter.yml @@ -36,12 +36,3 @@ jobs: - name: Run tests run: pnpm --filter typespec-versioning-changelog run test:coverage - - - name: Audit dependencies - # Gated to PRs into `main` (and main-context workflow_call invocations) so - # advisories that live on `main` and can only be fixed there don't block - # PRs into HOLD-* batching branches or other non-main bases. The HOLD → main - # checkpoint PR re-runs this audit, so anything live at merge time is gated - # at the actionable boundary. - if: github.base_ref == 'main' || github.ref == 'refs/heads/main' - run: pnpm --filter typespec-versioning-changelog run audit diff --git a/.github/workflows/ci-lib-cli.yml b/.github/workflows/ci-lib-cli.yml index 3709cbad..bbdd89fb 100644 --- a/.github/workflows/ci-lib-cli.yml +++ b/.github/workflows/ci-lib-cli.yml @@ -41,12 +41,3 @@ jobs: - name: Build library run: pnpm --filter @common-grants/cli run build - - - name: Audit dependencies - # Gated to PRs into `main` (and main-context workflow_call invocations) so - # advisories that live on `main` and can only be fixed there don't block - # PRs into HOLD-* batching branches or other non-main bases. The HOLD → main - # checkpoint PR re-runs this audit, so anything live at merge time is gated - # at the actionable boundary. - if: github.base_ref == 'main' || github.ref == 'refs/heads/main' - run: pnpm --filter @common-grants/cli run audit diff --git a/.github/workflows/ci-lib-core.yml b/.github/workflows/ci-lib-core.yml index 61365605..2415c6df 100644 --- a/.github/workflows/ci-lib-core.yml +++ b/.github/workflows/ci-lib-core.yml @@ -38,12 +38,3 @@ jobs: - name: Emit TypeSpec outputs run: pnpm --filter @common-grants/core run typespec - - - name: Audit dependencies - # Gated to PRs into `main` (and main-context workflow_call invocations) so - # advisories that live on `main` and can only be fixed there don't block - # PRs into HOLD-* batching branches or other non-main bases. The HOLD → main - # checkpoint PR re-runs this audit, so anything live at merge time is gated - # at the actionable boundary. - if: github.base_ref == 'main' || github.ref == 'refs/heads/main' - run: pnpm --filter @common-grants/core run audit diff --git a/.github/workflows/ci-lib-ts-sdk.yml b/.github/workflows/ci-lib-ts-sdk.yml index fa01ab12..056dc2ce 100644 --- a/.github/workflows/ci-lib-ts-sdk.yml +++ b/.github/workflows/ci-lib-ts-sdk.yml @@ -38,12 +38,3 @@ jobs: - name: Run tests run: pnpm --filter @common-grants/sdk run test:coverage - - - name: Audit dependencies - # Gated to PRs into `main` (and main-context workflow_call invocations) so - # advisories that live on `main` and can only be fixed there don't block - # PRs into HOLD-* batching branches or other non-main bases. The HOLD → main - # checkpoint PR re-runs this audit, so anything live at merge time is gated - # at the actionable boundary. - if: github.base_ref == 'main' || github.ref == 'refs/heads/main' - run: pnpm --filter @common-grants/sdk run audit diff --git a/.github/workflows/ci-website-preview.yml b/.github/workflows/ci-website-preview.yml index 60941624..2b4f089a 100644 --- a/.github/workflows/ci-website-preview.yml +++ b/.github/workflows/ci-website-preview.yml @@ -17,9 +17,9 @@ env: CLOUDFLARE_WORKERS_DOMAIN: billy-daly.workers.dev jobs: - # Install, build, and run checks/tests/audit. All post-build steps are - # sequential but each runs regardless of the previous step's pass/fail so - # lint, test, and audit failures all surface in a single CI run. + # Install, build, and run checks/tests. All post-build steps are sequential + # but each runs regardless of the previous step's pass/fail so lint and test + # failures all surface in a single CI run. validate: runs-on: ubuntu-latest outputs: @@ -77,12 +77,8 @@ jobs: if: ${{ !cancelled() && steps.build.outcome == 'success' }} run: pnpm run test - - name: Audit dependencies - if: ${{ !cancelled() && steps.build.outcome == 'success' }} - run: pnpm run audit:high - # Deploy the built artifact to a per-PR Cloudflare Worker. Decoupled from - # the test/check/audit outcome (via artifact_ready) so previews stay + # the test/check outcome (via artifact_ready) so previews stay # available for reviewing UI changes on PRs that have unrelated failures. deploy-preview: runs-on: ubuntu-latest diff --git a/.github/workflows/deps-audit.yml b/.github/workflows/deps-audit.yml new file mode 100644 index 00000000..8f268011 --- /dev/null +++ b/.github/workflows/deps-audit.yml @@ -0,0 +1,59 @@ +name: "Deps: Scheduled Dependency Audit" + +# Daily workspace-wide advisory sweep on main. New GHSAs published against +# deps already on main surface here as a tracking issue within a day, instead +# of redding every open PR the moment they drop. PRs that actually change +# deps are still gated by the audit in ci-catalog-validation.yml (any dep +# change updates the root lockfile, which triggers it). +on: + schedule: + # Daily at ~7-8am PT (15:00 UTC = 8am PDT / 7am PST) + - cron: "0 15 * * *" + workflow_dispatch: + # Smoke-test on changes here. + pull_request: + paths: + - .github/workflows/deps-audit.yml + +permissions: + contents: read + issues: write + +jobs: + audit: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Install Node.js + uses: actions/setup-node@v6 + with: + node-version-file: .nvmrc + + - name: Install pnpm + uses: pnpm/action-setup@v6 + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Audit all workspace packages + # No --audit-level: pnpm's default is low, so the sweep reports + # everything, including advisories below the moderate threshold that + # gates dep-changing PRs in ci-catalog-validation.yml. + run: pnpm audit + + - name: Open tracking issue on scheduled failure + if: failure() && github.event_name != 'pull_request' + env: + GH_TOKEN: ${{ github.token }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + run: | + TITLE="Scheduled dependency audit is failing" + EXISTING=$(gh issue list --state open --search "in:title \"$TITLE\"" --json number --jq '.[0].number') + if [ -n "$EXISTING" ]; then + gh issue comment "$EXISTING" --body "Still failing: $RUN_URL" + else + gh issue create --title "$TITLE" --label dependencies \ + --body "The daily workspace-wide dependency audit found advisories against deps on \`main\`. See the run log for details: $RUN_URL" + fi