|
| 1 | +# Contributing — branching & releases (trunk-on-main) |
| 2 | + |
| 3 | +`ClaudeCodeCommons` is a shared library for the Claude routine family. It uses **trunk-based |
| 4 | +development**: `main` is always releasable, and every release is an annotated `vX.Y.Z` |
| 5 | +tag on `main` — no `develop` / `release` / `hotfix` branches. The plain `git` commands |
| 6 | +below are the whole workflow. |
| 7 | + |
| 8 | +The family deliberately picks its branching model by **deploy model**: pip-installed |
| 9 | +libraries and scheduled routines use trunk-on-main (this guide); gated multi-environment |
| 10 | +apps use Git Flow. The *release gate* — version = changelog = tag — is the same either |
| 11 | +way; only the branching differs. |
| 12 | + |
| 13 | +## Branch model |
| 14 | + |
| 15 | +| Branch | Purpose | |
| 16 | +| --- | --- | |
| 17 | +| `main` | The line. Always releasable, always green. Every release is a tag here. Default branch. | |
| 18 | +| `feature/*` (optional) | A short-lived branch for one unit of work, merged back with `git merge --no-ff`. For small changes, committing straight to `main` is fine. | |
| 19 | + |
| 20 | +Tags are always `vX.Y.Z` (a `v` prefix on the version). |
| 21 | + |
| 22 | +## Daily work |
| 23 | + |
| 24 | +Follow the **SCOPE → test → code → changelog** loop in `CLAUDE.md` (if present), or at |
| 25 | +minimum: add/adjust the test, change the code, keep `pytest` green, and add a line under |
| 26 | +`[Unreleased]` in `CHANGELOG.md`. Every public symbol downstream routines import is part |
| 27 | +of this library's contract — change it deliberately and note breaking changes. |
| 28 | + |
| 29 | +## Quality gates (run before every commit) |
| 30 | + |
| 31 | +```bash |
| 32 | +ruff check . |
| 33 | +ruff format --check . |
| 34 | +pytest # tests + line coverage >= 80% (use pytest --no-cov for subsets) |
| 35 | +``` |
| 36 | + |
| 37 | +CI runs exactly these on every push and PR. `ruff format` owns formatting; the linter is |
| 38 | +a small, stable rule set (`E`, `F`, `I`). |
| 39 | + |
| 40 | +## Cutting a release (the release gate lives here) |
| 41 | + |
| 42 | +The version in `pyproject.toml`, the topmost `CHANGELOG.md` heading, and the annotated |
| 43 | +tag must be the same `X.Y.Z`: |
| 44 | + |
| 45 | +```bash |
| 46 | +# on a clean, green main: |
| 47 | +# 1) bump "version" in pyproject.toml |
| 48 | +# 2) move CHANGELOG.md [Unreleased] entries under a new "## [X.Y.Z] - YYYY-MM-DD" heading |
| 49 | +# 3) ruff check . && ruff format --check . && pytest |
| 50 | +git commit -am "Added vX.Y.Z — <summary>" |
| 51 | +git tag -a vX.Y.Z -m "vX.Y.Z" |
| 52 | +git push origin main --tags |
| 53 | +``` |
| 54 | + |
| 55 | +Downstream routines pin this library by tag (`...@vX.Y.Z`), so a release is only "done" |
| 56 | +once the tag is pushed. Pushing the tag triggers `release.yml`, which creates the GitHub |
| 57 | +Release from the changelog. Release this package before the routines that need the new |
| 58 | +version, and don't break the public API without a major-version bump. |
0 commit comments