feat(ci): fail PRs containing unsigned commits via shared CI gate#302
feat(ci): fail PRs containing unsigned commits via shared CI gate#302JacobPEvans wants to merge 2 commits into
Conversation
Adds a new reusable workflow `_signed-commits-check.yml` that walks every commit in the active pull request via `pulls.listCommits` and fails the job if any commit returns `verification.verified === false`. Failures emit a clear multi-line `core.setFailed` message plus a markdown table in the GitHub-UI job summary listing each offending SHA, author, and verification reason. Wired into `_ci-gate.yml` as an always-on `signed-commits` job (gated on `github.event_name == 'pull_request'`, listed as an allowed-skip in `re-actors/alls-green` so non-PR runs aren't blocked). This is PR #5 of the 8-PR "eliminate unsigned automated commits" initiative — the PR-level regression backstop sitting behind the `required_signatures` branch-protection rulesets (PR #4). Even if a ruleset is bypassed (admin override, future ruleset edit), the PR can't get a green Merge Gate without signed commits. Four-tier search log (no-scripts rule): - Tier 1 (Native CLIs): `gh api repos/.../pulls/<n>/commits` works but walking the response + paginating + parsing in bash is fragile and exceeds the 10-line inline gate. - Tier 2 (Ecosystem primitives): no marketplace action exists for "fail PR on any unsigned commit"; closest match (`actions/github-script`) IS first-party GitHub and is what this workflow uses. - Tier 3 (Third-party packaged tools): none found. - Tier 4 (Popular community solutions): none found. Script extracted to `.github/scripts/signed-commits-check.js` per the no-scripts rule — exceeds the 10-line inline limit and lives in the allowed `.github/scripts/` directory. Assisted-by: Claude <noreply@anthropic.com>
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request implements a new security gate to enforce commit signing across the repository. By leveraging a reusable workflow and a custom script, it ensures that all commits within a pull request are cryptographically verified by GitHub. This change serves as a critical backstop for the ongoing initiative to eliminate unsigned automated commits, providing immediate feedback in the CI pipeline when non-compliant commits are detected. Highlights
Ignored Files
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. The commits must be signed and true, To pass the gate we built for you. If unsigned code should dare appear, The build will fail and make it clear. Footnotes
|
There was a problem hiding this comment.
Pull request overview
Adds an organization-wide CI backstop that fails pull requests containing any GitHub-unverified commits, ensuring downstream repos that use the shared merge gate can’t go green with unsigned commits.
Changes:
- Introduced a reusable workflow (
_signed-commits-check.yml) that runs a signed-commit verification gate for PRs. - Added a Node script (
.github/scripts/signed-commits-check.js) executed viaactions/github-scriptto paginate PR commits, detectverified:false, and emit clear failure output + job summary. - Wired the new check into
_ci-gate.yml(and intoMerge Gateaggregation) so all consumers inherit it automatically.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| .github/workflows/_signed-commits-check.yml | New reusable workflow that checks PR commits’ verification status via actions/github-script. |
| .github/workflows/_ci-gate.yml | Adds a new always-on signed-commits job (PR-only) and includes it in the merge gate aggregation/allowed skips. |
| .github/scripts/signed-commits-check.js | Implements PR commit pagination + verification filtering and formats failure output in both logs and job summary. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…se-checkout path The reusable workflow sparse-checks this script out of JacobPEvans/.github@main into ./.gh-shared/.github/scripts/, so the require() path the YAML actually uses includes that prefix. The header comment showed the in-tree path only, which would mislead a future maintainer trying to copy the example. Document both paths and which context each fits. Addresses Copilot review thread on PR #302. Assisted-by: Claude <noreply@anthropic.com>
|
This is not the right way to handle this. This can be done 100% natively by GitHub itself. |
Summary
_signed-commits-check.ymlfails any PR where a commit isverified:false_ci-gate.ymlso every downstream consumer gets it automaticallyFour-tier search log (no-scripts rule)
gh api repos/.../pulls/<n>/commitsworks, but pagination + JSON parsing + per-commit filter in bash exceeds the 10-line inline gate and is fragile.actions/github-script@v9— IS first-party GitHub and is what this workflow uses.Script extracted to
.github/scripts/signed-commits-check.jsper the no-scripts rule (logic exceeds the 10-line inline limit; allowed.github/scripts/directory).Implementation notes
core.setFailedwith multi-line message listing each offending short-SHA, author, andverification.reason.core.summaryalso writes a markdown table to the job summary so failures are browsable in the GitHub UI.core.infoconfirms N commits verified, summary writes a one-line confirmation.context.payload.pull_requestis absent.signed-commitsjob in_ci-gate.ymlis gated ongithub.event_name == 'pull_request'and listed as an allowed-skip inre-actors/alls-green.Verification (after merge)
git commit --no-gpg-sign -m test) on a consumer repo_ci-gate.ymlfails with a clear message listing the offending SHAPart of the 8-PR "eliminate unsigned automated commits" initiative.
Plan:
~/.claude/plans/you-are-opus-on-breezy-valiant.mdAssisted-by: Claude noreply@anthropic.com