feat: report linked libraries whose Git metadata enters the fingerprint - #615
Conversation
796edd3 to
7a07a77
Compare
A link: or file: dependency is a symlink into another checkout, so its .git lands under node_modules where @expo/fingerprint hashes it. Creating a worktree rewrites that metadata, and the main checkout and its worktrees never agree on a fingerprint even when the library's native sources match. Doctor now names the exact node_modules/<package>/.git entry to list in .fingerprintignore when the native build does not read Git state. Fixes #595
7a07a77 to
11c0ec9
Compare
|
CI note: GitHub stopped creating pull_request runs for this branch after the 03:39Z push (a reopen did not re-trigger them either). A workflow_dispatch run of ci.yml on the exact head commit 11c0ec9 passed: https://github.com/appandflow/stim/actions/runs/34435144431. A fresh push should re-attach checks to the PR. |
|
Fresh independent code review at 11c0ec9 is clear: actual Expo ignore-matcher checks cover .git pointer files/directories and preserve native sources. One evidence correction before merge: the Trailhead run has no linked library, so the new gate skips fingerprinting; it cannot prove the fingerprint call runs inside doctor as the body says. Please correct that sentence and preferably run the built doctor on an affected linked-library fixture, showing the finding before the narrow ignore and no finding afterward. Do not overlap native builds on this Mac; doctor-only metadata is fine. Root app-config607 full checks now complete; PR forthcoming. |
|
Codex completed the missing real affected-project check at11c0ec9: built doctor on the safe-area-context example reported the linked .git note before its exact ignore, then findings[] afterward. DEBUG=expo:fingerprint stayed off stdout, both outputs parsed as one JSON object. Disposable fixture restored clean. I replaced only the inaccurate Trailhead validation bullet with these observed results; source branch unchanged. Independent code review is clear. Proceeding with merge after exact-head required CI verification. |
|
PR615 is currently merge-conflicted and has no exact-head checks, so it cannot merge yet. I am taking the integration follow-up in a separate local checkout: merge current main without rewriting your commits, resolve overlapping guide/config additions, rerun checks and fresh review, then push only as a normal fast-forward. No force-push; a concurrent remote update will be preserved and reconciled. The actual linked-library diagnostic is now verified and the body corrected. |
|
CI clarification: the PR rollup was empty, but the exact 11c0ec9 head does have a successful manually dispatched CI run (34435144431). The merge conflict still requires an integration commit and new exact-head checks; no prior CI failure is implied. |
|
Final independent integration review is CLEAR at b4718a6. Current main config/scheme/reset changes are retained; the sole import conflict was resolved correctly. Reviewer checked the real before/after doctor evidence and single-JSON output. All local checks and required Node22/24/runtime20 CI passed. Merging this exact head. |
Description
stim doctornow names any.gitinside a directory the native fingerprint hashes, such as a symlinkedlink:orfile:library undernode_modules, and prints the exact.fingerprintignorelines for it.A linked dependency is a symlink into another checkout, so that checkout's
.gitlands in a directory@expo/fingerprinthashes whole. Git rewrites that metadata on every commit, checkout, or worktree of the linked checkout, so workspaces rarely compute the same fingerprint even when the library's native sources match, and every worktree compiles instead of reusing the artifact. Issue #595 measured this on the react-native-safe-area-context example: 231 differing files, all under the linked package's.git, and equal fingerprints once that one path was ignored.Solution
The check first looks for a symlinked package whose target holds a
.gitentry in everynode_modulesfrom the app directory up to the repository root, so hoisted workspace links count; that is a handful oflstatcalls. only then does it run the project fingerprint once in debug mode and walk itsdirsources, reporting a directory only when the fingerprint's own debug output shows it hashed a.gitchild. The printed path is therefore the one the fingerprint uses (thenode_modulesalias or a real path, whichever autolinking reported), packages that never enter the fingerprint are not mentioned, and a.gitthe project already excludes through.fingerprintignoreorfingerprint.config.jsis not reported, whatever pattern it used. It inspects the main checkout like the sibling doctor checks and honours--platform.fingerprintProjectalso passessilent: truenow, because withDEBUGset@expo/fingerprintprints profiling lines to stdout, which would breakdoctor --json.Two lines are printed per directory,
<dir>/.gitand<dir>/.git/**/*. The installed@expo/fingerprintmatches ignore patterns per file and only skips a directory for patterns ending in/**/*,/**or/, so the first form covers the pointer file a worktree has and the second the directory a main checkout has.Doctor does not write the file. The remedy holds only when the native build does not read Git state, which is the project's judgment, so the note says to ignore those entries alone, never the package. The guide's fingerprint section, the agent guide, and the commands page describe the finding.
Test plan
doctor.test.tsdrivesdetectLinkedLibraryGitMetadatawith a stub fingerprint whose debug output lists a scoped package that hashed.git, one that did not, andandroid. It asserts only the first is named with both ignore lines, that--platform,debugandsilentreach the fingerprint call, the plural form with a real-path source, silence once no directory hashes.git, silence on a failing fingerprint, that no fingerprint runs when nonode_modulesholds a symlinked package with.git, and a hoisted link found from an app directory inside a repository.11c0ec9against the real safe-area-context example with its linked native library.doctor --platform android --jsonreported onlylinked-library-git-metadatabefore the narrow ignore; after applying its exact printed.gitand.git/**/*entries, findings were empty. Both outputs parsed as one JSON payload withDEBUG=expo:fingerprint. The disposable fixture was restored to its clean baseline afterward; no native build or original repository changed.Fixes #595