Skip to content

ci(pods): recover the missing ConvertSwiftSDK 2.0.0 pod — no version bump - #50

Merged
abbaseya merged 1 commit into
mainfrom
fix/pod-publish-recovery
Jul 24, 2026
Merged

ci(pods): recover the missing ConvertSwiftSDK 2.0.0 pod — no version bump#50
abbaseya merged 1 commit into
mainfrom
fix/pod-publish-recovery

Conversation

@abbaseya

Copy link
Copy Markdown
Collaborator

The problem

v2.0.0 is published on every channel except one:

Channel v2.0.0 Evidence
SPM (primary) tag v2.0.0b8b89b7
GitHub Release created 18:06:48, Latest
CocoaPods ConvertSwiftSDKCore Trunk: 1.0.0, 1.0.1, 2.0.0
CocoaPods ConvertSwiftSDK Trunk: 1.0.0, 1.0.1

Run 30115531359 failed at the last step only:

[!] Calling the GitHub commit API timed out. Please check GitHub's status and try again later.
##[error]Process completed with exit code 1.

Transient — not the token, not a version mismatch, not push ordering. Core had already published; the umbrella died in CocoaPods' podspec validation.

Why it can't be repaired with what's in the repo today

  1. release.yml pushes core then the umbrella in one step under -e. Core 2.0.0 is now on Trunk, and Trunk rejects a duplicate name+version — so re-running the job aborts on the first push and never reaches the umbrella.
  2. A push: tags: workflow runs the workflow file as it exists at the tag's commit. Fixing release.yml on main does nothing for a re-run of v2.0.0.

Manual pod trunk push isn't a clean path either: pod-name ownership sits with the account that first pushed, and repository secrets can't be read back out.

The fix — publish at 2.0.0, change no versions

A workflow_dispatch-only Publish Pod workflow that publishes one podspec from an existing tag:

  • Checks out the tag, so the uploaded spec is byte-for-byte the one the release blessed — not whatever main holds later.
  • Asserts the podspec's s.version equals the tag, reusing release.yml's exact grep/sed.
  • Skips any version already on Trunk → idempotent, and immune to the duplicate-rejection trap that breaks the release-job re-run.
  • Pushes with release.yml's exact flags — --synchronous for the umbrella only, since it alone declares s.dependency 'ConvertSwiftSDKCore', s.version.to_s.
  • Confirms the version is live on Trunk (6 × 30s poll) so green means resolvable, not merely "exit 0".

No re-tagging. No version bump. No second GitHub Release. The podspecs are untouched — this PR contains zero changes to either .podspec.

Deliberately constrained

permissions: contents: read. It cannot create a Release, push a tag, or write to the repo, so it can never become a second release path. release.yml keeps its tag-only trigger and no workflow_dispatch — RELEASE.md safeguard #1 is about never releasing on a branch merge, which this doesn't do.

Verification

YAML parses; both shell paths exercised under bash (what Actions uses) against live Trunk data:

ConvertSwiftSDK      versions on Trunk: 1.0.0 1.0.1        -> ALREADY_PUBLISHED=false => PUSHES
ConvertSwiftSDKCore  versions on Trunk: 1.0.0 1.0.1 2.0.0  -> ALREADY_PUBLISHED=true  => SKIPS

Version assert against the tagged tree: both podspecs s.version=2.0.0 == tag 2.0.0

After merge

Actions → Publish Pod → Run workflow with tag: v2.0.0, podspec: ConvertSwiftSDK. (workflow_dispatch only becomes available once the file is on the default branch.)

…ecovery

v2.0.0 published to SPM and GitHub Releases, and ConvertSwiftSDKCore 2.0.0
reached CocoaPods Trunk, but the umbrella ConvertSwiftSDK push failed validation
with a transient `[!] Calling the GitHub commit API timed out.` (run
30115531359). That leaves the release half-published on CocoaPods with no way to
repair it in place:

  - release.yml pushes core then the umbrella in one `-e` step, so re-running the
    job aborts on the already-published core version (Trunk rejects duplicate
    name+version) and never reaches the umbrella; and
  - a `push: tags:` workflow always runs the workflow file AT THE TAG's commit, so
    fixing release.yml on main does not change what a re-run of v2.0.0 executes.

Add a `workflow_dispatch`-only workflow that publishes ONE podspec from an
EXISTING tag, at the same version — no re-tagging, no version bump, no second
Release. It checks out the tag (so the uploaded spec is the one the release
blessed), asserts the podspec's s.version equals the tag using release.yml's own
grep/sed, skips a version already on Trunk (making it idempotent and immune to
the duplicate-rejection trap), pushes with release.yml's exact flags
(`--synchronous` for the umbrella only, since it alone declares a dependency),
and polls Trunk afterwards so a green run means the version is actually
resolvable.

Scoped to `contents: read` — it cannot create a Release, push a tag, or write to
the repo, so it can never become a second release path. release.yml keeps its
tag-only trigger and no workflow_dispatch (RELEASE.md safeguard #1 is about never
releasing on a branch merge, which this does not do).

Also correct the RELEASE.md troubleshooting entry that advised re-running the
release job, which cannot work for this failure mode, and document the recovery.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@abbaseya abbaseya self-assigned this Jul 24, 2026
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@abbaseya
abbaseya requested a review from JosephSamirL July 24, 2026 18:23
@abbaseya
abbaseya merged commit 8d448e0 into main Jul 24, 2026
8 of 10 checks passed
@abbaseya
abbaseya deleted the fix/pod-publish-recovery branch July 24, 2026 18:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant