Skip to content

Enforce conventional commits#305

Open
piotrzajac wants to merge 1 commit intomasterfrom
feature/enforce-conventional-commits
Open

Enforce conventional commits#305
piotrzajac wants to merge 1 commit intomasterfrom
feature/enforce-conventional-commits

Conversation

@piotrzajac
Copy link
Copy Markdown
Collaborator

@piotrzajac piotrzajac commented Apr 9, 2026

Summary

Enforce conventional commits

Checklist

  • Commit messages follow Conventional Commits (type(scope): description)
  • dotnet build src/Objectivity.AutoFixture.XUnit2.AutoMock.sln passes with no warnings
  • dotnet test src/Objectivity.AutoFixture.XUnit2.AutoMock.sln passes on all framework slices
  • Code coverage remains at least at the level prior the change (verified by Codecov)
  • Mutation score remains at least at the level prior the change (verified by Stryker)
  • New tests follow the GIVEN/WHEN/THEN naming convention and AAA structure (see AGENTS.md)
  • No new [SuppressMessage] without a justification comment
  • No // TODO: comments added — open a GitHub issue instead
  • No new dependencies introduced that are incompatible with the MIT license (verified by FOSSA)

Summary by CodeRabbit

Release Notes

  • New Features

    • Commit messages are now validated to enforce Conventional Commits format, both locally during development and in CI/CD pipelines
    • Invalid commit messages are blocked at commit time
  • Documentation

    • Updated setup and contribution guidelines with local development tool installation requirements and commit message standards

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 9, 2026

📝 Walkthrough

Walkthrough

This pull request implements Conventional Commits enforcement across the repository by integrating Husky.NET with CommitLint.Net for local and CI validation. Changes include adding a GitHub Actions workflow, Git hooks, tool configuration, and commit message validation rules, along with documentation updates.

Changes

Cohort / File(s) Summary
Tool & Configuration Setup
dotnet-tools.json, commit-message-config.json
Added repository-local .NET tool declarations for Husky, CommitLint.Net, and Stryker, and configured commit message validation rules (Conventional Commits format, max 90-char subject, allowed types: feat, fix, refactor, build, chore, style, test, docs, perf, revert, ci).
Husky Hook Configuration
.husky/commit-msg, .husky/task-runner.json
Added commit-msg Git hook entry point that invokes Husky.NET task runner, and configured the commit-message-linter task to run dotnet commit-lint with validation config.
CI Validation
.github/workflows/commit-message.yml
Added GitHub Actions workflow triggered on pull requests, pushes to master, and manual dispatch to lint commit messages using dotnet commit-lint, handling both PR and direct push scenarios.
Documentation & Tooling Updates
CONTRIBUTING.md, AGENTS.md, .backlog/tasks/task-3 - Enforce-Conventional-Commits.md
Updated setup instructions to run dotnet tool restore and husky install, changed mutation testing to use local dotnet-stryker tool, and marked Conventional Commits enforcement task as complete with implementation details.

Sequence Diagram

sequenceDiagram
    participant Dev as Developer
    participant Git as Git Client
    participant Husky as Husky.NET Hook
    participant Lint as CommitLint.Net
    participant Config as commit-message-config.json
    participant GH as GitHub Actions
    
    Dev->>Git: git commit -m "feat: new feature"
    Git->>Husky: Trigger commit-msg hook
    Husky->>Lint: Run commit-lint with commit file
    Lint->>Config: Load validation rules
    Config-->>Lint: Return config (Conventional Commits, max 90 chars, etc.)
    alt Valid Message
        Lint-->>Husky: Exit 0 (success)
        Husky-->>Git: Proceed with commit
        Git-->>Dev: Commit created
    else Invalid Message
        Lint-->>Husky: Exit non-zero (failure)
        Husky-->>Git: Block commit
        Git-->>Dev: Commit rejected
    end
    
    Dev->>GH: Push to master / Create PR
    GH->>Lint: Run commit-message.yml workflow
    Lint->>Config: Validate all commits
    Config-->>Lint: Apply rules
    Lint-->>GH: Report validation results
    GH-->>Dev: Workflow status
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 A rabbit hops with glee, commits now follow the decree!
Conventional messages, no more freestyle spree,
Husky guards the gate, CommitLint keeps it clean,
GitHub Actions watch the flow, best-structured commits you've seen! 📝✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning PR description is incomplete: missing issue reference, PR labels not mentioned, and most checklist items are unchecked despite claim of completion. Add 'Closes #' reference, specify PR labels, and verify all checklist items match actual implementation status before merging.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Enforce conventional commits' directly and clearly summarizes the main objective of the pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/enforce-conventional-commits

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Apr 9, 2026

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (b6495c7) to head (36a74ce).
⚠️ Report is 5 commits behind head on master.
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff            @@
##            master      #305   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           39        39           
  Lines          424       424           
  Branches        55        55           
