Skip to content

Commit 5df0036

Browse files
bokelleyclaude
andauthored
docs(releasing): write the main, release/N.x, and next branch rules (#1535)
Record the branch model from adcp-client-python#1525 in RELEASING.md: which branch carries which spec line, how fixes move between them (backports, regular main to next merges, forward-port and backport labels), how next cuts 10.0.0-alpha.N pre-releases from its own release-please setup, the one-time procedure that keeps #1502 on next after main reverts it, and how next merges into main at ratification. CONTRIBUTING.md points feature branches at the right base. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent de6c53b commit 5df0036

2 files changed

Lines changed: 142 additions & 2 deletions

File tree

‎CONTRIBUTING.md‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,10 @@ These guards enforce the contract and run in `make ci-local`:
183183

184184
## Pull Request Process
185185

186-
1. Create a feature branch from `main`
186+
1. Create a feature branch from the branch that carries your spec line:
187+
`main` for the ratified AdCP version (fixes land here first), `next` for
188+
draft-spec work, or `release/N.x` only for a fix that applies to that older
189+
major alone (see [RELEASING.md](RELEASING.md))
187190
2. Make your changes
188191
3. Run tests and type checks
189192
4. Update documentation

‎RELEASING.md‎

Lines changed: 138 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,141 @@
11
# Releasing adcp
22

33
See [docs/releasing.md](docs/releasing.md) for the Release Please PR, GitHub
4-
environment approval, and PyPI verification steps.
4+
environment approval, and PyPI verification steps on `main`.
5+
6+
## Branches
7+
8+
Each branch carries one spec line. Draft-spec work stays out of stable
9+
releases ([#1525](https://github.com/adcontextprotocol/adcp-client-python/issues/1525)).
10+
11+
| Branch | Carries | Releases |
12+
| --- | --- | --- |
13+
| `main` | Work against the latest ratified AdCP version (3.2.x today) | The current major (9.x), through release-please |
14+
| `release/N.x` (`release/8.x`, `release/7.x`) | Fixes for an older major | Patch releases of that major, from the branch's own release workflow |
15+
| `next` | Work against draft specs, such as AdCP 3.3 agent identity and Web Bot Auth | Pre-releases only (`10.0.0-alpha.N`), from its own release-please configuration |
16+
17+
Open a PR against the branch that carries the spec it implements. Code written
18+
to an unratified spec (an open adcontextprotocol/adcp PR or a draft) targets
19+
`next`, never `main`.
20+
21+
## Moving changes between branches
22+
23+
- **Fixes land on `main` first.** A maintainer then backports the fix to each
24+
`release/N.x` that needs it, as a cherry-pick PR
25+
(`git cherry-pick -x <sha>`) into that branch.
26+
- **`next` takes `main` regularly**, so it doesn't drift. Merge `origin/main`
27+
into `next` with a true merge: push the merge to `next` directly, or merge
28+
the sync PR with **Create a merge commit**. Never squash or rebase a sync, or
29+
every later sync repeats the same conflicts. A forward-port PR (a cherry-pick
30+
onto `next`) also works for a single urgent fix.
31+
- **Draft-only changes stay on `next`.** If a change is needed only by
32+
draft-spec code, it never goes to `main`.
33+
- **At ratification, `next` merges into `main`**, and the next major releases
34+
from `main` (see [Ratification](#ratification)).
35+
- **Labels mark PRs that need a port**: `backport release/8.x` (and so on, one
36+
per maintained line) and `forward-port next`. Add the label to the merged PR;
37+
whoever opens the port PR links it back and removes the label. A backport
38+
action can open the port PRs later; until then this is manual.
39+
40+
### Resolving `main` → `next` merge conflicts
41+
42+
`next` uses separate release files, so release automation conflicts are
43+
limited:
44+
45+
- `CHANGELOG.md`, `release-please-config.json`, and
46+
`.release-please-manifest.json` belong to `main`. Take `main`'s version; on
47+
`next` nothing reads them except a test that accepts `main`'s version.
48+
- `CHANGELOG.next.md`, `release-please-config.next.json`,
49+
`.release-please-manifest.next.json`, and
50+
`.github/workflows/release-please-next.yml` exist only on `next`. `main`
51+
never changes them.
52+
- The `[project] version` line in `pyproject.toml` conflicts after both lines
53+
have released. Keep `next`'s version (`10.0.0aN`).
54+
55+
## Releasing from `next`
56+
57+
`next` has its own release-please setup. The files are separate from `main`'s
58+
so that merges in either direction never change the other line's release flow:
59+
60+
- `.github/workflows/release-please-next.yml` runs on pushes to `next` only,
61+
with its own concurrency group and `target-branch: next`.
62+
- `release-please-config.next.json` sets `versioning: prerelease`,
63+
`prerelease-type: alpha`, and `prerelease: true`, and writes
64+
`CHANGELOG.next.md`. `.release-please-manifest.next.json` holds `next`'s
65+
current version.
66+
- The commit that added the setup ends with `Release-As: 10.0.0-alpha.0`, so
67+
the first release is `10.0.0-alpha.0`. Every later release increments the
68+
alpha number (`10.0.0-alpha.1`, ...), whatever the commit type. Don't
69+
merge a `next` release PR that proposes a version without `-alpha.N`.
70+
- After release-please opens or updates the release PR, the workflow runs
71+
`scripts/normalize_pyproject_prerelease --release-prs --target-branch next`
72+
to rewrite `pyproject.toml` to PEP 440 (`10.0.0a0`). The normalizer accepts
73+
only `release-please--branches--next--components--adcp` PRs into `next`.
74+
- When the release PR merges, release-please tags `v10.0.0-alpha.N`, creates a
75+
GitHub release marked as a pre-release, and dispatches `release-publish.yml`
76+
with `--ref next`. That workflow waits for `next`'s CI at the release commit,
77+
then publishes to PyPI after the `release-publish` environment approval.
78+
PyPI treats `10.0.0aN` as a pre-release: `pip install adcp` keeps resolving
79+
to `main`'s releases, and adopters opt in with `pip install --pre adcp` or
80+
`adcp==10.0.0a0`.
81+
82+
One-time setup: add `next` to the `release-publish` environment's deployment
83+
branches (GitHub Settings → Environments). The PyPI Trusted Publisher needs no
84+
change, because it is bound to the `release-publish.yml` file name and the
85+
`release-publish` environment, not to a branch.
86+
87+
## Moving #1502 from `main` to `next` (one time)
88+
89+
#1502 added the experimental AdCP 3.3 identity code to `main`.
90+
The revert PR removes it from `main` before `9.0.0-beta.4` (#1465) ships;
91+
`next` already has the code. The trap: the next time `next` takes `main`, the
92+
revert would come along and delete the identity code from `next`.
93+
94+
Right after the revert merges to `main`, and before anyone else merges `main`
95+
into `next`, record the revert on `next` as merged without applying it:
96+
97+
```sh
98+
git fetch origin
99+
git switch next && git merge --ff-only origin/next
100+
REVERT=$(git log origin/main --format=%H -1 --grep='^revert: move experimental AdCP 3.3 identity')
101+
git merge --no-edit "$REVERT^" # main up to just before the revert
102+
git merge -s ours "$REVERT" -m "chore: record main's revert of #1502 as merged; next keeps the identity code"
103+
git merge --no-edit origin/main # the rest of main
104+
git push origin next
105+
```
106+
107+
The `-s ours` merge makes the revert an ancestor of `next` but keeps `next`'s
108+
tree, so later syncs never apply it. Keep these merge commits: push directly
109+
or merge with **Create a merge commit**.
110+
111+
Equivalent alternative: merge `origin/main` into `next` as usual, then
112+
`git revert <REVERT>` on `next` (a revert of the revert). It gives the same
113+
result but reports modify/delete conflicts wherever `next` has changed #1502's
114+
files since, so prefer the `-s ours` sequence.
115+
116+
Use the same procedure for any later change that has to leave `main` but stay
117+
on `next`.
118+
119+
## Ratification
120+
121+
When the draft spec that `next` tracks is ratified:
122+
123+
1. Merge `main` into `next` one last time and make sure `next`'s CI passes.
124+
2. Update `next` to the ratified spec (`src/adcp/ADCP_VERSION`, schemas,
125+
generated types, and the identity code's experimental markers).
126+
3. On `next`, delete `.github/workflows/release-please-next.yml`,
127+
`release-please-config.next.json`, `.release-please-manifest.next.json`,
128+
and `CHANGELOG.next.md`. Set `pyproject.toml`'s version back to `main`'s.
129+
4. Pick `main`'s first version of the new major. Commit it on `next` as a
130+
conventional commit that ends with a `Release-As:` footer, for example
131+
`Release-As: 10.0.0` or `Release-As: 10.0.0-beta.0`, and update
132+
`release-please-config.json`'s channel to match (see `docs/releasing.md`).
133+
This must be the newest `Release-As:` commit. Release-please uses the
134+
newest footer it finds, so it overrides `next`'s earlier
135+
`Release-As: 10.0.0-alpha.0`.
136+
5. If the 9.x line still needs fixes, create `release/9.x` from `main`, with
137+
its own release-please workflow like `release/8.x`'s.
138+
6. Open a PR from `next` into `main` and merge it with **Create a merge
139+
commit**, so `next`'s history (and the `-s ours` merges above) stays intact.
140+
7. Reset `next` to `main` (or delete it and recreate it when the next draft
141+
spec starts).

0 commit comments

Comments
 (0)