From f7d526f1d39e1af8d0b2af6234f7b2f124587b44 Mon Sep 17 00:00:00 2001 From: Chris Deacy Date: Wed, 8 Jan 2025 20:01:07 -0800 Subject: [PATCH 1/5] Add --immutable arg --- bin/cluster.js | 2 +- commands/add.js | 8 +- commands/ci.js | 2 +- commands/focus.js | 3 +- commands/install.js | 50 ++++++++++--- commands/remove.js | 8 +- index.js | 74 +++++++++++++++---- .../fixtures/immutable-install/a/package.json | 4 + .../fixtures/immutable-install/b/BUILD.bazel | 9 +++ .../fixtures/immutable-install/b/package.json | 7 ++ .../fixtures/immutable-install/manifest.json | 3 + tests/fixtures/immutable-install/package.json | 4 + .../third_party/jazelle/BUILD.bazel | 8 ++ .../jazelle/scripts/build-file-template.js | 8 ++ tests/fixtures/immutable-install/yarn.lock | 0 tests/index.js | 69 ++++++++++++++++- utils/cli.js | 28 +++++-- utils/generate-bazel-build-rules.js | 35 +++++++-- utils/generate-bazelignore.js | 21 +++++- 19 files changed, 296 insertions(+), 47 deletions(-) create mode 100644 tests/fixtures/immutable-install/a/package.json create mode 100644 tests/fixtures/immutable-install/b/BUILD.bazel create mode 100644 tests/fixtures/immutable-install/b/package.json create mode 100644 tests/fixtures/immutable-install/manifest.json create mode 100644 tests/fixtures/immutable-install/package.json create mode 100644 tests/fixtures/immutable-install/third_party/jazelle/BUILD.bazel create mode 100644 tests/fixtures/immutable-install/third_party/jazelle/scripts/build-file-template.js create mode 100644 tests/fixtures/immutable-install/yarn.lock diff --git a/bin/cluster.js b/bin/cluster.js index 4122329..bccb358 100644 --- a/bin/cluster.js +++ b/bin/cluster.js @@ -49,7 +49,7 @@ async function runMaster() { await install({ root, cwd: `${root}/${data[0].dir}`, - frozenLockfile: true, + immutable: true, conservative: true, }); diff --git a/commands/add.js b/commands/add.js index 3dda7a4..ac048d5 100644 --- a/commands/add.js +++ b/commands/add.js @@ -110,7 +110,13 @@ const add /*: Add */ = async ({root, cwd, args, dev = false}) => { dirs: projects.map(dir => `${root}/${dir}`), target: resolve(root, cwd), }); - await generateBazelBuildRules({root, deps, projects, dependencySyncRule}); + await generateBazelBuildRules({ + root, + deps, + projects, + dependencySyncRule, + immutable: false, + }); } }; diff --git a/commands/ci.js b/commands/ci.js index 14c8a5b..3fd1854 100644 --- a/commands/ci.js +++ b/commands/ci.js @@ -9,7 +9,7 @@ export type CiArgs = { export type Ci = (CiArgs) => Promise */ const ci /*: Ci */ = async ({root, cwd}) => { - await install({root, cwd, frozenLockfile: true, conservative: true}); + await install({root, cwd, immutable: true, conservative: true}); }; module.exports = {ci}; diff --git a/commands/focus.js b/commands/focus.js index 7922864..a69bd2a 100644 --- a/commands/focus.js +++ b/commands/focus.js @@ -88,12 +88,13 @@ const focus /*: Focus */ = async ({ await validateVersionPolicy({dirs: deps.map(dep => dep.dir), versionPolicy}); if (workspace === 'sandbox') { - await generateBazelignore({root}); + await generateBazelignore({root, immutable: false}); await generateBazelBuildRules({ root, deps, projects, dependencySyncRule, + immutable: false, }); } diff --git a/commands/install.js b/commands/install.js index 3cb704a..4ce299d 100644 --- a/commands/install.js +++ b/commands/install.js @@ -21,7 +21,7 @@ const {node, yarn} = require('../utils/binary-paths.js'); export type InstallArgs = { root: string, cwd: string, - frozenLockfile?: boolean, + immutable?: boolean, conservative?: boolean, skipPreinstall?: boolean, skipPostinstall?: boolean, @@ -33,7 +33,7 @@ export type Install = (InstallArgs) => Promise const install /*: Install */ = async ({ root, cwd, - frozenLockfile = false, + immutable = false, conservative = true, skipPreinstall = false, skipPostinstall = false, @@ -71,14 +71,27 @@ const install /*: Install */ = async ({ validateDeps({deps}); await validateVersionPolicy({dirs: deps.map(dep => dep.dir), versionPolicy}); - if (workspace === 'sandbox' && frozenLockfile === false) { - await generateBazelignore({root}); - await generateBazelBuildRules({ - root, - deps: all, - projects, - dependencySyncRule, - }); + if (workspace === 'sandbox') { + const changedGeneratedFiles = [ + ...(await generateBazelignore({ + root, + immutable, + })), + ...(await generateBazelBuildRules({ + root, + deps: all, + projects, + dependencySyncRule, + immutable, + })), + ]; + + if (immutable && changedGeneratedFiles.length > 0) { + throw new ImmutableInstallError( + `Generated files would have changed, but 'immutable' arg was passed`, + changedGeneratedFiles + ); + } } if (hooks.bool_shouldinstall) { @@ -97,7 +110,7 @@ const install /*: Install */ = async ({ const env = process.env; const path = dirname(node) + ':' + String(process.env.PATH); const spawnArgs = [yarn, 'install']; - if (frozenLockfile) { + if (immutable) { spawnArgs.push('--immutable'); } @@ -131,6 +144,19 @@ const install /*: Install */ = async ({ } }; +/** + * An error that's thrown when the `immutable` flag is + * `true` and generated files would have changed. + */ +class ImmutableInstallError extends Error { + /*:: changedFiles: Array; */ + + constructor(message /*: string */, changedFiles /*: Array */) { + super(message); + this.changedFiles = changedFiles; + } +} + const validateRegistration = ({root, cwd, projects}) => { if (!projects.find(dir => resolve(`${root}/${dir}`) === cwd)) { const registrationError = `Your cwd ${cwd} is not listed in manifest.json or package.json. If you are at the wrong directory, cd into your desired directory or use the --cwd flag. If you are in the desired directory, make sure it is listed in the projects field in manifest.json or workspaces field in package.json`; @@ -173,4 +199,4 @@ const validateVersionPolicy = async ({dirs, versionPolicy}) => { if (!result.valid) throw new Error(getErrorMessage(result, false)); }; -module.exports = {install}; +module.exports = {install, ImmutableInstallError}; diff --git a/commands/remove.js b/commands/remove.js index b873d6f..e99d93c 100644 --- a/commands/remove.js +++ b/commands/remove.js @@ -41,7 +41,13 @@ const remove /*: Remove */ = async ({root, cwd, args}) => { dirs: projects.map(dir => `${root}/${dir}`), target: resolve(root, cwd), }); - await generateBazelBuildRules({root, deps, projects, dependencySyncRule}); + await generateBazelBuildRules({ + root, + deps, + projects, + dependencySyncRule, + immutable: false, + }); } }; diff --git a/index.js b/index.js index 51032c1..1e4f5be 100644 --- a/index.js +++ b/index.js @@ -1,11 +1,11 @@ // @flow const {getRootDir} = require('./utils/get-root-dir.js'); const {parse, normalize} = require('./utils/parse-argv.js'); -const {cli} = require('./utils/cli.js'); +const {cli, CliError} = require('./utils/cli.js'); const {version} = require('./commands/version.js'); const {init} = require('./commands/init.js'); const {scaffold} = require('./commands/scaffold.js'); -const {install} = require('./commands/install.js'); +const {install, ImmutableInstallError} = require('./commands/install.js'); const {ci} = require('./commands/ci.js'); const {focus} = require('./commands/focus.js'); const {add} = require('./commands/add.js'); @@ -86,26 +86,46 @@ const runCLI /*: RunCLI */ = async argv => { --skipPreinstall Skip the preinstall hook --skipPostinstall Skip the postinstall hook --mode If set to skip-build, skips build scripts. If set to update-lockfile, skips link step + --immutable Fail if generated files need to be modified --verbose`, - async ({cwd, skipPreinstall, skipPostinstall, mode, verbose}) => - install({ - root: await rootOf(args), - cwd, - skipPreinstall: Boolean(skipPreinstall), - skipPostinstall: Boolean(skipPostinstall), - mode, - verbose: Boolean(verbose), - }), + async ({ + cwd, + skipPreinstall, + skipPostinstall, + mode, + immutable, + verbose, + }) => { + try { + await install({ + root: await rootOf(args), + cwd, + skipPreinstall: Boolean(skipPreinstall), + skipPostinstall: Boolean(skipPostinstall), + mode, + immutable: Boolean(immutable), + verbose: Boolean(verbose), + }); + } catch (error) { + handleInstallError(error); + } + }, ], ci: [ - `Install all dependencies for all project without modifying source files + `Install all dependencies for all projects, failing if any generated files need to be modified --cwd [cwd] Project directory to use`, - async ({cwd}) => ci({root: await rootOf(args), cwd}), + async ({cwd}) => { + try { + await ci({root: await rootOf(args), cwd}); + } catch (error) { + handleInstallError(error); + } + }, ], focus: [ `Install all dependencies for one or more projects without installing the rest - + --cwd [cwd] Project directory to use --all Install all dependencies, like regular yarn install --production Install only production dependencies, not devDependencies @@ -366,6 +386,32 @@ const runCLI /*: RunCLI */ = async argv => { ); }; +const ansiRed = '\x1b[91m'; +const ansiReset = '\x1b[0m'; +/** + * Checks whether the provided error is a `ImmutableInstallError`, + * and if it is, throws a `CliError` with a formatted message. + */ +function handleInstallError(error /*: Error | ImmutableInstallError */) { + if (error instanceof ImmutableInstallError) { + const shouldUseColors = process.stdout.isTTY || process.env.FORCE_COLOR; + const errorMessage = + (shouldUseColors ? ansiRed : '') + + 'ERROR: ' + + error.message + + '\n' + + error.changedFiles + .sort((a, b) => a.localeCompare(b)) + .map(l => ' - ' + l) + .join('\n') + + (shouldUseColors ? ansiReset : ''); + + throw new CliError(errorMessage, 1); + } else { + throw error; + } +} + async function rootOf(args) { return getRootDir({dir: args.cwd}); } diff --git a/tests/fixtures/immutable-install/a/package.json b/tests/fixtures/immutable-install/a/package.json new file mode 100644 index 0000000..f9244b8 --- /dev/null +++ b/tests/fixtures/immutable-install/a/package.json @@ -0,0 +1,4 @@ +{ + "name": "a", + "version": "0.0.0" +} diff --git a/tests/fixtures/immutable-install/b/BUILD.bazel b/tests/fixtures/immutable-install/b/BUILD.bazel new file mode 100644 index 0000000..88536dd --- /dev/null +++ b/tests/fixtures/immutable-install/b/BUILD.bazel @@ -0,0 +1,9 @@ +package(default_visibility = ["//visibility:public"]) +load("@jazelle//:build-rules.bzl", "web_library") + +web_library( + name = "b", + deps = [ + ], + dist = ["dist"], +) diff --git a/tests/fixtures/immutable-install/b/package.json b/tests/fixtures/immutable-install/b/package.json new file mode 100644 index 0000000..5149318 --- /dev/null +++ b/tests/fixtures/immutable-install/b/package.json @@ -0,0 +1,7 @@ +{ + "name": "b", + "version": "0.0.0", + "dependencies": { + "a": "0.0.0" + } +} diff --git a/tests/fixtures/immutable-install/manifest.json b/tests/fixtures/immutable-install/manifest.json new file mode 100644 index 0000000..a3a492e --- /dev/null +++ b/tests/fixtures/immutable-install/manifest.json @@ -0,0 +1,3 @@ +{ + "workspace": "sandbox" +} diff --git a/tests/fixtures/immutable-install/package.json b/tests/fixtures/immutable-install/package.json new file mode 100644 index 0000000..f4f1e6e --- /dev/null +++ b/tests/fixtures/immutable-install/package.json @@ -0,0 +1,4 @@ +{ + "private": true, + "workspaces": ["a", "b"] +} diff --git a/tests/fixtures/immutable-install/third_party/jazelle/BUILD.bazel b/tests/fixtures/immutable-install/third_party/jazelle/BUILD.bazel new file mode 100644 index 0000000..0c7b925 --- /dev/null +++ b/tests/fixtures/immutable-install/third_party/jazelle/BUILD.bazel @@ -0,0 +1,8 @@ +load("@jazelle//:build-rules.bzl", "web_library") + +package(default_visibility = ["//visibility:public"]) + +web_library( + name = "node_modules", + srcs = glob(["**/*"]), +) diff --git a/tests/fixtures/immutable-install/third_party/jazelle/scripts/build-file-template.js b/tests/fixtures/immutable-install/third_party/jazelle/scripts/build-file-template.js new file mode 100644 index 0000000..4f74739 --- /dev/null +++ b/tests/fixtures/immutable-install/third_party/jazelle/scripts/build-file-template.js @@ -0,0 +1,8 @@ +// @flow +module.exports.template = ({name, path, label, dependencies}) => ` +# +# name: ${name} +# path: ${path} +# label: ${label} +# dependencies: ${dependencies.join('|')} +#`; diff --git a/tests/fixtures/immutable-install/yarn.lock b/tests/fixtures/immutable-install/yarn.lock new file mode 100644 index 0000000..e69de29 diff --git a/tests/index.js b/tests/index.js index e28684d..ba192e3 100644 --- a/tests/index.js +++ b/tests/index.js @@ -6,7 +6,7 @@ const {readFileSync, createWriteStream} = require('fs'); const {runCLI} = require('../index'); const {init} = require('../commands/init.js'); const {scaffold} = require('../commands/scaffold.js'); -const {install} = require('../commands/install.js'); +const {install, ImmutableInstallError} = require('../commands/install.js'); const {add} = require('../commands/add.js'); const {bazel: bazelCmd} = require('../commands/bazel.js'); const {upgrade} = require('../commands/upgrade.js'); @@ -233,6 +233,7 @@ async function runTests() { await t(testBazelDependentBuilds); await t(testBazelDependentFailure); await t(testShouldInstall); + await t(testImmutableInstall); await exec(`rm -rf ${tmp}/tmp`); console.log('All tests pass'); @@ -1058,11 +1059,75 @@ async function testFindLocalDependency() { assert.deepEqual(notFound, undefined); } +async function testImmutableInstall() { + const fixtureName = 'immutable-install'; + const fixturePath = `${__dirname}/fixtures/${fixtureName}`; + const root = `${tmp}/tmp/${fixtureName}`; + + // fails when files would have been generated + { + await exec(`rm -rf ${root}`); + await exec(`cp -r ${fixturePath}/ ${root}`); + + try { + await install({root, cwd: root, immutable: true}); + // $FlowFixMe: bad libdef? + assert.fail('install should not succeed'); + } catch (error) { + if (!(error instanceof ImmutableInstallError)) throw error; + + const expectedChangedFiles = [ + '.bazelignore', + 'a/BUILD.bazel', + 'b/BUILD.bazel', + ]; + assert(error.changedFiles.length === expectedChangedFiles.length); + for (const file of expectedChangedFiles) { + assert( + error.changedFiles.includes(file), + `${file} should have been returned as a changed file` + ); + if (file === 'b/BUILD.bazel') { + // compare file with the original fixture file + assert( + (await read(`${root}/${file}`, 'utf-8')) === + (await read(`${fixturePath}/${file}`, 'utf-8')), + `${file} should not have been changed` + ); + } else { + assert( + !(await exists(`${root}/${file}`)), + `${file} should not have been written to disk` + ); + } + } + } + } + + // passes when no files need to be generated + { + await exec(`rm -rf ${root}`); + await exec(`cp -r ${fixturePath}/ ${root}`); + + // first run an install without `immutable` to prime the fixture + // with all the generated files + await install({root, cwd: root}); + + try { + await install({root, cwd: root, immutable: true}); + } catch (error) { + // $FlowFixMe: bad libdef? + assert.fail('install should succeed'); + } + } +} + async function testGenerateBazelignore() { const cmd = `cp -r ${__dirname}/fixtures/generate-bazelignore/ ${tmp}/tmp/generate-bazelignore`; await exec(cmd); await generateBazelignore({ root: `${tmp}/tmp/generate-bazelignore`, + immutable: false, projects: ['a', 'b'], }); const bazelignoreFile = `${tmp}/tmp/generate-bazelignore/.bazelignore`; @@ -1076,6 +1141,7 @@ async function testGenerateBazelBuildRules() { await exec(cmd); await generateBazelBuildRules({ root: `${tmp}/tmp/generate-bazel-build-rules`, + immutable: false, deps: [ { meta: JSON.parse( @@ -1122,6 +1188,7 @@ async function testGenerateBazelBuildRulesUpdate() { await exec(cmd); await generateBazelBuildRules({ root: `${tmp}/tmp/generate-bazel-build-rules-update`, + immutable: false, deps: [ { meta: JSON.parse( diff --git a/utils/cli.js b/utils/cli.js index 49a9a21..2b6a037 100644 --- a/utils/cli.js +++ b/utils/cli.js @@ -44,14 +44,32 @@ const cli /*: Cli */ = async (command, args, options, fallback) => { } } } catch (error) { - console.error(error.stack); - if (typeof error.status === 'number') { - process.exit(error.status); + if (error instanceof CliError) { + console.error(error.message); + process.exit(error.exitCode); } else { - process.exit(1); + console.error(error.stack); + if (typeof error.status === 'number') { + process.exit(error.status); + } else { + process.exit(1); + } } } } }; -module.exports = {cli}; +/** + * A way for a CLI command to control the error message + * that's emitted and the exit code of the process. + */ +class CliError extends Error { + /*:: exitCode: number; */ + + constructor(message /*: string */, exitCode /*: number */) { + super(message); + this.exitCode = exitCode; + } +} + +module.exports = {cli, CliError}; diff --git a/utils/generate-bazel-build-rules.js b/utils/generate-bazel-build-rules.js index a56af21..7e1a67a 100644 --- a/utils/generate-bazel-build-rules.js +++ b/utils/generate-bazel-build-rules.js @@ -17,8 +17,10 @@ export type GenerateBazelBuildRulesArgs = { deps: Array, projects: Array, dependencySyncRule: string, + immutable: boolean, } -export type GenerateBazelBuildRules = (GenerateBazelBuildRulesArgs) => Promise +// returns list of changed files +export type GenerateBazelBuildRules = (GenerateBazelBuildRulesArgs) => Promise> export type TemplateArgs = { name: string, path: string, @@ -32,22 +34,35 @@ const generateBazelBuildRules /*: GenerateBazelBuildRules */ = async ({ deps, projects, dependencySyncRule, + immutable, }) => { const depMap = deps.reduce((map, dep) => { map[dep.meta.name] = dep; return map; }, {}); + const changedFiles /*: Array */ = []; await Promise.all( deps.map(async dep => { - const build = `${dep.dir}/BUILD.bazel`; + const buildFilePath = `${dep.dir}/BUILD.bazel`; + const buildFileExists = await exists(buildFilePath); + + if (!buildFileExists) { + changedFiles.push(relative(root, buildFilePath)); + + if (immutable) { + // don't need to do any more work since we know it will change + return; + } + } + const dependencies = [ ...new Set([ ...getDepLabels(root, depMap, dep.meta.dependencies), ...getDepLabels(root, depMap, dep.meta.devDependencies), ]), ].sort(); - if (!(await exists(build))) { + if (!buildFileExists) { // generate BUILD.bazel file const path = relative(root, dep.dir); const name = basename(path); @@ -59,10 +74,10 @@ const generateBazelBuildRules /*: GenerateBazelBuildRules */ = async ({ label: `//${path}:${name}`, dependencies, }); - await write(build, rules.trim(), 'utf8'); + await write(buildFilePath, rules.trim(), 'utf8'); } else { // sync web_library deps list in BUILD.bazel with local dependencies in package.json - const src = await read(build, 'utf8'); + const src = await read(buildFilePath, 'utf8'); let code = src; const items = getCallArgItems(code, dependencySyncRule, 'deps'); dependencies @@ -91,10 +106,18 @@ const generateBazelBuildRules /*: GenerateBazelBuildRules */ = async ({ } }); const sorted = sortCallArgItems(code, dependencySyncRule, 'deps'); - if (src.trim() !== sorted.trim()) await write(build, sorted, 'utf8'); + if (src.trim() !== sorted.trim()) { + changedFiles.push(relative(root, buildFilePath)); + + if (!immutable) { + await write(buildFilePath, sorted, 'utf8'); + } + } } }) ); + + return changedFiles; }; const getDepLabels = (root, depMap, dependencies = {}) => { diff --git a/utils/generate-bazelignore.js b/utils/generate-bazelignore.js index 08005c6..57709ff 100644 --- a/utils/generate-bazelignore.js +++ b/utils/generate-bazelignore.js @@ -4,13 +4,20 @@ const {read, write} = require('./node-helpers.js'); /*:: export type GenerateBazelignoreArgs = { root: string, + immutable: boolean, }; -export type GenerateBazelignore = (GenerateBazelignoreArgs) => Promise; +// returns list of changed files +export type GenerateBazelignore = (GenerateBazelignoreArgs) => Promise>; */ -const generateBazelignore /*: GenerateBazelignore */ = async ({root}) => { - const file = `${root}/.bazelignore`; +const generateBazelignore /*: GenerateBazelignore */ = async ({ + root, + immutable, +}) => { + const fileName = '.bazelignore'; + const file = `${root}/${fileName}`; const bazelignore = await read(file, 'utf8').catch(() => ''); + const changedFiles /*: Array */ = []; const ignorePaths = [ ...new Set([ @@ -21,8 +28,14 @@ const generateBazelignore /*: GenerateBazelignore */ = async ({root}) => { ]; const updated = ignorePaths.sort().filter(Boolean).join('\n'); if (bazelignore.trim() !== updated.trim()) { - await write(`${root}/.bazelignore`, updated + '\n', 'utf8'); + changedFiles.push(fileName); + + if (!immutable) { + await write(`${root}/.bazelignore`, updated + '\n', 'utf8'); + } } + + return changedFiles; }; module.exports = {generateBazelignore}; From 41519af556b988615ca6aa11f9e9e8267f76f1ec Mon Sep 17 00:00:00 2001 From: Chris Deacy Date: Fri, 10 Jan 2025 11:17:39 -0800 Subject: [PATCH 2/5] fix starlark util --- utils/starlark.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/starlark.js b/utils/starlark.js index 89be630..1936e36 100644 --- a/utils/starlark.js +++ b/utils/starlark.js @@ -104,7 +104,7 @@ const sortCallArgItems /*: SortCallArgItems */ = (code, caller, argName) => { .filter(Boolean) .sort() .join(','); - return `[${sorted},${dedent}]`.replace(/,]/, ']'); + return `[${sorted},${dedent}]`.replace(/,]/, ']').replace(/\[,/, '['); }); }); }); From 58359486f6584c1b207380b51673b94c78e62a5b Mon Sep 17 00:00:00 2001 From: Chris Deacy Date: Fri, 10 Jan 2025 11:34:30 -0800 Subject: [PATCH 3/5] debug --- tests/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/index.js b/tests/index.js index ba192e3..01925bd 100644 --- a/tests/index.js +++ b/tests/index.js @@ -1111,7 +1111,7 @@ async function testImmutableInstall() { // first run an install without `immutable` to prime the fixture // with all the generated files - await install({root, cwd: root}); + await install({root, cwd: root, verbose: true}); try { await install({root, cwd: root, immutable: true}); From 7366ef1a615f8f5a8d43dda04775acc7c967c882 Mon Sep 17 00:00:00 2001 From: Chris Deacy Date: Fri, 10 Jan 2025 11:43:28 -0800 Subject: [PATCH 4/5] try fix --- tests/fixtures/immutable-install/yarn.lock | 26 ++++++++++++++++++++++ tests/index.js | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/fixtures/immutable-install/yarn.lock b/tests/fixtures/immutable-install/yarn.lock index e69de29..6b08a16 100644 --- a/tests/fixtures/immutable-install/yarn.lock +++ b/tests/fixtures/immutable-install/yarn.lock @@ -0,0 +1,26 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 8 + cacheKey: 10c0 + +"a@npm:0.0.0, a@workspace:a": + version: 0.0.0-use.local + resolution: "a@workspace:a" + languageName: unknown + linkType: soft + +"b@workspace:b": + version: 0.0.0-use.local + resolution: "b@workspace:b" + dependencies: + a: "npm:0.0.0" + languageName: unknown + linkType: soft + +"root-workspace-0b6124@workspace:.": + version: 0.0.0-use.local + resolution: "root-workspace-0b6124@workspace:." + languageName: unknown + linkType: soft diff --git a/tests/index.js b/tests/index.js index 01925bd..ba192e3 100644 --- a/tests/index.js +++ b/tests/index.js @@ -1111,7 +1111,7 @@ async function testImmutableInstall() { // first run an install without `immutable` to prime the fixture // with all the generated files - await install({root, cwd: root, verbose: true}); + await install({root, cwd: root}); try { await install({root, cwd: root, immutable: true}); From 17d077c22dc48f980478e57143335d40d5c3d2da Mon Sep 17 00:00:00 2001 From: Chris Deacy Date: Fri, 10 Jan 2025 11:52:34 -0800 Subject: [PATCH 5/5] try fix --- tests/fixtures/immutable-install/yarn.lock | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/fixtures/immutable-install/yarn.lock b/tests/fixtures/immutable-install/yarn.lock index 6b08a16..84af893 100644 --- a/tests/fixtures/immutable-install/yarn.lock +++ b/tests/fixtures/immutable-install/yarn.lock @@ -2,10 +2,9 @@ # Manual changes might be lost - proceed with caution! __metadata: - version: 8 - cacheKey: 10c0 + version: 6 -"a@npm:0.0.0, a@workspace:a": +"a@0.0.0, a@workspace:a": version: 0.0.0-use.local resolution: "a@workspace:a" languageName: unknown @@ -15,7 +14,7 @@ __metadata: version: 0.0.0-use.local resolution: "b@workspace:b" dependencies: - a: "npm:0.0.0" + a: 0.0.0 languageName: unknown linkType: soft