=========================================
  Hits           424       424           
Flag Coverage Δ
unittests 99.76% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
.github/workflows/commit-message.yml (1)

43-45: Lint all pushed commits on push, not only HEAD.

Line 44 checks only the latest commit, so earlier commits in a multi-commit push can bypass this workflow.

♻️ Suggested update
-          } else {
-            $commits = git log -1 --pretty="%H"
+          } elseif ("${{ github.event.before }}" -and "${{ github.event.before }}" -ne "0000000000000000000000000000000000000000") {
+            $commits = git log --no-merges --pretty="%H" "${{ github.event.before }}..${{ github.sha }}"
+          } else {
+            $commits = git log -1 --pretty="%H" "${{ github.sha }}"
           }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/commit-message.yml around lines 43 - 45, The workflow only
captures HEAD by setting $commits via git log -1 --pretty="%H"; update the
$commits assignment to list all commits in the push (e.g., replace the git log
-1 command with a rev-list over the pushed range) so every pushed commit is
linted — for example set $commits using git rev-list --no-merges
--pretty=format:%H ${GITHUB_EVENT_BEFORE}..${GITHUB_SHA} (replace the existing
git log -1 --pretty="%H" invocation).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/commit-message.yml:
- Line 1: Normalize line endings in the workflow whose name is "📝 Commit
Message Lint" to LF (\n) so YAMLlint stops reporting CRLF; convert the file's
line endings from CRLF to LF (e.g., via your editor, git config
core.autocrlf=false and re-save, or run dos2unix) and commit the change, and
optionally add/update a .gitattributes entry to enforce LF for YAML files to
prevent future regressions.
- Around line 1-49: This change adds a new GitHub Actions workflow
(commit-message.yml / "📝 Commit Message Lint") which requires explicit
maintainer approval before merging; update the PR to request that explicit
approval from a repository maintainer (add a clear note in the PR description
that this modifies a workflow, request the specific approver(s) or team, and/or
add the repository's "workflow change" label), and do not merge the branch until
a maintainer has reviewed and explicitly approved the workflow change.

In `@commit-message-config.json`:
- Around line 22-26: The current config disables scope enforcement via
scopes.enabled and CommitLint.Net v0.8.0 cannot require scope presence; to fix,
add a custom commit-msg validation that enforces the "<type>(scope):
<description>" pattern (e.g., a small script run by the commit-msg hook that
checks for a scope between parentheses), or replace CommitLint.Net with a linter
that supports required scopes, or patch CommitLint.Net to validate presence of
scope; update the repo hooks to run that script and remove/ignore scopes.enabled
so the new validator enforces scope presence.

---

Nitpick comments:
In @.github/workflows/commit-message.yml:
- Around line 43-45: The workflow only captures HEAD by setting $commits via git
log -1 --pretty="%H"; update the $commits assignment to list all commits in the
push (e.g., replace the git log -1 command with a rev-list over the pushed
range) so every pushed commit is linted — for example set $commits using git
rev-list --no-merges --pretty=format:%H ${GITHUB_EVENT_BEFORE}..${GITHUB_SHA}
(replace the existing git log -1 --pretty="%H" invocation).
🪄 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

Run ID: 902c7d8a-2ae1-4976-aad3-65a101bf1b5e

📥 Commits

Reviewing files that changed from the base of the PR and between 08bc171 and 36a74ce.

📒 Files selected for processing (8)
  • .backlog/tasks/task-3 - Enforce-Conventional-Commits.md
  • .github/workflows/commit-message.yml
  • .husky/commit-msg
  • .husky/task-runner.json
  • AGENTS.md
  • CONTRIBUTING.md
  • commit-message-config.json
  • dotnet-tools.json

@@ -0,0 +1,49 @@
name: '📝 Commit Message Lint'
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 | 🟡 Minor

Normalize to LF line endings to satisfy YAMLlint.

