F43 Change Proposal: NodeJS metapackage (self contained)

NodeJS metapackage

This is a proposed Change for Fedora Linux.
This document represents a proposed Change. As part of the Changes process, proposals are publicly announced in order to receive community feedback. This proposal will only be implemented if approved by the Fedora Engineering Steering Committee.

Wiki
Announced

:link: Summary

The NodeJS team no longer wish to design 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.

:link: Owner

:link: 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.

:link: Implementation options

Currently, we are thinking about 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} …

We do not have a clear preference between those two, so feedback is welcome.

:link: Feedback

:link: 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.

:link: Scope

  • Proposal owners: Change the non-versioned packages generation logic in the existing NodeJS packages to accommodate this change; optionally re-introduce new nodejs 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)

:link: 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. nodejs → nodejs22).

:link: Early Testing

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

:link: 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.

:link: User Experience

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

:link: Dependencies

N/A

:link: 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.

:link: Documentation

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

:link: Release Notes

TODO

Last edited by @amoloney 2025-07-07T14:38:14Z

Last edited by @amoloney 2025-07-07T14:38:14Z

How do you feel about the proposal as written?

  • Strongly in favor
  • In favor, with reservations
  • Neutral
  • Opposed, but could be convinced
  • Strongly opposed
0 voters

If you are in favor but have reservations, or are opposed but something could change your mind, please explain in a reply.

We want everyone to be heard, but many posts repeating the same thing actually makes that harder. If you have something new to say, please say it. If, instead, you find someone has already covered what you’d like to express, please simply give that post a :heart: instead of reiterating. You can even do this by email, by replying with the heart emoji or just “+1”. This will make long topics easier to follow.

Please note that this is an advisory “straw poll” meant to gauge sentiment. It isn’t a vote or a scientific survey. See About the Change Proposals category for more about the Change Process and moderation policy.

In the first sentence of “Summary”, change “design” to “designate”. Also, the simplified example under #1 in “Implementation options” is all on one line, which makes it difficult to read. Same with the example in #2.

As a packager, I would like builds of my packages to use the latest nodejs release. Only if that fails, and I determine that an earlier version of nodejs is required, would I explicitly set the nodejs version in the BuildRequires. Is there some way I could express that, perhaps with %{nodejs_default_stream}, in the BuildRequires?

1 Like

In the first sentence of “Summary”, change “design” to “designate”. Also, the simplified example under #1 in “Implementation options” is all on one line, which makes it difficult to read. Same with the example in #2.

Thanks, English is not my first language. As for the formatting, it looks like it got messed up when translating from the wiki page to here. It’s more readable over there.

Looks like I cannot edit the post here, so I’ll be making all edits in the wiki.

As a packager, I would like builds of my packages to use the latest nodejs release. Only if that fails, and I determine that an earlier version of nodejs is required, would I explicitly set the nodejs version in the BuildRequires. Is there some way I could express that, perhaps with %{nodejs_default_stream}, in the BuildRequires?

Requesting specifically “always the newest” is not explicitly provided, the same as other potential requests like “always the latest LTS release” and similar. It would be nice to have, and we perhaps could hack together some virtual provides like nodejs-latest, nodejs-lts, … Nevertheless, this is out of scope of this change.

The metapackage is designed to allow for a sort-of hands-off approach – by requesting just nodejs, you would say “I do not care that much and trust you to deliver some supported stream”, with the understanding that it may not be the newest, but it should be new enough.