Skip to content

feat(manager): add nub package manager#44422

Open
colinhacks wants to merge 3 commits into
renovatebot:mainfrom
colinhacks:feat/nub-manager
Open

feat(manager): add nub package manager#44422
colinhacks wants to merge 3 commits into
renovatebot:mainfrom
colinhacks:feat/nub-manager

Conversation

@colinhacks

Copy link
Copy Markdown

Changes

Adds a nub package-manager manager.

Nub is a Node package manager published as @nubjs/nub on npm. It has its own lockfile, nub.lock, which is byte-compatible with the pnpm-lock v9 format. This manager gives nub-based projects lockfile-aware update PRs without keeping a foreign lockfile.

The manager is modeled on the existing bun manager:

  • Detects nub.lock, resolves the sibling package.json, and extracts dependencies through the shared npm extractor (extractPackageJson). The datasource stays npm.
  • Regenerates the lockfile in updateArtifacts by running nub install --lockfile-only (with --ignore-scripts unless scripts are allowed), then diffs the old and new nub.lock.
  • Sets supersedesManagers: ['npm'] so nub takes over from the npm manager only when nub.lock is present.
  • Registers nub in the Containerbase registry (toolDefinitions + allToolConfig.nub → npm @nubjs/nub), so the default binarySource=install runtime can provision it. This depends on the companion Containerbase tool: feat(tool): add nub package manager containerbase/base#7054.

Context

Please select one of the following:

  • This doesn't close an Issue, but I accept the risk that this PR may be closed if maintainers disagree with its opening or implementation

AI assistance disclosure

  • Yes — substantive assistance (AI-generated non‑trivial portions of code, tests, or documentation).

Code, tests, and the manager readme were written with substantive assistance from an AI coding agent (Claude).

Documentation (please check one with an [x])

  • I have updated the documentation

Adds lib/modules/manager/nub/readme.md, which is auto-rendered into the docs site.

How I've tested my work (please select one)

  • Newly added/modified unit tests

pnpm vitest run lib/modules/manager/nub --coverage passes with 100% statement/branch/function/line coverage. The manager, metadata, and fingerprint validators, the lib/util/exec and lib/config specs, and pnpm test-schema all pass.

Add a first-party manager for nub (https://nubjs.com), modeled on the bun manager. Detects nub.lock, extracts deps via the shared npm extractor (nub.lock is pnpm-lock v9 under nub's own filename), and regenerates the lockfile with 'nub install --lockfile-only'. Registers nub as a Containerbase tool (npm datasource, @nubjs/nub) so binarySource=install can provision it.
Copilot AI review requested due to automatic review settings July 7, 2026 17:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions github-actions Bot requested a review from viceice July 7, 2026 17:41
@cla-assistant

cla-assistant Bot commented Jul 7, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

- pass --no-frozen-lockfile so nub re-resolves the bumped manifest
  instead of rejecting the drift under its CI-frozen default
- detect the object form `workspaces: { packages: [...] }`
- add nub to ignoreScripts supportedManagers
Comment thread lib/modules/manager/nub/extract.ts Outdated
let workspaces = res?.managerData?.workspaces;

// nub also accepts the object form `workspaces: { packages: [...] }`.
if (typeof workspaces === 'object' && 'packages' in workspaces) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typeof workspaces === 'object' is also true for null, and managerData.workspaces comes straight from the parsed manifest. A "workspaces": null value makes 'packages' in workspaces throw and crashes extract. Use is.plainObject(workspaces), which also matches the prefer-is guideline.

Comment thread lib/modules/manager/nub/extract.ts Outdated
): Promise<PackageFile | null> {
const fileContent = await readLocalFile(packageFile, 'utf8');
if (!fileContent) {
logger.warn({ fileName: packageFile }, 'Could not read file content');

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This warns when a nub.lock has no readable sibling package.json, which is an expected case and will be noisy. Use logger.debug here, as the npm manager does.

Comment thread lib/modules/manager/nub/utils.ts Outdated
}
const relativeFile = upath
.relative(pwd, fileName)
.replace(/\/package\.json$/, '');

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the regEx() utility from lib/util/regex.ts instead of a regex literal.

Comment thread lib/modules/manager/nub/artifacts.ts Outdated
toolConstraints: [
{
toolName: 'nub',
constraint: updateArtifact?.config?.constraints?.nub,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updateArtifact and config are already in scope and always defined. Simplify to config.constraints?.nub.

Comment thread lib/modules/manager/nub/readme.md Outdated
Used for updating projects that use [nub](https://nubjs.com) as their package manager.
nub is a tool for JavaScript projects and therefore an alternative to managers like npm, pnpm and Yarn.

nub's `nub.lock` is the pnpm lockfile v9 format under nub's own filename, so dependencies resolve through the same npm datasource as the `npm` and `bun` managers.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid possessives like nub's. Rewrite, for example: the nub.lock file uses the pnpm lockfile v9 format under a nub-specific name.

{ manager: 'nub', lockFiles: ['nub.lock'] },
];
const oldLock = Buffer.from('old');
fs.readFile.mockResolvedValueOnce(oldLock as never);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as never bypasses the type system. Prefer typing the mock value or partial<T>() from test/util. The table-driven test lower down also hand-rolls a for loop over testCases; it.each fits better.

- extract: guard workspaces with isPlainObject so a `workspaces: null`
  value no longer throws on the `'packages' in` check
- extract: demote the missing sibling package.json read to logger.debug
- utils: wrap the package.json-suffix regex in regEx()
- artifacts: use the destructured config for the nub tool constraint
- readme: drop the possessive phrasing
- tests: mock the fs util instead of fs-extra (drops `as never`),
  convert the command-execution cases to it.each, and cover null workspaces
@colinhacks

Copy link
Copy Markdown
Author

All six addressed in 6d9ea8169:

  1. Replaced typeof workspaces === 'object' with isPlainObject(workspaces) in extract.ts (named import, matching the manager tree's convention), so a "workspaces": null manifest no longer throws on the 'packages' in check. Added a test covering the null case.
  2. Demoted the missing sibling package.json read to logger.debug.
  3. Wrapped the package.json-suffix regex in regEx().
  4. Simplified the tool constraint to config.constraints?.nub.
  5. Reworded the readme to drop the possessive.
  6. Reworked artifacts.spec.ts to mock the fs util instead of fs-extra, which removes the as never casts, and the command-execution cases are now it.each. Lockfile reads resolve to a Buffer; since readLocalFile is overloaded, they go through one typed handle rather than a cast.

Green locally: pnpm jest lib/modules/manager/nub (31 tests), tsc --noEmit, oxlint, prettier, and biome.

@RahulGautamSingh RahulGautamSingh left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Else LGTM

@@ -0,0 +1,6 @@
Used for updating projects that use [nub](https://nubjs.com) as their package manager.
nub is a tool for JavaScript projects and therefore an alternative to managers like npm, pnpm and Yarn.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
nub is a tool for JavaScript projects and therefore an alternative to managers like npm, pnpm and Yarn.
nub is a tool for JavaScript projects and therefore an alternative to managers like npm, pnpm and yarn.

consistent casing


The `nub.lock` file uses the pnpm lockfile v9 format under a nub-specific name, so dependencies resolve through the same npm datasource as the `npm` and `bun` managers.

If a `package.json` is found to be part of `nub` manager results then the same file will be excluded from the `npm` manager results unless an npm/pnpm/Yarn lock file is also found.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If a `package.json` is found to be part of `nub` manager results then the same file will be excluded from the `npm` manager results unless an npm/pnpm/Yarn lock file is also found.
If a `package.json` is found to be part of `nub` manager results then the same file will be excluded from the `npm` manager results unless an npm/pnpm/yarn lock file is also found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants