Skip to content

ci(lint): enforce Conventional Commits and branch-name conventions#209

Open
parth0025 wants to merge 1 commit into
stagingfrom
ci/conventional-commits-lint
Open

ci(lint): enforce Conventional Commits and branch-name conventions#209
parth0025 wants to merge 1 commit into
stagingfrom
ci/conventional-commits-lint

Conversation

@parth0025

@parth0025 parth0025 commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds CI enforcement and contributor-facing templates for the conventions documented in BRANCHING.md (PR #208):

  • PR titles must follow Conventional Commits (<type>(<scope>): <description>)
  • Commit messages must follow Conventional Commits
  • Branch names must follow <type>/<kebab-description>
  • PR template auto-populates with a useful default (replaces the old "chooser")
  • Issue chooser disables blank issues and routes contributors to Discussions / docs / private Security advisories

Step 3 of the open-source repo maintenance baseline initiative (#207 license, #208 branching).

Files changed (6)

File Status Purpose
commitlint.config.js New 11 commit types, lowercase subject, 100-char header limit
.github/workflows/commitlint.yml New Lints PR title + every commit in the PR; skips PRs labeled wip or do not merge
.github/workflows/branch-name.yml New Validates branch matches <type>/<kebab-description>; exempts release/v*, hotfix-backport/*, dependabot/*, renovate/*
.github/ISSUE_TEMPLATE/config.yml New Disables blank issues; links to Discussions, docs, and private Security advisories
.github/pull_request_template.md Replaced Default template now has Summary, Type-of-change, Related-issue, Test plan, Screenshots, Breaking-changes, Checklist sections. Specialized templates (bug_fix.md, new_feature.md, refactor.md) remain accessible via ?template= URL params.
package.json Modified Adds @commitlint/cli@^19.5.0 + @commitlint/config-conventional@^19.5.0 to devDeps, plus lint:commits script

How to test locally (after merge)

git pull
npm install               # picks up new devDeps
npm run lint:commits      # validate your own commits against the rules

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:

  • Default PR template is now actually useful (the old chooser is gone)
  • 3 new CI checks run on every PR:
    • PR title (Conventional Commits)
    • Commit messages (commitlint)
    • Branch name matches convention

Opening an issue:

  • "Open blank issue" is no longer offered — contributors must pick a template (bug / feature / docs)
  • Above templates, contact links direct usage questions to docs and Discussions, and security reports to private advisories

Test plan

  • After merge, open a test PR with a valid title (e.g., chore: test ci) → all 3 checks should pass
  • Open a test PR with an invalid title (e.g., Fixed login) → PR-title check should fail with a clear error
  • Open a test PR from a branch with invalid name (e.g., my-cool-fix) → branch-name check should fail
  • Apply wip label → PR-title check should be skipped
  • Verify the new default PR template renders when opening a PR via the normal "Compare & pull request" button
  • Verify specialized templates still work via ?template=bug_fix.md URL
  • Verify Issues page no longer offers "Open blank issue" and shows the 4 contact links

Decisions documented (push back during review if any feel wrong)

Decision Choice Why
Subject case Must start lowercase Conventional Commits norm
Header max length 100 chars Generous for feat(scope): description patterns
WIP exemption labels wip, do not merge Lets in-progress PRs not show red
Pre-commit hook (husky) NOT added Keeps scope tight; CI catches it
Bot-branch exemption dependabot/*, renovate/* Standard for bot-generated branches

Notes for reviewers

  • The PR template references 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.
  • Existing main.yml CI/deploy workflow is not touched — these new lint jobs run alongside it on PRs.
  • Existing specialized PR templates (bug_fix.md, new_feature.md, refactor.md) are not removed — only the default chooser is replaced.
  • Existing issue YAML forms (bug_report.yml, feature_request.yml, documentation.yml) are not touched — only config.yml is added alongside them.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores

    • Added branch naming validation and commit message linting checks to enforce development standards.
  • Documentation

    • Streamlined issue templates with curated contact links for faster issue resolution.
    • Enhanced pull request template with improved structure and contributor guidance.

- 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>
@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1e0e1557-998c-441b-8cdf-055cb7dca643

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/conventional-commits-lint

Comment @coderabbitai help to get the list of available commands and usage tips.

@parth0025 parth0025 self-assigned this Jun 8, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4dbe795 and 61739dc.

📒 Files selected for processing (6)
  • .github/ISSUE_TEMPLATE/config.yml
  • .github/pull_request_template.md
  • .github/workflows/branch-name.yml
  • .github/workflows/commitlint.yml
  • commitlint.config.js
  • package.json

Comment on lines +27 to +29
- [ ] 🚀 `feat` — New feature
- [ ] 🐛 `fix` — Bug fix
- [ ] 🔥 `hotfix` — Urgent production fix (targets `main`, not `staging`)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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.

Suggested change
- [ ] 🚀 `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.

Comment on lines +28 to +29
- name: Validate PR title
uses: amannn/action-semantic-pull-request@v5

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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.

Suggested change
- 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

Comment on lines +65 to +68
- name: Checkout (with full history)
uses: actions/checkout@v4
with:
fetch-depth: 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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.

Suggested change
- 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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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: npm

Check 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

Comment on lines +70 to +74
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: npm

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

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.

Suggested change
- 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

Comment thread package.json
"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"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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.

Suggested change
"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.

@parth0025 parth0025 requested a review from joshishiv4 June 8, 2026 11:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant