[Fix] First release publish fails when no previous GitHub release exists - #152
Conversation
…ists The deployment acceptance gate resolved its upgrade baseline from releases/latest with `|| true`, so a 404 (no release yet) leaked the JSON error body into the docker image tag. The main-channel fallback pulled the pre-release main image, whose controller crashes under the current compose. Resolve the baseline safely, skip upgrade validation when there is no usable previous release (fresh-install validation still runs), and never let a non-channel/non-v* string reach docker pull. Ships as v0.0.3 via changeset so the first fully published release goes out on the fixed gate.
|
Re-review complete. The latest change resolves the earlier observation; no new code issues. See task The new commit adds a strict "candidate must be newer than the resolved baseline" guard (
Review summaryThe only change since the last review is commit
Minor note (informational, not blocking): the downgrade guard only engages when |
…han the latest release Manual dispatch can re-publish an older version while a newer release is latest; validating baseline->candidate would then exercise a downgrade dressed up as an upgrade. Keep the upgrade leg only when the candidate is strictly newer than the resolved baseline (sort -V), and fall back to fresh-install validation otherwise.
What changed
Both publish runs for the v0.0.2 promote failed in the "Deployment acceptance" gate because this was the first release, so no previous release exists to validate upgrades against:
gh api repos/…/releases/latestoutput with|| true. With no GitHub Release yet, gh 404s but prints the JSON error body to stdout, so{"message":"Not Found",…}became the docker image tag →invalid reference format.main-channel image as the upgrade baseline. That image predates the release pipeline; its controller crashes on boot (requiresS3_*env the current compose no longer passes), so the baseline stack could never start.The
baselinestep inpublish-ghcr.ymlnow:releases/latestinside anif !guard, so a failed lookup yields an empty baseline instead of leaking the error body.v0.0.1) as skip upgrade validation —deploy/ci/deployment-smoke.shalready handles an emptyBASELINE_VERSIONby validating a fresh install of the candidate instead (stack boot, health checks, Docker task launch, backup/restore all still run).main-channel and manual-dispatch runs instead of the ancientmainalias, and adds a final allowlist (''/develop/v[0-9]*) so nothing malformed can ever reachdocker pull. Thedevelopchannel baseline is unchanged.v*version is strictly newer than the resolved baseline (sort -V): a manual dispatch that re-publishes an older or identical version no longer exercises a downgrade dressed up as an upgrade, and falls back to fresh-install validation instead.main-<sha>candidates are unaffected.A changeset (patch) is included so this ships as v0.0.3, which will be the first fully published release (images + GitHub Release). v0.0.2 remains tag-only: tag re-runs execute the workflow frozen at the tag, so it cannot be rescued by re-running.
Why this change was made
The upgrade-validation gate assumed a previous published release always exists. On the very first gated release that assumption produced two different hard failures, blocking the v0.0.2 image publish and GitHub Release entirely.
Impact
main-channel publish runs validate against the previous release instead of a known-broken pre-release image.develop→develop;latest/mainon this repo (no releases) → empty (skip);lateston a repo with releases → cleanv*tag; candidate-vs-baseline ordering (v0.0.4>v0.0.3keeps validation,v0.0.2<v0.0.5and equal versions skip,v0.0.10>v0.0.9sorts correctly). YAML parse,bash -n, and prettier all pass.