diff --git a/CHANGELOG.md b/CHANGELOG.md index e66176c..642a2d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,28 @@ which records not just what changed but what each drill run proved. ### Added +- **The installer defaults to the latest release, and releases publish + themselves** (#83) — `curl | bash` used to hand out whatever `main` was at + that second: the 0.6.0 release was a bookmark, not a package, and two + operators "on 0.6.0" could be running different trees. `install.sh` now + resolves the latest release tag by following GitHub's `releases/latest` + redirect (one HEAD request — no API, no token, no rate-limit pain) and + downloads that tag's tarball; a failed resolution refuses loudly, naming + `BOX_REF` as the way out — it never hangs and never silently falls back to + `main`. A set `BOX_REF` is tried as a tag first, then as a branch, so one + knob yields three channels: default = latest release, `BOX_REF=0.6.0` = + pinned, `BOX_REF=main` = dev. A new `release.yml` (on a bare `X.Y.Z` tag + push — the `0.6.0` tag set the no-`v` precedent) asserts the tag names the + tree's own `VERSION` (a mismatch fails loudly and creates nothing) and + publishes the GitHub release with that version's `CHANGELOG.md` section as + the body (`.github/scripts/release-notes.sh` — the curated prose, not the + generated PR list; no assets, the source tarball for the tag IS the + package). And `main`'s `VERSION` now carries `-dev` between releases + (this PR: `0.6.1-dev`): the versioned layout names install trees after + `VERSION`, so a `main` install without the bump would land in + `versions/0.6.0` and impersonate the released tree. `test/release.sh` + drives all of it offline — the extraction against fixtures and the real + changelog, the resolution and every channel against a shim curl. - **`setup-host` auto-picks a free subnet — nested box-in-box with zero flags** (#80, completing its fix #1: "refuse … or automatically select a non-colliding subnet"). A bare `box setup-host` now decides the subnet diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2013c37..aff4a2e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -41,6 +41,29 @@ labels tell you where everything is without opening anything. 7. **Checks must be green**: `shellcheck` and `bash test/cli.sh` locally mirror what CI runs; the multi-user rehearsal runs in CI on a real Incus. +## Releases + +A release is a PR, then a tag ([#83](https://github.com/heavy-duty/box/issues/83)): + +1. **The release PR** — `release: X.Y.Z`, labeled `release` — bumps `VERSION` + from `X.Y.Z-dev` and stamps the `## Unreleased` section with version + + date (feature PRs land their changelog entry as part of the PR, so the + section is already written). This PR is where the release ritual hangs: + the full drill on real hardware, recorded in + [drill/RUNS.md](drill/RUNS.md) — CI proves the tier's semantics on every + PR, a release still proves the boundary. +2. **Merge, then tag the merge commit** bare `X.Y.Z` — no `v` prefix, the + `0.6.0` tag set the precedent — and push the tag. + [release.yml](.github/workflows/release.yml) takes it from there: it + asserts the tag names the tree's own `VERSION` (a mismatch fails loudly + and creates nothing) and publishes the GitHub release with that version's + `CHANGELOG.md` section as the body. No assets — the source tarball for + the tag is the package, and `install.sh` downloads exactly that. +3. **Immediately after: bump `main`'s `VERSION` to `X.Y.(Z+1)-dev`.** Not + cosmetic — the versioned layout names install trees after `VERSION`, so a + `main` install without the bump would land in `versions/X.Y.Z` and + impersonate the release you just cut. + ## Labels — who sets what The full taxonomy lives in [LABELS.md](LABELS.md). What matters day to day is diff --git a/README.md b/README.md index f0d82f3..3e09390 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,22 @@ design rationale. curl -fsSL https://raw.githubusercontent.com/heavy-duty/box/main/install.sh | bash ``` +By default that installs the **latest release** — the installer resolves the +release tag off GitHub's `releases/latest` redirect (no API, no token) and +downloads exactly that tree, so two operators running it get the same box. +If the resolution fails it says so and stops — it never silently hands out +`main`. `BOX_REF` picks another channel (a set ref is tried as a tag first, +then as a branch — [#83](https://github.com/heavy-duty/box/issues/83)): + +```sh +curl -fsSL .../install.sh | bash # the latest release (default) +curl -fsSL .../install.sh | BOX_REF=0.6.0 bash # pin a release +curl -fsSL .../install.sh | BOX_REF=main bash # the development tip +``` + +(A dev tree's `VERSION` carries a `-dev` suffix, so it lands beside your +releases under `versions/`, never on top of one.) + It asks first — **"Install box?"** — then downloads the tree into a **versioned** install (the way plenty of CLIs manage theirs), links `box` onto your `PATH`, and on a fresh host asks a second question: **"Set up this