Retire staged Yarn dependencies during Nix installation (#473)
This commit is contained in:
parent
43fcf6b27a
commit
a962586381
@@ -69,6 +69,12 @@ describes its install-state file as an optimization cache in its
|
|||||||
This helper output is a dependency directory for a build, not a standalone
|
This helper output is a dependency directory for a build, not a standalone
|
||||||
Package or a runnable Yarn project. Its `devShell` supplies freestanding Yarn for
|
Package or a runnable Yarn project. Its `devShell` supplies freestanding Yarn for
|
||||||
editable projects; do not run Yarn against the readonly dependency output.
|
editable projects; do not run Yarn against the readonly dependency output.
|
||||||
|
Installation discards its disposable archive cache and streams dependencies into
|
||||||
|
the output while retiring staged files, including across separate build/store
|
||||||
|
mounts. It preserves package layout, native results, hidden data and executable
|
||||||
|
links without holding two complete dependency trees. The maintained
|
||||||
|
`camino-yarn-dependencies` check covers transfer and runtime layout; consuming
|
||||||
|
Studio and Package-builder checks retain real locked-installation coverage.
|
||||||
|
|
||||||
Use the shared `installDependencies` assembly for consumers: authored libraries
|
Use the shared `installDependencies` assembly for consumers: authored libraries
|
||||||
are copied into the consumer's `node_modules`, where Node can find their
|
are copied into the consumer's `node_modules`, where Node can find their
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# Tiny generated-project interface fixture. Real offline Yarn installation
|
||||||
|
# remains covered by the consuming Studio and Package-builder checks.
|
||||||
|
{ stdenvNoCC, nodejs }:
|
||||||
|
{ src, overrideAttrs ? null }:
|
||||||
|
let
|
||||||
|
project = stdenvNoCC.mkDerivation {
|
||||||
|
name = "yarn-dependencies-transfer-fixture";
|
||||||
|
inherit src;
|
||||||
|
configurePhase = ''
|
||||||
|
mkdir -p node_modules/fixture node_modules/.bin .yarn/cache
|
||||||
|
printf '%s\n' '{"main":"index.cjs"}' > node_modules/fixture/package.json
|
||||||
|
printf '%s\n' 'module.exports = {value: "retained dependency"};' > node_modules/fixture/index.cjs
|
||||||
|
ln node_modules/fixture/index.cjs node_modules/fixture/twin.cjs
|
||||||
|
ln -s fixture node_modules/alias
|
||||||
|
printf '%s\n' '#!${nodejs}/bin/node' 'console.log("linked executable");' > node_modules/fixture/cli.cjs
|
||||||
|
chmod +x node_modules/fixture/cli.cjs
|
||||||
|
ln -s ../fixture/cli.cjs node_modules/.bin/fixture
|
||||||
|
printf '%s\n' 'hidden dependency data' > node_modules/.fixture-data
|
||||||
|
printf '%s\n' 'disposable linker state' > node_modules/.yarn-state.yml
|
||||||
|
printf '%s\n' 'disposable archive' > .yarn/cache/fixture.zip
|
||||||
|
'';
|
||||||
|
postInstall = ''
|
||||||
|
test ! -e node_modules
|
||||||
|
test ! -e .yarn/cache
|
||||||
|
test ! -e "$out/.yarn-state.yml"
|
||||||
|
test ! -e "$out/node_modules"
|
||||||
|
test "$(stat -c %i "$out/fixture/index.cjs")" = "$(stat -c %i "$out/fixture/twin.cjs")"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
in
|
||||||
|
if overrideAttrs == null then project else project.overrideAttrs overrideAttrs
|
||||||
@@ -9,10 +9,18 @@ let
|
|||||||
overrideAttrs = _: {
|
overrideAttrs = _: {
|
||||||
buildPhase = "runHook preBuild; runHook postBuild";
|
buildPhase = "runHook preBuild; runHook postBuild";
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
|
set -o pipefail
|
||||||
runHook preInstall
|
runHook preInstall
|
||||||
test -d node_modules
|
test -d node_modules
|
||||||
|
test ! -L node_modules
|
||||||
mkdir -p "$out"
|
mkdir -p "$out"
|
||||||
cp -a node_modules/. "$out/"
|
# Installation is finished: retire its disposable archive cache, then
|
||||||
|
# stream dependencies across the build/store mount boundary without
|
||||||
|
# retaining a second complete tree. This is the same installation
|
||||||
|
# policy used by Central's dependency derivations.
|
||||||
|
rm -rf .yarn/cache
|
||||||
|
${pkgs.gnutar}/bin/tar --create --file=- --remove-files node_modules \
|
||||||
|
| ${pkgs.gnutar}/bin/tar --extract --file=- --strip-components=1 --directory="$out"
|
||||||
# Node resolves installed packages directly. This generated index is for
|
# Node resolves installed packages directly. This generated index is for
|
||||||
# Yarn's linker, not a runtime input; do not export build-session state.
|
# Yarn's linker, not a runtime input; do not export build-session state.
|
||||||
rm -f "$out/.yarn-state.yml"
|
rm -f "$out/.yarn-state.yml"
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
{ pkgs }:
|
||||||
|
let
|
||||||
|
dependencies = import ./yarn-dependencies.nix {
|
||||||
|
inherit pkgs;
|
||||||
|
src = ./test/yarn-dependencies;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
pkgs.runCommand "quixos-yarn-dependencies-check" { nativeBuildInputs = [ pkgs.nodejs_24 ]; } ''
|
||||||
|
node - ${dependencies} <<'JS'
|
||||||
|
const assert = require('node:assert/strict');
|
||||||
|
const fs = require('node:fs');
|
||||||
|
const path = require('node:path');
|
||||||
|
const {execFileSync} = require('node:child_process');
|
||||||
|
const root = process.argv[2];
|
||||||
|
assert.deepEqual(require(path.join(root, 'fixture')), {value: 'retained dependency'});
|
||||||
|
assert.deepEqual(require(path.join(root, 'alias')), {value: 'retained dependency'});
|
||||||
|
assert.equal(fs.readlinkSync(path.join(root, 'alias')), 'fixture');
|
||||||
|
assert.equal(fs.readlinkSync(path.join(root, '.bin/fixture')), '../fixture/cli.cjs');
|
||||||
|
assert.equal(execFileSync(path.join(root, '.bin/fixture'), {encoding: 'utf8'}), 'linked executable\n');
|
||||||
|
assert.equal(fs.readFileSync(path.join(root, '.fixture-data'), 'utf8'), 'hidden dependency data\n');
|
||||||
|
assert.equal(fs.existsSync(path.join(root, '.yarn-state.yml')), false);
|
||||||
|
JS
|
||||||
|
touch "$out"
|
||||||
|
''
|
||||||
Reference in New Issue
Block a user