Skip to content
Closed
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
8 changes: 4 additions & 4 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
silently missing from CHANGELOG.md. The `PR title` check enforces this.
See RELEASING.md.

The version is pinned to the alpha stream. While it is, a breaking marker
is refused. That means a `!` in the subject, or a `BREAKING CHANGE:`
footer. Such a marker moves the base version instead of the alpha
counter. Describe the break here instead. -->
A breaking marker — a `!` in the subject, or a `BREAKING CHANGE:` footer —
moves the base version, so the alpha stream goes from 0.0.1-alpha.N to
0.1.0-alpha.N. Use one where a consumer has to change something, and say
what here. -->

## What this changes

Expand Down
71 changes: 6 additions & 65 deletions .github/workflows/pr-title.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,12 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
# Only the manifest, because only the manifest is read: the base-version
# guard below needs it, and a full checkout would fetch the tree to run a
# regex over one line of JSON.
- name: Fetch the version manifest
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
sparse-checkout: .release-please-manifest.json
sparse-checkout-cone-mode: false
persist-credentials: false

- name: Validate the subject that will land on main
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
NUMBER: ${{ github.event.pull_request.number }}
PR_TITLE: ${{ github.event.pull_request.title }}
PR_BODY: ${{ github.event.pull_request.body }}
COMMIT_COUNT: ${{ github.event.pull_request.commits }}
run: |
set -euo pipefail
Expand All @@ -86,66 +75,19 @@ jobs:
echo "ok: ${what} — ${subject}"
}

# Every subject GitHub could squash with, and every message a footer
# can hide in. A one-commit PR is squashed with that commit's own
# title, so both must reach both checks below — and the commit's whole
# message is kept, not just its first line, because a 'BREAKING
# CHANGE:' footer lives in the body.
#
# Checking only $PR_TITLE and $PR_BODY is how lpspec shipped
# 0.1.0-alpha.226 and .227 and had to withdraw them: the '!' was in
# the single commit's title, which the guard never read.
# Every subject GitHub could squash with. A one-commit PR is squashed
# with that commit's own title, so $PR_TITLE alone is not the subject
# that lands on main.
titles=("PR title|${PR_TITLE}")
messages=("the PR body|${PR_BODY:-}")
if [[ "$COMMIT_COUNT" == "1" ]]; then
only=$(gh api "repos/${REPO}/pulls/${NUMBER}/commits" --jq '.[0].commit.message')
titles+=("the single commit's title|$(head -1 <<<"$only")")
messages+=("the single commit's message|${only}")
fi

for entry in "${titles[@]}"; do
check "${entry%%|*}" "${entry#*|}"
done

# A breaking marker moves the *base* version, not the alpha counter.
# While the base is 0.0.0 that is harmless — under `versioning:
# prerelease` a zero patch is an absorbing state, so every bump only
# increments the counter — but the immunity goes away the moment the
# stream leaves 0.0.0, and then `feat!:` on 0.0.1-alpha.12 yields
# 0.1.0-alpha.12 and the project has jumped a minor by accident. The
# marker is refused here rather than discovered in a release PR.
#
# Both ways this can go wrong are named, because either one leaves the
# guard below not running: a missing file aborts the step under `set
# -e` with only sed's own message, and a manifest whose shape changed
# yields an empty $base, which fails *open* — every '!' would sail
# through and the version would move off the stream unannounced.
manifest=.release-please-manifest.json
if [[ ! -f "$manifest" ]]; then
echo "::error::${manifest} not found — the base-version guard cannot run."
exit 1
fi
base=$(sed -n 's/.*"\.": *"\([^"]*\)".*/\1/p' "$manifest")
if [[ -z "$base" ]]; then
echo "::error::no \".\" version in ${manifest} — the base-version guard cannot run."
exit 1
fi

if [[ "$base" == 0.* ]]; then
for entry in "${titles[@]}"; do
if [[ "${entry#*|}" =~ ^[a-z]+(\([a-z0-9._/-]+\))?!: ]]; then
echo "::error::'!' in ${entry%%|*} bumps the base version off the pinned alpha stream (currently ${base})."
fail=1
fi
done
for entry in "${messages[@]}"; do
if grep -qE '^BREAKING[ -]CHANGE:' <<<"${entry#*|}"; then
echo "::error::a 'BREAKING CHANGE:' footer in ${entry%%|*} bumps the base version off the pinned alpha stream (currently ${base})."
fail=1
fi
done
fi

if (( fail )); then
cat <<'MSG'

Expand All @@ -156,10 +98,9 @@ jobs:
fix(parser): where clauses with a trailing comma
docs: describe the two expression tiers

A '!' (or a 'BREAKING CHANGE:' footer) is refused while the version is
pinned to an alpha stream: it moves the *base* version, not the counter.
Describe the break in the PR body instead — the alpha stream carries no
compatibility promise, so there is nothing for the version to announce.
A '!' (or a 'BREAKING CHANGE:' footer) moves the base version: the
stream goes from 0.0.1-alpha.N to 0.1.0-alpha.N. Use one where a
consumer has to change something, and say what in the PR body.

Fix the PR title — no need to rewrite the branch. Edits re-run this check.
MSG
Expand Down
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.0.0-alpha.96"
".": "0.0.1-alpha.96"
}
15 changes: 7 additions & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ answer here is the mistake.

## Renaming and deleting

