From d8e7e9d2ed8c5d2c111af69884803a00b828abef Mon Sep 17 00:00:00 2001 From: Daniel Baker Date: Mon, 6 Jul 2026 18:03:43 -0700 Subject: [PATCH 1/3] ci: resolve zizmor pedantic findings (perms, comments, job names) Address the zero-behavior-change pedantic findings: - Move the workflow-level permissions in netlify-deploy.yml and release-npm-package.yaml down to their single job (excessive-permissions); identical effective permissions, since the caller still sets the ceiling. - Add an explanatory comment to every write permission (undocumented-permissions). - Give every job a name (anonymous-definition). Takes zizmor --pedantic from 21 findings to 3 (only concurrency-limits, which is handled in a separate commit). --- .github/workflows/check.yml | 8 +++++++- .github/workflows/netlify-deploy.yml | 10 ++++++---- .github/workflows/release-guide.yml | 11 ++++++----- .github/workflows/release-npm-package.yaml | 8 +++++--- 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index e5b00b5..417f2c7 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -24,6 +24,7 @@ permissions: jobs: format: + name: Flake check runs-on: ubuntu-latest steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 @@ -33,6 +34,7 @@ jobs: - run: nix flake check --print-build-logs build-the-world: + name: Build all artifacts runs-on: ubuntu-latest steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 @@ -42,6 +44,7 @@ jobs: - run: nix run .#nixos-branding.verification.verify-nixos-branding-all --print-build-logs compare-artifacts-build: + name: Build artifact comparison runs-on: ubuntu-latest needs: build-the-world if: github.event_name == 'pull_request' @@ -112,6 +115,7 @@ jobs: if-no-files-found: error compare-artifacts-comment: + name: Comment artifact comparison runs-on: ubuntu-latest needs: compare-artifacts-build # Skip on fork PRs (read-only token can't post). Also implicitly @@ -119,7 +123,7 @@ jobs: # itself is gated to those. if: github.event.pull_request.head.repo.full_name == github.repository permissions: - pull-requests: write + pull-requests: write # post the artifact-comparison sticky comment steps: - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: @@ -165,6 +169,7 @@ jobs: branding-guide-changelog: + name: Changelog query runs-on: ubuntu-latest steps: - name: Checkout @@ -190,6 +195,7 @@ jobs: printf '%s\n' "$NOTES" workflow-security: + name: Workflow security runs-on: ubuntu-latest steps: - name: Checkout diff --git a/.github/workflows/netlify-deploy.yml b/.github/workflows/netlify-deploy.yml index bff7fcd..89e8348 100644 --- a/.github/workflows/netlify-deploy.yml +++ b/.github/workflows/netlify-deploy.yml @@ -5,14 +5,16 @@ on: workflow_call: workflow_dispatch: -permissions: - contents: write - statuses: write - deployments: write +permissions: {} jobs: deploy: + name: Deploy media kit to Netlify runs-on: ubuntu-latest + permissions: + contents: write # Netlify action posts a commit comment + statuses: write # Netlify action sets a commit status + deployments: write # Netlify action creates a GitHub deployment steps: - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 diff --git a/.github/workflows/release-guide.yml b/.github/workflows/release-guide.yml index 8df50cf..a41d01c 100644 --- a/.github/workflows/release-guide.yml +++ b/.github/workflows/release-guide.yml @@ -15,10 +15,11 @@ jobs: contents: read release: + name: Create GitHub release needs: check runs-on: ubuntu-latest permissions: - contents: write + contents: write # gh release create publishes the release steps: - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 @@ -84,13 +85,13 @@ jobs: uses: ./.github/workflows/netlify-deploy.yml needs: release permissions: - contents: write - statuses: write - deployments: write + contents: write # Netlify action posts a commit comment + statuses: write # Netlify action sets a commit status + deployments: write # Netlify action creates a GitHub deployment release-npm-package: uses: ./.github/workflows/release-npm-package.yaml needs: release permissions: - id-token: write + id-token: write # OIDC for npm provenance publish contents: read diff --git a/.github/workflows/release-npm-package.yaml b/.github/workflows/release-npm-package.yaml index daacc44..11c0468 100644 --- a/.github/workflows/release-npm-package.yaml +++ b/.github/workflows/release-npm-package.yaml @@ -5,13 +5,15 @@ on: workflow_call: workflow_dispatch: -permissions: - id-token: write # Required for OIDC - contents: read +permissions: {} jobs: build-npm-package: + name: Build and publish npm package runs-on: ubuntu-latest + permissions: + id-token: write # Required for OIDC + contents: read steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: From 5f82cac48b95c0391b65201dbe4b97ca8cb22ae0 Mon Sep 17 00:00:00 2001 From: Daniel Baker Date: Mon, 6 Jul 2026 18:05:21 -0700 Subject: [PATCH 2/3] ci: add concurrency limits to release workflows Add a concurrency group to release-guide.yml, netlify-deploy.yml, and release-npm-package.yaml with cancel-in-progress: false, so overlapping runs queue rather than interrupt an in-progress release, deploy, or publish (zizmor concurrency-limits). check.yml already had concurrency. With this, zizmor --pedantic reports 0 findings. --- .github/workflows/netlify-deploy.yml | 5 +++++ .github/workflows/release-guide.yml | 5 +++++ .github/workflows/release-npm-package.yaml | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/.github/workflows/netlify-deploy.yml b/.github/workflows/netlify-deploy.yml index 89e8348..a0b51f8 100644 --- a/.github/workflows/netlify-deploy.yml +++ b/.github/workflows/netlify-deploy.yml @@ -5,6 +5,11 @@ on: workflow_call: workflow_dispatch: +concurrency: + # Never interrupt an in-progress deploy; queue the next run instead. + group: netlify-deploy-${{ github.ref }} + cancel-in-progress: false + permissions: {} jobs: diff --git a/.github/workflows/release-guide.yml b/.github/workflows/release-guide.yml index a41d01c..df96d58 100644 --- a/.github/workflows/release-guide.yml +++ b/.github/workflows/release-guide.yml @@ -6,6 +6,11 @@ on: tags: - "nixos-branding-guide-v*.*.*" +concurrency: + # Serialize release runs for a tag; never interrupt a release in progress. + group: release-guide-${{ github.ref }} + cancel-in-progress: false + permissions: {} jobs: diff --git a/.github/workflows/release-npm-package.yaml b/.github/workflows/release-npm-package.yaml index 11c0468..8fc6894 100644 --- a/.github/workflows/release-npm-package.yaml +++ b/.github/workflows/release-npm-package.yaml @@ -5,6 +5,11 @@ on: workflow_call: workflow_dispatch: +concurrency: + # Never interrupt an in-progress publish; queue the next run instead. + group: release-npm-package-${{ github.ref }} + cancel-in-progress: false + permissions: {} jobs: From 1140e4911efb1832378ea981e52d108c9ba7d794 Mon Sep 17 00:00:00 2001 From: Daniel Baker Date: Mon, 6 Jul 2026 18:54:21 -0700 Subject: [PATCH 3/3] ci: add report-only pedantic zizmor SARIF workflow Add .github/workflows/zizmor.yml (modeled on NixOS/infra) that runs zizmor --pedantic --format sarif and uploads the result to code scanning. SARIF mode exits 0, so it is report-only: pedantic findings surface as PR annotations and in the Security tab for triage, while the blocking gate remains the regular-persona run in check.yml. Runs on PRs and pushes to main that touch .github/** or flake.lock. zizmor comes from the flake's pinned nixpkgs (.#zizmor); upload-sarif is SHA-pinned. --- .github/workflows/zizmor.yml | 44 ++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 .github/workflows/zizmor.yml diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml new file mode 100644 index 0000000..a2a2481 --- /dev/null +++ b/.github/workflows/zizmor.yml @@ -0,0 +1,44 @@ +name: Workflow security report + +on: + push: + branches: + - main + paths: + - ".github/**" + - flake.lock + pull_request: + paths: + - ".github/**" + - flake.lock + +concurrency: + group: zizmor-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: {} + +jobs: + zizmor: + name: zizmor pedantic audit (report-only) + runs-on: ubuntu-latest + permissions: + contents: read # checkout + security-events: write # upload the SARIF report to code scanning + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - uses: ./.github/actions/setup-nix + - name: Run zizmor (pedantic, SARIF) + # SARIF mode exits 0 even with findings, so this reports rather than + # blocks; the blocking gate is the regular-persona run in check.yml. + env: + GH_TOKEN: ${{ github.token }} + run: nix run .#zizmor -- --format sarif --pedantic . > results.sarif + - name: Upload SARIF to code scanning + uses: github/codeql-action/upload-sarif@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3 + with: + sarif_file: results.sarif + category: zizmor