Files
uptop/.github/workflows/mirror-release.yml
T
lerko 96eb3e8185
CI / test (pull_request) Successful in 1m52s
CI / lint (pull_request) Successful in 1m16s
CI / vulncheck (pull_request) Successful in 50s
fix(release): scan gates docker push, rc tags spare :latest, mirror waits for stable assets
rc.2 proved the grype gate was decorative — buildx pushed before the
scan ran, so a red run still shipped the image (and rc tags moved
:latest). Build amd64 locally, scan that, then run the multi-arch push
from the warm builder cache. :latest now only moves on non-rc tags.

mirror-release: poll until the Gitea asset count is stable across two
polls (GoReleaser uploads sequentially — assets>0 could mirror a partial
set) and stretch the timeout to 20 min since the release run can queue
behind the Docker job on the single runner.
2026-06-12 17:20:48 -04:00

82 lines
2.9 KiB
YAML

name: Mirror Release to GitHub
on:
push:
tags:
- "v[0-9]*"
permissions:
contents: write
jobs:
mirror:
runs-on: ubuntu-latest
steps:
- name: Wait for Gitea release
id: gitea
env:
TAG: ${{ github.ref_name }}
run: |
API="https://gitea.lerkolabs.com/api/v1/repos/lerkolabs/uptop/releases/tags/${TAG}"
# 40 x 30s = 20 min: the Gitea release can queue behind the ~18-min
# Docker job on the single runner. Asset count must hold steady for
# two consecutive polls — GoReleaser uploads one file at a time, and
# mirroring mid-upload would publish a partial asset set.
PREV_COUNT=0
ASSET_COUNT=0
for i in $(seq 1 40); do
if RESPONSE=$(curl -sf "$API" 2>/dev/null); then
ASSET_COUNT=$(echo "$RESPONSE" | jq '.assets | length')
if [ "$ASSET_COUNT" -gt 0 ] && [ "$ASSET_COUNT" -eq "$PREV_COUNT" ]; then
echo "Found release with $ASSET_COUNT assets (stable)"
break
fi
echo "Release has $ASSET_COUNT assets (was $PREV_COUNT)... attempt $i/40"
PREV_COUNT="$ASSET_COUNT"
else
echo "Waiting for Gitea release... attempt $i/40"
fi
sleep 30
done
if [ -z "$RESPONSE" ] || [ "$ASSET_COUNT" -eq 0 ]; then
echo "::error::Gitea release for ${TAG} not found or has no assets after 20 minutes"
exit 1
fi
# select() so an empty-string body produces an empty file — `// empty`
# treats "" as truthy and wrote a blank line, defeating this fallback.
echo "$RESPONSE" | jq -r '.body | select(. != null and . != "")' > /tmp/release-notes.md
if [ ! -s /tmp/release-notes.md ]; then
echo "Release ${TAG} from [Gitea](https://gitea.lerkolabs.com/lerkolabs/uptop/releases/tag/${TAG})" > /tmp/release-notes.md
fi
mkdir -p /tmp/assets
echo "$RESPONSE" | jq -r '.assets[] | .browser_download_url' | while read -r url; do
filename=$(basename "$url")
echo "Downloading $filename"
curl -sSL -o "/tmp/assets/${filename}" "$url"
done
- name: Delete existing GitHub release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ github.ref_name }}
run: gh release delete "$TAG" --repo "$GITHUB_REPOSITORY" --yes 2>/dev/null || true
- name: Create GitHub release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ github.ref_name }}
run: |
PRERELEASE=""
case "$TAG" in *-*) PRERELEASE="--prerelease" ;; esac
gh release create "$TAG" \
--repo "$GITHUB_REPOSITORY" \
--title "$TAG" \
--notes-file /tmp/release-notes.md \
$PRERELEASE \
/tmp/assets/*