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
|
||||
Package or a runnable Yarn project. Its `devShell` supplies freestanding Yarn for
|
||||
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
|
||||
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 = _: {
|
||||
buildPhase = "runHook preBuild; runHook postBuild";
|
||||
installPhase = ''
|
||||
set -o pipefail
|
||||
runHook preInstall
|
||||
test -d node_modules
|
||||
test ! -L node_modules
|
||||
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
|
||||
# Yarn's linker, not a runtime input; do not export build-session state.
|
||||
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