Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ repos:
types: [python]
pass_filenames: false
args: [src/adcp]
- id: check-commit-msg
name: release-please commit subject check
entry: scripts/check-commit-msg.sh
language: script
stages: [commit-msg]

# Security scanning with bandit
- repo: https://github.com/PyCQA/bandit
Expand Down
38 changes: 37 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ git clone https://github.com/adcontextprotocol/adcp-client-python.git
cd adcp-client-python
```

2. Install dependencies:
2. Install dependencies and pre-commit hooks:
```bash
pip install -e ".[dev]"
pre-commit install
pre-commit install --hook-type commit-msg
```

3. Run tests:
Expand Down Expand Up @@ -82,6 +84,40 @@ src/adcp/
4. Update documentation
5. Submit PR with clear description

### PR Title Format

This repository uses squash merges. The PR title becomes the commit subject that
release-please reads to build the CHANGELOG and determine version bumps.

**The description portion of the commit subject — the text after `type(scope):` —
must not contain `(`, `)`, or `"` characters.** The release-please parser treats
those characters as grammar tokens when they appear in the description and silently
drops the commit from the CHANGELOG with no error signal. (The `type(scope)` prefix
itself is fine; only the description portion is constrained.)

**Wrong — parser drops these commits silently:**

```
fix(auth): synthesize AuthInfo(kind="bearer") in _build_request_context
feat(auth): serve(auth=BearerTokenAuth(...)) — A2A sibling shortcut
```

**Right — move code examples and parenthetical details to the PR body:**

```
fix(auth): synthesize bearer AuthInfo in _build_request_context
feat(auth): add A2A sibling and cross-transport shortcut for bearer auth
```

Place code snippets, type names with parens, and parenthetical clarifications in the PR
body (release-please reads body footers like `BREAKING CHANGE:` and `Fixes #N` but
otherwise ignores the body for CHANGELOG purposes).

A `commit-msg` pre-commit hook (`scripts/check-commit-msg.sh`) catches violations on
direct commits. It does **not** catch squash-merge subjects (those are set by GitHub on
merge from the PR title), so keeping the PR title clean is the primary responsibility.
Hook setup is included in step 2 of Development Setup above.

## Questions?

Open an issue or email maintainers@adcontextprotocol.org
38 changes: 38 additions & 0 deletions scripts/check-commit-msg.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/usr/bin/env bash
# Validates commit subjects against release-please parser constraints.
# Embedded ( ) or " in the description silently drop commits from the CHANGELOG.
# NOTE: this hook runs on direct commits only — squash-merge subjects (set by
# GitHub from the PR title) bypass it. Keep the PR title clean as the primary fix.
#
# Enable: pre-commit install --hook-type commit-msg

set -euo pipefail

msg_file="$1"
subject=$(head -1 "$msg_file")

# Only validate conventional commit messages: type(scope): desc or type: desc
cc_pattern='^[a-z]+(\([^)]*\))?(!)?: '
if echo "$subject" | grep -qE "$cc_pattern"; then
description="${subject#*: }"
if echo "$description" | grep -qE '[()"]'; then
echo ""
echo "commit-msg: release-please will silently drop this commit from the CHANGELOG."
echo ""
echo " Subject: $subject"
echo ""
echo ' The description (text after "type(scope):") contains ( ) or " characters,'
echo " which break release-please's conventional commit parser."
echo ""
echo " Fix: reword to avoid parentheses and quotes in the description."
echo " Move code snippets and type names with parens to the PR body instead."
echo ""
echo " Example:"
echo ' Wrong: fix(auth): synthesize AuthInfo(kind="bearer") in _build_request_context'
echo " Right: fix(auth): synthesize bearer AuthInfo in _build_request_context"
echo ""
exit 1
fi
fi

exit 0
Loading