ci: centralize CI workflows and pre-commit hooks#45
Conversation
Replace inline PR title, branch name, commit message, verified commit, and Go build/test/lint/vuln jobs with calls to reusable workflows from sensiblebit/.github. Project-specific jobs (WASM, Web, Lint) remain. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move go-vet, go-build, go-test, goimports, branch-name, commit-message, and wasm hooks to the org-wide .github repo. Remove local scripts/checks.py — single source of truth is now the central repo. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Calls org-wide reusable workflow to run `pre-commit autoupdate` weekly and open a PR when hook versions are outdated. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR centralizes CI and pre-commit enforcement by switching this repo to org-wide reusable workflows and shared pre-commit hooks in sensiblebit/.github, removing the duplicated local implementation.
Changes:
- Replace local pre-commit hook implementations with hooks sourced from
sensiblebit/.githuband removescripts/checks.py. - Refactor GitHub Actions CI to use org-wide reusable workflows for PR conventions and Go CI, while keeping project-specific jobs (e.g., WASM).
- Add a scheduled/manual workflow to run
pre-commit autoupdate, and pin Prettier back to a stable v3 release in pre-commit.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
scripts/checks.py |
Removes the local shared-checks implementation now replaced by centralized tooling. |
.pre-commit-config.yaml |
Switches several hooks to sensiblebit/.github and downgrades the Prettier mirror to v3.1.0. |
.github/workflows/pre-commit-autoupdate.yml |
Adds a scheduled/manual workflow that delegates to the org-wide autoupdate workflow. |
.github/workflows/ci.yml |
Replaces local CI jobs with org-wide reusable workflows and keeps/updates project-specific job wiring. |
|
|
||
| - repo: local | ||
| - repo: https://github.com/sensiblebit/.github | ||
| rev: "27cc26b" |
There was a problem hiding this comment.
The hook repo revision is pinned to a short SHA ("27cc26b"). For reproducibility and supply-chain safety, pin to an immutable ref (prefer a full commit SHA or a version tag) so pre-commit resolves the exact intended revision even if the short SHA becomes ambiguous.
| rev: "27cc26b" | |
| rev: "27cc26b4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b" |
|
|
||
| jobs: | ||
| autoupdate: | ||
| uses: sensiblebit/.github/.github/workflows/pre-commit-autoupdate.yml@main |
There was a problem hiding this comment.
This workflow calls a reusable workflow pinned to the moving @main ref. Consider pinning to a tag or full commit SHA to avoid unexpected CI changes/breakages when the central workflow is updated.
| uses: sensiblebit/.github/.github/workflows/pre-commit-autoupdate.yml@main | |
| uses: sensiblebit/.github/.github/workflows/pre-commit-autoupdate.yml@v1 |
| pr-conventions: | ||
| name: PR Conventions | ||
| if: github.event_name == 'pull_request' | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| with: | ||
| fetch-depth: 0 | ||
| - name: Check branch name | ||
| id: branch | ||
| run: python3 scripts/checks.py branch-name "${{ github.head_ref }}" | ||
| - name: Check commit messages | ||
| if: success() || failure() | ||
| id: commits | ||
| run: python3 scripts/checks.py commit-message --ci --base-ref "origin/${{ github.base_ref }}" | ||
| - name: Check commits are verified | ||
| if: success() || failure() | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: python3 scripts/checks.py verified-commits "${{ github.repository }}" "${{ github.event.pull_request.number }}" | ||
|
|
||
| # ── Go ────────────────────────────────────────────── | ||
|
|
||
| go-checks: | ||
| name: Go Checks | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| - uses: actions/setup-go@v6 | ||
| with: | ||
| go-version: stable | ||
| check-latest: true | ||
| cache: true | ||
| - name: Build | ||
| id: build | ||
| run: go build -trimpath ./... | ||
| - name: Vet | ||
| if: success() || failure() | ||
| id: vet | ||
| run: go vet ./... | ||
| - name: Check goimports | ||
| if: success() || failure() | ||
| run: python3 scripts/checks.py goimports | ||
|
|
||
| go-test: | ||
| name: Go Test | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| - uses: actions/setup-go@v6 | ||
| with: | ||
| go-version: stable | ||
| check-latest: true | ||
| cache: true | ||
| - run: go test -race -count=1 ./... | ||
|
|
||
| golangci-lint: | ||
| name: Lint (golangci-lint) | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| - uses: actions/setup-go@v6 | ||
| with: | ||
| go-version: stable | ||
| check-latest: true | ||
| cache: true | ||
| - uses: golangci/golangci-lint-action@v9 | ||
| with: | ||
| version: latest | ||
| uses: sensiblebit/.github/.github/workflows/pr-conventions.yml@main | ||
|
|
||
| govulncheck: | ||
| name: Vulnerability Check | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| - uses: actions/setup-go@v6 | ||
| with: | ||
| go-version: stable | ||
| check-latest: true | ||
| cache: true | ||
| - name: Install govulncheck | ||
| run: go install golang.org/x/vuln/cmd/govulncheck@latest | ||
| - name: Run govulncheck | ||
| run: govulncheck ./... | ||
| go-ci: | ||
| uses: sensiblebit/.github/.github/workflows/go-ci.yml@main |
There was a problem hiding this comment.
Both reusable workflows are referenced via the moving @main ref. To make CI deterministic and reduce the risk of unexpected breakages, pin these to a tag or full commit SHA (and bump intentionally when you want updates).
.github/workflows/ci.yml
Outdated
| if: success() || failure() | ||
| run: npx markdownlint-cli@0.47.0 --config .markdownlint.yaml '**/*.md' |
There was a problem hiding this comment.
The PR description says Prettier is downgraded to v3.1.0, but CI still runs npx prettier@latest --check ..., which can reintroduce v4+ behavior and create CI vs pre-commit drift. Pin the CI Prettier version to match .pre-commit-config.yaml (or update the PR description if using latest is intentional).
Replace inline prettier + markdownlint steps with call to sensiblebit/.github lint workflow. Only wasm_exec.js exclusion is project-specific. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This comment has been minimized.
This comment has been minimized.
Replace inline @claude mention handler with thin caller to sensiblebit/.github reusable workflow. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This comment has been minimized.
This comment has been minimized.
Issue templates now come from sensiblebit/.github fallback. PR template kept as project-specific override (changelog checklist). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| actions: read | ||
|
|
||
| jobs: | ||
| claude: |
There was a problem hiding this comment.
The job-level if: guard was removed when switching to the reusable workflow, so this workflow will invoke the Claude workflow on every matching event (issue comment, review comment, issue opened/assigned, review submitted). That increases CI noise/cost and can expose the Claude secret to untrusted triggers unless the reusable workflow re-implements the same authorization and @claude-mention gating. Re-add an if: condition here (as before) or pass explicit inputs to ensure only trusted users and explicit @claude mentions can trigger runs.
| claude: | |
| claude: | |
| if: > | |
| (github.event_name == 'issue_comment' && | |
| contains(github.event.comment.body, '@claude') && | |
| (github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'OWNER' || github.event.comment.author_association == 'COLLABORATOR')) || | |
| (github.event_name == 'pull_request_review_comment' && | |
| contains(github.event.comment.body, '@claude') && | |
| (github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'OWNER' || github.event.comment.author_association == 'COLLABORATOR')) || | |
| (github.event_name == 'pull_request_review' && | |
| contains(github.event.review.body, '@claude') && | |
| (github.event.review.author_association == 'MEMBER' || github.event.review.author_association == 'OWNER' || github.event.review.author_association == 'COLLABORATOR')) || | |
| (github.event_name == 'issues' && | |
| contains(github.event.issue.body, '@claude') && | |
| (github.event.issue.author_association == 'MEMBER' || github.event.issue.author_association == 'OWNER' || github.event.issue.author_association == 'COLLABORATOR')) |
| if: success() || failure() | ||
| run: python3 scripts/checks.py goimports | ||
| go-ci: | ||
| uses: sensiblebit/.github/.github/workflows/go-ci.yml@main |
There was a problem hiding this comment.
go-ci is now delegated to a reusable workflow, but this repo’s documented CI requirements include running go test -race in CI (CLAUDE.md T-3) plus the previous lint/vuln checks that were removed from this file. Please ensure the reusable go-ci.yml still runs go test -race and the required checks, or add/enable the missing steps/inputs here so CI enforcement remains unchanged.
| uses: sensiblebit/.github/.github/workflows/go-ci.yml@main | |
| uses: sensiblebit/.github/.github/workflows/go-ci.yml@main | |
| with: | |
| run-race: true | |
| run-lint: true | |
| run-vuln: true |
|
|
||
| - repo: local | ||
| - repo: https://github.com/sensiblebit/.github | ||
| rev: "27cc26b" |
There was a problem hiding this comment.
The pre-commit rev is pinned to a short SHA (27cc26b). For reproducibility and to avoid ambiguity, pin to a full commit SHA (40 chars) or a signed/tagged release in sensiblebit/.github.
| rev: "27cc26b" | |
| rev: v1.0.0 |
| always_run: true | ||
| pass_filenames: false | ||
|
|
||
| - id: commit-message |
There was a problem hiding this comment.
The commit-message hook previously ran only at the commit-msg stage. With the stage override removed here, it will run at the default stage unless the hook itself declares stages: [commit-msg] in the central repo. To avoid silently losing commit-msg enforcement, explicitly set stages: [commit-msg] for this hook in this config (or confirm it’s enforced by the hook definition).
| - id: commit-message | |
| - id: commit-message | |
| stages: [commit-msg] |
Avoid spinning up a runner for every issue comment/review when only @claude mentions need processing. Auth check stays in the reusable workflow. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Code reviewIssue found: Missing CHANGELOG.md entry This PR modifies CI configuration files, adds a new workflow ( Rule violated: CL-1 (MUST)
This PR is notable because:
Recommendation: Add an entry to the ### Changed
- Migrate CI workflows and pre-commit hooks to organization-wide reusable workflows ([#45])Checked for bugs and CLAUDE.md compliance. |
Code review1 security issue found: Security: Authorization check removed from Claude workflowLocation: Issue: The authorization check that restricted Claude Code workflow execution to repository owner, org members, and collaborators has been removed from the caller workflow. Original code (before this PR): if: |
(
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
) && (
github.event.sender.login == github.repository_owner ||
github.event.comment.author_association == 'OWNER' ||
github.event.comment.author_association == 'MEMBER' ||
github.event.comment.author_association == 'COLLABORATOR'
)New code (after this PR): if: |
(
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
)Security implications: This represents a defense-in-depth regression:
Recommendation: Either:
Security best practice for GitHub Actions is to gate secret-consuming workflows as early as possible. The caller-side authorization gate should be retained. |
Defense-in-depth: gate secret transmission behind OWNER/MEMBER/ COLLABORATOR check at the caller level, not just the reusable workflow. Also adds missing CHANGELOG entry for #45. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Defense-in-depth: gate secret transmission behind OWNER/MEMBER/ COLLABORATOR check at the caller level, not just the reusable workflow. Also adds missing CHANGELOG entry for #45. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Defense-in-depth: gate secret transmission behind OWNER/MEMBER/ COLLABORATOR check at the caller level, not just the reusable workflow. Check author_association on the correct event object for each trigger type (comment, review, issue) — previously only comment-based events were checked, silently blocking members on review and issue events. Also adds missing CHANGELOG entries for #45 and #46. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Defense-in-depth: gate secret transmission behind OWNER/MEMBER/ COLLABORATOR check at the caller level, not just the reusable workflow. Check author_association on the correct event object for each trigger type (comment, review, issue) — previously only comment-based events were checked, silently blocking members on review and issue events. Also adds missing CHANGELOG entries for #45 and #46. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Summary
sensiblebit/.githubsensiblebit/.githubscripts/checks.py— single source of truth is now the central repopre-commit autoupdateworkflow to keep hook versions currentTest plan
.githubrepocmd/wasmpath argument needed)🤖 Generated with Claude Code