fix(swiftpm): actually read the artifacts version pin back - #57762
Closed
chrfalch wants to merge 2 commits into
Closed
fix(swiftpm): actually read the artifacts version pin back#57762chrfalch wants to merge 2 commits into
chrfalch wants to merge 2 commits into
Conversation
chrfalch
requested review from
cipolleschi and
Copilot
and removed request for
Copilot
July 30, 2026 09:04
cipolleschi
approved these changes
Jul 31, 2026
|
@cipolleschi has imported this pull request. If you are a Meta employee, you can view this in D114318107. |
`spm add --version <ver>` / `spm update --version <ver>` already wrote an
`artifactsVersionOverride` into the `.spm-injected.json` marker, and
`readArtifactsVersionOverride` already existed to read it back — but nothing
ever called it. Only the write half was wired; every reference to the reader
was a test.
The sole resolver, determineVersion, went straight from the `--version` flag to
node_modules/react-native/package.json. So after `spm add --version X`, a later
flagless `spm update` silently re-pointed the project at package.json's version
instead, while the marker went on claiming X. `--version` was effectively
single-use. In this monorepo package.json is 1000.0.0, which has no published
artifacts, so a flagless run after a pinned add fails outright — hence the
standing advice to pass `--version` on every invocation.
Insert the pin between the two existing sources:
--version -> pinned override -> react-native/package.json
`spm download` and the scaffold path pick it up for free, since both use the
same resolved value. Since this is persistent state, log one line when the pin
is the source, so a stale pin is diagnosable rather than silent; there is still
no way to clear it short of `deinit`.
Three comments claimed the build-time sync read this override via
readArtifactsVersionOverride. It does not, and never did — the sync action
returns before artifacts are resolved at all. They now name the real consumer.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The SwiftPM docs still described `--version` as "RN version (default: from package.json)", which stopped being true once determineVersion started reading the `artifactsVersionOverride` pin back out of `.spm-injected.json`. Document the real resolution order and why it matters: - The `--version` row in "CLI Options" now names all three sources in order — the flag, the pin a previous `--version` wrote into the marker, then node_modules/react-native/package.json — and says you pass it once. - A new "Pinning the React Native version" subsection explains the failure the pin prevents, which is not self-evident: the resolved version selects which artifact slots the project is wired to, so a flagless run falling back to package.json re-points the project at different slots while the marker still advertises the pinned one. It also states that `deinit` drops the marker and with it the pin, so a later `add` resolves package.json again unless you pass `--version`. - The `.spm-injected.json` row in "What to commit" described the marker only as a record of the edits `add` made. One appended sentence makes its second role visible; the row is otherwise untouched, since sibling PRs edit it too. No advice to repeat `--version` on every invocation existed in the docs to correct — that workaround was only ever passed on verbally. The file is not Prettier-formatted on this branch, so it was deliberately not reformatted: prose stays wrapped near 80 columns and table rows stay on one line, matching the surrounding style. [Internal] - Document the `spm --version` pin and its resolution order Docs-only change; no code or tests touched. Verified against the branch's own diff that the marker key is `artifactsVersionOverride` (read by `readArtifactsVersionOverride` in scripts/spm/generate-spm-xcodeproj.js) and that `determineVersion` in scripts/setup-apple-spm.js resolves flag → pin → node_modules/react-native/package.json. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
chrfalch
force-pushed
the
chrfalch/spm-read-version-pin
branch
from
August 1, 2026 07:21
dd7f1f3 to
a56f200
Compare
|
@cipolleschi merged this pull request in b0b5409. |
meta-codesync Bot
pushed a commit
that referenced
this pull request
Aug 19, 2026
…correct the rest (#58006) Summary: Rebased onto `main` after #57757, #57756, #57762 and #57744 landed. Because this PR renames `__doc__` and Prettier-formats every file, a hunk-level rebase was the wrong tool — it stopped on the second of nine commits and the reformat commit then conflicted with everything after it. So the history is **replayed** on top of the new `main` instead, and reordered to put Prettier *before* the content edits, which makes the substantive diff reviewable rather than tangled with reflow. Verified nothing those four PRs added was lost: every heading on `main` survives except the two this PR deliberately renames, and their facts — the `artifactsVersionOverride` pin, the autolinking-config-command pin, the pre-injection build-setting values, and the promoted-scalar caveat — are carried into the new "Files the tool touches" table rather than sitting in a row this PR deletes. Housekeeping and accuracy pass over `packages/react-native/scripts/spm/__docs__`. Docs only — no code or test changes. **Rename.** `scripts/spm/__doc__` was the only `__doc__` directory in the repo; every other subsystem uses `__docs__` (27+ directories, and the convention documented in `__docs__/GUIDELINES.md`). The misspelling also meant these files were **published to npm**: `package.json` includes `scripts/spm` in `files` and excludes `!**/__docs__/**`, which the misspelled directory dodged. **Removed two superseded documents.** `rfc-spm-xcframework.md` (707 lines) was a stale ancestor of RFC0994, still describing `spm init`, xcodeproj *generation*, the `.xcodeproj.legacy` rename migration, a `spm clean` command that does not exist, stub `Package.swift` files and VFS overlays. `spm-plugins-assessment.md` evaluated SwiftPM plugins as a replacement for the injected build phases — conclusion valid, detail stale (it listed a "Prepare VFS Overlay" phase). Both have had their durable content folded into RFC0994. **Corrected the remaining docs against the implementation.** The substantive one: auto-sync is **two** hooks, not one — a scheme pre-action in the app's *shared* scheme plus the build phase. The docs described only the phase. Two claims here are corrections of my own earlier drafts, made after testing them on `private/helloworld` rather than reading the code: - Neither hook can bootstrap a clean checkout. With `build/` deleted, `xcodebuild -scheme … build` fails in nine lines of log, `Resolve Package Graph` first, the pre-action never running. The one-time setup run really is required, and the ordering table now shows the measured sequence. - A sync failure is not unconditionally non-fatal. Exit 2 — a dependency with no `Package.swift` — maps to `exit 1` and fails the build deliberately; only other non-zero codes warn. As written, the doc also contradicted the exit-2 behaviour documented elsewhere in the same file. Smaller fixes: `hermesvm` → `hermes-engine` (that name is in no code), plugin `watchPaths` added to the staleness inputs, and the `#auto-sync-build-phase` anchors left dangling by the heading rename. **Added a `__docs__/README.md` index**, per `GUIDELINES.md`, plus a **"Files the tool touches"** table — there was no single answer to what the tool creates or modifies. Writing it surfaced that `add` creates or appends to `ios/.gitignore` (documented nowhere), and that `deinit` does not revert that block, anything `--deintegrate` changed, or a promoted array setting — so the "exact inverse of `add`" claim needed qualifying in three places. **Documented `spm.dependencies`**, the SwiftPM analog of a podspec's `s.dependency`, which was implemented but absent from every doc, and corrected the scaffold prerequisite: it is `add`/`update` that stops, with a distinct exit code 2, not the build. **Prettier-formatted the docs, in its own commit.** These were the only unformatted markdown files in the repository, so `prettier --list-different "./**/*.md"` goes from three failures to clean. ## Changelog: [Internal] - SwiftPM docs: rename `__doc__` to `__docs__`, remove two superseded documents, and correct the rest against the implementation Pull Request resolved: #58006 Test Plan: - `npx prettier --check "packages/react-native/scripts/spm/__docs__/*.md"` passes; `npx prettier --list-different "./**/*.md"` is empty for the whole repo. - All 19 intra-doc anchor links verified against GitHub's slug rules; none dead. Every relative path out of the new README resolves, including the root-index hop. - `npm pack --dry-run --ignore-scripts` lists no `scripts/spm/__docs__/` entries while every `scripts/spm/*.js` still ships. - The Prettier commit is content-neutral: comparing `[A-Za-z0-9]+` token streams across it, all three files are identical word for word. - Behavioural claims traced to source: `VALID_ACTIONS` in `setup-apple-spm.js`; `injectOrCreateScheme` / `addPreActionToScheme` and the `RC -eq 2` branch of `buildSyncAutolinkingScript` in `generate-spm-xcodeproj.js`; `BUILTIN_FRAMEWORKS` in `flavored-frameworks.js`; `generateXCFrameworksPackageSwift` in `generate-spm-package.js`; `ensureGitignoreSpmEntries` and its `action =--sanitized-- Reviewed By: fabriziocucci Differential Revision: D116598871 Pulled By: cipolleschi fbshipit-source-id: b1822dcc885b9c882ec3a2626addc42553244b51
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:
spm add --version <ver>pinned a value that nothing ever read back.The marker write has been there all along, and so has the reader —
readArtifactsVersionOverride()inspm/generate-spm-xcodeproj.js, exported and unit-tested. It just had zero production callers. Every reference to it was a test.determineVersion— the only resolver — went straight from the flag topackage.json:That value picks which artifact slots the project gets wired to. So:
spm add --version 0.88.0-nightly-…→ wires the nightly's slots, pins the label ✅spm update(no flag) → silently resolvespackage.json's version instead, re-pointing the project at different slots, while the marker still claims the nightly ❌--versionwas effectively single-use. In this monorepopackage.jsonis1000.0.0, which has no published artifacts, so a flagless run after a pinnedaddfails outright — which is why the standing advice has been to pass--versionon every invocation. That advice was working around this bug.Fix: insert the pin between the two existing sources.
15 lines of logic.
spm downloadand the scaffold path pick it up for free, since both consume the same resolved value. Because this is persistent state, one line is logged when the pin is the source, so a stale pin is diagnosable instead of silent; there is still no way to clear it short ofdeinit.Three comments were actively wrong and are corrected here: the reader's doc block, the marker-field comment, and
findInjectedXcodeproj's comment all asserted that the build-time sync calls this viareadArtifactsVersionOverride. It does not and never did — thesyncaction returns before artifacts are resolved at all. Those comments are what made the gap invisible; they misled me while investigating.Changelog:
[Internal] [Fixed] - SwiftPM:
spm --versionnow sticks, so a later run without the flag keeps using the pinned artifact versionTest Plan:
yarn jest packages/react-native/scripts→ 31 suites, 684 tests, all green.New tests, written red first — the load-bearing one failed with
Expected: "0.80.0" / Received: "1000.0.0", i.e. exactly the reported bug:--versiongiven → wins, even with a different value pinnedpackage.json's version (unchanged behaviour)package.json's version, no throwThe three fallback cases passed before the fix too, which is the point — they pin today's behaviour so this change can't regress it.
Note on landing order
Touches
setup-apple-spm.jsandspm/generate-spm-xcodeproj.js, which #57744, #57756 and #57757 also touch. All are cut independently frommain; whichever lands first, I'll rebase the rest. #57756 is the closest relative — it does the same wiring for--config-command, which had the identical write-only-pin shape.