Commit 25b10bd1 authored by Jakub Jirutka's avatar Jakub Jirutka
Browse files

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
244cc743), 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 script).
parent 3601817f
......@@ -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.
pkgdesc="JavaScript runtime built on V8 engine - LTS version"
arch="all !mips64 !mips64el"
......@@ -84,7 +84,8 @@ makedepends="
subpackages="$pkgname-dev $pkgname-doc npm::noarch"
subpackages="$pkgname-dev $pkgname-doc"
provides="nodejs-lts=$pkgver" # for backward compatibility
replaces="nodejs-current nodejs-lts" # nodejs-lts for backward compatibility
......@@ -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 --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 \
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
# XXX: Workaround for
(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() {
npm() {
pkgdesc="A package manager for JavaScript"
# 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"
# 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).
exit 0
# Contributor: Jakub Jirutka <>
# Maintainer: Jakub Jirutka <>
pkgdesc="The package manager for JavaScript"
replaces="nodejs-doc" # for backward compatibility
subpackages="$pkgname-doc $pkgname-bashcomp"
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
local f name
for f in configuring-npm/ configuring-npm/ using-npm/*.md; do
name=$(basename $f .md)
sed -Ei "s/^title: $name/title: npm-$name/" "$f"
mv "$f" "$(dirname $f)/npm-$"
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() {
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"
Description: don't check for last version
Author: Xavier Guimard <>
Forwarded: not-needed
Last-Update: 2021-03-02
--- 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) ||
--- a/Makefile
+++ b/Makefile
@@ -47,7 +47,7 @@
## build-time dependencies for the documentation
- 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/ scripts/docs-build.js
# Do not modify this file - use /etc/npmrc instead!
Description: Use source-date-epoch as timestamp source for documentation
Author: James Addison <>
Forwarded: no
Last-Update: 2020-11-11
--- a/scripts/docs-build.js
+++ b/scripts/docs-build.js
@@ -34,7 +34,8 @@
.replace(/\[([^\]]+)\]\(\/using-npm\/([^)]+)\)/g, replacer)
- 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)
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 => {
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment