Skip to content

Do not override the minimum frontend package age configured for the package manager - #25173

Open
Artur- wants to merge 14 commits into
mainfrom
minage
Open

Do not override the minimum frontend package age configured for the package manager#25173
Artur- wants to merge 14 commits into
mainfrom
minage

Conversation

@Artur-

@Artur- Artur- commented Aug 11, 2026

Copy link
Copy Markdown
Member

Problem

The minimumFrontendPackageAgeDays parameter defaulted to 1 and was always passed as a command line argument to the package manager. A command line argument takes precedence over every configuration source of npm, pnpm and bun, so a project that had configured min-release-age in its .npmrc (or minimumReleaseAge in pnpm-workspace.yaml) silently got the Vaadin default instead — mvn vaadin:build-frontend and a manually run npm install disagreed on which package versions were allowed to be installed.

What changed

The parameter is now unset by default (Integer/null rather than int/1):

  • A value configured on the Vaadin side is used as is, 0 still disables the check.
  • When nothing is configured, the package manager is asked what it resolves for its own minimum release age setting. If it already has one, no argument is passed and the package manager applies its own configuration; this is logged at info level along with the parameter to set in order to override it.
  • Only when neither is configured does the one-day default (TaskRunNpmInstall.DEFAULT_MINIMUM_FRONTEND_PACKAGE_AGE_DAYS) apply.

Reading the package manager configuration

The resolved configuration is read from the tool itself with config list --json, so it accounts for every configuration source and precedence rule the tool applies (command line, environment variables, project/user/global/builtin .npmrc, and for pnpm pnpm-workspace.yaml). The subcommand has to be spelled list — pnpm does not know the ls alias npm accepts, which is what made an earlier attempt at this fail on pnpm.

The npm registry lookup already ran the same command, so both now share FrontendTools.getResolvedConfiguration and there is a single way to ask npm or pnpm what it resolves for a directory. Details handled along the way:

  • Key spelling varies by version: pnpm 11 reports the setting camel-cased as minimumReleaseAge while pnpm 10 reports it kebab-cased, so getConfiguredSetting takes the keys to look for in order of preference.
  • Only scalars are read: npm lists some of its settings (omit, noproxy) as arrays, which JsonNode.asString does not accept. The guard against that previously lived only in the registry lookup; reading a setting now skips anything that is not a scalar, and null (which npm uses for keys it knows but that are not configured) counts as unset.
  • Old npm: where --min-release-age is unsupported and the --before=<date> fallback is used, the before setting is read as the configuration counterpart.
  • A tool answering in a non-JSON format is ignored rather than failing the build.
  • bun is not asked. Detecting a value configured for bun meant parsing bunfig.toml by hand, as bun has no command for printing its resolved configuration (oven-sh/bun#7140). That hand-written parser recognized only a subset of what TOML allows, so it could just as easily miss a configured value as pick up something that was not one. It has been removed — for bun the Vaadin default applies as before, and the documentation says so.

Refactoring

resolveMinimumFrontendPackageAgeArgument now returns the install argument to add, or nothing. Previously the day-count resolution returned 0 both for a check that is explicitly disabled and for one the package manager already handles itself, and the caller had to repeat the same check to know whether it needed to ask npm for its version at all. The remaining argument-formatting method only converts a positive number of days into the flag for the package manager in use.

Tests

  • Covers the old-npm path (where the before counterpart is read instead of min-release-age), which had no coverage at all.
  • The bun test previously relied on a mock that reports nothing for any key, so it passed even if bun were asked for its configuration; it now stubs a value and asserts that it is neither read nor used.
  • Argument-formatting assertions that duplicated the resolution tests were dropped; the pnpm and bun ones remain, where the day count is converted to minutes and seconds and a wrong conversion would otherwise pass unnoticed.

Also restores the flow-client lockfile that a local build had rewritten.

API Changes

com.vaadin.flow.server.frontend.Options

// Changed
- public Options withMinimumFrontendPackageAgeDays(int minimumFrontendPackageAgeDays)
+ public Options withMinimumFrontendPackageAgeDays(@Nullable Integer minimumFrontendPackageAgeDays) // null means "use the package manager configuration"
- public int getMinimumFrontendPackageAgeDays()
+ public @Nullable Integer getMinimumFrontendPackageAgeDays() // null when nothing is configured on the Vaadin side

com.vaadin.flow.plugin.base.PluginAdapterBuild

// Changed
- default int minimumFrontendPackageAgeDays() // returned 1
+ default Integer minimumFrontendPackageAgeDays() // returns null

com.vaadin.flow.plugin.maven.BuildFrontendMojo

// Changed
- public int minimumFrontendPackageAgeDays()
+ public Integer minimumFrontendPackageAgeDays() // the vaadin.npm.minimumFrontendPackageAgeDays parameter no longer has a default value

com.vaadin.flow.plugin.maven.BuildDevBundleMojo

// Changed
- public int minimumFrontendPackageAgeDays()
+ public Integer minimumFrontendPackageAgeDays() // the vaadin.npm.minimumFrontendPackageAgeDays parameter no longer has a default value

The minimumFrontendPackageAgeDays parameter defaulted to 1 and was always
passed as a command line argument, which takes precedence over every
configuration source of npm, pnpm and bun. A project that configures
min-release-age in .npmrc got the Vaadin default instead, so
`mvn vaadin:build-frontend` and a manually run `npm install` disagreed on
which package versions are allowed.

The parameter is now unset by default. When nothing is configured on the
Vaadin side, the package manager is asked what it resolves for its own
minimum release age setting (`config get` for npm and pnpm, bunfig.toml
for bun) and no argument is passed when it already has one. The one day
default applies only when neither is configured.
@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Test Results

 1 384 files  ±0   1 385 suites  ±0   1h 28m 7s ⏱️ + 1m 15s
10 556 tests +1  10 489 ✅ +1  67 💤 ±0  0 ❌ ±0 
10 875 runs  +1  10 807 ✅ +1  68 💤 ±0  0 ❌ ±0 

Results for commit d372fc4. ± Comparison against base commit 65c7ff3.

♻️ This comment has been updated with latest results.

Artur- added 5 commits August 11, 2026 15:32
The parameter type changed from int to Integer, which the javadoc build
flags as a reference that cannot be resolved.
Reading the minimum release age used `config get <key>` while the
registry lookup already ran `config ls --json`, which resolves the same
configuration and contains every key. Both now share
getResolvedConfiguration, so there is a single way to ask npm or pnpm
what it resolves for a directory, and no string parsing of the tool
output is needed to tell a configured value from an unset one.
resolveMinimumFrontendPackageAgeDays returned 0 both for a check that is
explicitly disabled and for one the package manager already handles
itself, and the caller repeated the same check to know whether to ask npm
for its version at all. Resolution now returns the install argument to
add, or nothing, and the remaining day count method only formats a
positive number of days for the package manager in use.
Detecting a minimum release age configured for bun meant parsing
bunfig.toml by hand, as bun has no command for printing its resolved
configuration (oven-sh/bun#7140). That parser only recognized a subset of
what the TOML format allows, so it could just as well miss a configured
value as pick up something that is not one.

Only npm and pnpm, which can both report their resolved configuration,
are now asked. For bun the Vaadin default applies as before, and the
documentation says so.

@Artur- Artur- left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Does not work on pnpm:

% npx pnpm config  ls --json            
{
  "error": {
    "code": "ERR_PNPM_CONFIG_UNKNOWN_SUBCOMMAND",
    "message": "This subcommand is not known"
  }
}
% npx pnpm config
[ERR_PNPM_CONFIG_NO_SUBCOMMAND] Please specify the subcommand

Usage: pnpm config set <key> <value>
       pnpm config get <key>
       pnpm config get --json <key>
       pnpm config delete <key>
       pnpm config list

Manage the pnpm configuration files.

Commands:
      delete               Remove the config key from the config file
      get                  Print the config value for the provided key
      list                 Show all the config settings
      set                  Set the config key to the value provided

Options:
  -g, --global                     Sets the configuration in the global config file
      --json                       Show all types of values in JSON format (not just objects and arrays)
      --location <project|global>  When set to "project", the pnpm-workspace.yaml file will be used if it exists. If only .npmrc exists, it will be used. If neither exists, a pnpm-workspace.yaml file
                                   will be created.

Visit https://pnpm.io/11.x/cli/config for documentation about this command.

and in the config file, the key is minimumReleaseAge

pnpm has no `config ls --json` subcommand, so reading the resolved
configuration that way always failed and the minimum release age
configured for pnpm was silently overridden by the Vaadin default. The
value is now read one key at a time with `config get <key>`, which both
npm and pnpm support and which prints the same shape on every version,
unlike `pnpm config list` (INI in pnpm 10, JSON in pnpm 11).

pnpm names the setting `minimumReleaseAge`, not `minimum-release-age`,
so the key it is asked for is now the one pnpm knows. Reading the npm
registries keeps using `npm config ls --json`, as the whole listing is
needed there.

Also renames getPackageManagerMinimumReleaseAge to
getPackageManagerConfiguredMinimumReleaseAge to make it clear that it
returns the package manager's own configuration option.
The old-npm path, where the counterpart of the --before fallback is read
instead of min-release-age, had no coverage at all. The bun test relied
on a mock that reports nothing for any key, so it passed even if bun
were asked for its configuration; it now stubs a value and asserts that
it is neither read nor used.

Drops the pnpm default-value test, which only combined the argument
formatting and the default fallback that are each already covered.
@totally-not-ai totally-not-ai Bot changed the title fix: do not override the package manager minimum package age fix: do not override a minimum frontend package age configured for npm or pnpm Aug 24, 2026
@totally-not-ai

Copy link
Copy Markdown
Contributor

@Artur- Good catch, fixed in d1bf85a.

pnpm has no config ls --json subcommand, so that read always failed and the age configured for pnpm was silently overridden by the Vaadin default anyway. The value is now read one key at a time with config get <key>, which npm and pnpm both support and which prints the same shape on every version — unlike pnpm config list, which is INI in pnpm 10 and JSON in pnpm 11. The key asked for is now minimumReleaseAge, the name pnpm knows. Reading the npm registries still uses npm config ls --json, since the whole listing is needed there.

Verified against the real tools — pnpm 10.34 with minimum-release-age in .npmrc, pnpm 11.23 with minimumReleaseAge in pnpm-workspace.yaml, and npm 11.19/12.0 with min-release-age and before — set and unset in each case. All four print null or undefined when the key has no value, so the one day default still applies when nothing is configured.

Test coverage in 795a6e1: the config get command shape is pinned, both placeholder spellings are parsed as "not configured", and the pnpm, bun and pre-11.10 npm (--before) resolution branches each have a test.

@totally-not-ai totally-not-ai Bot changed the title fix: do not override a minimum frontend package age configured for npm or pnpm fix: do not override the minimum frontend package age configured for npm or pnpm Aug 24, 2026
@Artur-
Artur- marked this pull request as ready for review August 24, 2026 12:15
totally-not-ai Bot and others added 6 commits August 24, 2026 12:27
Reading a single key at a time was a workaround for pnpm not knowing
'config ls'; the subcommand it does not know is the 'ls' alias, not the
listing itself. Both pnpm 10 and 11 print the resolved configuration for
'config list --json', so the whole listing is read in one call again and
the value is picked from it.

pnpm 11 reports the setting camel-cased as minimumReleaseAge while pnpm
10 reports it kebab-cased, so getConfiguredSetting now takes the keys to
look for in order of preference.
npm lists some of its settings as arrays, which JsonNode.asString does
not accept, and the guard against that lived only in the registry
lookup. Reading a setting now skips anything that is not a scalar, the
same way the registry lookup skips anything that is not a string.

Also covers a tool answering in a format other than JSON, which is
ignored rather than failing the build, and corrects the subcommand the
registry lookup documents.
The two argument tests for npm asserted exactly what the resolution
tests assert while going through the same code, so only the pnpm and bun
ones are left, where the day count is converted to minutes and seconds
and a wrong conversion would otherwise pass unnoticed.

The two ways of failing to read a configuration are one test now, as
both only establish that the value is ignored rather than failing.
The merged test asked for a key the fixture cannot yield in any reading,
so it no longer established that only JSON is accepted. It now asks for
the key the output would produce if it were read as key=value pairs, and
says which of the two ways of failing to read a configuration broke.
@totally-not-ai totally-not-ai Bot changed the title fix: do not override the minimum frontend package age configured for npm or pnpm Do not override the minimum frontend package age configured for the package manager Aug 24, 2026
@sonarqubecloud

Copy link
Copy Markdown

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant