fix: improve partial publishing recovery for CocoaPods and GitHub targets#821
Merged
Conversation
…gets - CocoaPods: Add selective retry for `pod trunk push` with exponential backoff. Retries on transient errors (CDN timeouts, 5xx, network errors) but fails fast on permanent errors (spec validation, auth). - GitHub: Detect existing releases on re-run. If a previous run published the release but crashed before persisting state, skip creation instead of failing with 422. - GitHub: Re-fetch release state before rollback deletion. Prevents deleting a live release when `publishRelease()` half-succeeded (server processed it but response timed out). Also handles immutable releases gracefully. - GitHub: Make floating tag failures non-fatal after successful publish. Prevents marking the target as failed when the release is already live, which would cause duplicate-release errors on re-run.
Aligns with the Crates target naming convention (MAX_ATTEMPTS) and clarifies that the value represents total attempts including the initial one, not just retries after the first failure.
Replace broad patterns like '502', '503', and 'http error' with more specific ones like '502 bad gateway', '503 service unavailable', and 'server error (5' to avoid misclassifying permanent errors that happen to contain those substrings.
When a pod trunk push attempt succeeds on the server but the response times out, the retry fails with "has already been pushed". Treat this as success (same pattern as the Crates target with "is already uploaded") instead of failing the publish.
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit f3fc912. Configure here.
- CRITICAL: getReleaseByTag returns 404 for draft releases. Replaced upfront draft detection with 422-recovery pattern: catch the 422 from createDraftRelease, find the conflicting draft via listReleases, delete it, and retry. Published release detection via getReleaseByTag still works correctly (main recovery scenario). - MEDIUM: Removed overly broad 'timeout' and 'cdn:' transient error patterns. Added 'trunk.cocoapods.org' alongside 'cdn.cocoapods.org' for specificity. - MEDIUM: Added TOCTOU race condition comment in rollback section. - MEDIUM: Improved 'already published' comment to document that it also handles the re-run-of-entire-pipeline case. - Fixed test mock isolation: use resetAllMocks instead of clearAllMocks, use mockRejectedValueOnce consistently to prevent state leaks between tests.
Addresses BugBot feedback about pagination. A leftover draft from a crashed run will be among the most recent releases, so the first page is sufficient. Increased from 30 to 100 for extra safety margin.
If deleteRelease fails for all leftover drafts (e.g., immutable releases), re-throw the original 422 instead of retrying createDraftRelease which would just produce another 422.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Fixes partial publishing recovery issues where Craft loses publishing progress and fails unrecoverably on re-run. Triggered by this CI failure.
Changes
CocoaPods: selective retry for
pod trunk pushpod trunk pushinwithRetry()with 5 retries and exponential backoff (5s initial, 2x factor)GitHub: detect existing releases on re-run
createDraftRelease(), checks if a release for the tag already exists via newgetReleaseByTag()methodGitHub: safe rollback with re-fetch
getRelease()method to check its actual statepublishRelease()half-succeeded (server processed it but response timed out), the release is now published — skips deletion to avoid destroying a live releaseGitHub: non-fatal floating tag updates
updateFloatingTags()in try/catch after successfulpublishRelease()Tests
getRelease/getReleaseByTagedge cases)