mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
* feat(release): add one-dispatch stable rollback A stable release publishes its artifacts to an immutable stable/versions/<version> prefix and then copies the pointer objects into stable/latest. latest is therefore derived state, and retracting a release is copying an older version prefix over it again — but until now nothing in the repo could do that, so a bad stable release had no stop button. Add `tools-release rollback-latest` plus a release-rollback workflow that dispatches it. The CLI refuses unless the live pointer still serves the version the operator typed as from_version, the target published completely (not partial, not a dry run), every ready platform's manifest and updater feed exist in the target prefix, and the current installer floor is satisfiable by the target. It re-resolves control.launcher.version from live channel policy rather than restoring the snapshot's, records rollback provenance, writes metadata.json last so latest never advertises a version whose feeds it does not yet serve, and verifies every object through both the origin and the public URL. The workflow shares release-stable's publish concurrency group so a rollback cannot overlap a publish, moves only the GitHub Release "Latest" badge (never a release body), and ends with a checklist of what a rollback does not reach: the download page's version-pinned links, the What's New card, the group announcement, and above all the installs already on the retracted version — the updater never offers a version that is not strictly newer than the running one, so this stops a rollout and cannot recall one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(release): group the rollback summary fallback redirects shellcheck SC2129 — CI runs actionlint with shellcheck wired in, which my local actionlint could not see without it installed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(release): prove the restored tag has a release before writing The badge move runs after the R2 write, so a missing GitHub Release for the restored version would have failed the run with stable/latest already moved. Check it up front instead. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(release): pass the stable installer-floor policy into rollback resolveLauncherVersionFloor() reads process env, and repository variables are not process env. Without the handoff a rollback resolved no floor at all: it would strip an active control.launcher.version from the restored metadata and stop refusing targets below the current minimum — the safeguard the workflow documents as enforced. Latent today only because no stable floor is set. release-stable.yml passes the same pair to metadata publish and verify; mirror it, with a topology assertion so a later edit cannot drop it silently. Also stamp RELEASE_BRANCH/RELEASE_COMMIT so the rollback provenance is not blank. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(release): require the restored release to be badge-eligible gh release view succeeds for a draft or a prerelease, but GitHub will not put the Latest badge on either — so the preflight passed and the edit failed with the R2 rollback already done, which is the half-complete state the preflight exists to prevent. Check isDraft and isPrerelease too, and cover the eligibility guard in the workflow test alongside its ordering. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Tools Release
tools-release owns release metadata, storage publishing, release reports, and
notification-facing data contracts. Packaged artifact build, cache, installer,
payload, and smoke work stays in tools-pack; release workflows compose the two
tools through CLI and file contracts.
Channel Architecture Snapshot
This matrix is a quick check before changing or validating the stable lane.
| Channel | Workflow / lane | Role | Build source | Publish gate | GitHub Release surface | R2 / storage surface | Linux policy | Dry-run focus |
|---|---|---|---|---|---|---|---|---|
beta |
release-beta / beta |
Daily R&D and fast validation | Build the current beta lane artifacts directly | No stable promotion gate | Beta artifacts according to beta policy | Beta channel metadata, feeds, platform manifests, payloads, and reports | Default-disabled in the current validation round | Fast build, cache, updater, and metadata validation |
prerelease |
release-prerelease / prerelease |
Stable delivery validation | Build prerelease artifacts directly | The only stable promotion gate | No final stable GitHub Release semantics | Prerelease metadata, feeds, platform manifests, payloads, and reports | Follows stable platform policy, including optional Linux enablement | Complete materials that a future stable release can promote |
stable |
release-stable / stable |
Formal public release | Promote from a validated vX.Y.Z prerelease, with prepublish validation when requested |
Must detect available prerelease artifacts for the exact vX.Y.Z target |
Installers/packages and matching SHA files only | All other platform artifacts, launcher payloads, manifests, metadata, feeds, and reports | Follows stable platform policy, including optional Linux enablement | metadata validates promotion inputs and plan; prepublish covers build, smoke, reports, and final publish plan without side effects |
Stable Quick Check
- Stable must verify an available, usable
vX.Y.Zprerelease artifact set before publication. - Non-stable channels publish counted versions with a
-<channel>.Nsuffix, for example-beta.Nand-prerelease.N; stable promotion checks must match the prerelease suffix while deriving the stablevX.Y.Ztarget. - Stable promotion depends on prerelease only.
--dry-run=metadatashould validate prerelease metadata, materials, and the stable publish plan without triggering build or smoke work.--dry-run=prepublishshould run all pre-publication build, smoke, payload or installer validation, report, artifact selection, and publish-plan work, while stopping before final external publishing side effects.- Stable GitHub Release assets should contain only user-facing installers or packages and matching SHA files.
- R2 remains the complete release/update storage surface for payloads, manifests, metadata, feeds, platform reports, and non-GitHub artifacts.
- The stable workflow should stay isomorphic with the other
release-*lanes. Stable-specific policy belongs behind scripts, CLI options, and file contracts, not as leaked tool internals in workflow YAML.