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..3048e250 100644 --- a/docs/example.md +++ b/docs/example.md @@ -1,376 +1,197 @@ -# 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 -``` - -2. **Create .pre-commit-config.yaml:** - -```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 -``` - -3. **Install the hooks:** - -```bash -pre-commit install --hook-type pre-commit --hook-type commit-msg -``` + ```console + $ commit-check -m commit_message.txt + ``` -4. **Test the integration:** +=== "From stdin" -```bash -# This will trigger validation automatically -git commit -m "feat: add new user authentication system" -``` - -### Pre-commit Validation Examples + Useful in scripts and for trying a message before committing it. -**✅ Successful Validation:** + ```console + $ echo "feat(auth): add OAuth2 login" | commit-check -m + ``` -```text -$ git commit -m "feat: add user authentication system" +### Trying a message before you write it -check commit message.....................................................Passed -check committer name.....................................................Passed -check committer email....................................................Passed -[main abc1234] feat: add 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 ``` -**❌ 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 || - _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ _.' '-' '._ -(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.) - `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ `-´ +Fix it and it goes quiet: -Commit rejected. - -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 - -Commit-check provides several command-line options for different validation scenarios. via options or STDIN - -!!! tip - - 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 +### Multi-line messages -# Validate current git commit message (from git log) -commit-check -m -``` - -**Reading from file:** +A body and trailers survive a heredoc, so you can test the whole thing: -```bash -# Create a commit message file -cat > commit_message.txt << EOF -fix(auth): resolve login timeout issue +```console +$ cat > /tmp/msg.txt << 'EOF' +fix(auth): resolve login timeout -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 +## Checking the branch -```bash -# Check current branch name -commit-check --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 - -```bash -# Check whether pushing HEAD to its configured upstream would require force -commit-check --no-force-push -``` +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: -```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 +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: -# Documentation update -echo "docs: add installation guide" | commit-check -m - -# Breaking change -echo "feat!: redesign API endpoints" | commit-check -m - -# 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 +!!! warning "Piping `git push` into it does not prevent anything" -```bash -# No type prefix -echo "added new feature" | 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. -# Capitalized (if configured to disallow) -echo "feat: Add new feature" | commit-check -m +## Pointing at a different config -# Too short -echo "fix" | commit-check -m - -# Non-imperative mood -echo "feat: added login functionality" | commit-check -m - -# 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:** - -```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 -``` +## Output for scripts and CI -**Branch Name Validation Failure:** +=== "JSON" -```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 -``` + Machine-readable, one object per check, including `rule_id` and `docs_url`. -**Commit Signature Validation Failure:** + ```console + $ commit-check -m --format json + ``` -```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 -``` +=== "Compact" -**Commit Message Validation Failure without ASCII Banner (`--no-banner`):** + One line per failure. Implies `--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 -``` + ```console + $ commit-check -m --compact + [FAIL] CC003 subject_imperative: docs: revamped the profile + ``` -**Compact Failure Output (`--compact`):** +=== "No banner" -```text -[FAIL] message: test commit message check -``` + Plain text without the ASCII art, which is noise in a CI log. -**Imperative Mood Validation Failure:** + ```console + $ commit-check -m --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 -``` +=== "Dry run" -## Integration Tips + Reports problems but always exits `0`. For adopting the policy on a + repository whose history is not clean yet. -### CI/CD Integration + ```console + $ commit-check -m --dry-run + ``` -You can use commit-check in CI/CD pipelines: +### Checking a range of commits -```bash -# In your CI script -git log --format="%s" -n 1 | commit-check -m +Nothing built in, but the exit code makes it a one-liner: -# or just -commit-check -m +```bash title="check-recent.sh" +#!/usr/bin/env bash +# Check the last N commit messages; exits non-zero if any fail. -# Keep plain-text output but remove the ASCII art banner -git log --format="%s" -n 1 | commit-check -m --no-banner +# 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 -# Emit one machine-friendly line per failure without switching to JSON -git log --format="%s" -n 1 | commit-check -m --compact +status=0 +for sha in $shas; 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..4858f8e7 100644 --- a/docs/what-is-new.md +++ b/docs/what-is-new.md @@ -1,365 +1,91 @@ -# 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 - -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 -[commit] -# "ignore" (default) | "forbid" -ai_attribution = "forbid" -``` - -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 - -### `dependabot/` and `renovate/` branches now pass by default - -`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. - -## Version 2.9.0 — AI Agent Branch Prefixes - -### Conventional Branch v1.1.0 AI agent prefixes supported by default - -`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. - -## Version 2.7.0 — Force Push Blocking - -### Force Push Detection and Prevention - -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`. - -**How it works:** - -* 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 -[push] -allow_force_push = false # default: true (force pushes allowed) -``` - -**New Python API:** - -```python -from commit_check.api import validate_push - -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]"] -``` - -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. - -### Organization-Level Config Inheritance (`inherit_from`) - -Teams can now share a **centralized base configuration** across all repositories in an organization using the new `inherit_from` top-level key. - -```toml -# .github/cchk.toml — in every repo -inherit_from = "github:my-org/.github:cchk.toml" +Commits carrying the trailers AI coding tools add — Claude Code, Copilot, +Codex, Gemini, Cursor, Devin, Aider, Windsurf, Tabby — can now be rejected. +```toml title="cchk.toml" [commit] -subject_max_length = 72 # Local override +ai_attribution = "forbid" # "ignore" is the default ``` -**Supported source formats:** +Whether AI-assisted commits are acceptable is a policy question with no single +right answer, so this stays off until you turn it on. -* `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 +[:octicons-arrow-right-24: AI attribution guide](guides/ai-attribution.md) · +[CC013](rules.md#cc013) -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. +## 2.10.0 — Bot branch prefixes accepted by default -### Git Config Author Validation +`dependabot/` and `renovate/` branches pass branch validation without +configuration. Automation was previously failing a check it could not satisfy. -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. +[:octicons-arrow-right-24: CC201](rules.md#cc201) -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. +## 2.9.0 — AI agent branch prefixes accepted by default -## Version 2.0.0 - Major Release +`ai/`, `claude/`, `codex/`, `copilot/` and `cursor/` joined the default branch +types, following +[Conventional Branch v1.1.0](https://conventional-branch.github.io/). -Version 2.0.0 represents a complete architectural overhaul of commit-check, introducing significant improvements in configuration, usability, and maintainability. +[:octicons-arrow-right-24: CC201](rules.md#cc201) -### **Overview** +## 2.8.0 — Custom message patterns -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. +`message_pattern` replaces the generated Conventional Commits regex with one of +your own, for teams that already enforce a different format. -**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 +```toml title="cchk.toml" [commit] -conventional_commits = true -allow_commit_types = ["build", "chore", "ci", "docs", "feat", "fix", "perf", "refactor", "style", "test"] +message_pattern = "^PROJ-\\d+: .+" ``` -**Benefits**: No more complex regex patterns, built-in [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) support, clearer configuration. +This release also dropped Python 3.9. The minimum is now 3.10. -#### Branch Naming Validation +[:octicons-arrow-right-24: CC001](rules.md#cc001) · +[Configuration](configuration.md) -Standardize branch naming with conventional patterns. +## 2.7.0 — Force push blocking -**Before (YAML v1.x):** +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. -```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 +```toml title="cchk.toml" +[push] +allow_force_push = false ``` -**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 | +[:octicons-arrow-right-24: CC301](rules.md#cc301) · +[Command-line recipes](example.md#blocking-force-pushes) -### **Getting Started with v2.0** +## 2.6.0 — Output controls for scripts and CI -#### **For New Users:** +`--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. -1. **Install commit-check v2.0+**: +[:octicons-arrow-right-24: Command-line recipes](example.md#output-for-scripts-and-ci) -```bash -pip install commit-check>=2.0.0 -``` - -2. **Start with defaults** (no configuration needed): - -```bash -commit-check --message --branch -``` +## 2.5.0 — Organization-wide configuration -3. **Customize as needed** with `cchk.toml`: +`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 -[commit] -conventional_commits = true -subject_max_length = 72 +```toml title=".github/cchk.toml" +inherit_from = "github:my-org/.github:cchk.toml" ``` -#### 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]