Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 71 additions & 6 deletions .github/workflows/release-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,77 @@ jobs:
--notes-file "${{ steps.changelog.outputs.notes_file }}"
# Moving pointer for a stable download URL:
# releases/download/macos-latest/BurnOSX-arm64.dmg
gh release delete macos-latest --repo "${GITHUB_REPOSITORY}" --yes --cleanup-tag || true
gh release create macos-latest "${DMG}" "${ZIP}" \
--repo "${GITHUB_REPOSITORY}" \
--target "${GITHUB_SHA}" \
--title "Burn for Mac (latest)" \
--notes "Latest macOS app build — points at ${TAG}."
# Preserve the live pointer until its replacement artifacts exist.
# Only a verified 404 permits creation; auth, rate-limit, and other
# probe failures stop the workflow instead of masquerading as absence.
RELEASE_PROBE="${RUNNER_TEMP}/macos-latest-release.txt"
RELEASE_PROBE_ERROR="${RUNNER_TEMP}/macos-latest-release-error.txt"
if gh api --include \
"repos/${GITHUB_REPOSITORY}/releases/tags/macos-latest" \
> "${RELEASE_PROBE}" 2> "${RELEASE_PROBE_ERROR}"; then
BACKUP_DIR="${RUNNER_TEMP}/macos-latest-backup"
BACKUP_DMG="${BACKUP_DIR}/$(basename "${DMG}")"
BACKUP_ZIP="${BACKUP_DIR}/$(basename "${ZIP}")"
mkdir -p "${BACKUP_DIR}"
gh release download macos-latest \
--repo "${GITHUB_REPOSITORY}" \
--dir "${BACKUP_DIR}" \
--pattern "$(basename "${DMG}")" \
--pattern "$(basename "${ZIP}")"
test -s "${BACKUP_DMG}"
test -s "${BACKUP_ZIP}"

upload_succeeded=false
for attempt in 1 2 3; do
if gh release upload macos-latest "${DMG}" "${ZIP}" \
--repo "${GITHUB_REPOSITORY}" \
--clobber; then
upload_succeeded=true
break
fi
echo "macos-latest replacement upload attempt ${attempt} failed"
done
if [ "${upload_succeeded}" != true ]; then
echo "replacement failed; restoring the previously downloaded assets" >&2
restore_succeeded=false
for attempt in 1 2 3; do
if gh release upload macos-latest "${BACKUP_DMG}" "${BACKUP_ZIP}" \
--repo "${GITHUB_REPOSITORY}" \
--clobber; then
restore_succeeded=true
break
fi
echo "macos-latest rollback attempt ${attempt} failed" >&2
done
if [ "${restore_succeeded}" != true ]; then
echo "macos-latest rollback failed; prior assets remain in ${BACKUP_DIR}" >&2
fi
exit 1
fi

gh release edit macos-latest \

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Roll back assets when pointer finalization fails

If gh release edit or the following ref PATCH fails—for example because of a transient API error or tag protection—the replacement upload has already clobbered both live assets, but the rollback block only handles upload failures. Because this workflow uses GitHub Actions' default bash shell, which runs with -e, the step exits here and leaves macos-latest serving the new artifacts with stale or partially updated tag/notes metadata rather than preserving a coherent previous pointer; guard and retry these finalization calls and restore the backups if they cannot complete. See the documented default shell invocation, bash --noprofile --norc -e -o pipefail {0}.

Useful? React with 👍 / 👎.

--repo "${GITHUB_REPOSITORY}" \
--target "${GITHUB_SHA}" \
--title "Burn for Mac (latest)" \
--notes "Latest macOS app build — points at ${TAG}."
# `release edit --target` updates release metadata but does not move
# an existing Git tag. Retarget the lightweight tag in place only
# after the replacement assets are live.
gh api --method PATCH \
"repos/${GITHUB_REPOSITORY}/git/refs/tags/macos-latest" \
-F "sha=${GITHUB_SHA}" \
-F force=true \
--silent
Comment on lines +165 to +177

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Finalization steps (metadata edit + tag retarget) have no retry or rollback, unlike the upload step right above them.

