Skip to content

fix(connect): make the xcframework bytes independent of the lockstep version - #105

Merged
auto-wood merged 5 commits into
mainfrom
fix/xcframework-version-independence
Sep 18, 2026
Merged

auto-wood merged 5 commits into
mainfrom
fix/xcframework-version-independence

Conversation

@auto-wood

Copy link
Copy Markdown
Contributor

Problem

The committed Swift xcframework could not stay fresh across a release. The version bump touches crates/spoke-connect/Cargo.toml and Cargo.lock, both inside the Xcframework workflow's path filter, so the job re-builds on every release PR — and the rebuild never reproduces the committed bytes. The result was a red Xcframework check on every release: reproduced on release/0.12.0 (run 35183686959, merged anyway) and again on the 0.13.0 bump.

Root cause

Cargo folds the package version into -C metadata, which derives the crate disambiguator and therefore every mangled symbol name. Measured on two builds of identical sources that differ only in the version (main run 35292260089 at 0.12.0 vs release run 35302982123 at 0.13.0):

  • macos-arm64/libspoke_connect.a: 38 887 064 vs 38 880 832 bytes, and all 196 spoke_connect symbols differ — e.g. __ZN13spoke_connect3ffi10NonceStore3new17hb545f67c8390cbf0E → …17h304d84016c7276f2E.
  • Local probe: -C metadata=5d93764ab45e6fbe at 0.12.0, different at 0.13.0.
  • A minimal-crate control reproduces it, and RUSTFLAGS='-C metadata=<fixed>' does not override cargo's value.

A second, smaller contributor: crates/spoke-connect/src/node.rs embedded env!("CARGO_PKG_VERSION") into the libp2p identify agent string.

Refreshing the artifact during the release was rejected: tooling/connect/apply-xcframework-artifact.sh documents that GITHUB_TOKEN cannot carry LFS objects or re-trigger workflows, so an automated refresh would need a new credential surface — and the release PR would still go red before the refresh landed.

Fix

Make the artifact a function of the sources only:

  • The build normalises the version. tooling/connect/build-swift-xcframework.sh rewrites every version surface (root [workspace.package].version, the workspace-member entries in Cargo.lock, and each member manifest's { version, path } inter-crate pin) to a sentinel for the duration of the build, and restores them unconditionally. It reuses the pure helpers in tooling/release/lockstep-surfaces.mjs rather than a second implementation.
  • The product carries no version. The identify agent string is a stable constant, so no version can be baked into the artifact once the build normalises it.
  • Restore is failure-proof. Backup deletion is conditional on a successful restore; a failed restore keeps the backup, prints its path, and names the failing file; INT/TERM are masked across the restore critical section.

The committed artifact was refreshed once from a CI build (apply-xcframework-artifact.sh, provenance- and manifest-verified). The drift gate keeps its strength: a genuine FFI source change still fails it.

Evidence

  • Local equivalence: normalised builds at two different lockstep versions are byte-identical (3ae2f233…), while the same experiment through the pre-change path produces different bytes (6e723882… vs 84b9de2e…) — the experiment is demonstrably sensitive.
  • Decisive CI proof: run 35309302133, on a branch carrying a version-bump-only commit over the refreshed artifact, completed success on every step — including Verify drift vs committed xcframework. That is the release-path regression, gone.
  • --locked still resolves under the sentinel; the built static lib contains neither the real nor the sentinel version string; a deliberate one-byte mutation still makes the drift script exit 1.
  • Restore failure retains its backup and names the failed file; manual recovery from that backup returns a clean tree; the happy path still removes the backup.
  • QC: Approve with zero findings after closing one review finding (F-001, the restore-failure backup loss). QA (mandatory/acceptance-only): AC1–AC8 all verified.

Follow-up

With this merged, a release bump no longer invalidates the committed xcframework. Re-run New release for 0.13.0 and the bump PR should come up completely clean.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Risk: medium. Approved. Cursor Bugbot and Cursor Security Agent were not present after the first poll, and no applicable approval policy requires human review. No reviewers assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@greptile-apps

greptile-apps Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

The PR appears safe to merge; no outstanding correctness, security, or repository-rule violations were identified.

Summary

The PR makes committed Swift xcframework artifacts independent of the workspace lockstep version.

  • Normalizes Cargo workspace, lockfile, and member-manifest version surfaces during xcframework builds and restores them during cleanup.
  • Uses a checkout-scoped atomic lock to prevent concurrent normalization.
  • Removes the package version from the libp2p identify agent string.
  • Refreshes the committed xcframework binaries and documents the deterministic build approach.
  • The two previous concurrency findings are resolved by exclusive lock-file creation and ownership-safe stale/release handling.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Start xcframework build] --> B[Atomically acquire checkout lock]
  B --> C[Back up Cargo version surfaces]
  C --> D[Normalize versions to sentinel]
  D --> E[Build xcframework slices]
  E --> F[Restore original Cargo files]
  F --> G[Release owned lock]
  G --> H[Exit with build or restoration status]
Loading

Reviews (3) · Last reviewed commit: "fix(connect): harden xcframework version..."

Comment thread tooling/connect/build-swift-xcframework.sh
Comment thread tooling/connect/build-swift-xcframework.sh Outdated
@auto-wood
auto-wood merged commit 7d07981 into main Sep 18, 2026
20 checks passed
@auto-wood
auto-wood deleted the fix/xcframework-version-independence branch September 18, 2026 07:03
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