ci(release): verify a tag release actually shipped its artifacts #123
@@ -98,6 +98,31 @@ jobs:
|
|||||||
echo "code=${COMMIT_COUNT}" >> "$GITHUB_OUTPUT"
|
echo "code=${COMMIT_COUNT}" >> "$GITHUB_OUTPUT"
|
||||||
echo "::notice::APK version: ${VERSION_NAME} (code=${COMMIT_COUNT})"
|
echo "::notice::APK version: ${VERSION_NAME} (code=${COMMIT_COUNT})"
|
||||||
|
|
||||||
|
# Checked BEFORE the expensive work, not after it. "Attach APK to gitea
|
||||||
|
# Release" below resolves the release by tag and fails if it is absent —
|
||||||
|
# but that is the final step, so a tag pushed without a release built an
|
||||||
|
# APK for several minutes first and only then discovered it had nowhere to
|
||||||
|
# put it. Same check, seconds in instead of minutes.
|
||||||
|
#
|
||||||
|
# Releases are normally created through the API (which creates the tag and
|
||||||
|
# the release together, so this passes). A bare `git push origin vX` is the
|
||||||
|
# case this catches.
|
||||||
|
- name: Release must exist for this tag
|
||||||
|
shell: bash
|
||||||
|
working-directory: ${{ github.workspace }}
|
||||||
|
env:
|
||||||
|
CI_TOKEN: ${{ secrets.CI_TOKEN }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
TAG="${GITHUB_REF#refs/tags/}"
|
||||||
|
if ! curl -fsSL -o /dev/null \
|
||||||
|
-H "Authorization: token ${CI_TOKEN}" \
|
||||||
|
"https://git.fabledsword.com/api/v1/repos/${GITHUB_REPOSITORY}/releases/tags/${TAG}"; then
|
||||||
|
echo "::error::no release exists for ${TAG}. Create the release (which creates the tag) rather than pushing a bare tag — otherwise there is nothing to attach the APK to."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "::notice::release found for ${TAG}"
|
||||||
|
|
||||||
- name: Cache Gradle dirs
|
- name: Cache Gradle dirs
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
@@ -376,4 +401,25 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "::notice::${TAG} verified — APK attached: ${APK}"
|
echo "::notice::APK attached: ${APK}"
|
||||||
|
|
||||||
|
# The other half. Checking only the APK would report success on a release
|
||||||
|
# whose image push failed — which is precisely the second thing that was
|
||||||
|
# missing when v2026.08.07 had to be re-cut. `always()` on this job means
|
||||||
|
# it runs even when image-release failed, so without this the guard would
|
||||||
|
# cheerfully verify an incomplete release.
|
||||||
|
- name: Immutable image tag must exist
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
TAG="${GITHUB_REF#refs/tags/}"
|
||||||
|
IMAGE="git.fabledsword.com/bvandeusen/minstrel"
|
||||||
|
|
||||||
|
echo "${{ secrets.CI_TOKEN }}" \
|
||||||
|
| docker login git.fabledsword.com -u "${{ github.actor }}" --password-stdin
|
||||||
|
|
||||||
|
if ! docker manifest inspect "${IMAGE}:${TAG}" > /dev/null 2>&1; then
|
||||||
|
echo "::error::image ${IMAGE}:${TAG} was never pushed — the release tag has no immutable image, so there is nothing to pin or roll back to. Re-run this workflow run."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "::notice::image verified: ${IMAGE}:${TAG}"
|
||||||
|
|||||||
Reference in New Issue
Block a user