RPM Macros and Utilities for Node.js Packaging
Go to file
Evgeni Golov 70538358df
Properly handle @group/package deps in nodejs-symlink-deps
Node packages can have dependencies of the for "@group/package" instead of just "package".
Calling symlink() (and thus os.symlink()) in such a case fails when there is no "@group" directory yet.

```
+ /usr/lib/rpm/nodejs-symlink-deps /usr/lib/node_modules

ERROR: the path for dependency "@babel/runtime" already exists

This could mean that bundled modules are being installed.  Bundled libraries are
forbidden in Fedora. For more information, see:
    <https://fedoraproject.org/wiki/Packaging:No_Bundled_Libraries>

It is generally reccomended to remove the entire "node_modules" directory in
%prep when it exists. For more information, see:
    <https://fedoraproject.org/wiki/Packaging:Node.js#Removing_bundled_modules>

If you have obtained permission from the Fedora Packaging Committee to bundle
libraries, please use `%nodejs_fixdep -r` in %prep to remove the dependency on
the bundled module. This will prevent an unnecessary dependency on the system
version of the module and eliminate this error.
error: Bad exit status from /var/tmp/rpm-tmp.nn3mkP (%install)
```

The reported error is misleading - the path does not exist yet, but it also can't be created.
os.symlink throws OSError in both cases.

The patch prevents the issue by calling os.makedirs on the group-part of the dependency if there is one.

Signed-off-by: Jan Staněk <jstanek@redhat.com>
Resolves: RHEL-121583
2025-10-31 13:51:30 +01:00
.fmf Setup gating for c10s 2024-08-01 15:08:51 +02:00
plans Setup gating for c10s 2024-08-01 15:08:51 +02:00
test Add test case for symlinked dependencies bug fix 2025-10-14 15:08:14 +02:00
.gitignore Make dist-git the upstream repo 2020-09-18 15:50:14 -04:00
changelog Update version and switch to rpmautospec 2023-03-10 10:57:08 -05:00
gating.yaml Setup gating for c10s 2024-08-01 15:08:51 +02:00
LICENSE Make dist-git the upstream repo 2020-09-18 15:50:14 -04:00
macros.nodejs Set correct %nodejs_sitelib path 2023-03-10 10:37:32 -05:00
multiver_modules Make dist-git the upstream repo 2020-09-18 15:50:14 -04:00
nodejs-fixdep Make dist-git the upstream repo 2020-09-18 15:50:14 -04:00
nodejs-packaging-bundler Bundler: Update to modern npm arguments 2023-03-10 09:44:24 -05:00
nodejs-packaging.spec Move ABI dependency generator to nodejs package 2025-02-25 12:20:22 +01:00
nodejs-setversion Make dist-git the upstream repo 2020-09-18 15:50:14 -04:00
nodejs-symlink-deps Properly handle @group/package deps in nodejs-symlink-deps 2025-10-31 13:51:30 +01:00
nodejs.attr Restrict autoprovides and requires to top-level 2023-10-26 10:04:04 -04:00
nodejs.prov nodejs.prov: find namespaced bundled dependencies 2022-01-20 12:24:09 +01:00
nodejs.req Correctly determine if a package has bundled dependencies 2025-10-10 12:21:49 +02:00
README.md Drop instructions for upgrading node pkg 2023-04-27 11:44:13 -04:00
sources Make dist-git the upstream repo 2020-09-18 15:50:14 -04:00

How to bundle nodejs libraries in Fedora

The upstream Node.js stance on global library packages is that they are ".. best avoided if not needed." In Fedora, we take the same stance with our nodejs packages. You can provide a package that uses nodejs, but you should bundle all the nodejs libraries that are needed.

We are providing a sample spec file and bundling script here.
For more detailed packaging information go to the Fedora Node.js Packaging Guildelines

Bundling Script

nodejs-packaging-bundler <npm_name> [version] [tarball]

nodejs-packaging-bundler is it's own package, nodejs-packaging-bundler and must be installed before use.
nodejs-packaging-bundler gets the latest npm version available, if no version is given, or uses the existing tarball if one is given. Using npm is preferred for to ease reproducibility. If a local tarball is required (e.g. because the package is missing from npm or its version is too old), please ensure to document how the tarball was created. It produces four files and puts them in ${HOME}/rpmbuild/SOURCES

  • <npm_name>-.tgz - This is the tarball from npm.org
  • <npm_name>--nm-prod.tgz - This is the tarball that contains all the bundled nodejs modules <npm_name> needs to run
  • <npm_name>--nm-dev.tgz - This is the tarball that contains all the bundled nodejs modules <npm_name> needs to test
  • <npm_name>--bundled-licenses.txt - This lists the bundled licenses in <npm_name>--nm-prod.tgz

Sample Spec File

%global npm_name my_nodejs_application
...
License:  <license1> and <license2> and <license3>
...
Source0:  http://registry.npmjs.org/%{npm_name}/-/%{npm_name}-%{version}.tgz
Source1:  %{npm_name}-%{version}-nm-prod.tgz
Source2:  %{npm_name}-%{version}-nm-dev.tgz
Source3:  %{npm_name}-%{version}-bundled-licenses.txt
...
BuildRequires: nodejs-devel
...
%prep
%setup -q -n package
cp %{SOURCE3} .
...
%build
# Setup bundled node modules
tar xfz %{SOURCE1}
mkdir -p node_modules
pushd node_modules
ln -s ../node_modules_prod/* .
ln -s ../node_modules_prod/.bin .
popd
...
%install
mkdir -p %{buildroot}%{nodejs_sitelib}/%{npm_name}
cp -pr index.js lib package.json %{buildroot}%{nodejs_sitelib}/%{npm_name}
# Copy over bundled nodejs modules
cp -pr node_modules node_modules_prod %{buildroot}%{nodejs_sitelib}/%{npm_name}
...
%check
%nodejs_symlink_deps --check
# Setup bundled dev node_modules for testing
tar xfz %{SOURCE2}
pushd node_modules
ln -s ../node_modules_dev/* .
popd
pushd node_modules/.bin
ln -s ../../node_modules_dev/.bin/* .
popd
# Example test run using the binary in ./node_modules/.bin/
./node_modules/.bin/vows --spec --isolate
...
%files
%doc HISTORY.md
%license LICENSE.md %{npm_name}-%{version}-bundled-licenses.txt
%{nodejs_sitelib}/%{npm_name}