Refuse a 0.x minor mismatch, and republish the overview from the named release's tree
CI / full-gate (push) Successful in 2m50s
CI / full-gate (push) Successful in 2m50s
This commit is contained in:
@@ -5,7 +5,7 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
overview_version:
|
overview_version:
|
||||||
description: 'Version the overview should tell adopters to pull (e.g. 0.1.0)'
|
description: 'Released version to republish the overview for, without the leading v (e.g. 0.1.0)'
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -72,7 +72,11 @@ jobs:
|
|||||||
needs: [retag-image]
|
needs: [retag-image]
|
||||||
runs-on: docker-host
|
runs-on: docker-host
|
||||||
steps:
|
steps:
|
||||||
|
# Publish the named release's own tree, so the page never pairs one Plainpages tag with another
|
||||||
|
# release's sidecar pins. A version that was never released fails here.
|
||||||
- uses: actions/checkout@v7.0.1
|
- uses: actions/checkout@v7.0.1
|
||||||
|
with:
|
||||||
|
ref: ${{ inputs.overview_version && format('refs/tags/v{0}', inputs.overview_version) || github.ref }}
|
||||||
- name: Publish the Docker Hub overview
|
- name: Publish the Docker Hub overview
|
||||||
env:
|
env:
|
||||||
DOCKERHUB_OVERVIEW_TOKEN: ${{ secrets.DOCKERHUB_OVERVIEW_TOKEN }}
|
DOCKERHUB_OVERVIEW_TOKEN: ${{ secrets.DOCKERHUB_OVERVIEW_TOKEN }}
|
||||||
|
|||||||
@@ -607,17 +607,20 @@ provider/consumer semantics in `checkApiVersion`:
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| same major, same minor (patch ignored) | `ok` | load |
|
| same major, same minor (patch ignored) | `ok` | load |
|
||||||
| same major, plugin minor **<** host minor | `warn` | load, log — built against an older release; check that release's notes |
|
| same major, plugin minor **<** host minor | `warn` | load, log — built against an older release; check that release's notes |
|
||||||
|
| **major `0`**, any minor mismatch | `refuse` | **abort boot** — pre-1.0 the minor is the breaking slot |
|
||||||
| same major, plugin minor **>** host minor | `refuse` | **abort boot** — plugin needs a newer host |
|
| same major, plugin minor **>** host minor | `refuse` | **abort boot** — plugin needs a newer host |
|
||||||
| different major | `refuse` | **abort boot** — incompatible contract |
|
| different major | `refuse` | **abort boot** — incompatible contract |
|
||||||
| missing / not a valid semver | `refuse` | **abort boot** — must be declared |
|
| 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 plugin pins one exact version (no ranges, per the project's pinning rules); the *host* supplies
|
||||||
the caret-style compatibility. One digit carries the whole release, so a **minor** means either the
|
the compatibility. One digit carries the whole release, so a **minor** means either the plugin
|
||||||
plugin contract changed or a dependency moved far enough to warrant one. A `warn` therefore says
|
contract changed or a dependency moved far enough to warrant one.
|
||||||
"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
|
While Plainpages is `0.x` the major stays `0`, which leaves the minor as the only slot a breaking
|
||||||
built against `0.1.0` still loads on a `0.9.0` host with a `warn`; reaching `1.0.0` refuses everything
|
change can use — so a minor mismatch is refused rather than warned: a plugin declaring `0.1.0` will
|
||||||
built against `0.x`, which is the point of that milestone.
|
not boot on a `0.2.0` host until it is rebuilt against it. Once `1.0.0` lands the minor becomes
|
||||||
|
additive and the `warn` row applies, saying "built against an older release" rather than promising
|
||||||
|
new features.
|
||||||
|
|
||||||
### Conflict rules
|
### Conflict rules
|
||||||
|
|
||||||
|
|||||||
@@ -86,6 +86,9 @@ test("checkApiVersion: semver compat — equal/patch ok, older minor warns, newe
|
|||||||
assert.equal(checkApiVersion("1.3.0", "1.2.0").level, "refuse"); // needs features a newer host has
|
assert.equal(checkApiVersion("1.3.0", "1.2.0").level, "refuse"); // needs features a newer host has
|
||||||
assert.equal(checkApiVersion("2.0.0", "1.5.0").level, "refuse"); // incompatible major (newer)
|
assert.equal(checkApiVersion("2.0.0", "1.5.0").level, "refuse"); // incompatible major (newer)
|
||||||
assert.equal(checkApiVersion("1.0.0", "2.0.0").level, "refuse"); // incompatible major (older)
|
assert.equal(checkApiVersion("1.0.0", "2.0.0").level, "refuse"); // incompatible major (older)
|
||||||
|
assert.equal(checkApiVersion("0.1.0", "0.1.9").level, "ok"); // pre-1.0 patch is still ignored
|
||||||
|
assert.equal(checkApiVersion("0.1.0", "0.2.0").level, "refuse"); // pre-1.0 the minor IS the breaking slot
|
||||||
|
assert.equal(checkApiVersion("0.2.0", "0.1.0").level, "refuse");
|
||||||
for (const bad of ["1", "1.2", "v1.2.3", "01.2.3", "1.2.x", "", 1, undefined, null]) {
|
for (const bad of ["1", "1.2", "v1.2.3", "01.2.3", "1.2.x", "", 1, undefined, null]) {
|
||||||
assert.equal(checkApiVersion(bad).level, "refuse", `${String(bad)} must refuse`);
|
assert.equal(checkApiVersion(bad).level, "refuse", `${String(bad)} must refuse`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,6 +156,12 @@ export function checkApiVersion(pluginVersion: unknown, hostVersion: string = HO
|
|||||||
if (plugin.major !== host.major) {
|
if (plugin.major !== host.major) {
|
||||||
return { level: "refuse", message: `plugin targets apiVersion ${pluginVersion}; host is ${hostVersion} — incompatible major` };
|
return { level: "refuse", message: `plugin targets apiVersion ${pluginVersion}; host is ${hostVersion} — incompatible major` };
|
||||||
}
|
}
|
||||||
|
// Pre-1.0 the major is pinned at 0 until the 1.0.0 milestone, so a breaking change can only land
|
||||||
|
// as a minor (release-tooling/next-version.ts shifts every level down). Treating that as additive
|
||||||
|
// would let a stale plugin boot and fail at runtime instead of at discovery.
|
||||||
|
if (host.major === 0 && plugin.minor !== host.minor) {
|
||||||
|
return { level: "refuse", message: `plugin targets apiVersion ${pluginVersion}; host is ${hostVersion} — pre-1.0 a minor is a contract break, rebuild against ${hostVersion}` };
|
||||||
|
}
|
||||||
if (plugin.minor > host.minor) {
|
if (plugin.minor > host.minor) {
|
||||||
return { level: "refuse", message: `plugin targets apiVersion ${pluginVersion} but host is ${hostVersion}; upgrade the host` };
|
return { level: "refuse", message: `plugin targets apiVersion ${pluginVersion} but host is ${hostVersion}; upgrade the host` };
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user