Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): refactor lock file parsing and pruning #13864

Merged
merged 52 commits into from
Feb 6, 2023

Conversation

meeroslav
Copy link
Contributor

@meeroslav meeroslav commented Dec 16, 2022

Progress tracking:

  • Parsing
    • Alias packages
    • Duplicate packages
    • Tarball packages
    • Workspaces
    • NPM
    • Yarn
    • Pnpm
  • Mapping to project graph
  • Pruning
  • Stringification
    • NPM 1
    • NPM 2
    • NPM 3
    • Yarn Classic
    • Yarn Berry
    • Pnpm (map to default)
  • Cleanup of old functionality
  • E2E tests for pruning
  • Implement/Unit tests workspaces support
  • Unit tests for pruning alias and tarball packages

Current Behavior

State of the existing implementation:

  • It’s heavily guided by final stringification, so the intermediate structure carries a lot of metadata from lock files
  • The structure has flaws that are not verified on the construction
  • The resulting lock file is sometimes inaccurate (leading to failed installation)
  • We have no way to test the validity of the parsed/pruned structure
  • The code/logic is very complex, hacky and hard to read

Expected Behavior

The goal of the rewriting:

  • Simplify the graph representation
  • Have a way to check the validity
  • Prune graph instead of metadata
  • Separate graph logic from package manager specifics

Implementation clarification

  • New logic uses a builder similar to ProjectGraphBuilder to construct a graph from packages and dependencies, which allows us to:
    • Check the consistency (all nodes should have incoming nodes, each edge must have defined from and to node, etc.)
    • Easily tree-shake and traverse graph when pruning
  • The graph contains minimal information from lock files:
    • Dependency name
    • Package name (if different from dependency name)
    • Version (or URL for tarball packages)
  • Stringification is decoupled from the actual pruning process
    • We prune the LockFileGraph and then use this as a base for lock file stringification
    • Stringification uses content from the original lock file. This is trivial for Yarn and Pnpm but requires some gymnastics for Npm (find the package hierarchy and handle V1 and V3 mapping separately).
  • Unit tests use actual generated lock files as input params
    • Unit tests are grouped around logic problems
      • Alias and tarball packages
      • Same package with same version installed twice in different locations
      • Real-world NextJS examples
      • Pruning single and multiple dependencies
      • Optional children
      • Workspaces
    • Additional manually crafted will be added to test a few corner cases which are not that easy to generate
  • The resulting code has a lot of validations all over the place to ensure we detect broken things

Note, due to complexity and differences between PRs, the code is larger than 1000 loc (without warnings, etc.)
We can compress files more, but that would come at the expense of readability.

Related Issue(s)

Fixes #13863
Fixes #14096
Fixes #14275
Fixes #14721
Related to #9761
Related to #14106

@meeroslav meeroslav self-assigned this Dec 16, 2022
@vercel
Copy link

vercel bot commented Dec 16, 2022

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated
nx-dev ✅ Ready (Inspect) Visit Preview 💬 Add your feedback Feb 6, 2023 at 0:36AM (UTC)

@meeroslav meeroslav force-pushed the fix-lock-files branch 2 times, most recently from 1e8abab to 6b68cd7 Compare December 16, 2022 15:40
@meeroslav meeroslav force-pushed the fix-lock-files branch 2 times, most recently from c842cea to 94db30c Compare January 3, 2023 22:38
@meeroslav meeroslav changed the title fix(core): refactor lock file parsing and pruning feat(core): refactor lock file parsing and pruning Feb 2, 2023
const { combinedOutput: nestCombinedOutput } = await runCLIAsync(
`build ${nestapp} --generatePackageJson`
);
expect(nestCombinedOutput).not.toMatch(/Graph is not consistent/);
Copy link
Collaborator

Choose a reason for hiding this comment

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

remove this

@@ -33,6 +33,7 @@
"homepage": "https://nx.dev",
"dependencies": {
"@parcel/watcher": "2.0.4",
"@pnpm/lockfile-types": "^4.3.6",
Copy link
Collaborator

Choose a reason for hiding this comment

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

remove

}
});
} else {
Object.entries(data.dependencies).forEach(([packageName, snapshot]) => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Consider moving this to a separate file.


const output: NpmLockFile = {
name: packageJson.name || rootLockFile.name,
version: packageJson.version || '0.0.1',
Copy link
Collaborator

Choose a reason for hiding this comment

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

TODO: If there is no version in packageJson, npm doesn't produce a version so we should probably do the same.

const child = keyMap.get(searchPath);
if (
child.data.version === versionRange ||
satisfies(child.data.version, versionRange)
Copy link
Collaborator

Choose a reason for hiding this comment

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

What is this for? It shouldn't matter if the version matches.

If the node is there, then it will be depended upon; Correct version or not.

@github-actions
Copy link

github-actions bot commented Mar 3, 2023

This pull request has already been merged/closed. If you experience issues related to these changes, please open a new issue referencing this pull request.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 3, 2023
@meeroslav meeroslav deleted the fix-lock-files branch April 27, 2023 10:00
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.