The project is on the `0.0.0-alphaN` stream, and it holds no compatibility
The project is on the `0.0.1-alphaN` stream, and it holds no compatibility
promise.

So when you are asked to change something, change it. Rename it, move it, or
Expand All @@ -121,11 +121,10 @@ the valid keys, and that is the whole migration story.
**A test that asserts the old behaviour is not a blocker.** Say in the PR what
coverage moved where.

There is one place where this costs something. A breaking marker in the PR title
is **refused** by the `Conventional commit subject` check. A breaking marker is
a `!`, or a `BREAKING CHANGE:` footer. It is refused because it would move the
base version rather than the alpha counter. Describe the break in the PR body
instead.
This costs one thing. A breaking marker in the PR title moves the minor, so
the stream goes from `0.0.1-alphaN` to `0.1.0-alphaN`. A breaking marker is a
`!`, or a `BREAKING CHANGE:` footer. Use one where a consumer has to change
something, and say what broke in the PR body.

## Numbers and claims

Expand Down Expand Up @@ -375,8 +374,8 @@ Then write the subject:
- **Write a subject the changelog reader can name.** Not `a pass` or `a walk`,
and not `dim`, `coord` or `AST`.

Use lower case, no full stop, and conventional-commit form. The breaking marker
is refused. See [CONTRIBUTING.md](CONTRIBUTING.md#commit-messages). The 72
Use lower case, no full stop, and conventional-commit form. A breaking marker
bumps the minor. See [CONTRIBUTING.md](CONTRIBUTING.md#commit-messages). The 72
character warning in `pr-title.yml` is about `git log --oneline`. The changelog
does not truncate.

Expand Down
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ hidden. A subject the parser cannot read is not an error — the entry
simply never appears — so the `Conventional commit subject` check enforces the
format on every pull request.

While the version is pinned to the alpha stream, a breaking marker (`!`, or a
`BREAKING CHANGE:` footer) is refused, because it moves the base version rather
than the alpha counter. Describe the break in the PR body instead. See
A breaking marker (`!`, or a `BREAKING CHANGE:` footer) moves the base version,
so the alpha stream goes from `0.0.1-alpha.N` to `0.1.0-alpha.N`. Use one where
a consumer has to change something, and say what in the PR body. See
[RELEASING.md](https://github.com/energy-models/math-spec/blob/main/RELEASING.md).

Beyond the subject line, write whatever body the change deserves — a paragraph
Expand Down
34 changes: 17 additions & 17 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,15 @@ will be created.

## The alpha stream

The manifest is seeded at `0.0.0-alpha.0`, and the config is in sticky
`prerelease` mode. So every release is `0.0.0-alpha.N`, which is the
distribution version `0.0.0aN`.
The config is in sticky `prerelease` mode, so every release is
`0.0.1-alpha.N`, which is the distribution version `0.0.1aN`. The manifest
carries the base, and one thing moves it: a breaking change.

The seed is what pins the `0.0.0`. release-please increments the counter only
when the version it starts from already carries a prerelease. From a plain
`0.0.0` it would bump the patch first, and the stream would be
`0.0.1-alpha.N`.
The base was `0.0.0` while the stream was pinned there. Under
`versioning: prerelease` a bump lands on the counter whenever the digits below
it are already zero, so at `0.0.0` a minor bump was absorbed and a breaking
marker changed nothing at all. At `0.0.1` the patch is not zero, so the minor
bump bites and one `feat!:` gives `0.1.0-alpha.N`.

None of these versions carries a semantic promise. The point of them is that an
early user always has a number to quote in a bug report, instead of a commit
Expand All @@ -80,14 +81,14 @@ Two consequences worth knowing:
that is not a prerelease. So the first official version stops the automation,
and nobody has to remember to do it. To pause it earlier, set the repository
variable `AUTO_RELEASE` to `false`, and merge the release PRs by hand.
- **Breaking markers are refused.** A `!` in the subject, or a
`BREAKING CHANGE:` footer, moves the _base_ version rather than the counter.
Under `versioning: prerelease`, a zero patch is an absorbing state. So at
`0.0.0` a breaking marker is currently harmless. But that immunity disappears
the moment the stream moves, and then one `feat!:` turns `0.0.1-alpha.12`
into `0.1.0-alpha.12`. So `pr-title.yml` refuses the marker. Describe the
break in the PR body instead. The alpha stream carries no compatibility
promise, so there is nothing for the version to announce.
- **A breaking marker bumps the minor.** A `!` in the subject, or a
`BREAKING CHANGE:` footer, moves the base from `0.0.1` to `0.1.0`, and the
counter carries on rather than restarting. That is the one compatibility
signal the stream has: the minor says a consumer has to change something, and
the counter says nothing at all. `pr-title.yml` used to refuse the marker,
because the base was pinned to `0.0.0` and a marker would have moved it off
the stream unannounced. The base is no longer pinned, so the check no longer
looks.

## Leaving the alpha stream

Expand All @@ -98,8 +99,7 @@ When the project is ready for a real version:
2. Remove `versioning`, `prerelease` and `prerelease-type` from
`.release-please-config.json`.
3. Set the manifest to the last version you want release-please to bump _from_.
4. Drop the base-version guard from `pr-title.yml`, so `!` works again.
5. Merge the next release PR by hand.
4. Merge the next release PR by hand.

## One-time setup

Expand Down