Under GitHub Actions' default bash invocation (-e is on by default for run: steps), a transient failure in gh release edit (Lines 165-169) or the tag PATCH (Lines 173-177) aborts the job immediately here — after the new assets have already been uploaded and the old backup already consumed. There is no retry and no path back to a consistent state: the release could end up with new assets but a metadata/tag still pointing at the old commit, with no automated remediation (unlike the upload path just above, which has 3 attempts and a backup-restore fallback).

💡 Suggested fix: wrap both calls in the same retry pattern used for uploads
-            gh release edit macos-latest \
-              --repo "${GITHUB_REPOSITORY}" \
-              --target "${GITHUB_SHA}" \
-              --title "Burn for Mac (latest)" \
-              --notes "Latest macOS app build — points at ${TAG}."
-            # `release edit --target` updates release metadata but does not move
-            # an existing Git tag. Retarget the lightweight tag in place only
-            # after the replacement assets are live.
-            gh api --method PATCH \
-              "repos/${GITHUB_REPOSITORY}/git/refs/tags/macos-latest" \
-              -F "sha=${GITHUB_SHA}" \
-              -F force=true \
-              --silent
+            finalize_succeeded=false
+            for attempt in 1 2 3; do
+              if gh release edit macos-latest \
+                --repo "${GITHUB_REPOSITORY}" \
+                --target "${GITHUB_SHA}" \
+                --title "Burn for Mac (latest)" \
+                --notes "Latest macOS app build — points at ${TAG}." \
+              && gh api --method PATCH \
+                "repos/${GITHUB_REPOSITORY}/git/refs/tags/macos-latest" \
+                -F "sha=${GITHUB_SHA}" \
+                -F force=true \
+                --silent; then
+                finalize_succeeded=true
+                break
+              fi
+              echo "macos-latest finalization attempt ${attempt} failed" >&2
+              sleep 15
+            done
+            if [ "${finalize_succeeded}" != true ]; then
+              echo "macos-latest metadata/tag update failed after retries; assets were replaced but the release may be inconsistent" >&2
+              exit 1
+            fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
gh release edit macos-latest \
--repo "${GITHUB_REPOSITORY}" \
--target "${GITHUB_SHA}" \
--title "Burn for Mac (latest)" \
--notes "Latest macOS app build — points at ${TAG}."
# `release edit --target` updates release metadata but does not move
# an existing Git tag. Retarget the lightweight tag in place only
# after the replacement assets are live.
gh api --method PATCH \
"repos/${GITHUB_REPOSITORY}/git/refs/tags/macos-latest" \
-F "sha=${GITHUB_SHA}" \
-F force=true \
--silent
finalize_succeeded=false
for attempt in 1 2 3; do
if gh release edit macos-latest \
--repo "${GITHUB_REPOSITORY}" \
--target "${GITHUB_SHA}" \
--title "Burn for Mac (latest)" \
--notes "Latest macOS app build — points at ${TAG}." \
&& gh api --method PATCH \
"repos/${GITHUB_REPOSITORY}/git/refs/tags/macos-latest" \
-F "sha=${GITHUB_SHA}" \
-F force=true \
--silent; then
finalize_succeeded=true
break
fi
echo "macos-latest finalization attempt ${attempt} failed" >&2
sleep 15
done
if [ "${finalize_succeeded}" != true ]; then
echo "macos-latest metadata/tag update failed after retries; assets were replaced but the release may be inconsistent" >&2
exit 1
fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release-macos.yml around lines 165 - 177, Wrap the
finalization commands—gh release edit and the git tag PATCH—in the same
three-attempt retry and failure-recovery pattern used by the upload step above.
Ensure transient failures are retried, and if all attempts fail, restore the
existing backup release/tag state before exiting so the release remains
consistent.

elif grep -Eq '^HTTP/[0-9.]+ 404 ' "${RELEASE_PROBE}"; then
gh release create macos-latest "${DMG}" "${ZIP}" \
--repo "${GITHUB_REPOSITORY}" \
--target "${GITHUB_SHA}" \
--title "Burn for Mac (latest)" \
--notes "Latest macOS app build — points at ${TAG}."
else
cat "${RELEASE_PROBE_ERROR}" >&2
exit 1
fi

- name: Upload build artifacts
if: always()
Expand Down
Loading