Skip to content

Check in CI that spm deinit takes the template app back to CocoaPods - #59783

Merged
meta-codesync[bot] merged 3 commits into
mainfrom
chrfalch/spm-optout-roundtrip-ci
Nov 6, 2026
Merged

meta-codesync[bot] merged 3 commits into
mainfrom
chrfalch/spm-optout-roundtrip-ci

Conversation

@chrfalch

@chrfalch chrfalch commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

npx react-native spm deinit takes an app from SwiftPM back to CocoaPods. No CI job tests this today. The unit tests mock pod and xcodebuild, and no job runs deinit. The CocoaPods jobs build apps that were never converted. A later change could break the way back without any failing check.

This PR adds the full round trip to the SwiftPM new-app job (test-ios-spm-newapp.yml), in the Debug cell only. deinit does not depend on the flavor, and the job does not retry, so a failure shows up once, where people look for SwiftPM problems.

  1. Before spm add, the job runs assert-spm-deinit.sh record. It saves the sha256 of ios/Podfile and ios/.gitignore (or absent), and fails at once if the Podfile is missing. The job also copies ios/.
  2. After the SwiftPM build, the job runs npx react-native spm deinit.
  3. The job prints diff -r between the copy and ios/. This is for information only and never fails the job. It also prints when a later step fails.
  4. assert-spm-deinit.sh check then checks:
    • the Podfile is byte-identical;
    • .gitignore is byte-identical, or gone if it was absent before;
    • the .spm-injected.json marker and ios/ReactNativeSPM/ are gone;
    • project.pbxproj has no SwiftPM package references, product dependencies, ReactNativeSPM paths, or SwiftPM build phases;
    • no shared scheme still has the SwiftPM pre-action.
  5. The job runs pod install the same way as the HelloWorld CocoaPods job, then builds the workspace in Debug for the simulator.

The Debug cell takes longer now, because it runs pod install and a second app build. The Release cell is unchanged.

The check assumes the app had no Swift packages before spm add. The script header says so.

Changelog:

[INTERNAL] [ADDED] - CI check that spm deinit takes an app back to CocoaPods and that the app then builds

Test Plan:

I ran the script locally on copies of private/helloworld/ios with a test Podfile:

  • record: prints and writes both checksums; with no Podfile it fails with a clear error.
  • check after a real deinit: passes.
  • check with no deinit: fails with one error for each SwiftPM change still in place.
  • Wrong arguments: prints the usage and exits 2.
  • bash -n passes on the script, and the workflow YAML parses.

Not run locally: shellcheck (not installed), and the workflow itself. CI on this PR runs it.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Nov 3, 2026
@chrfalch
chrfalch requested a review from cipolleschi November 3, 2026 20:33
@chrfalch
chrfalch marked this pull request as ready for review November 3, 2026 20:33
@chrfalch
chrfalch force-pushed the chrfalch/spm-optout-roundtrip-ci branch from 116499b to 7ffb988 Compare November 5, 2026 15:02
@chrfalch
chrfalch changed the base branch from chrfalch/spm-ci-default to main November 5, 2026 15:02

@cipolleschi cipolleschi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for adding this, it's the check I was asking for on #59742. 🙏

My main concern is where it runs. e2e-ios-templateapp.yml exists for the Maestro tests, and it's a bad place for a check that fails the same way every time:

  1. The test job has needs: build. If the deinit check fails in either flavor, the Maestro tests are skipped for both. A bug in the SwiftPM tooling would then hide the template E2E results.
  2. test-all.yml reruns the whole workflow up to twice when it fails (test_e2e_ios_templateapp_retry_1 / _retry_2). Those retries are for flaky Maestro runs. A deinit failure won't go away on retry, so we'd pay for three template builds on macos-26-large before we see it.
  3. The failure gets reported through recordJobFailure / reportTestResults as an E2E failure, which is misleading.

Could we move the check to test-ios-spm-newapp.yml, or to the end of the SwiftPM path in the test-ios-helloworld action? Both already run spm add --deintegrate, they don't retry, and they fail where people look for SwiftPM problems. It's also enough to run it in one flavor: deinit doesn't depend on the flavor.

Separately, and not something this PR has to do: the iOS template app still builds inside the retried E2E workflow, so every retry rebuilds it. #59135 (Maestro on remote simulators) doesn't change that: test-all.yml doesn't pass artifact-run-id, and test still needs build. #59646 also changes this file and keeps the build in the retry loop on purpose. Building the template in its own job, as RNTester and the Android template already do, would make it cleaner to add checks like this one to that job later.

One more question: going back to CocoaPods means spm deinit and then pod install. The CocoaPods jobs from #59742 only build apps that were never converted, so no job runs the full round trip. Could we add pod install plus a Debug workspace build after deinit, in one cell? A follow-up PR is fine too.

# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

# Checks that `npx react-native spm deinit` left an iOS app with only its

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: the script fails on any packageReferences / packageProductDependencies in the pbxproj, so it assumes the app had no Swift packages before spm add. That's true for the template, but the header says it checks "an iOS app". Can we say that in the comment, so nobody reuses the script on an app that already has Swift packages?

@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Nov 5, 2026
@chrfalch
chrfalch requested a review from cipolleschi November 6, 2026 08:55
No CI job tested the CocoaPods opt-out: after the SwiftPM build, nothing
ran `spm deinit` or looked at the files it leaves. The template app job now
records the Podfile and ios/.gitignore checksums before `spm add`, runs
`spm deinit` after the app upload, and checks that the Podfile and
.gitignore are unchanged, the marker and ReactNativeSPM/ are gone, and the
Xcode project and shared scheme have no SwiftPM references left.

The check reads files only; `deinit` does not run `pod install`.
@chrfalch
chrfalch force-pushed the chrfalch/spm-optout-roundtrip-ci branch from f34512d to bf87974 Compare November 6, 2026 09:51
@meta-codesync

meta-codesync Bot commented Nov 6, 2026

Copy link
Copy Markdown

@cipolleschi has imported this pull request. If you are a Meta employee, you can view this in D130158963.

@cortinico cortinico left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review automatically exported from Phabricator review in Meta.

@meta-codesync
meta-codesync Bot merged commit 676c516 into main Nov 6, 2026
93 checks passed
@react-native-bot

Copy link
Copy Markdown
Collaborator

This pull request was successfully merged by @chrfalch in 676c516

When will my fix make it into a release? | How to file a pick request?

@react-native-bot react-native-bot added the Merged This PR has been merged. label Nov 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Merged This PR has been merged. p: Expo Partner: Expo Partner Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants