-
Notifications
You must be signed in to change notification settings - Fork 50
Add auto-labelling and security linting for workflows #260
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
rlahfa-dinum
wants to merge
5
commits into
main
Choose a base branch
from
autolabeller
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
234af9c
npins/sources: update
rlahfa-dinum e8c90f0
ci: add zizmor as a pre-push hook and fix existing workflows
rlahfa-dinum 8348da5
ci: add zizmor as a CI check
rlahfa-dinum e55da31
.github/workflows: auto-label pull requests by area
rlahfa-dinum 06cdd98
.github/workflows: relabel pull requests by status
rlahfa-dinum File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| # SPDX-FileCopyrightText: 2026 Ryan Lahfa <ryan.lahfa.ext@numerique.gouv.fr> | ||
| # | ||
| # SPDX-License-Identifier: MIT | ||
|
|
||
| # Path-based auto-labelling for A/* area labels. | ||
| # Used by .github/workflows/auto-label-areas.yml via actions/labeler@v5. | ||
| # One PR can match multiple areas (e.g. modules + testing). | ||
|
|
||
| "A/hardening": | ||
| - changed-files: | ||
| - any-glob-to-any-file: | ||
| - "modules/anssi/**" | ||
| - "modules/auditd.nix" | ||
|
|
||
| "A/auth": | ||
| - changed-files: | ||
| - any-glob-to-any-file: | ||
| - "modules/security-keys.nix" | ||
| - "modules/pam/**" | ||
| - "modules/ssh-tpm-agent.nix" | ||
| - "modules/superadmins/**" | ||
| - "modules/admins/**" | ||
|
|
||
| "A/encryption": | ||
| - changed-files: | ||
| - any-glob-to-any-file: "modules/filesystems/**" | ||
|
|
||
| "A/secure-boot": | ||
| - changed-files: | ||
| - any-glob-to-any-file: "modules/bootloader.nix" | ||
|
|
||
| "A/networking": | ||
| - changed-files: | ||
| - any-glob-to-any-file: | ||
| - "modules/networking.nix" | ||
| - "modules/networkmanager-events.nix" | ||
| - "modules/vpn/**" | ||
| - "modules/http-proxy/**" | ||
| - "modules/bastion/**" | ||
|
|
||
| "A/modules": | ||
| - changed-files: | ||
| - any-glob-to-any-file: | ||
| - "modules/chromium/**" | ||
| - "modules/graphical-interface/**" | ||
| - "modules/tools/**" | ||
| - "modules/console.nix" | ||
| - "modules/shells.nix" | ||
| - "modules/pki.nix" | ||
|
|
||
| "A/nixos": | ||
| - changed-files: | ||
| - any-glob-to-any-file: | ||
| - "lib/**" | ||
| - "default.nix" | ||
| - "shell.nix" | ||
| - "npins/**" | ||
| - "pkgs/overlay.nix" | ||
|
|
||
| "A/hardware": | ||
| - changed-files: | ||
| - any-glob-to-any-file: "hardware/**" | ||
|
|
||
| "A/docs": | ||
| - changed-files: | ||
| - any-glob-to-any-file: | ||
| - "docs/**" | ||
| - "*.md" | ||
| - "LICENSES/**" | ||
|
|
||
| "A/testing": | ||
| - changed-files: | ||
| - any-glob-to-any-file: | ||
| - "tests/**" | ||
| - ".github/workflows/securix-testsuite.yaml" | ||
| - "workflows/**" | ||
|
|
||
| "A/lifecycle": | ||
| - changed-files: | ||
| - any-glob-to-any-file: | ||
| - "modules/updates/**" | ||
| - "modules/self.nix" | ||
| - "modules/distribution.nix" | ||
|
|
||
| "A/infra": | ||
| - changed-files: | ||
| - any-glob-to-any-file: | ||
| - ".github/workflows/**" | ||
| - "config.yml" | ||
| - "statix.toml" | ||
| - ".pre-commit-config.yaml" |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # SPDX-FileCopyrightText: 2026 Ryan Lahfa <ryan.lahfa.ext@numerique.gouv.fr> | ||
| # | ||
| # SPDX-License-Identifier: MIT | ||
|
|
||
| name: "Auto-label: areas" | ||
|
|
||
| on: | ||
| pull_request_target: | ||
| types: [opened, reopened, synchronize, ready_for_review] | ||
|
|
||
| permissions: {} | ||
|
|
||
| jobs: | ||
| label: | ||
| # pull_request_target is safe here: labeler is pinned, configuration is | ||
| # read from the base branch, and the action only uses the GitHub API. | ||
| if: github.event.pull_request.head.repo.full_name == github.repository | ||
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/labeler@bf12e9b00b37c5c0ca2b87b79b2daf7891dbda13 # v7 | ||
| with: | ||
| configuration-path: .github/labeler.yml | ||
| sync-labels: false | ||
| dot: false |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| # SPDX-FileCopyrightText: 2026 Ryan Lahfa <ryan.lahfa.ext@numerique.gouv.fr> | ||
| # | ||
| # SPDX-License-Identifier: MIT | ||
|
|
||
| name: "Auto-label: status" | ||
|
|
||
| on: | ||
| pull_request_target: # zizmor: ignore[dangerous-triggers] - safe: pinned action, no secrets, same-repo only | ||
| types: [opened, reopened, synchronize, ready_for_review] | ||
| pull_request_review: | ||
| types: [submitted] | ||
| pull_request_review_comment: | ||
| types: [created] | ||
| issues: | ||
| types: [opened] | ||
|
|
||
| permissions: {} | ||
|
|
||
| jobs: | ||
| pr-opened: | ||
| # pull_request_target is safe here: github-script is pinned, no secrets are | ||
| # used, and the action only calls the GitHub API to manage labels. | ||
| if: github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name == github.repository | ||
| permissions: | ||
| pull-requests: write | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/github-script@d746ffe35508b1917358783b479e04febd2b8f71 # v9.0.0 | ||
| with: | ||
| script: | | ||
| const pr = context.payload.pull_request; | ||
| if (!pr) return; | ||
| const issue_number = pr.number; | ||
| const repo = context.repo; | ||
| const labels = pr.labels.map(l => l.name); | ||
| const has = n => labels.includes(n); | ||
|
|
||
| // On open/sync, ensure awaiting-maintainers is set and awaiting-author is cleared | ||
| // This implements: new PR -> awaiting-maintainers | ||
| if (!has('status: awaiting-maintainers') && !has('status: ready-to-merge') && !has('status: awaiting smoke testing') && !has('status: blocked')) { | ||
| await github.rest.issues.addLabels({ ...repo, issue_number, labels: ['status: awaiting-maintainers'] }); | ||
| } | ||
| if (has('status: awaiting-author')) { | ||
| try { await github.rest.issues.removeLabel({ ...repo, issue_number, name: 'status: awaiting-author' }); } catch(e) {} | ||
| } | ||
| // New author push after review -> flip back from awaiting-author is handled here via synchronize | ||
| // If PR was in awaiting-author and author pushed, the above remove + add covers it | ||
|
|
||
| review: | ||
| if: github.event_name == 'pull_request_review' || github.event_name == 'pull_request_review_comment' | ||
| permissions: | ||
| pull-requests: write | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/github-script@d746ffe35508b1917358783b479e04febd2b8f71 # v9.0.0 | ||
| with: | ||
| script: | | ||
| const review = context.payload.review; | ||
| const pr = context.payload.pull_request || review?.pull_request; | ||
| if (!pr || !review) return; | ||
| const issue_number = pr.number; | ||
| const repo = context.repo; | ||
| const assoc = review.author_association; // OWNER, MEMBER, COLLABORATOR, etc. | ||
| const isMaintainer = ['OWNER','MEMBER'].includes(assoc); | ||
| if (!isMaintainer) return; | ||
|
|
||
| const state = review.state; // approved, changes_requested, commented | ||
| // Fetch current labels (payload may be stale) | ||
| const { data: cur } = await github.rest.issues.get({ ...repo, issue_number }); | ||
| const has = n => cur.labels.some(l => l.name === n); | ||
|
|
||
| if (state === 'changes_requested' || (state === 'commented' && has('status: awaiting-maintainers'))) { | ||
| // Maintainer reviewed -> awaiting-author | ||
| if (has('status: awaiting-maintainers')) { | ||
| try { await github.rest.issues.removeLabel({ ...repo, issue_number, name: 'status: awaiting-maintainers' }); } catch(e) {} | ||
| } | ||
| if (!has('status: awaiting-author') && !has('status: blocked')) { | ||
| await github.rest.issues.addLabels({ ...repo, issue_number, labels: ['status: awaiting-author'] }); | ||
| } | ||
| } | ||
| if (state === 'approved') { | ||
| if (has('status: awaiting-author')) { | ||
| try { await github.rest.issues.removeLabel({ ...repo, issue_number, name: 'status: awaiting-author' }); } catch(e) {} | ||
| } | ||
| // ready-to-merge is set after CI checks pass; we only ensure not stuck in awaiting-* | ||
| // If checks already green, mark ready; otherwise awaiting-maintainers will be set on next sync | ||
| } | ||
|
|
||
| ci-result: | ||
| # workflow_run is safe here: github-script is pinned, no secrets are used, | ||
| # and the action only calls the GitHub API to manage labels. We only act on | ||
| # PRs from the same repository to avoid processing fork-sourced workflow runs. | ||
| if: github.event_name == 'workflow_run' && github.event.workflow_run.head_repository.full_name == github.repository | ||
| permissions: | ||
| pull-requests: write | ||
| issues: write | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/github-script@d746ffe35508b1917358783b479e04febd2b8f71 # v9.0.0 | ||
| with: | ||
| script: | | ||
| const run = context.payload.workflow_run; | ||
| if (!run) return; | ||
| // Only act on PRs | ||
| const prs = run.pull_requests; | ||
| if (!prs || prs.length === 0) return; | ||
| for (const pr of prs) { | ||
| const issue_number = pr.number; | ||
| const { data: cur } = await github.rest.issues.get({ ...context.repo, issue_number }); | ||
| const has = n => cur.labels.some(l => l.name === n); | ||
| if (run.conclusion === 'failure' || run.conclusion === 'timed_out') { | ||
| if (!has('status: awaiting-ci')) { | ||
| await github.rest.issues.addLabels({ ...context.repo, issue_number, labels: ['status: awaiting-ci'] }); | ||
| } | ||
| } else if (run.conclusion === 'success') { | ||
| if (has('status: awaiting-ci')) { | ||
| try { await github.rest.issues.removeLabel({ ...context.repo, issue_number, name: 'status: awaiting-ci' }); } catch(e) {} | ||
| } | ||
| // If PR is approved and CI just turned green, promote to ready-to-merge | ||
| // Check reviews: last review approved? | ||
| const { data: reviews } = await github.rest.pulls.listReviews({ ...context.repo, pull_number: issue_number, per_page: 20 }); | ||
| const last = [...reviews].reverse().find(r => ['OWNER','MEMBER'].includes(r.author_association)); | ||
| if (last && last.state === 'APPROVED' && !has('status: ready-to-merge') && !has('status: blocked')) { | ||
| await github.rest.issues.addLabels({ ...context.repo, issue_number, labels: ['status: ready-to-merge'] }); | ||
| if (has('status: awaiting-maintainers')) { | ||
| try { await github.rest.issues.removeLabel({ ...context.repo, issue_number, name: 'status: awaiting-maintainers' }); } catch(e) {} | ||
| } | ||
| if (has('status: awaiting-author')) { | ||
| try { await github.rest.issues.removeLabel({ ...context.repo, issue_number, name: 'status: awaiting-author' }); } catch(e) {} | ||
| } | ||
| } | ||
| } | ||
| } | ||
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,26 @@ | ||
| # SPDX-FileCopyrightText: 2026 Ryan Lahfa <ryan.lahfa.ext@numerique.gouv.fr> | ||
| # | ||
| # SPDX-License-Identifier: MIT | ||
|
|
||
| name: '[Sécurix] Formatting check' | ||
|
|
||
| on: | ||
| pull_request: | ||
| push: | ||
| branches: | ||
| - main | ||
|
|
||
| permissions: {} | ||
|
|
||
| jobs: | ||
| reuse_lint: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 | ||
| with: | ||
| persist-credentials: false | ||
| - uses: samueldr/lix-gha-installer-action@f526e761e1ad201b0f4231f61a2a569f17bcc2ac # main | ||
| - name: Check for statix | ||
| run: nix-shell --run 'statix check --config statix.toml' | ||
| - name: Check for formatting | ||
| run: nix-shell --run 'nixfmt -sc $(find . -name "*.nix" -not -path "./npins/*" -not -path "./lib/default.nix")' | ||
| name: '[Sécurix] Formatting check' | ||
| on: | ||
| pull_request: | ||
| push: | ||
| branches: | ||
| - main |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,24 @@ | ||
| # SPDX-FileCopyrightText: 2026 Ryan Lahfa <ryan.lahfa.ext@numerique.gouv.fr> | ||
| # | ||
| # SPDX-License-Identifier: MIT | ||
|
|
||
| name: '[Sécurix] REUSE Licensing conformance' | ||
|
|
||
| on: | ||
| pull_request: | ||
| push: | ||
| branches: | ||
| - main | ||
|
|
||
| permissions: {} | ||
|
|
||
| jobs: | ||
| reuse_lint: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 | ||
| with: | ||
| persist-credentials: false | ||
| - uses: samueldr/lix-gha-installer-action@f526e761e1ad201b0f4231f61a2a569f17bcc2ac # main | ||
| - name: Check for REUSE compliance | ||
| run: nix-shell --run 'reuse --root . lint' | ||
| name: '[Sécurix] REUSE Licensing conformance' | ||
| on: | ||
| pull_request: | ||
| push: | ||
| branches: | ||
| - main |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,26 @@ | ||
| # SPDX-FileCopyrightText: 2026 Ryan Lahfa <ryan.lahfa.ext@numerique.gouv.fr> | ||
| # | ||
| # SPDX-License-Identifier: MIT | ||
|
|
||
| name: '[Sécurix] Test the docs' | ||
|
|
||
| on: | ||
| pull_request: | ||
|
|
||
| permissions: {} | ||
|
|
||
| concurrency: | ||
| group: preview-pages-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| build_and_preview_manual_docs: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 | ||
| with: | ||
| persist-credentials: false | ||
| - uses: samueldr/lix-gha-installer-action@f526e761e1ad201b0f4231f61a2a569f17bcc2ac # main | ||
| - name: Build the manual documentation | ||
| run: nix-build -A docs.all | ||
| name: '[Sécurix] Test the docs' | ||
| on: | ||
| pull_request: | ||
|
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is
workflow_runmissing fromon:?