ci(lint): enforce Conventional Commits and branch-name conventions#209
ci(lint): enforce Conventional Commits and branch-name conventions#209parth0025 wants to merge 1 commit into
Conversation
- Add commitlint.config.js with the 11 types from BRANCHING.md - Add .github/workflows/commitlint.yml — validates PR title + every commit in the PR; skips PRs labeled wip or do-not-merge - Add .github/workflows/branch-name.yml — validates branch follows <type>/<kebab-description>, with exemptions for release/v*, hotfix-backport/*, dependabot/*, and renovate/* - Add .github/ISSUE_TEMPLATE/config.yml — disable blank issues, link to Discussions, docs, and private Security advisories - Replace .github/pull_request_template.md default chooser with a real template (Summary, Type-of-change, Test plan, Checklist). The 3 specialized templates (bug_fix/new_feature/refactor) remain accessible via ?template= URL params. - Add @commitlint/cli and @commitlint/config-conventional to devDependencies and a lint:commits script for local use. Step 3 of the open-source repo maintenance baseline initiative. Enforces the conventions established by BRANCHING.md (#208). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/pull_request_template.md:
- Around line 27-29: Remove the `hotfix` checklist item from the PR template so
it doesn't encourage using an invalid commit type; edit the block containing the
"Type of change" checklist (the lines showing `feat`, `fix`, `hotfix`) to delete
the `hotfix` entry and instead add a short comment/instruction near the
checklist (e.g., above it) explaining that hotfix branches should still use
`fix` as the commit/PR type; ensure you update the same checklist block in
.github/pull_request_template.md (where the three checkbox items are defined)
and keep the existing wording that the first checked item should match the PR
title prefix.
In @.github/workflows/commitlint.yml:
- Line 66: Replace mutable tag references for GitHub Actions with immutable
commit SHAs: update the uses entries that currently read "actions/checkout@v4"
and "actions/setup-node@v4" to their corresponding commit SHAs (e.g.,
"actions/checkout@<sha>" and "actions/setup-node@<sha>"). Locate the two
occurrences in the workflow (the uses lines) and fetch the latest stable commit
SHAs from the actions' GitHub releases pages before substituting them so the
workflow pins to fixed commits.
- Around line 65-68: The Checkout step ("Checkout (with full history)" using
actions/checkout@v4) currently omits disabling credential persistence; update
that step's with block to include persist-credentials: false so the GITHUB_TOKEN
is not persisted to subsequent steps, e.g., add the persist-credentials: false
key alongside fetch-depth to the actions/checkout@v4 invocation.
- Around line 70-74: The workflow step "Setup Node.js" currently sets
node-version: 22 which conflicts with package.json engines (node: 20.x); update
the "Setup Node.js" step to use node-version: 20 (or 20.x) so the CI runtime
matches package.json and removes EBADENGINE warnings, keeping the rest of that
step (uses: actions/setup-node@v4, cache: npm) unchanged.
- Around line 28-29: The workflow currently references the mutable tag
amannn/action-semantic-pull-request@v5; replace that tag with a specific commit
SHA (e.g., amannn/action-semantic-pull-request@<commit-sha>) to pin the action
for supply chain security. Find the stable SHA for the desired v5 release on the
action's GitHub releases or commit history and update the uses entry in the
Validate PR title step to use that full SHA instead of `@v5`.
In `@package.json`:
- Line 59: The package.json script "lint:commits" currently hardcodes
"origin/staging", which breaks for forks or different base branches; update the
"lint:commits" script to compute the base ref dynamically (e.g., use an
environment variable like COMMITLINT_BASE or derive it via git commands such as
git merge-base or using github.event.pull_request.base.sha when in CI) so the
command uses that dynamic base instead of "origin/staging"; modify the script
entry named "lint:commits" to accept and fallback to a sensible default if the
env var is missing.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 3831cb36-9138-4050-b91d-a7e20b4094bc
📒 Files selected for processing (6)
.github/ISSUE_TEMPLATE/config.yml.github/pull_request_template.md.github/workflows/branch-name.yml.github/workflows/commitlint.ymlcommitlint.config.jspackage.json
| - [ ] 🚀 `feat` — New feature | ||
| - [ ] 🐛 `fix` — Bug fix | ||
| - [ ] 🔥 `hotfix` — Urgent production fix (targets `main`, not `staging`) |
There was a problem hiding this comment.
Remove hotfix from the type-of-change list to match commitlint rules.
Line 29 lists hotfix as a type option, and Line 25 instructs contributors that "the first one should match your PR title prefix." However, hotfix is not included in the type-enum in commitlint.config.js, which explicitly states: "for commits within a hotfix, use fix." If a contributor checks the hotfix box and formats their PR title as hotfix: ..., the CI will fail validation since hotfix is a branch-type prefix only, not a valid Conventional Commits type.
✂️ Proposed fix to remove the hotfix checkbox
- [ ] 🚀 `feat` — New feature
- [ ] 🐛 `fix` — Bug fix
-- [ ] 🔥 `hotfix` — Urgent production fix (targets `main`, not `staging`)
- [ ] ♻️ `refactor` — Code refactor (no behavior change)If you need to preserve guidance about hotfix branches, consider adding a note in the instructions section or in the "Type of change" comment instead:
<!-- Check all that apply. The first one should match your PR title prefix.
Note: For urgent hotfix branches, use `fix` as the commit/PR type. -->📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - [ ] 🚀 `feat` — New feature | |
| - [ ] 🐛 `fix` — Bug fix | |
| - [ ] 🔥 `hotfix` — Urgent production fix (targets `main`, not `staging`) | |
| - [ ] 🚀 `feat` — New feature | |
| - [ ] 🐛 `fix` — Bug fix | |
| - [ ] ♻️ `refactor` — Code refactor (no behavior change) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/pull_request_template.md around lines 27 - 29, Remove the `hotfix`
checklist item from the PR template so it doesn't encourage using an invalid
commit type; edit the block containing the "Type of change" checklist (the lines
showing `feat`, `fix`, `hotfix`) to delete the `hotfix` entry and instead add a
short comment/instruction near the checklist (e.g., above it) explaining that
hotfix branches should still use `fix` as the commit/PR type; ensure you update
the same checklist block in .github/pull_request_template.md (where the three
checkbox items are defined) and keep the existing wording that the first checked
item should match the PR title prefix.
| - name: Validate PR title | ||
| uses: amannn/action-semantic-pull-request@v5 |
There was a problem hiding this comment.
Pin GitHub Actions to commit SHA for supply chain security.
The action reference amannn/action-semantic-pull-request@v5 uses a tag, which is mutable and poses a supply chain security risk. Pin to a specific commit SHA instead.
🔒 Suggested fix to pin action
- name: Validate PR title
- uses: amannn/action-semantic-pull-request@v5
+ uses: amannn/action-semantic-pull-request@0723387faaf9b38adef4775cd42cfd5155ed6017 # v5.5.3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}Check the releases page to find the latest v5.x commit SHA.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Validate PR title | |
| uses: amannn/action-semantic-pull-request@v5 | |
| - name: Validate PR title | |
| uses: amannn/action-semantic-pull-request@0723387faaf9b38adef4775cd42cfd5155ed6017 # v5.5.3 |
🧰 Tools
🪛 zizmor (1.25.2)
[error] 29-29: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/commitlint.yml around lines 28 - 29, The workflow
currently references the mutable tag amannn/action-semantic-pull-request@v5;
replace that tag with a specific commit SHA (e.g.,
amannn/action-semantic-pull-request@<commit-sha>) to pin the action for supply
chain security. Find the stable SHA for the desired v5 release on the action's
GitHub releases or commit history and update the uses entry in the Validate PR
title step to use that full SHA instead of `@v5`.
Source: Linters/SAST tools
| - name: Checkout (with full history) | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 |
There was a problem hiding this comment.
Set persist-credentials: false to prevent credential leakage.
The checkout action should explicitly disable credential persistence to prevent the GITHUB_TOKEN from being accessible to subsequent steps or scripts, reducing the attack surface.
🛡️ Proposed fix to disable credential persistence
- name: Checkout (with full history)
uses: actions/checkout@v4
with:
fetch-depth: 0
+ persist-credentials: false📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Checkout (with full history) | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Checkout (with full history) | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false |
🧰 Tools
🪛 zizmor (1.25.2)
[warning] 65-68: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 66-66: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/commitlint.yml around lines 65 - 68, The Checkout step
("Checkout (with full history)" using actions/checkout@v4) currently omits
disabling credential persistence; update that step's with block to include
persist-credentials: false so the GITHUB_TOKEN is not persisted to subsequent
steps, e.g., add the persist-credentials: false key alongside fetch-depth to the
actions/checkout@v4 invocation.
Source: Linters/SAST tools
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout (with full history) | ||
| uses: actions/checkout@v4 |
There was a problem hiding this comment.
Pin GitHub Actions to commit SHAs for supply chain security.
The actions actions/checkout@v4 and actions/setup-node@v4 use tag references, which are mutable. Pin to specific commit SHAs to prevent supply chain attacks.
🔒 Suggested fix to pin actions
- name: Checkout (with full history)
- uses: actions/checkout@v4
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- name: Setup Node.js
- uses: actions/setup-node@v4
+ uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: 20
cache: npmCheck the respective repositories for the latest commit SHAs:
Also applies to: 71-71
🧰 Tools
🪛 zizmor (1.25.2)
[error] 66-66: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/commitlint.yml at line 66, Replace mutable tag references
for GitHub Actions with immutable commit SHAs: update the uses entries that
currently read "actions/checkout@v4" and "actions/setup-node@v4" to their
corresponding commit SHAs (e.g., "actions/checkout@<sha>" and
"actions/setup-node@<sha>"). Locate the two occurrences in the workflow (the
uses lines) and fetch the latest stable commit SHAs from the actions' GitHub
releases pages before substituting them so the workflow pins to fixed commits.
Source: Linters/SAST tools
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: 22 | ||
| cache: npm |
There was a problem hiding this comment.
Critical: Node.js version mismatch with package.json engines.
The workflow uses node-version: 22, but package.json declares "engines": { "node": "20.x" }. This violates the project's declared runtime constraints and is causing pipeline warnings.
Pipeline failures confirm the mismatch:
npm warn EBADENGINE Unsupported engine for 'alian-hub-v3@14.0.26': required node '20.x' but current is 'v22.22.3'
🐛 Proposed fix to align Node.js versions
- name: Setup Node.js
uses: actions/setup-node@v4
with:
- node-version: 22
+ node-version: 20
cache: npm📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| cache: npm |
🧰 Tools
🪛 zizmor (1.25.2)
[error] 71-71: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/commitlint.yml around lines 70 - 74, The workflow step
"Setup Node.js" currently sets node-version: 22 which conflicts with
package.json engines (node: 20.x); update the "Setup Node.js" step to use
node-version: 20 (or 20.x) so the CI runtime matches package.json and removes
EBADENGINE warnings, keeping the rest of that step (uses: actions/setup-node@v4,
cache: npm) unchanged.
Source: Pipeline failures
| "dev": "node scripts/dev.js --skip-install", | ||
| "setup:reset": "node scripts/dev.js --force" | ||
| "setup:reset": "node scripts/dev.js --force", | ||
| "lint:commits": "commitlint --from origin/staging --to HEAD --verbose" |
There was a problem hiding this comment.
Hardcoded branch reference may break local usage.
The lint:commits script hardcodes origin/staging, which will fail if:
- The remote is not named
origin(e.g., developers working with forks) - Contributors are working on PRs targeting a different base branch
The workflow (.github/workflows/commitlint.yml) correctly uses dynamic refs via github.event.pull_request.base.sha. Consider making the script more flexible.
♻️ Suggested fix using dynamic base detection
- "lint:commits": "commitlint --from origin/staging --to HEAD --verbose"
+ "lint:commits": "commitlint --from $(git merge-base HEAD origin/staging || git merge-base HEAD upstream/staging || echo 'origin/staging') --to HEAD --verbose"Or use an environment variable approach:
- "lint:commits": "commitlint --from origin/staging --to HEAD --verbose"
+ "lint:commits": "commitlint --from ${BASE_BRANCH:-origin/staging} --to HEAD --verbose"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "lint:commits": "commitlint --from origin/staging --to HEAD --verbose" | |
| "lint:commits": "commitlint --from ${BASE_BRANCH:-origin/staging} --to HEAD --verbose" |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@package.json` at line 59, The package.json script "lint:commits" currently
hardcodes "origin/staging", which breaks for forks or different base branches;
update the "lint:commits" script to compute the base ref dynamically (e.g., use
an environment variable like COMMITLINT_BASE or derive it via git commands such
as git merge-base or using github.event.pull_request.base.sha when in CI) so the
command uses that dynamic base instead of "origin/staging"; modify the script
entry named "lint:commits" to accept and fallback to a sensible default if the
env var is missing.
Summary
Adds CI enforcement and contributor-facing templates for the conventions documented in BRANCHING.md (PR #208):
<type>(<scope>): <description>)<type>/<kebab-description>Step 3 of the open-source repo maintenance baseline initiative (#207 license, #208 branching).
Files changed (6)
commitlint.config.js.github/workflows/commitlint.ymlwipordo not merge.github/workflows/branch-name.yml<type>/<kebab-description>; exemptsrelease/v*,hotfix-backport/*,dependabot/*,renovate/*.github/ISSUE_TEMPLATE/config.yml.github/pull_request_template.mdbug_fix.md,new_feature.md,refactor.md) remain accessible via?template=URL params.package.json@commitlint/cli@^19.5.0+@commitlint/config-conventional@^19.5.0to devDeps, pluslint:commitsscriptHow to test locally (after merge)
Try opening a draft PR with a malformed title (e.g.
Updated stuff) — the new check should fail with a clear error message explaining the expected format.What contributors will experience
Opening a PR:
PR title (Conventional Commits)Commit messages (commitlint)Branch name matches conventionOpening an issue:
Test plan
chore: test ci) → all 3 checks should passFixed login) → PR-title check should fail with a clear errormy-cool-fix) → branch-name check should failwiplabel → PR-title check should be skipped?template=bug_fix.mdURLDecisions documented (push back during review if any feel wrong)
feat(scope): descriptionpatternswip,do not mergedependabot/*,renovate/*Notes for reviewers
BRANCHING.md, which lands in PR #208. Until docs(branching): add branching strategy and update CONTRIBUTING #208 merges, that link will 404 for a brief window. Self-resolves on merge.main.ymlCI/deploy workflow is not touched — these new lint jobs run alongside it on PRs.bug_fix.md,new_feature.md,refactor.md) are not removed — only the default chooser is replaced.bug_report.yml,feature_request.yml,documentation.yml) are not touched — onlyconfig.ymlis added alongside them.🤖 Generated with Claude Code
Summary by CodeRabbit
Chores
Documentation