diff --git a/README.md b/README.md new file mode 100644 index 00000000..75a90176 --- /dev/null +++ b/README.md @@ -0,0 +1,494 @@ +# Commit Check + +[![CI](https://github.com/commit-check/commit-check/actions/workflows/main.yml/badge.svg)](https://github.com/commit-check/commit-check/actions/workflows/main.yml) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=commit-check_commit-check&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=commit-check_commit-check) +[![PyPI](https://img.shields.io/pypi/v/commit-check?logo=python&logoColor=white&color=%232c9ccd)](https://pypi.org/project/commit-check/) +[![PyPI Downloads](https://img.shields.io/pypi/dm/commit-check?color=%232c9ccd)](https://pypi.org/project/commit-check/) +[![Python Versions](https://img.shields.io/pypi/pyversions/commit-check?logo=python&logoColor=white)](https://pypi.org/project/commit-check/) +[![commit-check](https://img.shields.io/badge/commit--check-enabled-brightgreen?logo=Git&logoColor=white&color=%232c9ccd)](https://github.com/commit-check/commit-check) +[![CodeCov](https://codecov.io/gh/commit-check/commit-check/branch/main/graph/badge.svg?token=GC2U5V5ZRT)](https://codecov.io/gh/commit-check/commit-check) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/commit-check/commit-check/badge)](https://api.securityscorecards.dev/projects/github.com/commit-check/commit-check) + +## Table of Contents + +- [Overview](#overview) +- [Quick Start](#quick-start) +- [Installation](#installation) +- [Configuration](#configuration) + - [Use Default Configuration](#use-default-configuration) + - [Use Custom Configuration File](#use-custom-configuration-file) + - [Organization-Level Configuration (inherit_from)](#organization-level-configuration-inherit_from) + - [Use CLI Arguments or Environment Variables](#use-cli-arguments-or-environment-variables) + - [Check Push Safety](#check-push-safety) +- [AI-Native Usage](#ai-native-usage) + - [Machine-Readable JSON Output (--format json)](#machine-readable-json-output---format-json) + - [Quieter Human-Readable Output](#quieter-human-readable-output) + - [Python API (no subprocess required)](#python-api-no-subprocess-required) +- [Examples](#examples) +- [Badging your repository](#badging-your-repository) +- [Why Commit Check?](#why-commit-check) +- [Versioning](#versioning) +- [Have question or feedback?](#have-question-or-feedback) +- [License](#license) + +## Overview + +**Commit Check** is a lightweight policy engine for Git commit metadata. + +It validates commit messages, branch names, author identity, signoff trailers, +AI attribution policy, and push safety — using one versioned TOML policy across +local hooks, CI, GitHub Actions, and AI automation. + +- **One policy file:** `cchk.toml` +- **Multiple enforcement points:** CLI, pre-commit, CI / GitHub Actions +- **Machine-readable output:** JSON + Python API for automation and AI agents + +![commit-check demo](https://github.com/commit-check/commit-check/raw/main/docs/demo.gif) + +
+ +## Quick Start + +**1. Install and run with zero configuration:** + +```bash +pip install commit-check +commit-check --message --branch +``` + +**2. Add to your pre-commit hooks** (`.pre-commit-config.yaml`): + +```yaml +repos: + - repo: https://github.com/commit-check/commit-check + rev: v2.11.1 + hooks: + - id: check-message + - id: check-branch +``` + +**3. Add a badge to your repository:** + +```text +[![commit-check](https://img.shields.io/badge/commit--check-enabled-brightgreen?logo=Git&logoColor=white&color=%232c9ccd)](https://github.com/commit-check/commit-check) +``` + +## Installation + +To install Commit Check, you can use pip: + +```bash +pip install commit-check +``` + +Or install directly from the GitHub repository: + +```bash +pip install git+https://github.com/commit-check/commit-check.git@main +``` + +Then, run `commit-check --help` or `cchk --help` (alias for `commit-check`) from the command line. +For more information, see the [docs](https://commit-check.github.io/commit-check/cli_args.html). + +## Configuration + +Commit Check can be configured in three ways (in order of priority): + +1. **Command-line arguments** — Override settings for specific runs +2. **Environment variables** — Configure via `CCHK_*` environment variables +3. **Configuration files** — Use `cchk.toml` or `commit-check.toml` + +### Use Default Configuration + +- **Commit Check** uses a [default configuration](https://github.com/commit-check/commit-check/blob/main/docs/configuration.rst) if you do not provide a `cchk.toml` or `commit-check.toml` file. + +- The default configuration is lenient — it only checks whether commit messages follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/#summary) specification and branch names follow the [Conventional Branch](https://conventionalbranch.org#summary) convention. + +### Use Custom Configuration File + +To customize the behavior, create a configuration file named `cchk.toml` or `commit-check.toml` in your repository's root directory or in the `.github` folder, e.g., [`cchk.toml`](https://github.com/commit-check/commit-check/blob/main/cchk.toml) or `.github/cchk.toml`. + +```toml +[commit] +# https://www.conventionalcommits.org +conventional_commits = true +subject_imperative = true +subject_max_length = 80 +allow_commit_types = ["feat", "fix", "docs", "style", "refactor", "test", "chore", "ci"] +allow_merge_commits = true +allow_wip_commits = false +require_signed_off_by = false +# Bypass checks for bot/automation authors and co-authors: +ignore_authors = ["dependabot[bot]", "renovate[bot]", "copilot[bot]"] +# AI attribution policy: "ignore" (default) or "forbid" +# "forbid" rejects commits with known AI tool signatures +ai_attribution = "forbid" + +[branch] +# https://conventionalbranch.org +conventional_branch = true +allow_branch_types = ["feature", "bugfix", "hotfix", "release", "chore", "feat", "fix"] +``` + +> [!TIP] +> **IDE Autocompletion** +> +> commit-check's TOML schema is published on [SchemaStore](https://www.schemastore.org/), +> so editors like VS Code (via [Even Better TOML](https://marketplace.visualstudio.com/items?itemName=tamasfe.even-better-toml)), +> PyCharm, and IntelliJ provide autocompletion, validation, and documentation +> tooltips for `cchk.toml` out of the box — no manual schema path configuration needed. + +### Organization-Level Configuration (inherit_from) + +Share a base configuration across all repositories in your organization using `inherit_from`: + +```toml +# .github/cchk.toml — inherits from org-level config, then overrides locally +inherit_from = "github:my-org/.github:cchk.toml" + +[commit] +subject_max_length = 72 # Local override +``` + +The `inherit_from` field accepts: + +- A **GitHub shorthand** (recommended): `inherit_from = "github:owner/repo:path/to/cchk.toml"` +- A **GitHub shorthand with ref**: `inherit_from = "github:owner/repo@main:path/to/cchk.toml"` +- A **local file path** (relative or absolute): `inherit_from = "../shared/cchk.toml"` +- An **HTTPS URL**: `inherit_from = "https://example.com/cchk.toml"` + +The `github:` shorthand fetches from `raw.githubusercontent.com`. HTTP (non-TLS) URLs are rejected for security. + +Local settings always **override** the inherited base configuration. + +### Use CLI Arguments or Environment Variables + +For one-off checks or CI/CD pipelines, you can configure via CLI arguments or environment variables: + +```bash +# Using CLI arguments +commit-check --message --subject-imperative=true --subject-max-length=72 + +# Using environment variables +export CCHK_SUBJECT_IMPERATIVE=true +export CCHK_SUBJECT_MAX_LENGTH=72 +commit-check --message + +# In pre-commit hooks (.pre-commit-config.yaml) +repos: + - repo: https://github.com/commit-check/commit-check + rev: v2.11.1 + hooks: + - id: check-message + args: + - --subject-imperative=false + - --subject-max-length=100 +``` + +See the [Configuration documentation](https://commit-check.github.io/commit-check/configuration.html) for all available options. + +### Check Push Safety + +Use `--no-force-push` in a `pre-push` hook to inspect the ref updates Git +provides on stdin, or run it directly to compare `HEAD` with the current +branch's configured upstream: + +```bash +# Standalone preflight check against the current branch's upstream +commit-check --no-force-push +``` + +```yaml +# In pre-commit hooks (.pre-commit-config.yaml) +repos: + - repo: https://github.com/commit-check/commit-check + rev: v2.11.1 + hooks: + - id: check-no-force-push + stages: [pre-push] +``` + +> [!NOTE] +> Piping `git push` into `commit-check` is not a prevention mechanism. The +> push has already been started, and standard `git push` output does not carry +> the pre-push ref metadata that `commit-check` uses. + +## AI-Native Usage + +Commit Check is designed to be consumed by AI agents, LLM toolchains, and +automation scripts — not just by humans reading terminal output. + +### Machine-Readable JSON Output (`--format json`) + +Pass `--format json` to any CLI invocation to receive structured JSON instead +of human-readable ASCII art. The exit code is unchanged (`0` = pass, `1` = fail), +so existing CI scripts continue to work: + +```bash +echo "feat: add streaming support" | commit-check -m --format json +``` + +```json +{ + "status": "pass", + "checks": [ + { "check": "message", "status": "pass", "value": "", "error": "", "suggest": "" }, + { "check": "subject_imperative", "status": "pass", "value": "", "error": "", "suggest": "" } + ] +} +``` + +On failure the failing checks carry the full `error` and `suggest` fields +an agent needs to self-correct: + +```bash +echo "wip bad commit" | commit-check -m --format json +``` + +```json +{ + "status": "fail", + "checks": [ + { + "check": "message", + "status": "fail", + "value": "wip bad commit", + "error": "The commit message should follow Conventional Commits. See https://www.conventionalcommits.org", + "suggest": "Use (): , where is one of: feat, fix, docs, ..." + } + ] +} +``` + +### Quieter Human-Readable Output + +For terminal workflows that still want plain text, commit-check now supports +two lower-noise output modes: + +- `--no-banner` keeps the normal failure details and suggestions, but removes + the ASCII-art failure banner. +- `--compact` emits a single `[FAIL]` line per failing check and implies + `--no-banner`. + +```bash +echo "wip bad commit" | commit-check -m --no-banner +``` + +```text +Type message check failed ==> wip bad commit +It doesn't match regex: ^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test){1}(\([\w\-\.]+\))?(!)?: ([\w ])+([\s\S]*)|(Merge).*|(fixup!.*) +The commit message should follow Conventional Commits. See https://www.conventionalcommits.org +Suggest: Use (): , where is one of: feat, fix, docs, ... +``` + +```bash +echo "wip bad commit" | commit-check -m --compact +``` + +```text +[FAIL] message: wip bad commit +``` + +### Python API (no subprocess required) + +The `commit_check.api` module exposes a lightweight, import-friendly interface +so AI agents, tools, and scripts can validate commits **without spawning a +subprocess**. All functions return plain dicts that are easy to serialise, +forward to an LLM, or chain into larger workflows: + +```python +from commit_check.api import validate_message, validate_branch, validate_all + +# --- validate a single commit message --- +result = validate_message("feat: add streaming support") +print(result["status"]) # "pass" + +# --- validate a branch name --- +result = validate_branch("feature/add-streaming") +print(result["status"]) # "pass" + +# --- run multiple checks at once --- +result = validate_all( + message="feat: implement new feature", + branch="feature/new-feature", + author_name="Ada Lovelace", + author_email="ada@example.com", +) +if result["status"] == "fail": + for check in result["checks"]: + if check["status"] == "fail": + print(f"[{check['check']}] {check['error']}") + print(f" suggestion: {check['suggest']}") + +# --- supply a custom config to restrict allowed types --- +result = validate_message( + "docs: update readme", + config={"commit": {"allow_commit_types": ["feat", "fix"]}}, +) +print(result["status"]) # "fail" — 'docs' not in allowed types +``` + +**Return-value schema** (all API functions): + +```python +{ + "status": "pass" | "fail", + "checks": [ + { + "check": "", + "status": "pass" | "fail", + "value": "", + "error": "", + "suggest": "", + }, + # ... one entry per active rule + ] +} +``` + +Available API functions: + +- `validate_message(message, *, config=None)` — validate a commit message string +- `validate_branch(branch=None, *, config=None)` — validate a branch name (defaults to current git branch) +- `validate_author(name=None, email=None, *, config=None)` — validate author name/email +- `validate_all(message, branch, author_name, author_email, *, config=None)` — run all checks at once + +For detailed usage instructions including pre-commit hooks, CLI commands, and STDIN examples, see the [Usage Examples documentation](https://commit-check.github.io/commit-check/example.html). + +## Examples + +### Check Commit Message Failed + +```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 +The commit message should follow Conventional Commits. See https://www.conventionalcommits.org +Suggest: Use (): , where is one of: feat, fix, docs, style, refactor, test, chore, ci +``` + +### Check Branch Naming Failed + +```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 +The branch should follow Conventional Branch. See https://conventionalbranch.org +Suggest: Use / with allowed types or add branch name to allow_branch_names in config, or use ignore_authors in config branch section to bypass +``` + +More examples see [example documentation](https://commit-check.github.io/commit-check/example.html). + +## Badging your repository + +You can add a badge to your repository to show that you use commit-check! + +[![commit-check](https://img.shields.io/badge/commit--check-enabled-brightgreen?logo=Git&logoColor=white&color=%232c9ccd)](https://github.com/commit-check/commit-check) + +**Markdown** + +```text +[![commit-check](https://img.shields.io/badge/commit--check-enabled-brightgreen?logo=Git&logoColor=white&color=%232c9ccd)](https://github.com/commit-check/commit-check) +``` + +**reStructuredText** + +```text +.. image:: https://img.shields.io/badge/commit--check-enabled-brightgreen?logo=Git&logoColor=white&color=%232c9ccd + :target: https://github.com/commit-check/commit-check + :alt: commit-check +``` + +## Why Commit Check? + +The table below compares common approaches to commit policy enforcement. +`commitlint` is a specialized commit-message linter. [GitHub Rulesets][github-rulesets] +are platform-native server-side enforcement. Custom Git hooks and the +`pre-commit` framework are integration mechanisms, so the last column +reflects a DIY approach rather than built-in product features. + +[github-rulesets]: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/about-rulesets + +| Feature | Commit Check | commitlint | YACC[^2] | GitHub Rulesets | Custom hooks | +|---------|-------------|------------|------|-----------------|-------------| +| Conventional Commits enforcement | ✅ | ✅ | Partial | Partial[^4] | DIY | +| Branch naming validation | ✅ | ❌ | ✅ | ✅[^4] | DIY | +| Force push blocking | ✅ | ❌ | ❌ | ✅ | DIY | +| Author name / email validation | ✅ | ❌ | ✅ | ✅[^4] | DIY | +| Signed-off-by trailer enforcement | ✅ | Partial[^1] | ❌ | ❌ | DIY | +| Co-author ignore list | ✅ | ❌ | Partial[^3] | ❌ | DIY | +| Organization-level shared config | ✅ | ✅ | ✅ | ✅ | DIY | +| Zero-config defaults | ✅ | ❌ | ❌ | ❌ | ❌ | +| Works without Node.js | ✅ | ❌ | ✅ | ✅ | Depends | +| Native TOML configuration | ✅ | ❌ | ❌ | ❌ | Depends | +| Git hook / pre-commit integration | ✅ | Partial | ❌ | ❌ | ✅ | +| CI/CD-friendly configuration | ✅ | Partial | ❌ | ❌ | DIY | +| Open source & free | ✅ | ✅ | ❌ | ❌[^5] | ✅ | +| Client-side (pre-commit) enforcement | ✅ | ✅ | ❌ | ❌ | ✅ | +| AI-native (JSON API + Python SDK) | ✅ | ❌ | ❌ | ❌ | ❌ | + +For `commitlint`, organization-level shared config is typically delivered via +shareable config packages or local files. + +For `YACC` (Yet Another Commit Checker), conventional commit enforcement +is regex-based rather than Conventional Commits-aware; author validation +verifies committer name/email against Bitbucket user accounts or custom regex; +the plugin supports global → project → repository config inheritance; +it is a server-side pre-receive hook and merge check (no client-side +pre-commit), is paid (per-user licensing), and runs on Java (no Node.js needed). + +For [GitHub Rulesets][github-rulesets], push rulesets enforce metadata via regex patterns — +they can match branch/tag names, commit messages, and author email, but have +no awareness of Conventional Commits semantics (types, scopes, breaking-change +markers). They apply server-side and require a GitHub plan (Free for public +repos, Team/Enterprise for private/internal repos with push rulesets). They +are not portable to other Git platforms and do not provide local pre-commit +feedback. + +`DIY` means you can implement a +capability with custom Git hooks or `pre-commit` scripts, but it is not +provided as a turnkey policy layer. + +[^1]: `commitlint` provides a community `signed-off-by` rule (`@commitlint/rule-signed-off-by`) that must be installed and configured separately; it is not part of the default `@commitlint/config-conventional` preset. + +[^2]: [Yet Another Commit Checker](https://marketplace.atlassian.com/apps/1211854/yet-another-commit-checker) is a paid Bitbucket Server / Data Center plugin (server-side pre-receive hook and merge check). + +[^3]: YACC can exclude commits from specific Bitbucket users, user groups, or service users (bots), but does not parse `Co-authored-by:` trailers in commit messages. + +[^4]: GitHub Rulesets enforce these via regex patterns in push rulesets (metadata restrictions). They are regex-based and do not understand Conventional Commits or Conventional Branch semantics. + +[^5]: GitHub Rulesets require a GitHub plan. Push rulesets (metadata restrictions) require Team or Enterprise plans for private/internal repos; branch/tag rulesets are available on Free plans for public repos. + +## Versioning + +Versioning follows [Semantic Versioning](https://semver.org/). + +## Have question or feedback? + +Please post to [issues](https://github.com/commit-check/commit-check/issues) or start a [discussion](https://github.com/commit-check/commit-check/discussions) for feedback, feature requests, or bug reports. + +## License + +This project is released under the [MIT License](https://github.com/commit-check/commit-check/blob/main/LICENSE). diff --git a/README.rst b/README.rst deleted file mode 100644 index 6f7e105a..00000000 --- a/README.rst +++ /dev/null @@ -1,624 +0,0 @@ -Commit Check -============ - -.. |pypi-version| image:: https://img.shields.io/pypi/v/commit-check?logo=python&logoColor=white&color=%232c9ccd - :target: https://pypi.org/project/commit-check/ - :alt: PyPI - -.. |ci-badge| image:: https://github.com/commit-check/commit-check/actions/workflows/main.yml/badge.svg - :target: https://github.com/commit-check/commit-check/actions/workflows/main.yml - :alt: CI - -.. |sonar-badge| image:: https://sonarcloud.io/api/project_badges/measure?project=commit-check_commit-check&metric=alert_status - :target: https://sonarcloud.io/summary/new_code?id=commit-check_commit-check - :alt: Quality Gate Status - -.. |codecov-badge| image:: https://codecov.io/gh/commit-check/commit-check/branch/main/graph/badge.svg?token=GC2U5V5ZRT - :target: https://codecov.io/gh/commit-check/commit-check - :alt: CodeCov - -.. |scorecard-badge| image:: https://api.securityscorecards.dev/projects/github.com/commit-check/commit-check/badge - :target: https://api.securityscorecards.dev/projects/github.com/commit-check/commit-check - :alt: OpenSSF Scorecard - -.. |commit-check-badge| image:: https://img.shields.io/badge/commit--check-enabled-brightgreen?logo=Git&logoColor=white&color=%232c9ccd - :target: https://github.com/commit-check/commit-check - :alt: commit-check - -.. |pypi-downloads| image:: https://img.shields.io/pypi/dm/commit-check?color=%232c9ccd - :target: https://pypi.org/project/commit-check/ - :alt: PyPI Downloads - -.. |python-versions| image:: https://img.shields.io/pypi/pyversions/commit-check?logo=python&logoColor=white - :target: https://pypi.org/project/commit-check/ - :alt: Python Versions - -|ci-badge| |sonar-badge| |pypi-version| |pypi-downloads| |python-versions| |commit-check-badge| |codecov-badge| - -.. contents:: Table of Contents - :depth: 2 - :local: - :backlinks: none - -Overview --------- - -**Commit Check** is a lightweight policy engine for Git commit metadata. - -It validates commit messages, branch names, author identity, signoff trailers, -AI attribution policy, and push safety — using one versioned TOML policy across -local hooks, CI, GitHub Actions, and AI automation. - -- **One policy file:** ``cchk.toml`` -- **Multiple enforcement points:** CLI, pre-commit, CI / GitHub Actions -- **Machine-readable output:** JSON + Python API for automation and AI agents - -.. image:: https://github.com/commit-check/commit-check/raw/main/docs/demo.gif - :alt: commit-check demo - :align: center - -| - -Quick Start ------------ - -**1. Install and run with zero configuration:** - -.. code-block:: bash - - pip install commit-check - commit-check --message --branch - -**2. Add to your pre-commit hooks** (``.pre-commit-config.yaml``): - -.. code-block:: yaml - - repos: - - repo: https://github.com/commit-check/commit-check - rev: v2.11.1 - hooks: - - id: check-message - - id: check-branch - -**3. Add a badge to your repository:** - -.. code-block:: text - - [![commit-check](https://img.shields.io/badge/commit--check-enabled-brightgreen?logo=Git&logoColor=white&color=%232c9ccd)](https://github.com/commit-check/commit-check) - -Installation ------------- - -To install Commit Check, you can use pip: - -.. code-block:: bash - - pip install commit-check - -Or install directly from the GitHub repository: - -.. code-block:: bash - - pip install git+https://github.com/commit-check/commit-check.git@main - -Then, run ``commit-check --help`` or ``cchk --help`` (alias for ``commit-check``) from the command line. -For more information, see the `docs `_. - - -Configuration -------------- - -Commit Check can be configured in three ways (in order of priority): - -1. **Command-line arguments** — Override settings for specific runs -2. **Environment variables** — Configure via ``CCHK_*`` environment variables -3. **Configuration files** — Use ``cchk.toml`` or ``commit-check.toml`` - -Use Default Configuration -~~~~~~~~~~~~~~~~~~~~~~~~~ - -- **Commit Check** uses a `default configuration `_ if you do not provide a ``cchk.toml`` or ``commit-check.toml`` file. - -- The default configuration is lenient — it only checks whether commit messages follow the `Conventional Commits `_ specification and branch names follow the `Conventional Branch `_ convention. - -Use Custom Configuration File -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To customize the behavior, create a configuration file named ``cchk.toml`` or ``commit-check.toml`` in your repository's root directory or in the ``.github`` folder, e.g., `cchk.toml `_ or ``.github/cchk.toml``. - -.. code-block:: toml - - [commit] - # https://www.conventionalcommits.org - conventional_commits = true - subject_imperative = true - subject_max_length = 80 - allow_commit_types = ["feat", "fix", "docs", "style", "refactor", "test", "chore", "ci"] - allow_merge_commits = true - allow_wip_commits = false - require_signed_off_by = false - # Bypass checks for bot/automation authors and co-authors: - ignore_authors = ["dependabot[bot]", "renovate[bot]", "copilot[bot]"] - # AI attribution policy: "ignore" (default) or "forbid" - # "forbid" rejects commits with known AI tool signatures - ai_attribution = "forbid" - - [branch] - # https://conventionalbranch.org - conventional_branch = true - allow_branch_types = ["feature", "bugfix", "hotfix", "release", "chore", "feat", "fix"] - -.. tip:: - **IDE Autocompletion** - - commit-check's TOML schema is published on `SchemaStore `_, - so editors like VS Code (via `Even Better TOML `_), - PyCharm, and IntelliJ provide autocompletion, validation, and documentation - tooltips for ``cchk.toml`` out of the box — no manual schema path configuration needed. - -Organization-Level Configuration (inherit_from) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Share a base configuration across all repositories in your organization using ``inherit_from``: - -.. code-block:: toml - - # .github/cchk.toml — inherits from org-level config, then overrides locally - inherit_from = "github:my-org/.github:cchk.toml" - - [commit] - subject_max_length = 72 # Local override - -The ``inherit_from`` field accepts: - -* A **GitHub shorthand** (recommended): ``inherit_from = "github:owner/repo:path/to/cchk.toml"`` -* A **GitHub shorthand with ref**: ``inherit_from = "github:owner/repo@main:path/to/cchk.toml"`` -* A **local file path** (relative or absolute): ``inherit_from = "../shared/cchk.toml"`` -* An **HTTPS URL**: ``inherit_from = "https://example.com/cchk.toml"`` - -The ``github:`` shorthand fetches from ``raw.githubusercontent.com``. HTTP (non-TLS) URLs are rejected for security. - -Local settings always **override** the inherited base configuration. - -Use CLI Arguments or Environment Variables -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -For one-off checks or CI/CD pipelines, you can configure via CLI arguments or environment variables: - -.. code-block:: bash - - # Using CLI arguments - commit-check --message --subject-imperative=true --subject-max-length=72 - - # Using environment variables - export CCHK_SUBJECT_IMPERATIVE=true - export CCHK_SUBJECT_MAX_LENGTH=72 - commit-check --message - - # In pre-commit hooks (.pre-commit-config.yaml) - repos: - - repo: https://github.com/commit-check/commit-check - rev: v2.11.1 - hooks: - - id: check-message - args: - - --subject-imperative=false - - --subject-max-length=100 - -See the `Configuration documentation `_ for all available options. - -Check Push Safety -~~~~~~~~~~~~~~~~~ - -Use ``--no-force-push`` in a ``pre-push`` hook to inspect the ref updates Git -provides on stdin, or run it directly to compare ``HEAD`` with the current -branch's configured upstream: - -.. code-block:: bash - - # Standalone preflight check against the current branch's upstream - commit-check --no-force-push - -.. code-block:: yaml - - # In pre-commit hooks (.pre-commit-config.yaml) - repos: - - repo: https://github.com/commit-check/commit-check - rev: v2.11.1 - hooks: - - id: check-no-force-push - stages: [pre-push] - -Piping ``git push`` into ``commit-check`` is not a prevention mechanism. The -push has already been started, and standard ``git push`` output does not carry -the pre-push ref metadata that ``commit-check`` uses. - -AI-Native Usage ---------------- - -Commit Check is designed to be consumed by AI agents, LLM toolchains, and -automation scripts — not just by humans reading terminal output. - -Machine-Readable JSON Output (``--format json``) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Pass ``--format json`` to any CLI invocation to receive structured JSON instead -of human-readable ASCII art. The exit code is unchanged (``0`` = pass, ``1`` = fail), -so existing CI scripts continue to work: - -.. code-block:: bash - - echo "feat: add streaming support" | commit-check -m --format json - -.. code-block:: json - - { - "status": "pass", - "checks": [ - { "check": "message", "status": "pass", "value": "", "error": "", "suggest": "" }, - { "check": "subject_imperative", "status": "pass", "value": "", "error": "", "suggest": "" } - ] - } - -On failure the failing checks carry the full ``error`` and ``suggest`` fields -an agent needs to self-correct: - -.. code-block:: bash - - echo "wip bad commit" | commit-check -m --format json - -.. code-block:: json - - { - "status": "fail", - "checks": [ - { - "check": "message", - "status": "fail", - "value": "wip bad commit", - "error": "The commit message should follow Conventional Commits. See https://www.conventionalcommits.org", - "suggest": "Use (): , where is one of: feat, fix, docs, ..." - } - ] - } - -Quieter Human-Readable Output -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -For terminal workflows that still want plain text, commit-check now supports -two lower-noise output modes: - -* ``--no-banner`` keeps the normal failure details and suggestions, but removes - the ASCII-art failure banner. -* ``--compact`` emits a single ``[FAIL]`` line per failing check and implies - ``--no-banner``. - -.. code-block:: bash - - echo "wip bad commit" | commit-check -m --no-banner - -.. code-block:: text - - Type message check failed ==> wip bad commit - It doesn't match regex: ^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test){1}(\([\w\-\.]+\))?(!)?: ([\w ])+([\s\S]*)|(Merge).*|(fixup!.*) - The commit message should follow Conventional Commits. See https://www.conventionalcommits.org - Suggest: Use (): , where is one of: feat, fix, docs, ... - -.. code-block:: bash - - echo "wip bad commit" | commit-check -m --compact - -.. code-block:: text - - [FAIL] message: wip bad commit - -Python API (no subprocess required) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The ``commit_check.api`` module exposes a lightweight, import-friendly interface -so AI agents, tools, and scripts can validate commits **without spawning a -subprocess**. All functions return plain dicts that are easy to serialise, -forward to an LLM, or chain into larger workflows: - -.. code-block:: python - - from commit_check.api import validate_message, validate_branch, validate_all - - # --- validate a single commit message --- - result = validate_message("feat: add streaming support") - print(result["status"]) # "pass" - - # --- validate a branch name --- - result = validate_branch("feature/add-streaming") - print(result["status"]) # "pass" - - # --- run multiple checks at once --- - result = validate_all( - message="feat: implement new feature", - branch="feature/new-feature", - author_name="Ada Lovelace", - author_email="ada@example.com", - ) - if result["status"] == "fail": - for check in result["checks"]: - if check["status"] == "fail": - print(f"[{check['check']}] {check['error']}") - print(f" suggestion: {check['suggest']}") - - # --- supply a custom config to restrict allowed types --- - result = validate_message( - "docs: update readme", - config={"commit": {"allow_commit_types": ["feat", "fix"]}}, - ) - print(result["status"]) # "fail" — 'docs' not in allowed types - -**Return-value schema** (all API functions): - -.. code-block:: python - - { - "status": "pass" | "fail", - "checks": [ - { - "check": "", - "status": "pass" | "fail", - "value": "", - "error": "", - "suggest": "", - }, - # ... one entry per active rule - ] - } - -Available API functions: - -* ``validate_message(message, *, config=None)`` — validate a commit message string -* ``validate_branch(branch=None, *, config=None)`` — validate a branch name (defaults to current git branch) -* ``validate_author(name=None, email=None, *, config=None)`` — validate author name/email -* ``validate_all(message, branch, author_name, author_email, *, config=None)`` — run all checks at once - -For detailed usage instructions including pre-commit hooks, CLI commands, and STDIN examples, see the `Usage Examples documentation `_. - -Examples --------- - -Check Commit Message Failed - -.. code-block:: 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 - The commit message should follow Conventional Commits. See https://www.conventionalcommits.org - Suggest: Use (): , where is one of: feat, fix, docs, style, refactor, test, chore, ci - - -Check Branch Naming Failed - -.. code-block:: 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 - The branch should follow Conventional Branch. See https://conventionalbranch.org - Suggest: Use / with allowed types or add branch name to allow_branch_names in config, or use ignore_authors in config branch section to bypass - -More examples see `example documentation `_. - -Badging your repository ------------------------ - -You can add a badge to your repository to show that you use commit-check! - -.. image:: https://img.shields.io/badge/commit--check-enabled-brightgreen?logo=Git&logoColor=white&color=%232c9ccd - :target: https://github.com/commit-check/commit-check - :alt: commit-check - -Markdown - -.. code-block:: text - - [![commit-check](https://img.shields.io/badge/commit--check-enabled-brightgreen?logo=Git&logoColor=white&color=%232c9ccd)](https://github.com/commit-check/commit-check) - -reStructuredText - -.. code-block:: text - - .. image:: https://img.shields.io/badge/commit--check-enabled-brightgreen?logo=Git&logoColor=white&color=%232c9ccd - :target: https://github.com/commit-check/commit-check - :alt: commit-check - - -Why Commit Check? ------------------ - -The table below compares common approaches to commit policy enforcement. -``commitlint`` is a specialized commit-message linter. `GitHub Rulesets`_ -are platform-native server-side enforcement. Custom Git hooks and the -``pre-commit`` framework are integration mechanisms, so the last column -reflects a DIY approach rather than built-in product features. - -.. _GitHub Rulesets: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/about-rulesets - -.. list-table:: - :header-rows: 1 - :widths: 20 14 14 14 14 24 - - * - Feature - - Commit Check - - commitlint - - YACC [#f2]_ - - GitHub Rulesets - - Custom hooks - * - Conventional Commits enforcement - - ✅ - - ✅ - - Partial - - Partial [#f4]_ - - DIY - * - Branch naming validation - - ✅ - - ❌ - - ✅ - - ✅ [#f4]_ - - DIY - * - Force push blocking - - ✅ - - ❌ - - ❌ - - ✅ - - DIY - * - Author name / email validation - - ✅ - - ❌ - - ✅ - - ✅ [#f4]_ - - DIY - * - Signed-off-by trailer enforcement - - ✅ - - Partial [#f1]_ - - ❌ - - ❌ - - DIY - * - Co-author ignore list - - ✅ - - ❌ - - Partial [#f3]_ - - ❌ - - DIY - * - Organization-level shared config - - ✅ - - ✅ - - ✅ - - ✅ - - DIY - * - Zero-config defaults - - ✅ - - ❌ - - ❌ - - ❌ - - ❌ - * - Works without Node.js - - ✅ - - ❌ - - ✅ - - ✅ - - Depends - * - Native TOML configuration - - ✅ - - ❌ - - ❌ - - ❌ - - Depends - * - Git hook / pre-commit integration - - ✅ - - Partial - - ❌ - - ❌ - - ✅ - * - CI/CD-friendly configuration - - ✅ - - Partial - - ❌ - - ❌ - - DIY - * - Open source & free - - ✅ - - ✅ - - ❌ - - ❌ [#f5]_ - - ✅ - * - Client-side (pre-commit) enforcement - - ✅ - - ✅ - - ❌ - - ❌ - - ✅ - * - AI-native (JSON API + Python SDK) - - ✅ - - ❌ - - ❌ - - ❌ - - ❌ - -*For* ``commitlint``, organization-level shared config is typically delivered via -shareable config packages or local files. - -*For* ``YACC`` (Yet Another Commit Checker), conventional commit enforcement -is regex-based rather than Conventional Commits-aware; author validation -verifies committer name/email against Bitbucket user accounts or custom regex; -the plugin supports global → project → repository config inheritance; -it is a server-side pre-receive hook and merge check (no client-side -pre-commit), is paid (per-user licensing), and runs on Java (no Node.js needed). - -*For* `GitHub Rulesets`_, push rulesets enforce metadata via regex patterns — -they can match branch/tag names, commit messages, and author email, but have -no awareness of Conventional Commits semantics (types, scopes, breaking-change -markers). They apply server-side and require a GitHub plan (Free for public -repos, Team/Enterprise for private/internal repos with push rulesets). They -are not portable to other Git platforms and do not provide local pre-commit -feedback. - -``DIY`` means you can implement a -capability with custom Git hooks or ``pre-commit`` scripts, but it is not -provided as a turnkey policy layer. - -.. [#f1] ``commitlint`` provides a community ``signed-off-by`` rule - (``@commitlint/rule-signed-off-by``) that must be installed and configured - separately; it is not part of the default - ``@commitlint/config-conventional`` preset. - -.. [#f2] `Yet Another Commit Checker - `_ - is a paid Bitbucket Server / Data Center plugin (server-side pre-receive hook - and merge check). - -.. [#f3] YACC can exclude commits from specific Bitbucket users, user groups, - or service users (bots), but does not parse ``Co-authored-by:`` trailers - in commit messages. - -.. [#f4] GitHub Rulesets enforce these via regex patterns in push rulesets - (metadata restrictions). They are regex-based and do not understand - Conventional Commits or Conventional Branch semantics. - -.. [#f5] GitHub Rulesets require a GitHub plan. Push rulesets (metadata - restrictions) require Team or Enterprise plans for private/internal repos; - branch/tag rulesets are available on Free plans for public repos. - - -Versioning ----------- - -Versioning follows `Semantic Versioning `_. - -Have question or feedback? --------------------------- - -Please post to `issues `_ or start a `discussion `_ for feedback, feature requests, or bug reports. - -License -------- - -This project is released under the `MIT License `_ diff --git a/docs/conf.py b/docs/conf.py index 62190a67..898349b0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -18,6 +18,7 @@ # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration extensions = [ + "myst_parser", "sphinx_immaterial", "sphinx.ext.autodoc", "sphinx.ext.intersphinx", @@ -25,6 +26,15 @@ "sphinx_issues", ] +source_suffix = { + ".rst": "restructuredtext", + ".md": "markdown", +} + +# Treat bare URLs as external links so MyST does not warn about TOC +# anchor references (e.g. `(#overview)`) being unresolved cross-references. +myst_all_links_external = True + autodoc_member_order = "bysource" templates_path = ["_templates"] diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..ab3fbfc3 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,14 @@ +```{include} ../README.md +``` + +```{toctree} +:hidden: +self +what-is-new +configuration +example +migration +troubleshoot +changelog +cli_args +``` diff --git a/docs/index.rst b/docs/index.rst deleted file mode 100644 index a54420c5..00000000 --- a/docs/index.rst +++ /dev/null @@ -1,29 +0,0 @@ -.. include:: ../README.rst - -.. toctree:: - :hidden: - - self - what-is-new - configuration - example - migration - troubleshoot - changelog - -.. toctree:: - :hidden: - - cli_args - -.. .. automodule:: commit_check.main -.. :members: - -.. .. automodule:: commit_check.branch -.. :members: - -.. .. automodule:: commit_check.commit -.. :members: - -.. .. automodule:: commit_check.config -.. :members: diff --git a/pyproject.toml b/pyproject.toml index 97ec3bcd..9841c626 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta" [project] name = "commit-check" description = "Check commit message formatting, branch naming, commit author, email, and more." -readme = "README.rst" +readme = "README.md" keywords = ["commit conventions", "conventional commits", "conventional branch", "branch naming", "commit-check", "message", "lint message", "devops"] license = "MIT" authors = [ @@ -48,7 +48,7 @@ tracker = "https://github.com/commit-check/commit-check/issues" [project.optional-dependencies] dev = ['nox'] test = ['coverage', 'pytest', 'pytest-mock', 'pytest-codspeed'] -docs = ['sphinx<9', 'sphinx-immaterial', 'sphinx-autobuild', 'sphinx_issues'] +docs = ['sphinx<9', 'sphinx-immaterial', 'sphinx-autobuild', 'sphinx_issues', 'myst-parser'] [tool.setuptools] zip-safe = false diff --git a/uv.lock b/uv.lock index f086e449..c2c20755 100644 --- a/uv.lock +++ b/uv.lock @@ -316,6 +316,8 @@ dev = [ { name = "nox" }, ] docs = [ + { name = "myst-parser", version = "4.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "myst-parser", version = "5.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "sphinx-autobuild", version = "2024.10.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, @@ -333,6 +335,7 @@ test = [ [package.metadata] requires-dist = [ { name = "coverage", marker = "extra == 'test'" }, + { name = "myst-parser", marker = "extra == 'docs'" }, { name = "nox", marker = "extra == 'dev'" }, { name = "pytest", marker = "extra == 'test'" }, { name = "pytest-codspeed", marker = "extra == 'test'" }, @@ -570,14 +573,32 @@ wheels = [ [[package]] name = "markdown-it-py" -version = "4.0.0" +version = "3.0.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] +dependencies = [ + { name = "mdurl", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload-time = "2023-06-03T06:41:14.443Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload-time = "2023-06-03T06:41:11.019Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.2.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.11'", +] dependencies = [ - { name = "mdurl" }, + { name = "mdurl", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } +sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, + { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" }, ] [[package]] @@ -665,6 +686,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, ] +[[package]] +name = "mdit-py-plugins" +version = "0.6.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "markdown-it-py", version = "4.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/59/fc/f8d0863f8862f25602c0404d75568e89fb6b4109804645e5cdfb1be5cf56/mdit_py_plugins-0.6.1.tar.gz", hash = "sha256:a2bca0f039f39dbd35fb74ae1b5f998608c437463371f0ff7f49a19a17a114d0", size = 56114, upload-time = "2026-05-13T09:03:38.91Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a5/69/6da5581c6a7fede7dc261bf4e67d6adca4196f176b43288b55b3db395b6e/mdit_py_plugins-0.6.1-py3-none-any.whl", hash = "sha256:214c82fb2ac524472ab6a5bcab1de80f73b50443e187f401bfd77efbc7c6481d", size = 66663, upload-time = "2026-05-13T09:03:37.76Z" }, +] + [[package]] name = "mdurl" version = "0.1.2" @@ -674,6 +708,46 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, ] +[[package]] +name = "myst-parser" +version = "4.0.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] +dependencies = [ + { name = "docutils", marker = "python_full_version < '3.11'" }, + { name = "jinja2", marker = "python_full_version < '3.11'" }, + { name = "markdown-it-py", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "mdit-py-plugins", marker = "python_full_version < '3.11'" }, + { name = "pyyaml", marker = "python_full_version < '3.11'" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/a5/9626ba4f73555b3735ad86247a8077d4603aa8628537687c839ab08bfe44/myst_parser-4.0.1.tar.gz", hash = "sha256:5cfea715e4f3574138aecbf7d54132296bfd72bb614d31168f48c477a830a7c4", size = 93985, upload-time = "2025-02-12T10:53:03.833Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/df/76d0321c3797b54b60fef9ec3bd6f4cfd124b9e422182156a1dd418722cf/myst_parser-4.0.1-py3-none-any.whl", hash = "sha256:9134e88959ec3b5780aedf8a99680ea242869d012e8821db3126d427edc9c95d", size = 84579, upload-time = "2025-02-12T10:53:02.078Z" }, +] + +[[package]] +name = "myst-parser" +version = "5.1.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.11'", +] +dependencies = [ + { name = "docutils", marker = "python_full_version >= '3.11'" }, + { name = "jinja2", marker = "python_full_version >= '3.11'" }, + { name = "markdown-it-py", version = "4.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "mdit-py-plugins", marker = "python_full_version >= '3.11'" }, + { name = "pyyaml", marker = "python_full_version >= '3.11'" }, + { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/21/dc/603751677fff302f34396e206b610f556a59d7fe58b9a2145f54e96b48e8/myst_parser-5.1.0.tar.gz", hash = "sha256:ab69322dc6719dcc7f296479dbb70181b66df6ed315064f92dbc85c0e1bf2f02", size = 101182, upload-time = "2026-05-13T09:38:19.361Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/09/dc/f3dfb7488b770f3f67e6545085bf2abea5172e88f57b8ad25ef860ca704c/myst_parser-5.1.0-py3-none-any.whl", hash = "sha256:9c91c52b3cdb4d94a6506e4fab4e2f296c7623a0da0dcbe6de1565c3dad67a8a", size = 85817, upload-time = "2026-05-13T09:38:17.904Z" }, +] + [[package]] name = "nox" version = "2026.4.10" @@ -1022,7 +1096,8 @@ name = "rich" version = "15.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "markdown-it-py" }, + { name = "markdown-it-py", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "markdown-it-py", version = "4.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "pygments" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }