mirror of
https://github.com/nix-community/dream2nix.git
synced 2024-09-11 14:35:30 +03:00
run install scripts: init
add option: 'trustedDeps'. Only install scripts of explizit added dependencies are run. In the future there may be wildcards to allow running all install scripts
This commit is contained in:
parent
0af1c36d17
commit
57fd52adcd
@ -123,6 +123,7 @@
|
||||
# TODO: Verify this is reasonable default;
|
||||
source = builtins.dirOf cfg.packageLockFile;
|
||||
makeNodeModules = ./build-node-modules.mjs;
|
||||
installTrusted = ./install-trusted-modules.mjs;
|
||||
in
|
||||
if path == ""
|
||||
then let
|
||||
@ -144,14 +145,17 @@
|
||||
name = entry.name + "-dist";
|
||||
src = source;
|
||||
buildInputs = with config.deps; [nodejs jq];
|
||||
env = {
|
||||
TRUSTED = builtins.toJSON cfg.trustedDeps;
|
||||
};
|
||||
configurePhase = ''
|
||||
cp -r ${prepared-dev}/node_modules node_modules
|
||||
# TODO: run installScripts of trusted dependencies
|
||||
|
||||
node ${installTrusted}
|
||||
'';
|
||||
buildPhase = ''
|
||||
echo "BUILDING... $name"
|
||||
if [ -n "$runBuild" ] && [ "$(jq '.scripts.build' ./package.json)" != "null" ]; then
|
||||
if [ "$(jq '.scripts.build' ./package.json)" != "null" ]; then
|
||||
echo "npm run build"
|
||||
npm run build
|
||||
fi;
|
||||
'';
|
||||
|
@ -0,0 +1,90 @@
|
||||
import fs from "fs";
|
||||
import { abort } from "process";
|
||||
import { execSync } from "child_process";
|
||||
|
||||
const { TRUSTED } = process.env;
|
||||
|
||||
/**@type {string[]} */
|
||||
const trusted = JSON.parse(TRUSTED);
|
||||
console.log({ trusted });
|
||||
|
||||
/**
|
||||
* @type {fs.Dirent[]}*/
|
||||
const packageJsonFiles = fs
|
||||
.readdirSync(
|
||||
"./node_modules",
|
||||
{ recursive: true, withFileTypes: true },
|
||||
(error) => {
|
||||
console.error({ error });
|
||||
abort();
|
||||
}
|
||||
)
|
||||
.filter(
|
||||
(/**@type {fs.Dirent}*/ entry) =>
|
||||
entry.isFile() &&
|
||||
entry.name === "package.json" &&
|
||||
// Reduce the number of packageJson files that we need to parse.
|
||||
// Note: The list may still have some false positives. They will be skipped later
|
||||
trusted.some((trustedName) => entry.path.endsWith(trustedName))
|
||||
);
|
||||
|
||||
// If a dependency is trusted
|
||||
// Run the following scripts if present
|
||||
//
|
||||
// preinstall
|
||||
// install
|
||||
// postinstall
|
||||
// prepublish
|
||||
// preprepare
|
||||
// prepare
|
||||
// postprepare
|
||||
//
|
||||
// The lifecycle scripts run only after node_modules are completely initialized with ALL modules
|
||||
//
|
||||
// Lifecycle scripts can execute arbitrary code.
|
||||
// They often violate isolation between packages which makes them potentially insecure.
|
||||
|
||||
const lifecycleScripts = [
|
||||
"preinstall",
|
||||
"install",
|
||||
"postinstall",
|
||||
"prepublish",
|
||||
"preprepare",
|
||||
"prepare",
|
||||
"postprepare",
|
||||
];
|
||||
|
||||
packageJsonFiles.forEach((pjs) => {
|
||||
const content = fs.readFileSync(`${pjs.path}/${pjs.name}`);
|
||||
|
||||
/**@type {{scripts?: { [k: string]: string}, name: string }}*/
|
||||
const info = JSON.parse(content.toString());
|
||||
const { scripts, name: packageName } = info;
|
||||
|
||||
// Skip false positives
|
||||
if (trusted.includes(packageName)) {
|
||||
const run =
|
||||
scripts &&
|
||||
Object.entries(scripts).filter(([k]) =>
|
||||
lifecycleScripts.some((s) => s === k)
|
||||
);
|
||||
if (run) {
|
||||
run.forEach(([scriptName, command]) => {
|
||||
console.log(`${packageName} - ${scriptName}: ${command}`);
|
||||
try {
|
||||
const result = execSync(command, { cwd: pjs.path });
|
||||
console.log(result.toString());
|
||||
} catch (err) {
|
||||
console.error(
|
||||
`Could not execute lifecycle script '${scriptName}' for ${packageName} (See Trusted Dependencies)`
|
||||
);
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.warn(
|
||||
`Trusted package ${packageName} doesnt have any lifecycle scripts. This entry does not have any affect.`
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
@ -14,11 +14,50 @@ in {
|
||||
The package-lock.json file to use.
|
||||
'';
|
||||
};
|
||||
|
||||
packageLock = {
|
||||
type = t.attrs;
|
||||
description = "The content of the package-lock.json";
|
||||
};
|
||||
|
||||
trustedDeps = {
|
||||
type = t.listOf (t.str);
|
||||
default = [];
|
||||
example = ["@babel/core"];
|
||||
description = ''
|
||||
A list of trusted dependencies.
|
||||
|
||||
If a dependency is trusted.
|
||||
Run the following scripts in order if present:
|
||||
|
||||
> All versions of a dependency are trusted if there are multiple versions.
|
||||
|
||||
preinstall
|
||||
install
|
||||
postinstall
|
||||
prepublish
|
||||
preprepare
|
||||
prepare
|
||||
postprepare
|
||||
|
||||
The lifecycle scripts run only after node_modules are completely initialized with ALL dependencies.
|
||||
Lifecycle scripts can execute arbitrary code. Which makes them potentially insecure.
|
||||
They often violate isolation between packages. Which makes them potentially insecure.
|
||||
|
||||
*TODO*:
|
||||
|
||||
Trust all dependencies:
|
||||
|
||||
trustedDeps [ "*" ]
|
||||
|
||||
Trust all dependencies starting with "@org"
|
||||
|
||||
trustedDeps [ "@org/*" ]
|
||||
|
||||
which is usefull if you want to add all dependendencies within an organization.
|
||||
'';
|
||||
};
|
||||
|
||||
inherit
|
||||
(import ./types.nix {
|
||||
inherit
|
||||
|
Loading…
Reference in New Issue
Block a user