diff --git a/plan/publishing.md b/plan/publishing.md index 049750e..c1808f6 100644 --- a/plan/publishing.md +++ b/plan/publishing.md @@ -80,6 +80,19 @@ site. ## Done +- [x] `scripts/release.sh` refuses to cut 1.0.0 or later while `cliff.toml` + still carries the 0.x bumping rule. `breaking_always_bump_major = false` + is correct below 1.0 and argued where it is set — no compatibility + promise has been made, so a `!` moving the minor is the usual reading of + semver's 0.y.z clause, and 1.0.0 is meant to be a version somebody types + on purpose. What nothing enforced was the other half: on the day 1.0.0 + ships that flag has to become `true`, or the first breaking change after + it computes 1.1.0 and publishes silently, and `docs/output.md`'s promise + that renaming a `--json` field is a breaking `!` stops meaning anything + when a `!` and a plain `feat` produce the same number. A wrong version on + crates.io cannot be unpublished or reused, so it is checked rather than + remembered + - [x] `--version` says which build, not just which release — the commit on the version line, then target triple, profile and rustc under it. `-V` stays one bare line for scripts. `build.rs` records the four while they are diff --git a/scripts/release.sh b/scripts/release.sh index 232f79c..ed458f4 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -1,3 +1,41 @@ #!/bin/bash -cargo release "$(git cliff --unreleased --bumped-version | sed 's/^v//')" --execute +# Cut a release: work out the next version from the conventional commits since +# the last tag, let `cargo release` stamp and tag it, and push the tag. +# +# The guard below is the whole reason this is a script rather than one line. +set -euo pipefail + +next="$(git cliff --unreleased --bumped-version | sed 's/^v//')" + +# **`cliff.toml` bumps the minor for a breaking change, and that is only right +# below 1.0.** The reasoning is written out where the flag is set: under 0.x no +# compatibility promise has been made, so a `!` moving the minor is the usual +# reading of semver's "anything MAY change at any time" clause, and 1.0.0 is +# meant to be a version somebody types on purpose rather than one that falls +# out of a subject line. +# +# What nothing enforced is the other half: the day 1.0.0 ships, that flag has +# to become `true` or the *first* breaking change after it computes 1.1.0 and +# publishes silently. `docs/output.md` promises that renaming a `--json` field +# is a breaking `!`; with the flag still false a `!` and a plain `feat` produce +# the same number, and the promise is worth nothing. A wrong version on +# crates.io cannot be unpublished or reused, so this is checked here rather +# than remembered. +major="${next%%.*}" +breaking="$(sed -n 's/^breaking_always_bump_major *= *//p' cliff.toml)" +if [ "$major" != "0" ] && [ "$breaking" != "true" ]; then + cat >&2 <<'MSG' +error: this release is 1.0.0 or later and cliff.toml still has + breaking_always_bump_major = false, which is the 0.x rule. + + Left as it is, the next `feat!` bumps the minor instead of the major + and publishes a version that claims compatibility it does not have. + + Set it to true in cliff.toml, and update the comment above it to say + the 0.x reasoning no longer applies, before cutting this release. +MSG + exit 1 +fi + +cargo release "$next" --execute git push origin main --follow-tags