diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 34ac2b6..2b90211 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -51,18 +51,22 @@ # # Prerequisites (Settings → Actions → Secrets on RunicGateway/servuo-plugins): # REGISTRY_TOKEN — Gitea access token with `write:repository`, to push the -# tag and create the release. +# tag and create the release. The final step also dispatches +# RunicGateway/installer's bundle workflow, so the token +# ideally has write there too — a nicety, not a requirement: +# without it the step warns and that repo's nightly cron +# picks the release up instead. # REGISTRY_USER — the Gitea username that token belongs to. # # These are checked by an explicit preflight step rather than left to fail # wherever they happen to be used first — see the comment on that step for why # an absent token does NOT simply fail the tag push. # -# TODO (Phase 0 item 3): once the installer repo's bundle workflow exists, append -# a final step here that POSTs to its workflow-dispatch endpoint, so a new -# overlay release recomposes the bundle immediately instead of waiting for the -# nightly cron (PLAN.md §7.2). Deliberately absent until there is something to -# dispatch — a step that 404s every release is worse than no step. +# The final step POSTs to the installer repo's bundle workflow, so a new overlay +# release recomposes the compat matrix immediately instead of waiting for that +# repo's nightly cron (PLAN.md §7.2). It was deliberately absent until Phase 0 +# item 3 landed something to dispatch — a step that 404s on every release is +# worse than no step. name: Release overlay @@ -84,6 +88,9 @@ env: # house style set by link (pre-1.0; the release version is independent of the # protocol version, which lives in overlay.toml). SEED_VERSION: "0.1.0" + # Notified after a release so the installer's compat matrix picks up this + # overlay immediately rather than at its next nightly run (PLAN.md §7.2). + INSTALLER_REPO: RunicGateway/installer jobs: release: @@ -425,3 +432,45 @@ jobs: -F "attachment=@dist/${f}" >/dev/null echo " uploaded ${f}" done + + # ── Recompose the installer's bundle manifest ──────────────────────── + # The installer does not resolve "latest" at run time — it deploys the + # exact overlay named by a published bundle (docs/installer/PLAN.md §7.1). + # An overlay release that nobody recomposes around is therefore a release + # no operator will ever be offered. This tells the installer repo to + # rebuild that manifest now rather than leaving the new version invisible + # until its nightly cron. + # + # That job re-reads this tarball's manifest.json and checks its declared + # `protocol` against the sidecar's PROTOCOL_VERSION before publishing + # anything (PLAN.md §7.1, gate 1) — which is the check this repo cannot + # perform for itself, since the C# plugin announces no version on the wire. + # + # DISPATCH, DON'T WAIT (PLAN.md §7.3). Gitea's workflow-dispatch endpoint + # returns no run handle, so there is nothing to poll: a waiting step would + # have to guess which run is its own and hold a runner idle to do it. + # + # A failure here is a WARNING, never a failure of this job. The release is + # already published and correct by this point, and failing the run would + # misreport that. The installer's nightly cron recomposes from whatever the + # latest releases actually are, so a dropped dispatch costs latency, not + # correctness. + - name: Ask the installer repo to recompose its bundle + if: ${{ steps.plan.outputs.release == 'true' }} + env: + REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} + run: | + set -euo pipefail + CI_TOKEN="$(printf '%s' "${REGISTRY_TOKEN}" | tr -d '\r\n')" + HTTP="$(curl -s -o /dev/null -w '%{http_code}' -X POST \ + -H "Authorization: token ${CI_TOKEN}" \ + -H "Content-Type: application/json" \ + -d '{"ref":"main"}' \ + "https://${GITEA_HOST}/api/v1/repos/${INSTALLER_REPO}/actions/workflows/bundle.yml/dispatches" || echo 000)" + case "$HTTP" in + 20*) echo "Dispatched ${INSTALLER_REPO} bundle.yml (HTTP ${HTTP}) — not waiting for it." ;; + 403|404) + echo "::warning::Could not dispatch ${INSTALLER_REPO} bundle.yml (HTTP ${HTTP}). REGISTRY_TOKEN likely lacks write:repository on that repo. Release ${{ steps.plan.outputs.tag }} is published and fine; its bundle will be composed by the installer's nightly cron instead." ;; + *) + echo "::warning::Dispatching ${INSTALLER_REPO} bundle.yml returned HTTP ${HTTP}. Release ${{ steps.plan.outputs.tag }} is published and fine; the nightly cron will recompose the bundle." ;; + esac