From Fedora Project Wiki


NodeJS metapackages

Summary

The NodeJS team no longer wish to designate one of the maintained NodeJS streams as the "default" or "preferred" one explicitly, but wishes for the users to retain the ability to install "any" NodeJS stream when the specific major version is not important to them. To that end, the non-versioned nodejs package will become an empty "metapackage" pulling one of the versioned nodejsXY packages as it's dependency.

Owner


Current status

Detailed Description

This is a part of a larger iteration in a way we package NodeJS for Fedora and RHEL. The other parts are Changes/NodejsNodeModulesPath and Changes/NodejsAlternativesSystem. This change deals specifically with the ability to install any supported version of NodeJS, without specifying a major version.

Previously, this was achieved by selecting one of the streams as a "default" one. This stream then would produce only non-versioned rpms (nodejs vs. nodejs22), and thus be selected when doing # dnf install nodejs. # dnf install nodejs22 also worked thanks to a virtual Provides: nodejs22 specified in the spec file.

This approach works reasonably well, but also have several drawbacks:

  1. Producing only non-versioned rpms has various corner cases, such as breaking test assertions like # dnf install nodejs22; dnf list installed | grep nodejs22.
  2. There is no way to tell if a specific version was requested: results of # dnf install nodejs and # dnf install nodejs22 are exactly the same.

    This means we have no way to infer whether it is "safe" to update the non-versioned rpms to another stream, and essentially forces us to have single default stream for the entire lifetime of the distribution. For Fedora itself, that is not that big of a problem, since the lifetime of a branched release roughly matches the span of upstream support for a LTS stream, but it becomes much larger problem in a long-living distribution such as RHEL.

To address these drawbacks, the following changes are proposed:

  • All NodeJS streams will always produce full set of versioned rpms (nodejs22 nodejs22-npm …). The non-versioned rpms (nodejs nodejs-npm …) will be provided in addition to those above.
  • The non-versioned rpms (nodejs) rpms will explicitly represent the desire to have any stream installed, without any guarantees about which version gets installed or keeping that version the same during the entire lifetime of the distribution.

    (The working internal term for this non-guarantees and behavior is "rolling stream".)

It is assumed that the non-version rpms (the "metapackages") will always pull their versioned equivalent from one of the supported streams and be otherwise empty. Which specific stream they delegate to will be left to the maintainer's discretion and the needs of the specific distribution.

Implementation options

We had 2 possible ways to implement this change.

  1. Adding an extra set of sub-packages to the current SPEC file(s), hidden behind a %bcond. Only one of these %bconds should ever be active at once. Simplified example:
    %bcond metapackages %[%{node_version_major} == %{nodejs_default_stream}]  # %nodejs_default_stream presumably defined in nodejs-packaging globally
    ...
    %if %{with metapackages}
    %package -n nodejs
    Requires:   nodejs%{node_version_major} = %{node_version}
    ...
    %endif
    

    This would most closely mirror how the non-versioned packages are generated now.

  2. Shipping separate empty package nodejs.
    Name: nodejs
    Version: 24  # the default stream
    Summary: nodejs metapackage
    Requires: nodejs%{version}
    ...
    

After testing and discovering problems along the way we ultimately went with option 2: separate empty metapackage.

That later evolved to a full set of sub packages, mirroring versioned streams: nodejs, nodejs-bin, nodejs-npm and so on. All of them are used to pull corresponding parts of nodejs and introducing dnf conflicts where needed (no 2 -bin packages could be installed at the same time).

Feedback

Benefit to Fedora

We'll give users the option to choose between specific NodeJS stream and "any" NodeJS stream explicitly, and then work with the streams accordingly. Those wishing to have "any" NodeJS version available will always get (and keep) known-good version without worrying too much about which major version is currently supported, recommended, or chosen for them.

Those wishing to have specific NodeJS stream can install one of the versioned stream explicitly and know that it will always stay on that particular major version.

Usage example

'Rolling' Stream (Any Version)

dnf install nodejs will give you all necessary to run nodejs: nodejsXX, nodejsXX-npm, nodejs-bin

node --version works, pointing to chosen (by us) XX stream

During system upgrade:

  1. Fedora 42 -> 43: metapackage pointer changes nodejs22 -> 24
  2. Old: nodejs -> nodejs22 -> nodejs-bin -> /usr/bin/node-22
  3. New: nodejs -> nodejs24 -> nodejs-bin -> /usr/bin/node-24
  4. User's node command still works, just points to newer version.

Specific Version Stream

Alternatively users still can opt for one of the versioned streams with their corresponding -bin packages. Better described in -bin packages change proposal

Scope

  • Proposal owners: Re-introduce nodejs package to act as a selector package and produce -bin rpms.
  • Other developers: Review their usage of nodejs and adjust them to comply with the new semantics.
  • Release engineering: Should not be necessary.
  • Policies and guidelines: Update to the new semantics of installation.
  • Trademark approval: N/A (not needed for this Change)

Upgrade/compatibility impact

A decision needs to be made to what kind of stream users with the current default stream installed will be migrated:

  1. . Treating current "default" stream as the "rolling" stream and simply update the installation to using the metapackages.
  2. . Treating current "default" stream as weirdly named "specific" stream, and setting Obsoletes so that the installation would move to using the versioned packages (e.g. nodejsnodejs22).

Early Testing

After gathering initial round of feedback, a COPR set up, so that the changes can be tested before implementing them in the distribution proper.

How To Test

  1. Enable the COPR mentioned above.
  2. Try updating your NodeJS installation, or install new one from scratch. Brave testers might even tests rollbacks to previous versions.

User Experience

  • Ability to better select between NodeJS streams and have the selection honored going forward.

Dependencies

N/A

Contingency Plan

  • Contingency mechanism: Not merging the Koji side tag. Keep using the (perhaps slightly tweaked) current approach, without any semantic changes.
  • Contingency deadline: Beta freeze.
  • Blocks release? No, asuming the builds and rebuilds will be done in separate environment (Koji side tag) and then merged atomically. Otherwise, YES.


Documentation

This is a downstream initiative; documentation will need to be created, but that was already mentioned in the Policies and Guidelines bullet above.

Release Notes

Proposal owners will use Bugzilla Package Review Request for reviving nodejs package and provide more details about in the ticket. Unless new discussion thread would be opened for it.