-
Notifications
You must be signed in to change notification settings - Fork 3
Review for buildNpmPackage #2
Changes from all commits
33ca36a
b11dd41
b418dd5
d8cbeab
0aec71f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
{ stdenvNoCC, writeShellScriptBin, writeText, stdenv, fetchurl, makeWrapper, nodejs-10_x }: | ||
with stdenv.lib; | ||
let | ||
inherit (builtins) fromJSON toJSON split; | ||
|
||
depsToFetches = deps: concatMap depToFetch (attrValues deps); | ||
depFetchOwn = { resolved, integrity, ... }: let | ||
ssri = split "-" integrity; # standard subresource integrity | ||
hashType = head ssri; | ||
hash = elemAt ssri 2; | ||
in nameValuePair resolved (fetchurl { | ||
url = resolved; | ||
"${hashType}" = hash; | ||
}); | ||
|
||
depToFetch = args @ { resolved ? null, dependencies ? {}, ... }: | ||
(optional (resolved != null) (depFetchOwn args)) ++ (depsToFetches dependencies); | ||
|
||
npmCacheInput = lock: writeText "npm-cache-input.json" (toJSON (listToAttrs (depToFetch lock))); | ||
|
||
patchShebangs = writeShellScriptBin "patchShebangs.sh" '' | ||
set -e | ||
source ${stdenvNoCC}/setup | ||
patchShebangs "$@" | ||
''; | ||
|
||
shellWrap = writeShellScriptBin "npm-shell-wrap.sh" '' | ||
set -e | ||
if [ ! -e .shebangs_patched ]; then | ||
${patchShebangs}/bin/patchShebangs.sh . | ||
touch .shebangs_patched | ||
fi | ||
exec bash "$@" | ||
''; | ||
in | ||
args @ { lockfile, src, buildInputs ? [], npmFlags ? [], ... }: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where is |
||
let | ||
lock = fromJSON (readFile lockfile); | ||
in | ||
stdenv.mkDerivation ({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is |
||
inherit (lock) version; | ||
name = "${lock.name}-${lock.version}"; | ||
|
||
XDG_CONFIG_DIRS = "."; | ||
NO_UPDATE_NOTIFIER = true; | ||
preBuildPhases = [ "npmCachePhase" ]; | ||
preInstallPhases = [ "npmPackPhase" ]; | ||
installJavascript = true; | ||
npmCachePhase = '' | ||
node ${./mkcache.js} ${npmCacheInput lock} | ||
''; | ||
buildPhase = '' | ||
runHook preBuild | ||
npm ci $npmFlags | ||
runHook postBuild | ||
''; | ||
# make a package .tgz (no way around it) | ||
npmPackPhase = '' | ||
npm prune --production $npmFlags | ||
npm pack --ignore-scripts $npmFlags | ||
''; | ||
# unpack the .tgz into output directory and add npm wrapper | ||
installPhase = '' | ||
mkdir -p $out/bin | ||
tar xzvf ./${lock.name}-${lock.version}.tgz -C $out --strip-components=1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could use |
||
if [ "$installJavascript" -eq "1" ]; then | ||
cp -R node_modules $out/ | ||
makeWrapper ${nodejs-10_x}/bin/npm $out/bin/npm --run "cd $out" | ||
fi | ||
''; | ||
} // args // { | ||
buildInputs = [ nodejs-10_x makeWrapper ] ++ buildInputs; | ||
npmFlags = [ "--cache=./npm-cache" "--offline" "--script-shell=${shellWrap}/bin/npm-shell-wrap.sh" ] ++ npmFlags; | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
const assert = require('assert') | ||
const fs = require('fs') | ||
const path = require('path') | ||
const {promisify} = require('util') | ||
|
||
// find pacote from npm dependencies | ||
module.paths.push(path.join(process.argv[0], "../../lib/node_modules/npm/node_modules")) | ||
const pacote = require('pacote') | ||
lukateras marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
function traverseDeps(pkg, fn) { | ||
Object.values(pkg.dependencies).forEach(dep => { | ||
if (dep.resolved && dep.integrity) fn(dep) | ||
if (dep.dependencies) traverseDeps(dep, fn) | ||
}) | ||
} | ||
|
||
async function main(lockfile, nix, cache) { | ||
var promises = Object.keys(nix).map(async function(url) { | ||
var tar = nix[url] | ||
const manifest = await pacote.manifest(tar, {offline: true, cache}) | ||
return [url, manifest._integrity] | ||
}) | ||
var hashes = new Map(await Promise.all(promises)) | ||
traverseDeps(lockfile, dep => { | ||
if (dep.integrity.startsWith("sha1-")) { | ||
assert(hashes.has(dep.resolved)) | ||
dep.integrity = hashes.get(dep.resolved) | ||
obfusk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
else { | ||
assert(dep.integrity == hashes.get(dep.resolved)) | ||
} | ||
}) | ||
await promisify(fs.writeFile)("./package-lock.json", JSON.stringify(lock, null, 4)) | ||
obfusk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
const lock = JSON.parse(fs.readFileSync('./package-lock.json', 'utf8')) | ||
const nix_pkgs = JSON.parse(fs.readFileSync(process.argv[2], 'utf8')) | ||
main(lock, nix_pkgs, './npm-cache/_cacache') | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,8 @@ in | |
rev = "76dc0f06d21f6063cb7b7d2291b8623da24affa9"; | ||
}) {}; | ||
|
||
buildNpmPackage = callPackage ./buildNpmPackage {}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be nicer if this were a separate repo, I don't think it's right to commit JS code into a closure which is supposed to mostly point to stuff. |
||
|
||
buildMacOSApp = callPackage (fetchGit { | ||
url = https://github.com/serokell/nix-macos-app; | ||
rev = "192f3c22b4270be84aef9176fdf52a41d0d85b32"; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aren't you also getting non-production dependencies here?