mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-02-18 00:17:39 +01:00
fix: Make release workflow idempotent for re-runs
- Check if tag exists before creating (skip if pointing to HEAD, fail with helpful message if pointing elsewhere) - Check if draft release exists before creating (update existing draft) - Add --clobber to all asset uploads to allow re-uploading on retry
This commit is contained in:
100
.github/workflows/create-release.yml
vendored
100
.github/workflows/create-release.yml
vendored
@@ -370,11 +370,31 @@ jobs:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
TAG="${{ needs.extract_version.outputs.tag }}"
|
||||
echo "Creating tag ${TAG}..."
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git tag -a "${TAG}" -m "Release ${TAG}"
|
||||
git push origin "${TAG}"
|
||||
HEAD_SHA=$(git rev-parse HEAD)
|
||||
|
||||
# Check if tag already exists on remote
|
||||
REMOTE_TAG_SHA=$(git ls-remote --tags origin "refs/tags/${TAG}" | awk '{print $1}')
|
||||
|
||||
if [ -n "$REMOTE_TAG_SHA" ]; then
|
||||
# Tag exists - check if it points to current HEAD
|
||||
# For annotated tags, we need to dereference to get the commit
|
||||
REMOTE_COMMIT_SHA=$(git ls-remote --tags origin "refs/tags/${TAG}^{}" | awk '{print $1}')
|
||||
# If no dereferenced tag, it's a lightweight tag pointing directly to the commit
|
||||
[ -z "$REMOTE_COMMIT_SHA" ] && REMOTE_COMMIT_SHA="$REMOTE_TAG_SHA"
|
||||
|
||||
if [ "$REMOTE_COMMIT_SHA" = "$HEAD_SHA" ]; then
|
||||
echo "Tag ${TAG} already exists and points to HEAD - continuing"
|
||||
else
|
||||
echo "::error::Tag ${TAG} already exists but points to ${REMOTE_COMMIT_SHA}, not HEAD (${HEAD_SHA}). Delete the tag first: git push origin --delete ${TAG}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Creating tag ${TAG}..."
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git tag -a "${TAG}" -m "Release ${TAG}"
|
||||
git push origin "${TAG}"
|
||||
fi
|
||||
|
||||
- name: Create draft release
|
||||
id: create_release
|
||||
@@ -383,27 +403,45 @@ jobs:
|
||||
run: |
|
||||
TAG="${{ needs.extract_version.outputs.tag }}"
|
||||
NOTES_FILE="${{ steps.generate_notes.outputs.notes_file }}"
|
||||
|
||||
echo "Creating draft release for ${TAG}..."
|
||||
|
||||
# Tag must exist first - draft releases can't create tags (GitHub API limitation)
|
||||
# See: https://github.com/cli/cli/issues/11589
|
||||
# Create as draft first so we can upload assets before publishing
|
||||
IS_PRERELEASE="${{ needs.extract_version.outputs.is_prerelease }}"
|
||||
|
||||
RELEASE_JSON=$(gh api "repos/${{ github.repository }}/releases" \
|
||||
-X POST \
|
||||
-F tag_name="${TAG}" \
|
||||
-F name="Pulse ${TAG}" \
|
||||
-F body="$(cat $NOTES_FILE)" \
|
||||
-F draft=true \
|
||||
-F prerelease=${IS_PRERELEASE})
|
||||
|
||||
# Check if a release already exists for this tag
|
||||
EXISTING_RELEASE=$(gh api "repos/${{ github.repository }}/releases/tags/${TAG}" 2>/dev/null || echo "")
|
||||
|
||||
if [ -n "$EXISTING_RELEASE" ]; then
|
||||
RELEASE_ID=$(echo "$EXISTING_RELEASE" | jq -r '.id')
|
||||
RELEASE_URL=$(echo "$EXISTING_RELEASE" | jq -r '.html_url')
|
||||
IS_DRAFT=$(echo "$EXISTING_RELEASE" | jq -r '.draft')
|
||||
|
||||
if [ "$IS_DRAFT" = "true" ]; then
|
||||
echo "Draft release already exists for ${TAG} - updating it"
|
||||
# Update the existing draft with new notes
|
||||
gh api "repos/${{ github.repository }}/releases/${RELEASE_ID}" \
|
||||
-X PATCH \
|
||||
-F body="$(cat $NOTES_FILE)" \
|
||||
-F prerelease=${IS_PRERELEASE} > /dev/null
|
||||
else
|
||||
echo "::error::Published release already exists for ${TAG}. Cannot re-release the same version."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Creating draft release for ${TAG}..."
|
||||
# Tag must exist first - draft releases can't create tags (GitHub API limitation)
|
||||
# See: https://github.com/cli/cli/issues/11589
|
||||
RELEASE_JSON=$(gh api "repos/${{ github.repository }}/releases" \
|
||||
-X POST \
|
||||
-F tag_name="${TAG}" \
|
||||
-F name="Pulse ${TAG}" \
|
||||
-F body="$(cat $NOTES_FILE)" \
|
||||
-F draft=true \
|
||||
-F prerelease=${IS_PRERELEASE})
|
||||
|
||||
RELEASE_ID=$(echo "$RELEASE_JSON" | jq -r '.id')
|
||||
RELEASE_URL=$(echo "$RELEASE_JSON" | jq -r '.html_url')
|
||||
fi
|
||||
|
||||
rm -f "$NOTES_FILE"
|
||||
|
||||
RELEASE_ID=$(echo "$RELEASE_JSON" | jq -r '.id')
|
||||
RELEASE_URL=$(echo "$RELEASE_JSON" | jq -r '.html_url')
|
||||
|
||||
if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then
|
||||
echo "::error::Failed to extract release ID from API response"
|
||||
exit 1
|
||||
@@ -420,11 +458,11 @@ jobs:
|
||||
TAG="${{ needs.extract_version.outputs.tag }}"
|
||||
|
||||
echo "Uploading checksums.txt..."
|
||||
gh release upload "${TAG}" release/checksums.txt
|
||||
gh release upload "${TAG}" release/checksums.txt --clobber
|
||||
|
||||
# Upload individual .sha256 files for backward compatibility
|
||||
echo "Uploading .sha256 checksum files..."
|
||||
gh release upload "${TAG}" release/*.sha256
|
||||
gh release upload "${TAG}" release/*.sha256 --clobber
|
||||
|
||||
- name: Upload release assets
|
||||
env:
|
||||
@@ -435,24 +473,24 @@ jobs:
|
||||
echo "Uploading release assets..."
|
||||
|
||||
# Upload tarballs
|
||||
gh release upload "${TAG}" release/*.tar.gz
|
||||
gh release upload "${TAG}" release/*.tar.gz --clobber
|
||||
|
||||
# Upload Windows zip files
|
||||
gh release upload "${TAG}" release/*.zip
|
||||
gh release upload "${TAG}" release/*.zip --clobber
|
||||
|
||||
# Upload Helm chart if it exists
|
||||
if ls release/*.tgz 1> /dev/null 2>&1; then
|
||||
echo "Uploading Helm chart..."
|
||||
gh release upload "${TAG}" release/*.tgz
|
||||
gh release upload "${TAG}" release/*.tgz --clobber
|
||||
fi
|
||||
|
||||
# Upload install scripts as standalone assets
|
||||
# Users can now use: curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install.sh | bash
|
||||
# This ensures scripts are version-locked to the release, not pulled from main branch
|
||||
gh release upload "${TAG}" release/install.sh
|
||||
gh release upload "${TAG}" release/install-sensor-proxy.sh
|
||||
gh release upload "${TAG}" release/install-docker.sh
|
||||
gh release upload "${TAG}" release/pulse-auto-update.sh
|
||||
gh release upload "${TAG}" release/install.sh --clobber
|
||||
gh release upload "${TAG}" release/install-sensor-proxy.sh --clobber
|
||||
gh release upload "${TAG}" release/install-docker.sh --clobber
|
||||
gh release upload "${TAG}" release/pulse-auto-update.sh --clobber
|
||||
|
||||
- name: Publish release
|
||||
if: ${{ github.event.inputs.draft_only != 'true' }}
|
||||
|
||||
Reference in New Issue
Block a user