Skip to content

feat: exclude @vaadin packages from the minimum frontend package age - #25620

Merged
Artur- merged 10 commits into
mainfrom
feat/exclude-vaadin-packages-from-the-minimum-release-age
Sep 14, 2026
Merged

Artur- merged 10 commits into
mainfrom
feat/exclude-vaadin-packages-from-the-minimum-release-age

Conversation

@totally-not-ai

@totally-not-ai totally-not-ai Bot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Summary

The minimum frontend package age blocks packages that were published very recently. Because the @vaadin packages are pinned to the platform version, a build started right after a Vaadin release had no older version to fall back to and failed. Vaadin now tells the package manager to exempt @vaadin/* from that check, and warns when the package manager cannot do it.

What changed

Behavior change: every build that runs with a minimum frontend package age now gets extra install arguments, and some builds get a new warning. Nothing is added when no age applies.

  • npm 11.17.0 and newer: --min-release-age-exclude=@vaadin/* is passed. It exempts the matching packages from both --min-release-age and --before.
  • pnpm 10.17.0 and newer: --config.minimum-release-age-exclude=@vaadin/* is passed. When there is a single pattern it is passed twice, because pnpm reads the setting as a list only when the argument occurs more than once, and pnpm 11 excludes every package when the value is a plain string.
  • Patterns already configured in .npmrc / pnpm config are kept. A command line value replaces the configured list instead of adding to it, so Vaadin reads the configured patterns and passes them along with @vaadin/*. Without this, a project that excludes its own scope silently lost that exclusion.
  • bun, older npm, older pnpm: nothing can be passed, so the build is warned that an install during the first day after a Vaadin release may fail. The warning names the remedy for the package manager in use — upgrade npm to 11.17.0 (first shipped with Node.js 24.19.0), upgrade pnpm to 10.17.0, or, for bun, list the @vaadin packages one by one in minimumReleaseAgeExcludes in a bunfig.toml, since bun matches exact names only.
  • bun without a warning: the project bunfig.toml is now read, and the warning is skipped when a @vaadin package is an actual value of minimumReleaseAgeExcludes. A commented-out line or an unrelated mention is not enough.
  • minimumFrontendPackageAgeDays = 0: Vaadin still passes no age argument, but an age that npm or pnpm resolves from its own configuration still applies to the install. That age is now reported as applying, so the @vaadin packages are excluded from it instead of being blocked silently. When the package manager itself resolves an age of 0, nothing applies and nothing is excluded or warned about.
  • Reading a list-valued setting no longer splits list entries on commas. Only a comma-separated string value is split, because a list entry is complete on its own and may contain a comma of its own in a brace expansion such as @acme/{ui,core}.
  • Javadoc for minimumFrontendPackageAgeDays in Options, InitParameters, BuildFrontendMojo and BuildDevBundleMojo now documents the exclusion and the required npm/Node.js/pnpm versions.

No public or protected API changed. The new methods and the internal resolveMinimumFrontendPackageAge rename are package-private.

Use case

A team builds their app with bun, and CI runs a few minutes after a Vaadin release. The install fails because the freshly published @vaadin packages are younger than the minimum age, and bun cannot take an exclusion from the command line. The build log now tells them what to do: add the packages they depend on to a bunfig.toml next to package.json.

[install]
minimumReleaseAgeExcludes = ["@vaadin/react-components"]

After that the install succeeds, and Vaadin stops printing the warning on every build.

Test summary

# Status What the test verifies Why it matters
1 ✅ npm gets --min-release-age-exclude=@vaadin/* and no warning Core fix: a build right after a release must not be blocked
2 ✅ pnpm gets --config.minimum-release-age-exclude=@vaadin/* twice A single occurrence makes pnpm 11 exclude every package, turning the age check off
3 ✅ Patterns configured in the package manager are passed along with @vaadin/* A command line value replaces them, so a project would silently lose its own exclusion
4 ✅ A real pnpm install command contains the exclude argument Pins that the argument actually reaches the install, not just the resolver
5 ✅ npm/pnpm too old or bun: no argument, and a warning naming the version or the bunfig setting The only signal a user gets when the exclusion is impossible
6 ✅ A bunfig.toml listing a @vaadin package silences the warning; other packages or a comment do not A bun project that fixed it must not be nagged; a fake match must not hide a real problem
7 ✅ With Vaadin configured to 0 and no package manager age: no argument, no exclusion, no warning A project that opted out must stay fully opted out
8 ✅ With Vaadin configured to 0 but npm configured with 7 days: the age applies, so @vaadin/* is excluded The silently blocking case this PR fixes
9 ✅ A package manager age of 0 counts as no age at all Avoids arguments and warnings when nothing is blocked
10 ✅ List settings are read from an array and from a comma-separated string; a brace expansion in a list is kept whole; a null/empty key gives an empty list Splitting @acme/{ui,core} would produce two broken patterns
11 ❗ gap npmSupportsMinReleaseAgeExclude / pnpmSupportsMinimumReleaseAgeExclude comparing a real reported version against 11.17.0 / 10.17.0 A wrong threshold would pass an unknown argument to an old tool; callers only mock these
  • TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_npm_excludesVaadinPackages — 1
  • TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_pnpm_excludesVaadinPackagesAsAList — 2
  • TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_configuredPatterns_areKept — 3
  • TaskRunPnpmInstallTest.runPnpmInstall_excludesVaadinPackagesFromTheMinimumAge — 4
  • TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_npmTooOld_warnsInsteadOfExcluding — 5
  • TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_pnpmTooOld_warnsInsteadOfExcluding — 5
  • TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_bun_warnsInsteadOfExcluding — 5
  • TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_bunfigListsThePackages_noWarning — 6
  • TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_bunfigListsOtherPackages_warns — 6
  • TaskRunNpmInstallTest.resolveMinimumFrontendPackageAge_zeroConfigured_noArgumentAndNoAge — 7, 9
  • TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_noAgeApplies_noArgumentOrWarning — 7
  • TaskRunNpmInstallTest.resolveMinimumFrontendPackageAge_zeroConfiguredWithNpmrcValue_ageStillApplies — 8
  • TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_npmrcValue_isStillExcludedFrom — 8
  • TaskRunNpmInstallTest.resolveMinimumFrontendPackageAge_npmrcValueOfZero_noAgeApplies — 9
  • FrontendToolsTest.getConfiguredSettingValues_listAndCommaSeparatedValue_areRead — 10
  • FrontendToolsTest.getConfiguredSettingValues_braceExpansionInAList_isKeptTogether — 10
  • FrontendToolsTest.getConfiguredSettingValues_keyWithoutValue_isEmpty — 10

Left untested on purpose: the exact wording of the warning (only the key facts are asserted), and the unreadable-bunfig.toml path, which just falls back to warning.

The packages Vaadin publishes are pinned to the version of the platform in
use, so the minimum frontend package age blocks an installation that runs
during the first day after a Vaadin release: there is no older version to
fall back to and the build fails.

Specifies with tests how each package manager should be told to exempt those
packages, and that the build is warned when the package manager cannot do
it. The resolution itself is left unimplemented until the approach is
agreed on; the version checks that tell which package managers support
excluding are already in place.
Passes --min-release-age-exclude=@vaadin/* to npm 11.17 and newer, and
--config.minimum-release-age-exclude=@vaadin/* to pnpm 10.17 and newer, so
that a project can be built with a Vaadin version that was released a moment
ago. The argument is also passed when the age itself comes from the package
manager configuration.

bun accepts exclusions only as exact package names in a bunfig.toml, and
older npm and pnpm versions do not know the setting at all. Those builds are
warned that an installation started during the first day after a Vaadin
release may fail, and how to turn the age check off.
A command line value replaces the exclusions the package manager resolves
from its own configuration instead of adding to them, so a project that
excludes its own scope silently lost that exclusion. The configured patterns
are now passed along with '@vaadin/*'.

The pnpm argument is also passed twice when there is a single pattern: pnpm
reads the setting as a list only when the argument occurs more than once,
and pnpm 11 excludes every package when the value is a plain string, which
turned the age check off altogether.

Nothing is excluded and nothing is warned about when no age applies, which
now includes the package manager itself being configured with an age of 0.
Artur-
Artur- previously requested changes Sep 10, 2026

@Artur- Artur- left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We might want to mention the node version that ships with a new enough npm also

}
if (options.isEnableBun()) {
warnAboutPackagesThatCannotBeExcluded(logger,
"bun accepts exclusions only as exact package names in the 'minimumReleaseAgeExcludes' setting of a bunfig.toml");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should this tell what you should add to match the npm/pnpm behavior?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes — the warning now ends with the remedy for the package manager in use. For bun it says to list the @vaadin packages the project depends on one by one in the minimumReleaseAgeExcludes setting of a bunfig.toml, since bun matches exact names only (@vaadin/* does not match) and has no command line equivalent. pnpm and npm get their own line: upgrade to 10.17.0 and 11.17.0 respectively.

+ "minimum frontend package age, as {}. Installing a "
+ "Vaadin version during the first day after its "
+ "release may therefore fail. Upgrade the package "
+ "manager, or set the '{}' parameter to 0 to turn "

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should not suggest turning off the age check

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed — the warning no longer mentions the age parameter at all. Instead of suggesting to turn the check off, it now names the upgrade that makes the exclusion work: npm 11.17.0 (first shipped with Node.js 24.19.0), pnpm 10.17.0, or the exact @vaadin package names in a bunfig.toml for bun.

The warning no longer suggests turning the age check off. It now ends with
the remedy for the package manager in use: upgrading npm to 11.17.0, which
Node.js 24.19.0 is the first release to ship, upgrading pnpm to 10.17.0, or,
for bun, listing the '@vaadin' packages one by one in the
'minimumReleaseAgeExcludes' setting of a bunfig.toml, as bun matches exact
names only. The parameter documentation names the Node.js version as well.
Only the npm remedy was asserted, so swapping the other two messages would
have gone unnoticed.
@totally-not-ai

Copy link
Copy Markdown
Contributor Author

@Artur- Added the Node.js version in both places: the npm warning now reads "Upgrade npm to 11.17.0 or newer, which Node.js 24.19.0 and newer ship with", and the same hint is in the minimumFrontendPackageAgeDays documentation of the Maven parameters, InitParameters and Options. Node.js 24.19.0 is the first release of the 24 line that bundles npm 11.17.0; the Node.js version Vaadin installs itself (v24.21.0, npm 11.19.0) is already new enough, so the warning only appears with an older globally installed npm.

* date npm falls back to is not a number and always blocks something.
*/
private static boolean blocksNothing(String packageManagerValue) {
try {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this a method for comparing a string with "0" that is always used in an inverted manner !blocksNothing?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It compared the age that npm or pnpm resolves for itself against zero, which is the one value that blocks nothing (before is a date, so it always blocks something). Turned around into blocksSomeVersion, so the call site reads without a negation.

}
if (options.isEnableBun()) {
warnAboutPackagesThatCannotBeExcluded(logger,
"bun accepts exclusions only as exact package names in the 'minimumReleaseAgeExcludes' setting of a bunfig.toml",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If this is done by the user, will the warning still be printed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It was, on every build, with nothing the project could do about it. The bunfig.toml next to the package.json is now read, and the warning is skipped when it lists Vaadin packages in minimumReleaseAgeExcludes. The file is read as it is, since bun has no command for printing its resolved configuration, so a bunfig.toml outside the project (the one in the home directory) is still not seen.

}

@Test
void minimumFrontendPackageAgeExclude_pnpmTooOld_warnsInsteadOfExcluding() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Shouldn't pnpm tests be in the pnpm test class?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

These are unit tests of the argument resolution with a mocked FrontendTools, not tests of a pnpm install, and the class already holds the pnpm and bun variants of the neighbouring age tests (minimumFrontendPackageAge_pnpm_usesMinimumReleaseAgeInMinutes, resolveMinimumFrontendPackageAge_pnpmConfiguredValue_doesNotOverrideIt), so the whole npm/pnpm/bun matrix stays in one place. The test that runs a real pnpm install and checks the argument reaches the command is in TaskRunPnpmInstallTest. Happy to move the pnpm ones over if you prefer them separated.

A bun build could do nothing to stop the warning, as the exclusion it asks
for cannot be seen from the command line. The bunfig.toml of the project is
now read, and the warning is skipped when it lists Vaadin packages in
'minimumReleaseAgeExcludes'.

Also states the check of the age a package manager resolved for itself the
way it is used, instead of negating it at the call site.
Both strings were looked for anywhere in the bunfig.toml, so a commented out
setting or an unrelated mention of a Vaadin package was enough to lose the
warning. The package now has to be a value of the setting.
@github-actions

github-actions Bot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Test Results

 1 440 files  ±0   1 524 suites  ±0   1h 34m 4s ⏱️ -8s
12 060 tests ±0  11 992 ✅ ±0  68 💤 ±0  0 ❌ ±0 
12 378 runs  ±0  12 310 ✅ ±0  68 💤 ±0  0 ❌ ±0 

Results for commit 7fbdd2f. ± Comparison against base commit 8365470.

♻️ This comment has been updated with latest results.

@Artur-
Artur- requested a review from caalador September 11, 2026 14:34
@totally-not-ai

Copy link
Copy Markdown
Contributor Author

The failing it-tests (2, …) job is not caused by this branch. PostinstallIT.postinstallRanForProject in vite-basics errored with a NullPointerException because the main.postinstall resource was missing, while every frontend install in that job logged "Frontend dependencies resolved successfully" with the new arguments (--min-release-age=1 --min-release-age-exclude=@vaadin/* for npm, the duplicated --config.minimum-release-age-exclude=@vaadin/* for pnpm). The previous full validation run of this branch ran the very same install command and PostinstallIT passed; the only change since then is the merge of main. The WebComponentIT error in the same job passed on retry. So I re-ran the failed jobs instead of pushing a change.

Comment thread flow-build-tools/src/main/java/com/vaadin/flow/server/frontend/FrontendTools.java Outdated
With 'minimumFrontendPackageAgeDays' set to 0 Vaadin passes no argument, but
an age npm or pnpm resolves from its own configuration still applies to the
install. That age is now reported as applying, so the packages Vaadin
publishes are excluded from it instead of being blocked silently.

The values of a configured exclusion list are no longer split on commas
either. Only a comma separated string is, as a list value is complete on its
own and may contain a comma of its own in a brace expansion such as
'@acme/{ui,core}'.
The zero case only checked the argument, so a regression could have turned
the exclusions and the warning back on for a project that opted out. Also
lets the new case resolve the exclusions from the age it resolved, instead
of from a hardcoded flag, and fixes the braces of a javadoc example.
@totally-not-ai

Copy link
Copy Markdown
Contributor Author

On the CI failure: the re-run failed the same way, so it is reproducible rather than flaky, and my earlier comment was too quick to call it unrelated. What still holds is that every frontend install in the job succeeds with the new arguments and that only PostinstallIT fails, on the main.postinstall file that the project's own postinstall script writes into target/classes; the dev mode install of vite-basics runs in the forked Jetty process, whose log is not in the job output. This push starts a fresh run, and I will dig into the forked process log if it persists.

@sonarqubecloud

Copy link
Copy Markdown

@Artur-
Artur- enabled auto-merge September 14, 2026 08:44
@Artur-
Artur- added this pull request to the merge queue Sep 14, 2026
Merged via the queue into main with commit f6f8978 Sep 14, 2026
48 checks passed
@Artur-
Artur- deleted the feat/exclude-vaadin-packages-from-the-minimum-release-age branch September 14, 2026 10:00
vaadin-bot added a commit that referenced this pull request Sep 14, 2026
…25620) (CP: 25.3) (#25702)

This PR cherry-picks changes from the original PR #25620 to branch 25.3.
---
#### Original PR description
> ## Summary
> 
> The minimum frontend package age blocks packages that were published
very recently. Because the `@vaadin` packages are pinned to the platform
version, a build started right after a Vaadin release had no older
version to fall back to and failed. Vaadin now tells the package manager
to exempt `@vaadin/*` from that check, and warns when the package
manager cannot do it.
> 
> ## What changed
> 
> **Behavior change:** every build that runs with a minimum frontend
package age now gets extra install arguments, and some builds get a new
warning. Nothing is added when no age applies.
> 
> - **npm 11.17.0 and newer:** `--min-release-age-exclude=@vaadin/*` is
passed. It exempts the matching packages from both `--min-release-age`
and `--before`.
> - **pnpm 10.17.0 and newer:**
`--config.minimum-release-age-exclude=@vaadin/*` is passed. When there
is a single pattern it is passed twice, because pnpm reads the setting
as a list only when the argument occurs more than once, and pnpm 11
excludes *every* package when the value is a plain string.
> - **Patterns already configured in `.npmrc` / pnpm config are kept.**
A command line value replaces the configured list instead of adding to
it, so Vaadin reads the configured patterns and passes them along with
`@vaadin/*`. Without this, a project that excludes its own scope
silently lost that exclusion.
> - **bun, older npm, older pnpm:** nothing can be passed, so the build
is warned that an install during the first day after a Vaadin release
may fail. The warning names the remedy for the package manager in use —
upgrade npm to 11.17.0 (first shipped with Node.js 24.19.0), upgrade
pnpm to 10.17.0, or, for bun, list the `@vaadin` packages one by one in
`minimumReleaseAgeExcludes` in a `bunfig.toml`, since bun matches exact
names only.
> - **bun without a warning:** the project `bunfig.toml` is now read,
and the warning is skipped when a `@vaadin` package is an actual value
of `minimumReleaseAgeExcludes`. A commented-out line or an unrelated
mention is not enough.
> - **`minimumFrontendPackageAgeDays = 0`:** Vaadin still passes no age
argument, but an age that npm or pnpm resolves from its own
configuration still applies to the install. That age is now reported as
applying, so the `@vaadin` packages are excluded from it instead of
being blocked silently. When the package manager itself resolves an age
of `0`, nothing applies and nothing is excluded or warned about.
> - Reading a list-valued setting no longer splits list entries on
commas. Only a comma-separated string value is split, because a list
entry is complete on its own and may contain a comma of its own in a
brace expansion such as `@acme/{ui,core}`.
> - Javadoc for `minimumFrontendPackageAgeDays` in `Options`,
`InitParameters`, `BuildFrontendMojo` and `BuildDevBundleMojo` now
documents the exclusion and the required npm/Node.js/pnpm versions.
> 
> No public or protected API changed. The new methods and the internal
`resolveMinimumFrontendPackageAge` rename are package-private.
> 
> ## Use case
> 
> A team builds their app with bun, and CI runs a few minutes after a
Vaadin release. The install fails because the freshly published
`@vaadin` packages are younger than the minimum age, and bun cannot take
an exclusion from the command line. The build log now tells them what to
do: add the packages they depend on to a `bunfig.toml` next to
`package.json`.
> 
> ```toml
> [install]
> minimumReleaseAgeExcludes = ["@vaadin/react-components"]
> ```
> 
> After that the install succeeds, and Vaadin stops printing the warning
on every build.
> 
> ## Test summary
> 
> | # | Status | What the test verifies | Why it matters |
> |---|--------|------------------------|----------------|
> | 1 | ✅ | npm gets `--min-release-age-exclude=@vaadin/*` and no
warning | Core fix: a build right after a release must not be blocked |
> | 2 | ✅ | pnpm gets `--config.minimum-release-age-exclude=@vaadin/*`
twice | A single occurrence makes pnpm 11 exclude every package, turning
the age check off |
> | 3 | ✅ | Patterns configured in the package manager are passed along
with `@vaadin/*` | A command line value replaces them, so a project
would silently lose its own exclusion |
> | 4 | ✅ | A real pnpm install command contains the exclude argument |
Pins that the argument actually reaches the install, not just the
resolver |
> | 5 | ✅ | npm/pnpm too old or bun: no argument, and a warning naming
the version or the bunfig setting | The only signal a user gets when the
exclusion is impossible |
> | 6 | ✅ | A `bunfig.toml` listing a `@vaadin` package silences the
warning; other packages or a comment do not | A bun project that fixed
it must not be nagged; a fake match must not hide a real problem |
> | 7 | ✅ | With Vaadin configured to `0` and no package manager age: no
argument, no exclusion, no warning | A project that opted out must stay
fully opted out |
> | 8 | ✅ | With Vaadin configured to `0` but npm configured with 7
days: the age applies, so `@vaadin/*` is excluded | The silently
blocking case this PR fixes |
> | 9 | ✅ | A package manager age of `0` counts as no age at all |
Avoids arguments and warnings when nothing is blocked |
> | 10 | ✅ | List settings are read from an array and from a
comma-separated string; a brace expansion in a list is kept whole; a
null/empty key gives an empty list | Splitting `@acme/{ui,core}` would
produce two broken patterns |
> | 11 | ❗ **gap** | `npmSupportsMinReleaseAgeExclude` /
`pnpmSupportsMinimumReleaseAgeExclude` comparing a real reported version
against 11.17.0 / 10.17.0 | A wrong threshold would pass an unknown
argument to an old tool; callers only mock these |
> 
> -
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_npm_excludesVaadinPackages`
— 1
> -
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_pnpm_excludesVaadinPackagesAsAList`
— 2
> -
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_configuredPatterns_areKept`
— 3
> -
`TaskRunPnpmInstallTest.runPnpmInstall_excludesVaadinPackagesFromTheMinimumAge`
— 4
> -
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_npmTooOld_warnsInsteadOfExcluding`
— 5
> -
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_pnpmTooOld_warnsInsteadOfExcluding`
— 5
> -
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_bun_warnsInsteadOfExcluding`
— 5
> -
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_bunfigListsThePackages_noWarning`
— 6
> -
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_bunfigListsOtherPackages_warns`
— 6
> -
`TaskRunNpmInstallTest.resolveMinimumFrontendPackageAge_zeroConfigured_noArgumentAndNoAge`
— 7, 9
> -
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_noAgeApplies_noArgumentOrWarning`
— 7
> -
`TaskRunNpmInstallTest.resolveMinimumFrontendPackageAge_zeroConfiguredWithNpmrcValue_ageStillApplies`
— 8
> -
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_npmrcValue_isStillExcludedFrom`
— 8
> -
`TaskRunNpmInstallTest.resolveMinimumFrontendPackageAge_npmrcValueOfZero_noAgeApplies`
— 9
> -
`FrontendToolsTest.getConfiguredSettingValues_listAndCommaSeparatedValue_areRead`
— 10
> -
`FrontendToolsTest.getConfiguredSettingValues_braceExpansionInAList_isKeptTogether`
— 10
> -
`FrontendToolsTest.getConfiguredSettingValues_keyWithoutValue_isEmpty` —
10
> 
> Left untested on purpose: the exact wording of the warning (only the
key facts are asserted), and the unreadable-`bunfig.toml` path, which
just falls back to warning.

Co-authored-by: totally-not-ai[bot] <290682512+totally-not-ai[bot]@users.noreply.github.com>
Co-authored-by: Artur Signell <artur@vaadin.com>
sissbruecker pushed a commit to vaadin/flow-components that referenced this pull request Sep 15, 2026
Removes the `@NpmPackage` 24h gate workflow
(`.github/workflows/npm-package-gate.yml`) from 25.3. Same change as
#10118 on `main`.

## Why

The gate blocked every PR that added an `@NpmPackage` version for 24
hours, because `vaadin.npm.minimumFrontendPackageAgeDays` defaults to
`1` and a freshly published `@vaadin` package would otherwise break the
snapshot builds of downstream projects.

vaadin/flow#25620 ("exclude `@vaadin` packages from the minimum frontend
package age") removes that reason: the minimum age no longer applies to
`@vaadin` packages.

## ⚠️ Merge order

The cherry-pick of that fix to flow 25.3 — vaadin/flow#25702 — **is
still open at the time of writing**. Please merge this PR only after
vaadin/flow#25702 has landed, otherwise 25.3 loses the gate while flow
25.3 still enforces the minimum age for `@vaadin` packages.

## Scope

The gate is intentionally kept on **25.2**, which does not get the
exclusion.

## Risk

Low, CI-only. The webjar/`@NpmPackage` update PRs (e.g. `chore: Update
NpmPackages Webjars versions (25.3)`) stop being blocked and
auto-approved after 24h — they now follow the normal review and merge
flow. Nothing in the build or in any component changes. Reverting is a
single-file revert.

## How to test

Open or push a PR against 25.3 that adds an `@NpmPackage` version and
check that no `CHANGES_REQUESTED` review from the review bot appears and
no "NpmPackage 24h gate" workflow run is started.

Co-authored-by: totally-not-ai[bot] <290682512+totally-not-ai[bot]@users.noreply.github.com>
sissbruecker added a commit to vaadin/flow-components that referenced this pull request Sep 15, 2026
…0127)

This PR cherry-picks changes from the original PR #10125 to branch 25.3.
---
#### Original PR description
> Follow-up to #10118
> Related to vaadin/flow#25620
> 
> - Removed the `.pnpmfile.cjs` from all 52 integration test modules,
which excluded `@vaadin/*` packages from pnpm's minimum release age
check
> - Removed the step in `scripts/mergeITs.js` that copied that file into
the merged IT module
> - Removed the `!**/.pnpmfile.cjs` entry from
`vaadin-spreadsheet-flow-parent/.gitignore`, which only existed to
un-ignore the file from the `.pnpm*` pattern
> 
> Flow now passes `--config.minimum-release-age-exclude=@vaadin/*` to
the pnpm install it runs, so the project-level exclusion is redundant.
Every pnpm install in this repository goes through Flow — the IT builds,
`jetty:run`, and `scripts/wtr.js` — so nothing else relies on it. The
files stay on 25.2, which builds against a Flow version without the
exclusion.
>

Co-authored-by: Sascha Ißbrücker <sissbruecker@vaadin.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@vaadin-bot

Copy link
Copy Markdown
Collaborator

Hi @totally-not-ai[bot] and @Artur-, when i performed cherry-pick to this commit to 25.2, i have encountered the following issue. Can you take a look and pick it manually?
Error Message:
Error: Command failed: git cherry-pick f6f8978
error: could not apply f6f8978... feat: exclude @vaadin packages from the minimum frontend package age (#25620)
hint: After resolving the conflicts, mark them with
hint: "git add/rm ", then run
hint: "git cherry-pick --continue".
hint: You can instead skip this commit with "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".

ZheSun88 pushed a commit that referenced this pull request Sep 18, 2026
…25620) (CP: 25.2) (#25795)

## Summary

A build that started right after a Vaadin release could fail, because
the minimum frontend package age blocks packages that were published a
moment ago. Vaadin now tells npm and pnpm to exempt `@vaadin/*` from
that check, and warns when the package manager cannot do it. The PR also
stops pnpm from starting a second, failing install of its own before a
`postinstall` script.

## What changed

**Behavior change 1:** every build that runs with a minimum frontend
package age now gets extra install arguments, and some builds get a new
warning. Nothing is added when no age applies. This affects all users
who leave the age check on (the default).

**Behavior change 2:** a `postinstall` script that exits with a non-zero
status now fails the build with an `ExecutionFailedException` that names
the package and includes the script output. Before, the exit code was
thrown away and the build continued as if nothing happened. This affects
any project whose `postinstall` script fails — the build now stops
instead of continuing with a broken `node_modules`.

Excluding the Vaadin packages:

- **npm 11.17.0 and newer:** `--min-release-age-exclude=@vaadin/*` is
passed. It exempts the matching packages from both `--min-release-age`
and `--before`.
- **pnpm 10.17.0 and newer:**
`--config.minimum-release-age-exclude=@vaadin/*` is passed. A single
pattern is passed twice, because pnpm reads the setting as a list only
when the argument occurs more than once, and pnpm 11 excludes *every*
package when the value is a plain string.
- **Patterns already configured in `.npmrc` / pnpm config are kept.** A
command line value replaces the configured list instead of adding to it,
so Vaadin reads the configured patterns and passes them along with
`@vaadin/*`. Without this, a project that excludes its own scope
silently lost that exclusion.
- **bun, older npm, older pnpm:** nothing can be passed, so the build is
warned that an install during the first day after a Vaadin release may
fail. The warning names the remedy for the package manager in use —
upgrade npm to 11.17.0 (first shipped with Node.js 24.19.0), upgrade
pnpm to 10.17.0, or, for bun, list the `@vaadin` packages one by one in
`minimumReleaseAgeExcludes` in a `bunfig.toml`, since bun matches exact
names only.
- **bun without a warning:** the project `bunfig.toml` is now read, and
the warning is skipped when a `@vaadin` package is an actual value of
`minimumReleaseAgeExcludes`. A commented-out line or an unrelated
mention is not enough.
- **`minimumFrontendPackageAgeDays = 0`:** Vaadin still passes no age
argument, but an age that npm or pnpm resolves from its own
configuration still applies to the install. That age is now reported as
applying, so the `@vaadin` packages are excluded from it instead of
being blocked silently. When the package manager itself resolves an age
of `0`, nothing applies and nothing is excluded or warned about.
- Reading a list-valued setting no longer splits list entries on commas.
Only a comma-separated string value is split, because a list entry is
complete on its own and may contain a comma of its own in a brace
expansion such as `@acme/{ui,core}`.
- Javadoc for `minimumFrontendPackageAgeDays` in `Options`,
`InitParameters`, `BuildFrontendMojo` and `BuildDevBundleMojo` now
documents the exclusion and the required npm/Node.js/pnpm versions.

The pnpm `postinstall` fix:

- The command that runs a `postinstall` script now gets
`--config.verify-deps-before-run=false` when pnpm is in use. Before
running a script, pnpm checks that `node_modules` is up to date, and
that check starts its own install. That install repeats the one Flow
just ran, but without the arguments that exempt the Vaadin packages from
the minimum release age and without `--ignore-scripts`. When it failed,
the `postinstall` script was never run.
- Nothing extra is passed for npm or bun. Neither checks anything before
running a script, and bun fails on an argument it does not know.
- The postinstall command is now also logged at debug level, next to the
install command.

No public or protected API changed. The new methods are package-private.

## Use case

A team builds their app with bun, and CI runs a few minutes after a
Vaadin release. The install fails because the freshly published
`@vaadin` packages are younger than the minimum age, and bun cannot take
an exclusion from the command line. The build log now tells them what to
do: add the packages they depend on to a `bunfig.toml` next to
`package.json`.

```toml
[install]
minimumReleaseAgeExcludes = ["@vaadin/react-components"]
```

After that the install succeeds, and Vaadin stops printing the warning
on every build.

## Test summary

| # | Status | What the test verifies | Why it matters |
|---|--------|------------------------|----------------|
| 1 | ✅ | npm gets `--min-release-age-exclude=@vaadin/*` and no warning
| Core fix: a build right after a release must not be blocked |
| 2 | ✅ | pnpm gets `--config.minimum-release-age-exclude=@vaadin/*`
twice | A single occurrence makes pnpm 11 exclude every package, turning
the age check off |
| 3 | ✅ | Patterns configured in the package manager are passed along
with `@vaadin/*` | A command line value replaces them, so a project
would silently lose its own exclusion |
| 4 | ✅ | A real pnpm install command contains the exclude argument |
Pins that the argument actually reaches the install, not just the
resolver |
| 5 | ✅ | npm/pnpm too old or bun: no argument, and a warning naming the
version or the bunfig setting | The only signal a user gets when the
exclusion is impossible |
| 6 | ✅ | A `bunfig.toml` listing a `@vaadin` package silences the
warning; other packages or a comment do not | A bun project that fixed
it must not be nagged; a fake match must not hide a real problem |
| 7 | ✅ | With Vaadin configured to `0` and no package manager age: no
argument, no exclusion, no warning | A project that opted out must stay
fully opted out |
| 8 | ✅ | With Vaadin configured to `0` but npm configured with 7 days:
the age applies, so `@vaadin/*` is excluded | The silently blocking case
this PR fixes |
| 9 | ✅ | A package manager age of `0` counts as no age at all | Avoids
arguments and warnings when nothing is blocked |
| 10 | ✅ | List settings are read from an array and from a
comma-separated string; a brace expansion in a list is kept whole; a
missing key gives an empty list | Splitting `@acme/{ui,core}` would
produce two broken patterns |
| 11 | ✅ | A `postinstall` script that exits non-zero makes `execute()`
throw, and the message names the package and contains what the script
printed | This was silently ignored before; without it a broken install
looks like a successful build |
| 12 | ✅ | The command actually run for pnpm contains
`--config.verify-deps-before-run=false` | Pins the fix end-to-end —
dropping the call that adds the argument would otherwise keep the suite
green |
| 13 | ✅ | Postinstall options resolve to exactly that one flag for pnpm
and to nothing for npm and bun | The exact flag spelling is what stops
pnpm's extra install, and bun fails on an unknown argument |
| 14 | ❗ **gap** | `npmSupportsMinReleaseAgeExclude` /
`pnpmSupportsMinimumReleaseAgeExclude` comparing a real reported version
against 11.17.0 / 10.17.0 | A wrong threshold would pass an unknown
argument to an old tool; callers only mock these |

-
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_npm_excludesVaadinPackages`
→ 1
-
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_pnpm_excludesVaadinPackagesAsAList`
→ 2
-
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_configuredPatterns_areKept`
→ 3
-
`TaskRunPnpmInstallTest.runPnpmInstall_excludesVaadinPackagesFromTheMinimumAge`
→ 4
-
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_npmTooOld_warnsInsteadOfExcluding`
→ 5
-
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_pnpmTooOld_warnsInsteadOfExcluding`
→ 5
-
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_bun_warnsInsteadOfExcluding`
→ 5
-
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_bunfigListsThePackages_noWarning`
→ 6
-
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_bunfigListsOtherPackages_warns`
→ 6
-
`TaskRunNpmInstallTest.resolveMinimumFrontendPackageAge_zeroConfigured_noArgumentAndNoAge`
→ 7, 9
-
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_noAgeApplies_noArgumentOrWarning`
→ 7
-
`TaskRunNpmInstallTest.resolveMinimumFrontendPackageAge_zeroConfiguredWithNpmrcValue_ageStillApplies`
→ 8
-
`TaskRunNpmInstallTest.minimumFrontendPackageAgeExclude_npmrcValue_isStillExcludedFrom`
→ 8
-
`TaskRunNpmInstallTest.resolveMinimumFrontendPackageAge_npmrcValueOfZero_noAgeApplies`
→ 9
-
`FrontendToolsTest.getConfiguredSettingValues_listAndCommaSeparatedValue_areRead`
→ 10
-
`FrontendToolsTest.getConfiguredSettingValues_braceExpansionInAList_isKeptTogether`
→ 10
- `FrontendToolsTest.getConfiguredSettingValues_keyWithoutValue_isEmpty`
→ 10
-
`TaskRunNpmInstallTest.runNpmInstall_postInstallFails_buildFailsWithTheScriptOutput`
→ 11 (inherited by `TaskRunPnpmInstallTest`, so it runs for npm and
pnpm)
-
`TaskRunPnpmInstallTest.runPnpmInstall_postinstallDoesNotVerifyTheDependencies`
→ 12
-
`TaskRunNpmInstallTest.postinstallArguments_pnpm_doesNotVerifyTheDependencies`
→ 13
- `TaskRunNpmInstallTest.postinstallArguments_npmAndBun_needNone` → 13

Left untested on purpose: the exact wording of the warning (only the key
facts are asserted), the unreadable-`bunfig.toml` path, which just falls
back to warning, and the happy path of a `postinstall` script that
succeeds, which the existing `runNpmInstall_postInstall_*` tests already
pin. There is no end-to-end bun test class, so bun is covered at the
argument level only.

---------

Co-authored-by: totally-not-ai[bot] <290682512+totally-not-ai[bot]@users.noreply.github.com>
Co-authored-by: Artur Signell <artur@vaadin.com>
@vaadin-bot

Copy link
Copy Markdown
Collaborator

This ticket/PR has been released with Vaadin 25.4.0-alpha1.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants