ci: update releases in place instead of delete-and-recreate

The same-day rerun path deleted and recreated the release tag within
seconds, which corrupted GitHub's release index (release 2026.07.05 was
hidden from the public list and floated to the top for maintainers).
Replace it with gh release create/edit: force-move the tag in place on
reruns so it matches the rebuilt Docker image, exclude today's tag when
collecting release notes so reruns cover the whole day, and pin the
created tag to the triggering commit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Alex Shnitman
2026-07-18 16:44:52 +03:00
parent c519f45908
commit 707f700609
+32 -46
View File
@@ -117,25 +117,27 @@ jobs:
- name: Get current date - name: Get current date
id: date id: date
run: echo "date=$(date +'%Y.%m.%d')" >> $GITHUB_OUTPUT run: echo "date=$(date +'%Y.%m.%d')" >> $GITHUB_OUTPUT
- name: Checkout - name: Checkout
uses: actions/checkout@v7 uses: actions/checkout@v7
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Get commits since last release - name: Get commits since last release
id: commits id: commits
env:
DATE: ${{ steps.date.outputs.date }}
run: | run: |
# Fetch all tags
git fetch --tags git fetch --tags
# Get the last tag (sorted by version, using date format YYYY.MM.DD) # Exclude today's tag: on a same-day rerun the notes must cover the
LAST_TAG=$(git tag -l --sort=-version:refname | grep -E '^[0-9]{4}\.[0-9]{2}\.[0-9]{2}$' | head -n 1) # whole day, not just the commits since the morning release.
LAST_TAG=$(git tag -l --sort=-version:refname | grep -E '^[0-9]{4}\.[0-9]{2}\.[0-9]{2}$' | grep -v "^${DATE}$" | head -n 1)
if [ -z "$LAST_TAG" ]; then if [ -z "$LAST_TAG" ]; then
# No previous release, skip commits for first release
COMMITS="" COMMITS=""
echo "has_commits=false" >> $GITHUB_OUTPUT echo "has_commits=false" >> $GITHUB_OUTPUT
else else
# Get commits since last tag
COMMITS=$(git log ${LAST_TAG}..HEAD --pretty=format:"- %s (%h)" --no-merges) COMMITS=$(git log ${LAST_TAG}..HEAD --pretty=format:"- %s (%h)" --no-merges)
if [ -z "$COMMITS" ]; then if [ -z "$COMMITS" ]; then
echo "has_commits=false" >> $GITHUB_OUTPUT echo "has_commits=false" >> $GITHUB_OUTPUT
@@ -143,18 +145,13 @@ jobs:
echo "has_commits=true" >> $GITHUB_OUTPUT echo "has_commits=true" >> $GITHUB_OUTPUT
fi fi
fi fi
# Escape for use in YAML/multiline output
{ {
echo 'commits<<EOF' echo 'commits<<EOF'
echo "$COMMITS" echo "$COMMITS"
echo EOF echo EOF
} >> $GITHUB_OUTPUT } >> $GITHUB_OUTPUT
# Also output for debugging
echo "Last tag: ${LAST_TAG:-none}"
echo "Commits since last release:"
echo "$COMMITS"
- name: Generate release body - name: Generate release body
id: release_body id: release_body
env: env:
@@ -176,7 +173,7 @@ jobs:
echo '**GitHub Container Registry:**' echo '**GitHub Container Registry:**'
echo "- \`${GHCR_REPO}:latest\`" echo "- \`${GHCR_REPO}:latest\`"
echo "- \`${GHCR_REPO}:${DATE}\`" echo "- \`${GHCR_REPO}:${DATE}\`"
if [ "$HAS_COMMITS" = "true" ] && [ -n "$COMMITS" ]; then if [ "$HAS_COMMITS" = "true" ] && [ -n "$COMMITS" ]; then
echo '' echo ''
echo '## Changes' echo '## Changes'
@@ -184,39 +181,28 @@ jobs:
echo "$COMMITS" echo "$COMMITS"
fi fi
} > release_body.txt } > release_body.txt
{ - name: Create or update GitHub Release (mark as latest)
echo 'body<<EOF'
cat release_body.txt
echo EOF
} >> $GITHUB_OUTPUT
- name: Delete existing release if present
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG_NAME: ${{ steps.date.outputs.date }} TAG_NAME: ${{ steps.date.outputs.date }}
run: | run: |
# Check if release exists and delete it if gh release view "$TAG_NAME" >/dev/null 2>&1; then
if gh release view "$TAG_NAME" &>/dev/null; then echo "Release $TAG_NAME exists; updating."
echo "Release $TAG_NAME already exists, deleting it..." # Force-move the tag in place so it matches the rebuilt Docker
gh release delete "$TAG_NAME" --yes || true # image. Never delete+recreate the tag: that corrupts GitHub's
# release index (broke release 2026.07.05).
gh api -X PATCH "repos/${GITHUB_REPOSITORY}/git/refs/tags/${TAG_NAME}" \
-f sha="$GITHUB_SHA" -F force=true
gh release edit "$TAG_NAME" \
--title "Release $TAG_NAME" \
--notes-file release_body.txt \
--latest
else
echo "Release $TAG_NAME does not exist; creating."
gh release create "$TAG_NAME" \
--target "$GITHUB_SHA" \
--title "Release $TAG_NAME" \
--notes-file release_body.txt \
--latest
fi fi
# Fetch tags to check remote
git fetch --tags
# Check if tag exists (locally or remotely) and delete it
if git rev-parse "$TAG_NAME" &>/dev/null 2>&1 || git ls-remote --tags origin "$TAG_NAME" | grep -q "$TAG_NAME"; then
echo "Tag $TAG_NAME already exists, deleting it..."
git tag -d "$TAG_NAME" 2>/dev/null || true
git push origin ":refs/tags/$TAG_NAME" || true
fi
- name: Create GitHub Release
uses: softprops/action-gh-release@v3
with:
tag_name: ${{ steps.date.outputs.date }}
name: Release ${{ steps.date.outputs.date }}
body_path: release_body.txt
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}