diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 9697a85..6b9fa78 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -7,7 +7,7 @@ on: workflow_dispatch: inputs: overview_version: - description: 'Version the overview should tell adopters to pull (e.g. 0.2.0)' + description: 'Version the overview should tell adopters to pull (e.g. 0.1.0)' required: true jobs: diff --git a/AGENTS.md b/AGENTS.md index de88490..7eeebec 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -293,7 +293,7 @@ Revisit only if the stated reason stops holding. docs and skip the gate over a source file that was gone. `src/ci-gate.test.ts` locks the flags as a *text* guard — the test image ships neither `git` nor `bash`. This is why the Docker Hub overview is `release-tooling/dockerhub-overview.md.tmpl` and not a `.md`: a release reads it and a unit test - guards it, so renaming it back would let a broken `{{VERSION}}` merge with its own guard skipped. + guards it, so giving it a `.md` name would let a broken `{{VERSION}}` merge with its own guard skipped. - **CI docker logins share the runner host's Docker config.** The act_runner is host-mode, so `docker login`/`logout` in the workflows mutate one shared `~/.docker/config.json`: concurrent jobs can race (one job's logout can 401 another's push — recover by re-running), and tokens sit in that @@ -353,9 +353,9 @@ one-time setup. A file-map or table row gets a clause, not a paragraph. trailer, so a dependency added anywhere else never escalates the release version and nothing fails to say so. A new manifest, compose file, custom manager or dep type is a decision: can it reach a running Plainpages? If yes it needs a rule; if no, record nothing and let it ride the next patch. -- **`HOST_API_VERSION` *is* the release version — one number, not two.** Its `major.minor` must equal - the release tag's, and both release paths refuse a tag that disagrees - (`release-tooling/contract-version.ts`). The patch digit may lag on purpose: `checkApiVersion` +- **`HOST_API_VERSION` *is* the release version.** Its `major.minor` must equal the release tag's, and + both release paths refuse a tag that disagrees (`release-tooling/contract-version.ts`). The patch + digit may lag on purpose: `checkApiVersion` ignores patch, and auto-release cuts patch releases with no commit to bump a constant in. So a dependency update big enough to force a **minor** is plugin-visible by definition — `auto-release` stops rather than tagging, and the fix is to bump `HOST_API_VERSION` to that `X.Y.0` in a PR, merge diff --git a/README.md b/README.md index ebe5110..a62ea15 100644 --- a/README.md +++ b/README.md @@ -594,9 +594,9 @@ works without editing host config. ### Contract versioning Each manifest declares `apiVersion` — a **semver** string naming the **Plainpages release** it was -built against. There is no second number to track: the host's `HOST_API_VERSION` *is* its release -version, so a plugin author reads one version off the image they run and writes it down. Both release -paths refuse a tag whose `major.minor` disagrees with the constant, so the two cannot drift. +built against. The host's `HOST_API_VERSION` *is* its release version, so a plugin author reads one +version off the image they run and writes it down — there is no separate contract number. Both +release paths refuse a tag whose `major.minor` disagrees with the constant, so the two cannot drift. Patch releases are invisible here — `checkApiVersion` ignores the patch digit, which is what lets dependency updates ship continuously without touching any plugin. At discovery the host parses both @@ -612,10 +612,10 @@ provider/consumer semantics in `checkApiVersion`: | missing / not a valid semver | `refuse` | **abort boot** — must be declared | The plugin pins one exact version (no ranges, per the project's pinning rules); the *host* supplies -the caret-style compatibility. Note what a **minor** means now that one digit carries the whole -release: either the plugin contract changed, or a dependency moved far enough to warrant one. A -`warn` therefore says "built against an older release", not "new plugin features exist" — check the -Upgrading section for that release before assuming there is anything to adopt. While Plainpages is `0.x` every release shares major `0`, so a plugin +the caret-style compatibility. One digit carries the whole release, so a **minor** means either the +plugin contract changed or a dependency moved far enough to warrant one. A `warn` therefore says +"built against an older release" rather than promising new plugin features; check that release's +notes before assuming there is anything to adopt. While Plainpages is `0.x` every release shares major `0`, so a plugin built against `0.1.0` still loads on a `0.9.0` host with a `warn`; reaching `1.0.0` refuses everything built against `0.x`, which is the point of that milestone. diff --git a/release-tooling/dockerhub-overview.test.ts b/release-tooling/dockerhub-overview.test.ts index 1b6c15b..56571cf 100644 --- a/release-tooling/dockerhub-overview.test.ts +++ b/release-tooling/dockerhub-overview.test.ts @@ -17,6 +17,6 @@ test("the real template renders clean and pins no literal image tag", () => { const rendered = renderOverview(readFileSync("release-tooling/dockerhub-overview.md.tmpl", "utf8"), "9.9.9"); assert.deepEqual(leftoverPlaceholders(rendered), []); assert.match(rendered, /larvit\/plainpages:9\.9\.9/); // the placeholder actually reaches the examples - // A hardcoded version here is what went stale on the live page; the release must own every one. + // The release owns every image tag on the page, so a literal one must not survive rendering. assert.doesNotMatch(rendered, /larvit\/plainpages:\d+\.\d+\.\d+(?