From 532e370c3521a9820bd11925f2c9efd8d08e3e57 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Mon, 3 Aug 2026 22:24:11 +0000 Subject: [PATCH 1/2] docs: add social cards and cut the two pages that repeated themselves MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sharing a documentation link produced a bare URL with no preview image. The social plugin now renders one card per page — the page title on the brand blue, at the 1200x630 the platforms expect — and the pages carry the og:image tag that points at it. Deploy previews skip the cards. Nobody shares a preview link for its preview image, and skipping them keeps those builds fast and clear of the system cairo dependency that rendering needs. Rewrite the two pages left over from the Sphinx site, both of which had been overtaken by the pages written around them. "Usage examples" opened with sections on running the checks as a GitHub Action and as a pre-commit hook — both of which now have guides of their own that go further. Removed, and what remains is what the page is for and what its navigation entry already called it: recipes for invoking the CLI. The scripting section now covers the output formats a script actually reaches for, and the jq example was checked against real output rather than written from memory. "What's New" re-explained every feature a second time, next to a changelog that already recorded them and guides that now document them properly. It is now an index: what changed, why it mattered, and a link to the page that covers it. 365 lines to 76. --- .github/workflows/main.yml | 5 + .gitignore | 1 + docs/example.md | 429 +++++++++++-------------------------- docs/what-is-new.md | 377 ++++---------------------------- mkdocs.yml | 10 + netlify.toml | 4 +- pyproject.toml | 2 +- 7 files changed, 185 insertions(+), 643 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index fffc07db..d7129887 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -95,6 +95,11 @@ jobs: with: python-version: "3.10" + # The social plugin renders the cards through cairo, which cairosvg + # loads at runtime rather than bundling. + - name: Install cairo + run: sudo apt-get install -y --no-install-recommends libcairo2 + - name: Install nox run: | python -m pip install --only-binary :all: --upgrade pip diff --git a/.gitignore b/.gitignore index 546ac132..531004f6 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ docs/__pycache__ # MkDocs site/ docs/cli.md +.cache/ diff --git a/docs/example.md b/docs/example.md index df5fcaf3..1e487b58 100644 --- a/docs/example.md +++ b/docs/example.md @@ -1,376 +1,191 @@ -# Usage Examples +# Command-line recipes -This guide demonstrates how to use commit-check to validate commit messages, branch names, and author information. +Ways to invoke the checks directly. For wiring them into a workflow, see the +[pre-commit](guides/pre-commit.md) and [GitHub Actions](guides/github-actions.md) +guides instead — those cover the setup this page assumes you already have. -There are several ways to use commit-check: as a pre-commit hook, via STDIN, or directly with files. +Every option is listed in the [CLI reference](cli.md). -## Running as GitHub Action +## Checking a commit message -Please see [commit-check/commit-check-action](https://github.com/commit-check/commit-check-action) +The message can come from the repository, a file, or standard input. -## Running as pre-commit hook +=== "From the repository" -1. **Install pre-commit:** + Validates `HEAD`'s message. This is what the `commit-msg` hook runs. -!!! tip + ```console + $ commit-check -m + ``` - Make sure `pre-commit` is [installed](https://pre-commit.com/#install). +=== "From a file" -```bash -pip install pre-commit -``` + ```console + $ commit-check -m commit_message.txt + ``` -2. **Create .pre-commit-config.yaml:** +=== "From stdin" -```yaml -- repo: https://github.com/commit-check/commit-check - rev: the tag or revision - hooks: - - id: check-message - stages: [commit-msg] - - id: check-branch - - id: check-author-name - - id: check-author-email -``` + Useful in scripts and for trying a message before committing it. -3. **Install the hooks:** - -```bash -pre-commit install --hook-type pre-commit --hook-type commit-msg -``` + ```console + $ echo "feat(auth): add OAuth2 login" | commit-check -m + ``` -4. **Test the integration:** +### Trying a message before you write it -```bash -# This will trigger validation automatically -git commit -m "feat: add new user authentication system" +```console +$ echo "updated the parser" | commit-check -m +CC001 message check failed ==> updated the parser +The commit message should follow Conventional Commits. +Suggest: Use (): , where is one of: feat, fix, ... +Docs: https://docs.commit-check.com/rules/#cc001 ``` -### Pre-commit Validation Examples - -**✅ Successful Validation:** - -```text -$ git commit -m "feat: add user authentication system" - -check commit message.....................................................Passed -check committer name.....................................................Passed -check committer email....................................................Passed -[main abc1234] feat: add user authentication system -``` - -**❌ Failed Validation:** - -```text -$ git commit -m "bad commit message" - -check commit message.....................................................Failed -- hook id: check-message -- exit code: 1 - -Commit rejected by Commit-Check. - - (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) - / ._. \ / ._. \ / ._. \ / ._. \ / ._. \ - __\( C )/__ __\( H )/__ __\( E )/__ __\( C )/__ __\( K )/__ -(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._) - || E || || R || || R || || O || || R || - _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ -(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.) - `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ - -Commit rejected. +Fix it and it goes quiet: -Type message check failed ==> bad commit message -It doesn't match regex: ^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .+ -The commit message should follow Conventional Commits. See https://www.conventionalcommits.org -Suggest: Use (): with allowed types +```console +$ echo "fix(parser): handle empty input" | commit-check -m ``` -## Running as CLI +### Multi-line messages -Commit-check provides several command-line options for different validation scenarios. via options or STDIN +A body and trailers survive a heredoc, so you can test the whole thing: -!!! tip +```console +$ cat > /tmp/msg.txt << 'EOF' +fix(auth): resolve login timeout - Validate commit messages by piping them through STDIN. This is useful for - testing or scripting. - -Available Commands see [commit-check --help](cli.md) - -### Message Validation Examples - -```bash -# Validate message from STDIN -echo "feat: new feature" | commit-check -m - -# Validate message from file -commit-check -m commit_message.txt - -# Validate current git commit message (from git log) -commit-check -m -``` - -**Reading from file:** - -```bash -# Create a commit message file -cat > commit_message.txt << EOF -fix(auth): resolve login timeout issue - -Users were experiencing timeouts during login. -Increased session timeout and improved error handling. +Users were timing out during login. Raises the session timeout and +reports the failure instead of hanging. Fixes #123 EOF - -# Validate from file -commit-check -m commit_message.txt - -# Or pipe file content -cat commit_message.txt | commit-check -m +$ commit-check -m /tmp/msg.txt ``` -### Branch Validation Examples - -```bash -# Check current branch name -commit-check --branch +## Checking the branch -# Example valid branch names: -# - feature/user-auth -# - fix/login-bug -# - hotfix/security-patch -# - release/v1.2.0 +```console +$ commit-check --branch ``` -### Push Validation Examples +Runs [CC201](rules.md#cc201), and [CC202](rules.md#cc202) if +`require_rebase_target` is set. `master`, `main`, `HEAD` and `PR-*` are always +accepted; everything else needs a `/` shape: -```bash -# Check whether pushing HEAD to its configured upstream would require force -commit-check --no-force-push -``` - -```yaml -# Configure the dedicated pre-push hook -- repo: https://github.com/commit-check/commit-check - rev: the tag or revision - hooks: - - id: check-no-force-push - stages: [pre-push] +```text +fix/empty-config-crash +feature/role-caching +release/v1.2.0 ``` -`git push | commit-check --no-force-push` is not a prevention mechanism. The -push has already started, and normal `git push` output does not include the -pre-push ref lines that Git provides to hooks. - -### Author Validation Examples - -```bash -# Check author name -commit-check --author-name +## Checking the committer -# Check author email -commit-check --author-email - -# Check both author name and email -commit-check --author-name --author-email +```console +$ commit-check --author-name --author-email ``` -### Configuration Examples +Either flag works alone. [CC101](rules.md#cc101) and +[CC102](rules.md#cc102) describe what the built-in patterns accept and how to +tighten them. -```bash -# Use custom configuration file -echo "feat: test" | commit-check --config my-config.toml -m +## Blocking force pushes -# Use configuration from different directory -commit-check --config /path/to/config/cchk.toml -m +```console +$ commit-check --no-force-push ``` -### Valid Commit Message Examples - -```bash -# Basic feature -echo "feat: add user registration" | commit-check -m - -# Feature with scope -echo "feat(auth): implement OAuth2 login" | commit-check -m - -# Bug fix -echo "fix: resolve memory leak in parser" | commit-check -m - -# Documentation update -echo "docs: add installation guide" | commit-check -m - -# Breaking change -echo "feat!: redesign API endpoints" | commit-check -m +Compares the current branch against its upstream and fails if pushing would +require a force. Better as a `pre-push` hook, which sees the actual refs being +pushed: -# Merge commit (automatically allowed) -echo "Merge pull request #123 from feature/new-api" | commit-check -m +```yaml title=".pre-commit-config.yaml" +repos: + - repo: https://github.com/commit-check/commit-check + rev: v2.11.0 + hooks: + - id: check-no-force-push + stages: [pre-push] ``` -### Invalid Commit Message Examples - -```bash -# No type prefix -echo "added new feature" | commit-check -m - -# Capitalized (if configured to disallow) -echo "feat: Add new feature" | commit-check -m +!!! warning "Piping `git push` into it does not prevent anything" -# Too short -echo "fix" | commit-check -m + `git push | commit-check --no-force-push` reads too late — the push has + already started — and `git push` output does not carry the ref lines Git + hands to a `pre-push` hook. Install the hook instead. -# Non-imperative mood -echo "feat: added login functionality" | commit-check -m +## Pointing at a different config -# Unknown type -echo "unknown: some changes" | commit-check -m +```console +$ commit-check -m --config /path/to/cchk.toml ``` -### Error Output Examples +Useful for testing a policy change before committing it, or for a monorepo +where one directory follows different rules. See +[Configuration](configuration.md) for where the file is looked up by default +and how CLI, environment and file settings override each other. -**Commit Message Validation Failure:** +## Output for scripts and CI -```text -Commit rejected by Commit-Check. - - (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) - / ._. \ / ._. \ / ._. \ / ._. \ / ._. \ - __\( C )/__ __\( H )/__ __\( E )/__ __\( C )/__ __\( K )/__ -(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._) - || E || || R || || R || || O || || R || - _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ -(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.) - `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ - -Commit rejected. - -Type message check failed ==> test commit message check -It doesn't match regex: ^(chore|ci|docs|feat|fix|refactor|style|test){1}(\([\w\-\.]+\))?(!)?: ([\w ])+([\s\S]*)|(Merge).*|(fixup!.*) -The commit message should follow Conventional Commits. See https://www.conventionalcommits.org -Suggest: Use (): with allowed types -``` +=== "JSON" -**Branch Name Validation Failure:** + Machine-readable, one object per check, including `rule_id` and `docs_url`. -```text -Commit rejected by Commit-Check. - - (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) - / ._. \ / ._. \ / ._. \ / ._. \ / ._. \ - __\( C )/__ __\( H )/__ __\( E )/__ __\( C )/__ __\( K )/__ -(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._) - || E || || R || || R || || O || || R || - _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ -(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.) - `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ - -Commit rejected. - -Type branch check failed ==> test-branch -It doesn't match regex: ^(feature|bugfix|hotfix|release|chore|feat|fix)\/.+|(master)|(main)|(HEAD)|(PR-.+) -The branch should follow Conventional Branch. See https://conventionalbranch.org -Suggest: Use / with allowed types or ignore_authors in config branch section to bypass -``` + ```console + $ commit-check -m --format json + ``` -**Commit Signature Validation Failure:** +=== "Compact" -```text -Commit rejected by Commit-Check. - - (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) - / ._. \ / ._. \ / ._. \ / ._. \ / ._. \ - __\( C )/__ __\( H )/__ __\( E )/__ __\( C )/__ __\( K )/__ -(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._) - || E || || R || || R || || O || || R || - _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ -(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.) - `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ - -Commit rejected. - -Type require_signed_off_by check failed ==> fix: add missing file -It doesn't match regex: Signed-off-by:.*[A-Za-z0-9]\s+<.+@.+> -Signed-off-by not found in latest commit -Suggest: git commit --amend --signoff or use --signoff on commit -``` - -**Commit Message Validation Failure without ASCII Banner (`--no-banner`):** - -```text -Type message check failed ==> test commit message check -It doesn't match regex: ^(chore|ci|docs|feat|fix|refactor|style|test){1}(\([\w\-\.]+\))?(!)?: ([\w ])+([\s\S]*)|(Merge).*|(fixup!.*) -The commit message should follow Conventional Commits. See https://www.conventionalcommits.org -Suggest: Use (): with allowed types -``` + One line per failure. Implies `--no-banner`. -**Compact Failure Output (`--compact`):** - -```text -[FAIL] message: test commit message check -``` + ```console + $ commit-check -m --compact + [FAIL] CC003 subject_imperative: docs: revamped the profile + ``` -**Imperative Mood Validation Failure:** +=== "No banner" -```text -Commit rejected by Commit-Check. - - (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c) - / ._. \ / ._. \ / ._. \ / ._. \ / ._. \ - __\( C )/__ __\( H )/__ __\( E )/__ __\( C )/__ __\( K )/__ -(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._) - || E || || R || || R || || O || || R || - _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ -(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.) - `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ - -Commit rejected. - -Type imperative check failed ==> fix: added missing file -It doesn't match regex: -Commit message should use imperative mood (e.g., 'Add feature' not 'Added feature') -Suggest: Use imperative mood in the subject line -``` + Plain text without the ASCII art, which is noise in a CI log. -## Integration Tips + ```console + $ commit-check -m --no-banner + ``` -### CI/CD Integration +=== "Dry run" -You can use commit-check in CI/CD pipelines: + Reports problems but always exits `0`. For adopting the policy on a + repository whose history is not clean yet. -```bash -# In your CI script -git log --format="%s" -n 1 | commit-check -m + ```console + $ commit-check -m --dry-run + ``` -# or just -commit-check -m +### Checking a range of commits -# Keep plain-text output but remove the ASCII art banner -git log --format="%s" -n 1 | commit-check -m --no-banner +Nothing built in, but the exit code makes it a one-liner: -# Emit one machine-friendly line per failure without switching to JSON -git log --format="%s" -n 1 | commit-check -m --compact +```bash title="check-recent.sh" +#!/usr/bin/env bash +# Check the last N commit messages; exits non-zero if any fail. +status=0 +for sha in $(git rev-list -n "${1:-10}" HEAD); do + if ! git log -1 --format=%B "$sha" | commit-check -m --compact; then + echo " ↑ $sha" + status=1 + fi +done +exit $status ``` -### Scripting - -Use commit-check in scripts to validate commit messages programmatically: - -```bash -#!/bin/bash -# validate-commits.sh - -# Get all commit messages from last 10 commits -for i in {0..9}; do - msg=$(git log --format="%s" -n 1 --skip=$i) - if [ -n "$msg" ]; then - echo "Validating: $msg" - echo "$msg" | commit-check -m || exit 1 - fi -done +### Reading the JSON -echo "All commits are valid!" +```console +$ commit-check -m --format json | jq -r '.checks[] | select(.status == "fail") | .rule_id' +CC001 ``` -For more configuration options, see the [Configuration Documentation](configuration.md). +Each failed check carries the rule ID, the offending value, the suggestion and +a link to its documentation — the same information the text output prints, in a +form other tools can consume. diff --git a/docs/what-is-new.md b/docs/what-is-new.md index b45c3a02..dc68ec64 100644 --- a/docs/what-is-new.md +++ b/docs/what-is-new.md @@ -1,365 +1,76 @@ -# What's New +# Release highlights -This document highlights the major changes and improvements in each version of commit-check. +The changes worth knowing about, newest first, each pointing at the page that +documents it properly. For the full record of every change, see the +[changelog](changelog.md). -## Version 2.11.0 — AI Attribution Governance +## 2.11.0 — AI attribution policy -### Enforce Your Project's AI Contribution Policy +Commits carrying the trailers AI coding tools add — Claude Code, Copilot, +Codex, Gemini, Cursor, Devin, Aider, Windsurf, Tabby — can now be rejected. -commit-check now supports **AI attribution governance** — a neutral enforcement -layer for the industry-wide discussion on AI disclosure in open source. - -Configured under `[commit]`: - -```toml +```toml title="cchk.toml" [commit] -# "ignore" (default) | "forbid" -ai_attribution = "forbid" +ai_attribution = "forbid" # "ignore" is the default ``` -When set to `"forbid"`, any commit containing known AI tool signatures is -rejected. The built-in signature database detects trailers and markers from: - -* **Claude Code** — `Co-authored-by: Claude`, `Assisted-by: Claude:...`, - `🤖 Generated with Claude`, `Claude-Session:`, `Claude-Workflow:` -* **GitHub Copilot** — `Co-authored-by: Copilot` -* **OpenAI Codex** — `Co-authored-by: Codex` -* **Gemini** — `Co-authored-by: Gemini` -* **Cursor** — `Co-authored-by: Cursor` -* **Devin** — `Co-authored-by: Devin` -* **Aider** — `Co-authored-by: Aider`, `Co-authored-by: ... (aider)` -* **Windsurf** — `Co-authored-by: Windsurf` -* **Tabby** — `Co-authored-by: Tabby` -* **Generic AI** — `Assisted-by:` (Linux kernel style, with tool list), - model names like `claude-sonnet-4`, `gpt-4-turbo` - -The signature database is designed to be extensible — adding a new tool is as -simple as adding a `KnownAiTool` entry with the tool's patterns. - -This feature is motivated by ongoing discussions in the CPython core -development community, the Linux kernel's `Assisted-by:` trailer standard, -VS Code, Apache, Fedora, and other foundations. - -See [Configuration Documentation](configuration.md) for details. - -## Version 2.10.0 — Bot Branch Types as Default +Whether AI-assisted commits are acceptable is a policy question with no single +right answer, so this stays off until you turn it on. -### `dependabot/` and `renovate/` branches now pass by default +[:octicons-arrow-right-24: AI attribution guide](guides/ai-attribution.md) · +[CC013](rules.md#cc013) -`dependabot` and `renovate` are now included in `DEFAULT_BRANCH_TYPES`, -so branches like `dependabot/go_modules/go-deps-c57c3fe1e0` and -`renovate/lodash-5.x` are automatically accepted without manual -`allow_branch_types` configuration. +## 2.10.0 — Bot branch prefixes accepted by default -## Version 2.9.0 — AI Agent Branch Prefixes +`dependabot/` and `renovate/` branches pass branch validation without +configuration. Automation was previously failing a check it could not satisfy. -### Conventional Branch v1.1.0 AI agent prefixes supported by default +[:octicons-arrow-right-24: CC201](rules.md#cc201) -`ai/`, `claude/`, `codex/`, `copilot/`, and `cursor/` have been -added to `DEFAULT_BRANCH_TYPES` as defined in [Conventional Branch v1.1.0](https://conventional-branch.github.io/). Branches created by AI -coding agents are now valid out of the box without extra configuration. +## 2.9.0 — AI agent branch prefixes accepted by default -## Version 2.7.0 — Force Push Blocking +`ai/`, `claude/`, `codex/`, `copilot/` and `cursor/` joined the default branch +types, following +[Conventional Branch v1.1.0](https://conventional-branch.github.io/). -### Force Push Detection and Prevention +[:octicons-arrow-right-24: CC201](rules.md#cc201) -commit-check now includes a **force push detection** feature that blocks -accidental `git push --force` / `git push -f` by inspecting pushed ref -ancestry via `git merge-base --is-ancestor`. +## 2.7.0 — Force push blocking -**How it works:** +A `pre-push` hook that refuses a force push to a shared branch, plus a +`--no-force-push` flag for running the same check by hand. -* Runs inside a Git `pre-push` hook — receives pushed ref metadata on stdin - and inspects the ancestry relationship. -* New branch pushes (remote SHA is all zeros) always pass. -* Fast-forward pushes (remote is ancestor of local) pass. -* When the remote commit is **not** an ancestor of the local commit, a force - push is detected and **blocked**. -* Git errors (e.g., unknown SHA) result in a safe pass. - -**Usage:** - -```bash -# Standalone: check whether pushing HEAD to its upstream requires force -commit-check --no-force-push -``` - -```yaml -# As a pre-commit pre-push hook -repos: - - repo: https://github.com/commit-check/commit-check - rev: v2.7.0 - hooks: - - id: check-no-force-push - stages: [pre-push] -``` - -```toml -# Configurable in cchk.toml +```toml title="cchk.toml" [push] -allow_force_push = false # default: true (force pushes allowed) +allow_force_push = false ``` -**New Python API:** +[:octicons-arrow-right-24: CC301](rules.md#cc301) · +[Command-line recipes](example.md#blocking-force-pushes) -```python -from commit_check.api import validate_push +## 2.6.0 — Output controls for scripts and CI -zero = "0000000000000000000000000000000000000000" -result = validate_push(f"refs/heads/main abc123 refs/heads/main {zero}") -print(result["status"]) # "pass" -``` - -See the [Push Safety section in README](https://github.com/commit-check/commit-check#check-push-safety) -and [Push Validation Examples](https://docs.commit-check.com/example.html#push-validation-examples) -for more details. - -## Version 2.6.0 — Output Controls for CLI Workflows - -### Quieter Human-Readable Failure Output - -commit-check now includes two CLI flags for workflows that want less verbose -terminal output without switching to JSON mode: - -* `--no-banner` suppresses the ASCII art failure banner while keeping the - detailed error message and suggestion output. -* `--compact` prints a single `[FAIL]` line per failing check and implies - `--no-banner`. - -These flags are useful in CI logs, pre-commit output, and agent-driven terminal -sessions where the full banner is noisy but plain-text diagnostics are still -helpful. - -## Version 2.5.0 — New Features - -### Co-author Bypass in `ignore_authors` - -commit-check can now skip validation when a **co-author** of the commit matches an entry in `ignore_authors`, not just the primary commit author. - -This is especially useful for AI-assisted workflows where a bot (e.g., `coderabbitai[bot]`, `copilot[bot]`) co-authors a commit that does not follow Conventional Commits format: - -```toml -[commit] -ignore_authors = ["dependabot[bot]", "renovate[bot]", "coderabbitai[bot]", "copilot[bot]"] -``` +`--format json` for machine-readable results, `--compact` for one line per +failure, and `--no-banner` to drop the ASCII art that only adds noise to a CI +log. -When a `Co-authored-by:` trailer in the commit message body matches any entry in the list, all commit checks are skipped for that commit. +[:octicons-arrow-right-24: Command-line recipes](example.md#output-for-scripts-and-ci) -### Organization-Level Config Inheritance (`inherit_from`) +## 2.5.0 — Organization-wide configuration -Teams can now share a **centralized base configuration** across all repositories in an organization using the new `inherit_from` top-level key. +`inherit_from` lets a repository pull a shared base config and override only +what it needs, so a policy change no longer means editing every repository. -```toml -# .github/cchk.toml — in every repo +```toml title=".github/cchk.toml" inherit_from = "github:my-org/.github:cchk.toml" - -[commit] -subject_max_length = 72 # Local override -``` - -**Supported source formats:** - -* `github:owner/repo:path/to/cchk.toml` — fetches from the default branch via `raw.githubusercontent.com` -* `github:owner/repo@main:path/to/cchk.toml` — pins to a specific branch, tag, or SHA -* A local file path (relative or absolute) -* An HTTPS URL - -Local settings always **override** the inherited configuration. HTTP (non-TLS) URLs are rejected for security. If the source is unreachable, the local config is used as-is. - -### Git Config Author Validation - -Author name and email validation now checks **`git config user.name` / `user.email`** first — the identity that will be used for the *next* commit — and falls back to the last commit's author only if git config is unset. - -Previously, a developer with a misconfigured `user.name` (e.g., starting with a digit) would pass validation as long as their most recent commit had a valid author name. This fix closes that gap. - -## Version 2.0.0 - Major Release - -Version 2.0.0 represents a complete architectural overhaul of commit-check, introducing significant improvements in configuration, usability, and maintainability. - -### **Overview** - -The most significant change in v2.0.0 is the transition from YAML to TOML configuration format, along with a complete redesign of the validation engine using SOLID principles. - -**Key Benefits:** - -* **Simplified Configuration**: More intuitive TOML syntax -* **Better Defaults**: Sensible out-of-the-box behavior -* **Enhanced Validation**: Built-in support for Conventional Commits and Conventional Branches -* **Improved Architecture**: Modular, maintainable codebase -* **Better Documentation**: Comprehensive guides and examples - -### **Documentation & Migration** - -* **Configuration Guide**: Updated [Configuration Documentation](configuration.md) with comprehensive examples -* **Migration Support**: Complete [Migration Guide](migration.md) for upgrading from v1.x to v2.0+ - -### **Configuration Format Migration** - -The configuration format has changed from YAML to TOML, providing better readability and easier maintenance. - -**Format Comparison:** - -| Feature | YAML (v1.x) | TOML (v2.0+) | -|---|---|---| -| **Syntax** | Complex nested structure | Simple key-value pairs | -| **Validation** | Custom regex patterns | Built-in conventional standards | -| **Configuration** | `.commit-check.yml` | `cchk.toml` or `commit-check.toml` | -| **Maintainability** | Manual regex maintenance | Standardized patterns | - -### **Configuration Examples** - -Below are side-by-side comparisons showing how common configurations translate from v1.x to v2.0+. - -#### Commit Message Validation - -Transform complex regex patterns into simple, standardized configuration. - -**Before (YAML v1.x):** - -```yaml -checks: - - check: message - regex: '^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test){1}(\([\w\-\.]+\))?(!)?: ([\w ])+([\s\S]*)|(Merge).*|(fixup!.*)' - error: "The commit message should be structured as follows:\n\n - [optional scope]: \n - [optional body]\n - [optional footer(s)]\n\n - More details please refer to https://www.conventionalcommits.org" - suggest: please check your commit message whether matches above regex -``` - -**After (TOML v2.0+):** - -```toml -[commit] -conventional_commits = true -allow_commit_types = ["build", "chore", "ci", "docs", "feat", "fix", "perf", "refactor", "style", "test"] -``` - -**Benefits**: No more complex regex patterns, built-in [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) support, clearer configuration. - -#### Branch Naming Validation - -Standardize branch naming with conventional patterns. - -**Before (YAML v1.x):** - -```yaml -checks: - - check: branch - regex: ^(bugfix|feature|release|hotfix|task|chore)\/.+|(master)|(main)|(HEAD)|(PR-.+) - error: "Branches must begin with these types: bugfix/ feature/ release/ hotfix/ task/ chore/" - suggest: run command `git checkout -b type/branch_name` -``` - -**After (TOML v2.0+):** - -```toml -[branch] -conventional_branch = true -allow_branch_types = ["bugfix", "feature", "release", "hotfix", "task", "chore"] -``` - -**Benefits**: Built-in [Conventional Branch](https://conventionalbranch.org) support, automatic handling of special branches (main, master, HEAD, PR-\*). - -#### Author Validation - -Flexible author validation with allow/ignore lists. - -**Before (YAML v1.x):** - -```yaml -checks: - - check: author_name - regex: ^[A-Za-zÀ-ÖØ-öø-ÿ\u0100-\u017F\u0180-\u024F ,.\'-]+$|.*(\[bot]) - error: The committer name seems invalid - suggest: run command `git config user.name "Your Name"` -``` - -**After (TOML v2.0+):** - -```toml -[commit] -# Built-in validation with sensible defaults for author name/email -# Optional: ignore specific authors (e.g., bots) -ignore_authors = ["dependabot[bot]", "renovate[bot]"] -``` - -**Benefits**: Built-in validation patterns, flexible ignore lists, automatic bot detection. - -#### Signed-off-by Requirements - -Simple boolean flag for DCO compliance. - -**Before (YAML v1.x):** - -```yaml -checks: - - check: commit_signoff - regex: Signed-off-by:.*[A-Za-z0-9]\s+<.+@.+> - error: Signed-off-by not found in latest commit - suggest: run command `git commit -m "conventional commit message" --signoff` -``` - -**After (TOML v2.0+):** - -```toml -[commit] -require_signed_off_by = true -``` - -**Benefits**: Simple boolean configuration, built-in DCO validation, clear error messages. - -### **Architecture Improvements** - -#### **New Validation Engine** - -* **SOLID Principles**: Maintainable, extensible design -* **Specialized Validators**: Dedicated classes for each validation type -* **Centralized Rules**: Rule catalog with consistent error messages -* **Flexible Configuration**: Dynamic rule building from configuration - -#### **Module Organization** - -| Module | Purpose | -|---|---| -| `config.py` | TOML configuration loading and validation | -| `engine.py` | Core validation engine and specialized validators | -| `rule_builder.py` | Builds validation rules from configuration | -| `rules_catalog.py` | Centralized catalog of validation rules and messages | -| `main.py` | CLI interface and orchestration | - -### **Getting Started with v2.0** - -#### **For New Users:** - -1. **Install commit-check v2.0+**: - -```bash -pip install commit-check>=2.0.0 -``` - -2. **Start with defaults** (no configuration needed): - -```bash -commit-check --message --branch -``` - -3. **Customize as needed** with `cchk.toml`: - -```toml -[commit] -conventional_commits = true -subject_max_length = 72 ``` -#### For Existing Users +[:octicons-arrow-right-24: Organization guide](guides/organization.md) -1. **Follow the Migration Guide**: See [Migration Guide](migration.md) -2. **Test thoroughly**: Validate your new configuration before deploying +## 2.0.0 — TOML configuration -### **Additional Resources** +The configuration format moved from YAML to TOML, the CLI was simplified, and +settings became overridable by environment variable and command-line flag. +This is a breaking change from 1.x. -* [Configuration Reference](configuration.md) - Complete configuration options -* [Migration Guide](migration.md) - Step-by-step upgrade instructions -* [CLI Reference](cli.md) - Command-line interface documentation +[:octicons-arrow-right-24: Migrating from v1](migration.md) diff --git a/mkdocs.yml b/mkdocs.yml index 04669a01..fa9cb77e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -102,6 +102,16 @@ markdown_extensions: plugins: - search + # Generates the preview image shown when a page is shared on Slack, X or + # LinkedIn. Needs cairo and pillow, which `pip install '.[docs]'` pulls in. + # + # Deploy previews turn this off (see netlify.toml): nobody shares a preview + # link for its preview image, and skipping the cards keeps those builds fast + # and free of the system cairo dependency. + - social: + enabled: !ENV [SOCIAL_CARDS, true] + cards_layout_options: + background_color: "#2c9ccd" hooks: - scripts/mkdocs_hooks.py diff --git a/netlify.toml b/netlify.toml index b0e18c1e..9231dfce 100644 --- a/netlify.toml +++ b/netlify.toml @@ -22,10 +22,10 @@ # unexpanded and be rejected as a URL without a scheme. The build command runs # in a shell, where the variable actually expands. [context.deploy-preview] - command = "pip install '.[docs]' && SITE_URL=\"$DEPLOY_PRIME_URL/\" mkdocs build --strict" + command = "pip install '.[docs]' && SITE_URL=\"$DEPLOY_PRIME_URL/\" SOCIAL_CARDS=false mkdocs build --strict" [context.branch-deploy] - command = "pip install '.[docs]' && SITE_URL=\"$DEPLOY_PRIME_URL/\" mkdocs build --strict" + command = "pip install '.[docs]' && SITE_URL=\"$DEPLOY_PRIME_URL/\" SOCIAL_CARDS=false mkdocs build --strict" # The URLs the Sphinx site served. The build does not emit redirect stubs on # Netlify (see scripts/mkdocs_hooks.py): a stub at rules.html would be served diff --git a/pyproject.toml b/pyproject.toml index 8a0a62eb..1d4d59c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,7 +48,7 @@ tracker = "https://github.com/commit-check/commit-check/issues" [project.optional-dependencies] dev = ['nox==2026.7.11'] test = ['coverage', 'pytest', 'pytest-mock', 'pytest-codspeed'] -docs = ['mkdocs-material>=9.7'] +docs = ['mkdocs-material[imaging]>=9.7'] ci = ['twine==7.0.0'] [tool.setuptools] From fe8bc74aef0a6bc8f7118a1dfb185ff006150338 Mon Sep 17 00:00:00 2001 From: shenxianpeng Date: Mon, 3 Aug 2026 22:32:11 +0000 Subject: [PATCH 2/2] docs: guard the range-check script and add the 2.8.0 highlight The check-recent.sh recipe expanded git rev-list inside the for loop, so a failure produced an empty list and the script exited 0: run outside a repository, or against an unreadable revision, it reported success without checking anything. Resolve the revisions first and exit on failure. Add the missing 2.8.0 entry: it introduced message_pattern and dropped Python 3.9, which is the kind of change the highlights page exists for. --- docs/example.md | 8 +++++++- docs/what-is-new.md | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/docs/example.md b/docs/example.md index 1e487b58..3048e250 100644 --- a/docs/example.md +++ b/docs/example.md @@ -169,8 +169,14 @@ Nothing built in, but the exit code makes it a one-liner: ```bash title="check-recent.sh" #!/usr/bin/env bash # Check the last N commit messages; exits non-zero if any fail. + +# Resolved before the loop rather than inside it: an unreadable range or a +# directory that is not a repository would otherwise expand to nothing, and +# a loop that never runs would report success. +shas=$(git rev-list -n "${1:-10}" HEAD) || exit 1 + status=0 -for sha in $(git rev-list -n "${1:-10}" HEAD); do +for sha in $shas; do if ! git log -1 --format=%B "$sha" | commit-check -m --compact; then echo " ↑ $sha" status=1 diff --git a/docs/what-is-new.md b/docs/what-is-new.md index dc68ec64..4858f8e7 100644 --- a/docs/what-is-new.md +++ b/docs/what-is-new.md @@ -35,6 +35,21 @@ types, following [:octicons-arrow-right-24: CC201](rules.md#cc201) +## 2.8.0 — Custom message patterns + +`message_pattern` replaces the generated Conventional Commits regex with one of +your own, for teams that already enforce a different format. + +```toml title="cchk.toml" +[commit] +message_pattern = "^PROJ-\\d+: .+" +``` + +This release also dropped Python 3.9. The minimum is now 3.10. + +[:octicons-arrow-right-24: CC001](rules.md#cc001) · +[Configuration](configuration.md) + ## 2.7.0 — Force push blocking A `pre-push` hook that refuses a force push to a shared branch, plus a