From 25b10bd1a93e12a7e49fee38b0a229281ae49fb7 Mon Sep 17 00:00:00 2001 From: Jakub Jirutka <jakub@jirutka.cz> Date: Sun, 11 Apr 2021 00:33:39 +0200 Subject: [PATCH] main/nodejs: move npm into a standalone aport npm is bundled in Node.js, but it's a standalone project with its own release cycle and version number. main/nodejs provides LTS version of Node.js, so it includes old version of npm. Alpine build tools don't handle subpackages with pkgver different from the origin pkgver. Thus the current 'npm' subpackage has version 14.16.1-r0 (version of the Node.js) which is confusing, because the real version of the packaged 'npm' is 6.14.11. Moreover, npm has gazillion bundled dependencies, so there's a high risk of security vulnerabilities; using npm bundled in Node.js quite complicates security patching and requires rebuilding complete Node.js package. For these reasons, I think it will be better to split npm into a separate aport and provide the latest version instead of some arbitrary version bundled in the Node.js tarball. Actually, I planned this three years ago (see commit message in 244cc743c4ae2fd0f517b74790674864cb293e9c), but forgot about it. There's one unpleasant consequence of this change - the latest npm version is 7.9.0 which is lower than 14.16.1 (version inherited from nodejs package). Since Alpine doesn't have "epoch" version as e.g. Fedora, there's nothing I can do about it beside informing the users (using nodejs.post-upgrade script). --- main/nodejs/APKBUILD | 39 ++---- main/nodejs/nodejs.post-upgrade | 26 ++++ main/npm/APKBUILD | 116 ++++++++++++++++++ main/npm/dont-check-for-last-version.patch | 18 +++ main/npm/make-dont-install-deps.patch | 11 ++ main/npm/npmrc | 6 + .../reproducible-documentation-build.patch | 20 +++ main/npm/smoke-tests-npm-location.patch | 23 ++++ 8 files changed, 229 insertions(+), 30 deletions(-) create mode 100644 main/nodejs/nodejs.post-upgrade create mode 100644 main/npm/APKBUILD create mode 100644 main/npm/dont-check-for-last-version.patch create mode 100644 main/npm/make-dont-install-deps.patch create mode 100644 main/npm/npmrc create mode 100644 main/npm/reproducible-documentation-build.patch create mode 100644 main/npm/smoke-tests-npm-location.patch diff --git a/main/nodejs/APKBUILD b/main/nodejs/APKBUILD index 9e52df1a0716..bb1b6648af4c 100644 --- a/main/nodejs/APKBUILD +++ b/main/nodejs/APKBUILD @@ -68,7 +68,7 @@ pkgname=nodejs # Note: Update only to even-numbered versions (e.g. 6.y.z, 8.y.z)! # Odd-numbered versions are supported only for 9 months by upstream. pkgver=14.16.1 -pkgrel=0 +pkgrel=1 pkgdesc="JavaScript runtime built on V8 engine - LTS version" url="https://nodejs.org/" arch="all !mips64 !mips64el" @@ -84,7 +84,8 @@ makedepends=" python3 zlib-dev " -subpackages="$pkgname-dev $pkgname-doc npm::noarch" +install="$pkgname.post-upgrade" +subpackages="$pkgname-dev $pkgname-doc" provides="nodejs-lts=$pkgver" # for backward compatibility replaces="nodejs-current nodejs-lts" # nodejs-lts for backward compatibility source="https://nodejs.org/dist/v$pkgver/node-v$pkgver.tar.gz @@ -121,6 +122,10 @@ build() { # couldn't upgrade nodejs package in stable branches to fix CVEs due to # libuv incompatibility. # + # NOTE: We don't package the bundled npm - it's a separate project with + # its own release cycle and version numbering, so it's better to keep + # it in a standalone aport. + # # TODO: After icu package is modified to split data into multiple # variants, change --with-intl to "system-icu". python3 configure.py --prefix=/usr \ @@ -132,7 +137,8 @@ build() { --shared-nghttp2 \ --openssl-use-def-ca-store \ --with-icu-default-data-dir=$(icu-config --icudatadir) \ - --with-intl=small-icu + --with-intl=small-icu \ + --without-npm make BUILDTYPE=Release } @@ -147,19 +153,6 @@ check() { package() { make DESTDIR="$pkgdir" install - - cp -pr "$pkgdir"/usr/lib/node_modules/npm/man "$pkgdir"/usr/share - local d; for d in docs man; do - rm -r "$pkgdir"/usr/lib/node_modules/npm/$d - done - - # XXX: Workaround for https://github.com/npm/cli/issues/780. - (cd "$pkgdir"/usr/share/man/man5 && find * \ - -type f ! \( -name 'package-json.*' -or -name 'npmrc.*' -or -name 'npm-*' \) \ - -exec mv {} npm-{} \;) - (cd "$pkgdir"/usr/share/man/man7 && find * \ - -type f ! \( -name 'semver.*' -or -name 'npm-*' \) \ - -exec mv {} npm-{} \;) } dev() { @@ -167,20 +160,6 @@ dev() { default_dev } -npm() { - pkgdesc="A package manager for JavaScript" - depends="$pkgname" - # for backward compatibility - provides="nodejs-npm=$pkgver-r$pkgrel nodejs-current-npm=$pkgver-r$pkgrel" - replaces="nodejs-npm nodejs-current-npm $pkgname" - - mkdir -p "$subpkgdir"/usr/bin - mv "$pkgdir"/usr/bin/np[mx] "$subpkgdir"/usr/bin/ - - mkdir -p "$subpkgdir"/usr/lib/node_modules - mv "$pkgdir"/usr/lib/node_modules/npm "$subpkgdir"/usr/lib/node_modules/ -} - sha512sums="40843674584c2010958b4faf12290b525f3e5b13d37e52e3b41d50691de16cc0a29ed1fbc81912a0f76f48648c603dfb726242d232e4542f46ab957a4042c05d node-v14.16.1.tar.gz dbe8167b61518f8f59176759d69834d57bf3e6a5a5fd3dfc2359cafe0325da08b27f8220d278ed77f50c9f63a03313eabbbb0eaca3e592e5bb4e0d5be0ced373 disable-running-gyp-on-shared-deps.patch 44e81fbf254bd79e38b813f7f5a1336df854588939cba50aaec600660495f9b7745a7049a99eb59d15a51100b3a44f66892a902d7fc32e1399b51883ad4c02cf link-with-libatomic-on-mips32.patch" diff --git a/main/nodejs/nodejs.post-upgrade b/main/nodejs/nodejs.post-upgrade new file mode 100644 index 000000000000..764aa17ff342 --- /dev/null +++ b/main/nodejs/nodejs.post-upgrade @@ -0,0 +1,26 @@ +#!/bin/sh + +# This file is not provided since splitting npm into a separate aport, +# so we use it to quickly detect presence of the old npm package. +if [ -f /usr/lib/node_modules/npm/configure ]; then + pkg_ver=$(apk info -W /usr/bin/npm 2>/dev/null \ + | sed -En 's/.*owned by npm-([^-]+).*/\1/p' \ + | grep .) || exit 0 + + npm_ver=$(/usr/bin/npm --version 2>/dev/null) || exit 0 + + [ "$pkg_ver" = "$npm_ver" ] && exit 0 + + cat >&2 <<-EOF + * + * You have an old version of the 'npm' package installed + * (pkg version: $pkg_ver, real version: $npm_ver). The newer package + * has a *lower* version number that now corresponds to the actual + * version of the 'npm' program. You have to reinstall the npm package + * (apk del npm; apk add npm) or upgrade all packages to the available + * versions (apk upgrade -a). + * + EOF +fi + +exit 0 diff --git a/main/npm/APKBUILD b/main/npm/APKBUILD new file mode 100644 index 000000000000..886a1e8a1c69 --- /dev/null +++ b/main/npm/APKBUILD @@ -0,0 +1,116 @@ +# Contributor: Jakub Jirutka <jakub@jirutka.cz> +# Maintainer: Jakub Jirutka <jakub@jirutka.cz> +pkgname=npm +pkgver=7.9.0 +pkgrel=0 +pkgdesc="The package manager for JavaScript" +url="https://npm.community" +arch="noarch" +license="Artistic-2.0" +depends="nodejs" +makedepends="bash" +replaces="nodejs-doc" # for backward compatibility +subpackages="$pkgname-doc $pkgname-bashcomp" +source="https://github.com/npm/cli/archive/v$pkgver/npm-cli-$pkgver.tar.gz + reproducible-documentation-build.patch + dont-check-for-last-version.patch + make-dont-install-deps.patch + smoke-tests-npm-location.patch + npmrc + " +builddir="$srcdir/cli-$pkgver" + +prepare() { + default_prepare + + # Remove bunch of unnecessary files to reduce size of the package. + + rm bin/npm bin/npx bin/*.cmd bin/node-gyp-bin/*.cmd + + cd node_modules + find . -type f \( \ + -name '.*' -o \ + -name '*.cmd' -o \ + -name '*.coffee' -o \ + -name '*.bat' -o \ + -name '*.map' -o \ + -name '*.md' -o \ + -name '*.ts' -o \ + -name 'AUTHORS*' -o \ + -name 'LICENSE*' -o \ + -name 'Makefile' -o \ + -name 'README*' -o \) -delete + rm -Rf ./*/.git* ./*/doc ./*/docs ./*/examples ./*/scripts ./*/test + + # No files should be executable here, except node-gyp. + find . -type f -executable ! -name 'node-gyp*' -exec chmod -x {} \; + + cd ../docs/content + + # XXX: Workaround for https://github.com/npm/cli/issues/780. + local f name + for f in configuring-npm/folders.md configuring-npm/install.md using-npm/*.md; do + name=$(basename $f .md) + sed -Ei "s/^title: $name/title: npm-$name/" "$f" + mv "$f" "$(dirname $f)/npm-$name.md" + done + + cd "$builddir" + + # Backup files that will be included in the package before installing + # additional dev dependencies and running tests. + mkdir -p "$srcdir"/npm + cp -r bin lib node_modules package.json "$srcdir"/npm/ + + # Install dependencies needed for mandocs and smoke-tests. + node bin/npm-cli.js install --ignore-scripts --no-audit --no-fund +} + +build() { + # Convert Markdown docs to man pages. + make mandocs + + # Generate bash completions. + node bin/npm-cli.js completion > npm.bash +} + +check() { + make smoke-tests NPM_LOCATION="$srcdir/npm" +} + +package() { + local destdir="$pkgdir/usr/lib/node_modules/npm" + + mkdir -p "$destdir" + cp -r "$srcdir"/npm/* "$destdir"/ + + install -m 644 "$srcdir"/npmrc -t "$destdir"/ + + mkdir -p "$pkgdir"/usr/bin + ln -s ../lib/node_modules/npm/bin/npm-cli.js "$pkgdir"/usr/bin/npm + ln -s ../lib/node_modules/npm/bin/npx-cli.js "$pkgdir"/usr/bin/npx + ln -s ../lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js "$pkgdir"/usr/bin/node-gyp + + cd "$builddir" + + mkdir -p "$pkgdir"/usr/share + cp -r man "$pkgdir"/usr/share/ + ln -s ../../../share/man "$destdir"/man + + install -Dm 644 LICENSE -t "$pkgdir"/usr/share/licenses/$pkgname/ + + install -Dm 644 npm.bash "$pkgdir"/usr/share/bash-completion/completions/npm +} + +doc() { + default_doc + + amove usr/lib/node_modules/npm/man +} + +sha512sums="ad59518cfa8990d61d662de6385489fa0f490f556d5de479890363feb74d8eadc3074e41c5899d09c94c15bc7661766eee20666fca97fac4178e6b26b9c7c6f7 npm-cli-7.9.0.tar.gz +44821978050194c126a9d3c0fb9df9204100d8e88c13a9aa8c0e74769f3a667ce605c1f37e053a658dde6ee8367cf71005ea3f1705b3a95700767bc041a28f15 reproducible-documentation-build.patch +92728357d9d03a40b275ba01980a569dc456f526a415edc22a4582162ff8dcafe8f32cb42f14bc93ea627f1ac9384a42abe2bcdfb8ed04c06491a27b1efc7e40 dont-check-for-last-version.patch +0aed63f6b541378d51794393bf70b6401c7bdbc8c1ebbf35fc8b91c8220fc5ab1753f577908b0dc24bdeaf4f9cabb3bb1a48329c2ac026aba1f479d6a53311d6 make-dont-install-deps.patch +bb0f40db679c4811531e0373cb133dc116cf0efe3e9b4619a73c6897ab440dd99c592fa4f682b72aaef311a231f5b02934b90f9aa538aadb106b49cb3f2ddd91 smoke-tests-npm-location.patch +60c2077177503af872c77fe0fedb039596b40142cead5dc9bcc84675b217b0ce332d5d8da9c2483a6e995e84934290934d64bb216dcdfef7e24ab8e7ea1722c5 npmrc" diff --git a/main/npm/dont-check-for-last-version.patch b/main/npm/dont-check-for-last-version.patch new file mode 100644 index 000000000000..56ca23511aa9 --- /dev/null +++ b/main/npm/dont-check-for-last-version.patch @@ -0,0 +1,18 @@ +Description: don't check for last version +Author: Xavier Guimard <yadd@debian.org> +Forwarded: not-needed +Last-Update: 2021-03-02 + +Patch-Source: https://sources.debian.org/src/npm/7.5.2+ds-2/debian/patches/dont-check-for-last-version.patch + +--- a/lib/utils/update-notifier.js ++++ b/lib/utils/update-notifier.js +@@ -38,6 +38,8 @@ + } + + const updateNotifier = module.exports = async (npm, spec = 'latest') => { ++ // Maintained by Debian JS Team ++ return null; + // never check for updates in CI, when updating npm already, or opted out + if (!npm.config.get('update-notifier') || + isGlobalNpmUpdate(npm) || diff --git a/main/npm/make-dont-install-deps.patch b/main/npm/make-dont-install-deps.patch new file mode 100644 index 000000000000..ac6aa0aa4971 --- /dev/null +++ b/main/npm/make-dont-install-deps.patch @@ -0,0 +1,11 @@ +--- a/Makefile ++++ b/Makefile +@@ -47,7 +47,7 @@ + + ## build-time dependencies for the documentation + dev-deps: +- node bin/npm-cli.js install --no-audit --ignore-scripts ++ true # skip + + ## targets for man files, these are encouraged to be only built by running `make docs` or `make mandocs` + man/man1/%.1: docs/content/commands/%.md scripts/docs-build.js diff --git a/main/npm/npmrc b/main/npm/npmrc new file mode 100644 index 000000000000..c8a17e066e49 --- /dev/null +++ b/main/npm/npmrc @@ -0,0 +1,6 @@ +# Do not modify this file - use /etc/npmrc instead! + +globalconfig=/etc/npmrc +globalignorefile=/etc/npmignore +prefix=/usr +python=/usr/bin/python3 diff --git a/main/npm/reproducible-documentation-build.patch b/main/npm/reproducible-documentation-build.patch new file mode 100644 index 000000000000..2a02d418c7de --- /dev/null +++ b/main/npm/reproducible-documentation-build.patch @@ -0,0 +1,20 @@ +Description: Use source-date-epoch as timestamp source for documentation +Author: James Addison <jay+salsa@jp-hosting.net> +Origin: https://salsa.debian.org/js-team/npm/-/merge_requests/7 +Forwarded: no +Last-Update: 2020-11-11 + +Patch-Source: https://sources.debian.org/src/npm/7.5.2+ds-2/debian/patches/2020_reproducible_documentation_build.patch + +--- a/scripts/docs-build.js ++++ b/scripts/docs-build.js +@@ -34,7 +34,8 @@ + .replace(/\[([^\]]+)\]\(\/using-npm\/([^)]+)\)/g, replacer) + .trim() + +- fs.writeFile(dest, marked(result), 'utf8', function (err) { ++ var date = new Date(process.env.SOURCE_DATE_EPOCH) ++ fs.writeFile(dest, marked(result, {date}), 'utf8', function (err) { + if (err) return console.log(err) + }) + }) diff --git a/main/npm/smoke-tests-npm-location.patch b/main/npm/smoke-tests-npm-location.patch new file mode 100644 index 000000000000..79f96758faee --- /dev/null +++ b/main/npm/smoke-tests-npm-location.patch @@ -0,0 +1,23 @@ +Allow to specify custom npm location for smoke-tests, so we can test npm +without development dependencies involved. + +--- a/smoke-tests/index.js ++++ b/smoke-tests/index.js +@@ -29,7 +29,7 @@ + }) + const localPrefix = resolve(path, 'project') + const userconfigLocation = resolve(path, '.npmrc') +-const npmLocation = resolve(__dirname, '..') ++const npmLocation = resolve(__dirname, process.env.NPM_LOCATION || '..') + const cacheLocation = resolve(path, 'cache') + const binLocation = resolve(path, 'bin') + const env = { +@@ -57,7 +57,7 @@ + t.equal(pkg.version, '1.0.0', 'should have expected generated version') + }) + +-t.test('npm (no args)', async t => { ++t.skip('npm (no args)', async t => { + const cmd = `"${process.execPath}" "${npmLocation}" --no-audit --no-update-notifier` + const cmdRes = await execAsync(cmd, { cwd: localPrefix, env }) + .catch(err => { -- GitLab