Static analysis reports wrong newline characters; convert this file to \n line endings to prevent lint failures.

🧰 Tools
🪛 YAMLlint (1.38.0)

[error] 1-1: wrong new line character: expected \n

(new-lines)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/commit-message.yml at line 1, Normalize line endings in
the workflow whose name is "📝 Commit Message Lint" to LF (\n) so YAMLlint stops
reporting CRLF; convert the file's line endings from CRLF to LF (e.g., via your
editor, git config core.autocrlf=false and re-save, or run dos2unix) and commit
the change, and optionally add/update a .gitattributes entry to enforce LF for
YAML files to prevent future regressions.

Comment on lines +1 to +49
name: '📝 Commit Message Lint'

on:
pull_request:
types: [opened, synchronize, reopened]
push:
branches:
- 'master'
workflow_dispatch:

defaults:
run:
shell: pwsh

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
lint:
runs-on: windows-latest
permissions:
contents: read
steps:
- name: 📥 checkout
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: 🛠️ setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: 8.0.x

- name: 📦 restore local tools
run: dotnet tool restore

- name: ✅ lint commit messages
run: |
$messagePath = Join-Path $env:RUNNER_TEMP "commit-message.txt"
if ("${{ github.event_name }}" -eq "pull_request") {
$commits = git log --no-merges --pretty="%H" "${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}"
} else {
$commits = git log -1 --pretty="%H"
}
foreach ($sha in ($commits -split "`n" | Where-Object { $_ -ne "" })) {
git log -1 --pretty="%B" $sha | Out-File -FilePath $messagePath -Encoding utf8
dotnet commit-lint --commit-file $messagePath --commit-message-config-file commit-message-config.json
}
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

Workflow-file changes need explicit maintainer approval.

This PR adds a new workflow under .github/workflows/, which is gated by repository policy and should be explicitly approved before merge.

As per coding guidelines: Changes to .github/workflows/ files require explicit approval.

🧰 Tools
🪛 YAMLlint (1.38.0)

[error] 1-1: wrong new line character: expected \n

(new-lines)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/commit-message.yml around lines 1 - 49, This change adds a
new GitHub Actions workflow (commit-message.yml / "📝 Commit Message Lint")
which requires explicit maintainer approval before merging; update the PR to
request that explicit approval from a repository maintainer (add a clear note in
the PR description that this modifies a workflow, request the specific
approver(s) or team, and/or add the repository's "workflow change" label), and
do not merge the branch until a maintainer has reviewed and explicitly approved
the workflow change.

Comment on lines +22 to +26
"scopes": {
"enabled": false,
"global": [],
"per-type": {}
}
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

🧩 Analysis chain

🌐 Web query:

In CommitLint.Net v0.8.0, what configuration enforces a required scope in Conventional Commits? I need to reject messages like "docs: update readme" and accept "docs(contributing): update readme".

💡 Result:

CommitLint.Net v0.8.0 does not have a configuration option to require that a scope be present.

Even with conventional-commit.scopes.enabled: true, the scope rules explicitly pass when no (scope) is found (“No scope found.”), so docs: update readme will not be rejected. (github.com)

So, in v0.8.0 you can only validate scope format (when present) and restrict allowed scope values (when present), but you can’t enforce “scope required” via config; you’d need a custom hook/regex check or a fork/patch. (nuget.org)

Citations:


Scopes cannot be enforced with the current CommitLint.Net v0.8.0 configuration.

Line 23 disables scopes (scopes.enabled: false), allowing messages like docs: ... to pass. However, verification reveals CommitLint.Net v0.8.0 has no built-in configuration option to require scopes; even if enabled, the tool only validates scope format when present but does not enforce scope presence itself. To align with the repo convention (<type>(scope): <description>), you'll need a custom validation hook, a different linting tool, or a patch to CommitLint.Net.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@commit-message-config.json` around lines 22 - 26, The current config disables
scope enforcement via scopes.enabled and CommitLint.Net v0.8.0 cannot require
scope presence; to fix, add a custom commit-msg validation that enforces the
"<type>(scope): <description>" pattern (e.g., a small script run by the
commit-msg hook that checks for a scope between parentheses), or replace
CommitLint.Net with a linter that supports required scopes, or patch
CommitLint.Net to validate presence of scope; update the repo hooks to run that
script and remove/ignore scopes.enabled so the new validator enforces scope
presence.

@piotrzajac piotrzajac self-assigned this Apr 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants