diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 577b5b45..8d1dc317 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -322,3 +322,58 @@ jobs: docker buildx build \ --build-arg MINSTREL_VERSION="${{ steps.tags.outputs.version }}" \ --push ${{ steps.tags.outputs.args }} . + + # Verifies a tag release actually ended up complete, and names the specific + # thing that's missing if not. + # + # Added 2026-08-07 after v2026.08.07 was re-cut. The android-release job never + # started — no log was written at all — so all eight of its steps reported + # `failure` with none executed and image-release showed `skipped`. The run was + # red, but the *release page rendered fine*, and `main`'s own push build had + # already moved `:latest`, so the code was deployable and nothing looked + # obviously wrong. The release was simply missing its APK and its immutable + # `:vYYYY.MM.DD` image, which is easy to skim past. + # + # This job cannot prevent that (the cause was a runner failing to launch, not + # anything in this file). What it does is turn an incomplete release into an + # explicit, named error instead of eight mystery step failures — so the + # consequence is legible without having to infer it. + # + # `if: always()` is the whole point: it has to report precisely when the jobs + # above did NOT succeed. + verify-release: + name: Verify release artifacts (tag releases only) + needs: [android-release, image-release] + if: ${{ always() && startsWith(github.ref, 'refs/tags/v') }} + runs-on: go-ci + container: + image: git.fabledsword.com/bvandeusen/ci-go:1.26 + + steps: + - name: Release must have an APK attached + shell: bash + env: + CI_TOKEN: ${{ secrets.CI_TOKEN }} + run: | + set -euo pipefail + TAG="${GITHUB_REF#refs/tags/}" + REPO="${GITHUB_REPOSITORY}" + + REL_JSON="$(curl -fsSL \ + -H "Authorization: token ${CI_TOKEN}" \ + "https://git.fabledsword.com/api/v1/repos/${REPO}/releases/tags/${TAG}" || true)" + if [ -z "${REL_JSON}" ]; then + echo "::error::no release found for ${TAG} — the tag exists but nothing was published" + exit 1 + fi + + APK="$(printf '%s' "${REL_JSON}" \ + | grep -oP '"browser_download_url":\s*"\K[^"]+' \ + | grep -E '\.apk$' | head -1 || true)" + if [ -z "${APK}" ]; then + echo "::error::release ${TAG} has NO APK attached — in-app update will offer nothing, and the bundled-APK path on future :latest builds has no source." + echo "::error::Fix by RE-RUNNING this workflow run. Do NOT delete and re-create the tag; if it fails again the runner never started the container, and the evidence is in act_runner on the host (Gitea will hold no job log)." + exit 1 + fi + + echo "::notice::${TAG} verified — APK attached: ${APK}"