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>