Run pods through bundler when the project pins them - #148
Merged
Conversation
A project root with both a Gemfile and a Gemfile.lock now gets `bundle check --dry-run`, `bundle install` only when gems are missing, then `bundle exec pod install`, so the CocoaPods the lockfile pins is the one that writes Podfile.lock. Bundler resolves and writes Gemfile.lock from check, install and even exec, so every bundler spawn runs with BUNDLE_FROZEN and the check runs --dry-run: stim never writes into the project tree. A Gemfile with no lockfile, and a machine with no `bundle` on PATH, stay on plain `pod install`. Refs #137
A Gemfile+Gemfile.lock that pins fastlane and nothing else pinned nothing for pods, so `bundle exec pod install` would fail where plain `pod install` worked. Rung 1 now requires a cocoapods spec entry in Gemfile.lock, and doctor's pod remedies read the same rule. Refs #137
Moves bundlerPin into engine/bundler.ts so doctor, worktree's carried-Pods warning and the xcodebuild sandbox-out-of-sync remedy print `bundle exec pod install` only when Gemfile.lock resolves cocoapods. Refs #137 Review fixes: report `bundle` (not CocoaPods) when the bundler branch hits ENOENT, rewrite the no-pod-in-bundle remedy for the states that can reach it, narrow the frozen-refusal match to bundler's own phrasing, label the check spawn `gems`, and note the project-local BUNDLE_PATH `bundle install` fills.
A leading ~ is expanded by bundler to $HOME, so it never lands in the project; resolve() would have read it as a directory named "~" and printed the in-project note anyway. The note now also says whether BUNDLE_PATH came from the environment or from .bundle/config, so nobody hunts for a file that is not there. Refs #137
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.
Description
doctorprintsbundle exec pod installwhen the project has a Gemfile, while the engine always spawned plainpod install(#137). For a project whoseGemfile.lockpins cocoapods, the CocoaPods that rewritesios/Podfile.lockduring a Stim build can then be a different one than the repo pins -- the lockfile churn and rvm activation trouble #133/#135 hit in the e2e fixture.Stim must not edit tracked project files, and bundler rewrites
Gemfile.lockwhenever it resolves, so every bundler spawn here runs withBUNDLE_FROZEN=trueand the check runs--dry-run. To be precise about the scope of that claim:BUNDLE_FROZENprotectsGemfile.lockspecifically.bundle installstill installs gems, and when the project's own committed.bundle/configpointsBUNDLE_PATHinside the tree -- the React Native template shipsvendor/bundle-- that is where they land. That is the project's dependency state written by the project's own toolchain config, the same class asPods/andnode_modules/, and the template gitignores it (--carry-ignoredcarries it into worktrees). I deliberately did not redirectBUNDLE_PATHto a Stim directory: the user's ownbundle exechas to find the same gems. The run now prints a dimpodsnote when the resolved bundle path is inside the project.What bundler 4.0.8 does to a Gemfile.lock that no longer matches its Gemfile (measured, not assumed)
bundle checkbundle check --dry-runbundle exec <cmd>BUNDLE_FROZEN=true bundle exec <cmd>Solution
The pod step takes the first rung that applies:
Gemfile+ aGemfile.lockthat resolves cocoapods --bundle check --dry-runat the Gemfile, thenbundle installonly if that reports missing gems, thenbundle exec pod installinios/.Gemfilewith noGemfile.lock-- plainpod install, exactly as before.bundle installthere would CREATE a lockfile in the checkout, which is the write Stim will not do; there is no pin to honor anyway.Gemfile.lockthat pins something else (fastlane-only bundles are common in RN repos) -- plainpod install. Nothing was pinned for pods, so nothing is gained by runningbundle exec pod installand failing where plainpodworked. No note: there is no pin to report.bundleon PATH -- plainpod installplus one dimpodsnote naming the pin it could not use. A note, not a failure.A drifted Gemfile (one that no longer matches its lockfile) fails the build rather than falling back to unpinned pods -- silently building with a different CocoaPods than the lockfile pins is the bug class this feature exists to kill -- and the failure carries the
bundle installremedy.Rung 1's test is a four-space-indented
cocoapods (spec line inGemfile.lock-- that is bundler's format for a resolved spec (six spaces marks a spec's dependencies, two marksDEPENDENCIES), so it catches cocoapods pulled in transitively, whichDEPENDENCIESwould miss. An unreadable or malformed lockfile is treated as "not pinned" rather than an error. The rule lives inengine/bundler.tsand every surface that prints a pod command reads it:doctor's two CocoaPods remedies,worktree create's carried-Pods warning, and the xcodebuild "sandbox is not in sync" remedy. A fastlane-only repo is toldpod installeverywhere; a pinned repo is toldbundle exec pod installeverywhere.All three bundler spawns keep
podEnv()(the.ruby-versionPATH/GEM_HOME handling) and addBUNDLE_GEMFILE. A Gemfile that has drifted from its lockfile now fails the run with a remedy pointing atbundle installinstead of having a tracked file updated underneath you; gems bundler cannot install keep the existing.ruby-versionhint. Thepodsphase line names the command that ran, andstim guide errorsdescribes the ladder under STIM_DEPS_FAILED. STIM_DEPS_FAILED itself and the extracted[!]/ruby diagnostics are unchanged.Test plan
Real tools,
stim ioson a bare RN 0.87 worktree withios/Podsandvendor/removed, which drives rung 1 end to end --bundle check --dry-run(missing gems) ->bundle install->bundle exec pod install-> build -> launch:git status --porcelainin that worktree was empty before and after, andgit diff -- Gemfile.lockwas empty: 45 gems and 86 pods installed without touching a tracked file. The gems did land in the worktree, invendor/bundleper the fixture's own.bundle/config-- gitignored, hence the clean status, and exactly what the new dim note now reports.node test/e2e/native/run-native-e2e.mjs --framework bare --platform ios-- PASS. Worth knowing: that e2e never reaches this code, becauseworktree create --carry-ignoredcarries a matchingios/Podsand the pod step is skipped. Hence the manual run above.bundle install, a fastlane-only lock and a Gemfile without a lockfile stay on plainpod install(asserting the fallback env carries noBUNDLE_FROZEN/BUNDLE_GEMFILE), a missingbundlefalls back with the note, and each new failure returns STIM_DEPS_FAILED with its remedy.engine-bundler.test.tspins the lockfile parse itself: CRLF, a GIT-sourced spec, a transitivecocoapodsdependency line with no spec of its own (negative), aCHECKSUMSentry alone (negative), and a lockfile that is a directory. A guide contract test ties the STIM_DEPS_FAILED text to the argv the engine actually spawns, so the two cannot drift again. The four-space spec match was also checked against a realbundle lockoutput pinning cocoapods 1.17.0.Fixes #137