diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index 3ff244e0a61..fcabc2ca214 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -131,8 +131,18 @@ jobs: ARGS="-pl ${{matrix.module}} -Dtest=${{matrix.args}}" || \ ARGS="-pl ${{matrix.args}}" cmd="mvn -B -ntp -T 1C $ARGS" - set -x -e -o pipefail - $cmd verify -Dmaven.javadoc.skip=false | tee mvn-unit-tests-${{matrix.current}}.out + set -x -e + LOG=mvn-unit-tests-${{matrix.current}}.out + $cmd verify -Dmaven.javadoc.skip=false "$LOG" 2>&1 & + MVN_PID=$! + tail -f --pid=$MVN_PID "$LOG" & + wait $MVN_PID + - name: Kill leftover Java processes + if: ${{ always() }} + run: | + pkill -TERM java || true + sleep 2 + pkill -KILL java || true - name: Package test-report files if: ${{ failure() || success() }} run: find . -name surefire-reports -o -name failsafe-reports -o -name error-screenshots -o -name "mvn-*.out" | tar -czf tests-report-unit-${{matrix.current}}.tgz -T - @@ -209,13 +219,27 @@ jobs: $cmd -T 1C || $cmd fi - name: Run ITs + timeout-minutes: 22 run: | [ -n "${{matrix.module}}" ] && \ ARGS="-Dfailsafe.forkCount=4 -pl ${{matrix.module}} -Dit.test=${{matrix.args}}" || \ ARGS="-pl ${{matrix.args}}" cmd="mvn -V -B -ntp -e -fae -Dcom.vaadin.testbench.Parameters.testsInParallel=5 -Dfailsafe.rerunFailingTestsCount=2 -Dmaven.wagon.httpconnectionManager.ttlSeconds=25 -Dmaven.wagon.http.retryHandler.count=3 -Pbun $ARGS" - set -x -e -o pipefail - $cmd verify | tee -a mvn-it-tests-${{matrix.current}}.out + set -x -e + LOG=mvn-it-tests-${{matrix.current}}.out + # Detach mvn's stdio from this shell so an orphan child JVM (e.g. a + # Spring Boot fork that spring-boot:stop failed to kill) can't pin + # the step open by holding the pipe to tee. + $cmd verify "$LOG" 2>&1 & + MVN_PID=$! + tail -f --pid=$MVN_PID "$LOG" & + wait $MVN_PID + - name: Kill leftover Java processes + if: ${{ always() }} + run: | + pkill -TERM java || true + sleep 2 + pkill -KILL java || true - name: Package test-report files if: ${{ always() }} run: find . -name surefire-reports -o -name failsafe-reports -o -name error-screenshots -o -name "mvn-*.out" -o -name "jetty-start.out" | tar -czf tests-report-it-${{matrix.current}}.tgz -T - diff --git a/flow-build-tools/src/main/java/com/vaadin/flow/server/frontend/FrontendTools.java b/flow-build-tools/src/main/java/com/vaadin/flow/server/frontend/FrontendTools.java index b22e98c65c8..e7153d091ce 100644 --- a/flow-build-tools/src/main/java/com/vaadin/flow/server/frontend/FrontendTools.java +++ b/flow-build-tools/src/main/java/com/vaadin/flow/server/frontend/FrontendTools.java @@ -364,7 +364,13 @@ public List getPnpmExecutable() { List pnpmCommand = getSuitablePnpm(); assert !pnpmCommand.isEmpty(); pnpmCommand = new ArrayList<>(pnpmCommand); - pnpmCommand.add("--shamefully-hoist=true"); + // Force hoisted (flat npm-style) layout. CLI takes precedence over + // .npmrc, so this is unambiguous even if the project lacks the + // generated .npmrc. Replaces the previous --shamefully-hoist=true, + // which only controls the partial-hoist heuristic on top of the + // default isolated layout and did not consistently expose every + // transitive at the project root. + pnpmCommand.add("--config.node-linker=hoisted"); return pnpmCommand; } diff --git a/flow-build-tools/src/test/java/com/vaadin/flow/server/frontend/FrontendToolsTest.java b/flow-build-tools/src/test/java/com/vaadin/flow/server/frontend/FrontendToolsTest.java index e111ed91872..f6d64f5c891 100644 --- a/flow-build-tools/src/test/java/com/vaadin/flow/server/frontend/FrontendToolsTest.java +++ b/flow-build-tools/src/test/java/com/vaadin/flow/server/frontend/FrontendToolsTest.java @@ -379,8 +379,9 @@ void knownFaultyNpmVersionThrowsException() { @Test void getPnpmExecutable_executableIsAvailable() { List executable = tools.getPnpmExecutable(); - // command line should contain --shamefully-hoist=true option - assertTrue(executable.contains("--shamefully-hoist=true")); + // command line should force hoisted node-linker so transitive + // deps are always installed at the project root + assertTrue(executable.contains("--config.node-linker=hoisted")); assertTrue(executable.stream().anyMatch(cmd -> cmd.contains("pnpm"))); } diff --git a/flow-build-tools/src/test/java/com/vaadin/flow/server/frontend/NodeUpdaterTest.java b/flow-build-tools/src/test/java/com/vaadin/flow/server/frontend/NodeUpdaterTest.java index 96a920f23df..9ef1b623f64 100644 --- a/flow-build-tools/src/test/java/com/vaadin/flow/server/frontend/NodeUpdaterTest.java +++ b/flow-build-tools/src/test/java/com/vaadin/flow/server/frontend/NodeUpdaterTest.java @@ -169,6 +169,7 @@ void getDefaultDevDependencies_includesAllDependencies_whenUsingVite() { expectedDependencies.add("transform-ast"); expectedDependencies.add("strip-css-comments"); expectedDependencies.add("@babel/preset-react"); + expectedDependencies.add("@babel/types"); expectedDependencies.add("@types/react"); expectedDependencies.add("@types/react-dom"); expectedDependencies.add("@preact/signals-react-transform"); diff --git a/flow-build-tools/src/test/java/com/vaadin/flow/server/frontend/TaskRunPnpmInstallTest.java b/flow-build-tools/src/test/java/com/vaadin/flow/server/frontend/TaskRunPnpmInstallTest.java index 22d40c7ff11..439c85e6fab 100644 --- a/flow-build-tools/src/test/java/com/vaadin/flow/server/frontend/TaskRunPnpmInstallTest.java +++ b/flow-build-tools/src/test/java/com/vaadin/flow/server/frontend/TaskRunPnpmInstallTest.java @@ -227,6 +227,7 @@ void runPnpmInstall_npmRcFileNotFound_newNpmRcFileIsGenerated() String content = FileUtils.readFileToString(npmRcFile, StandardCharsets.UTF_8); assertTrue(content.contains("shamefully-hoist")); + assertTrue(content.contains("node-linker=hoisted")); } @Test diff --git a/flow-server/src/main/resources/com/vaadin/flow/server/frontend/dependencies/vite/package.json b/flow-server/src/main/resources/com/vaadin/flow/server/frontend/dependencies/vite/package.json index af452fa2b59..61b76f61f4e 100644 --- a/flow-server/src/main/resources/com/vaadin/flow/server/frontend/dependencies/vite/package.json +++ b/flow-server/src/main/resources/com/vaadin/flow/server/frontend/dependencies/vite/package.json @@ -15,6 +15,7 @@ "@rollup/plugin-replace": "6.0.3", "@rollup/pluginutils": "5.3.0", "@babel/preset-react": "7.28.5", + "@babel/types": "7.28.5", "rollup-plugin-visualizer": "7.0.1", "rollup-plugin-brotli": "3.1.0", "vite-plugin-checker": "0.12.0", diff --git a/flow-server/src/main/resources/npmrc b/flow-server/src/main/resources/npmrc index ed70490312f..43df9048dc1 100644 --- a/flow-server/src/main/resources/npmrc +++ b/flow-server/src/main/resources/npmrc @@ -3,5 +3,11 @@ # # This file sets the default parameters for manual `pnpm install`. # +# node-linker=hoisted produces a flat node_modules layout (like npm), +# so every transitive dependency lives at the project root. Flow's +# frontend tooling and bundled Vite plugins (e.g. the React function +# location plugin) import transitive deps that pnpm's symlink-based +# layout did not consistently hoist, even with shamefully-hoist=true. +node-linker=hoisted shamefully-hoist=true strict-peer-dependencies=false diff --git a/flow-tests/test-redeployment/pom.xml b/flow-tests/test-redeployment/pom.xml index d2a889c9bec..ede800371da 100644 --- a/flow-tests/test-redeployment/pom.xml +++ b/flow-tests/test-redeployment/pom.xml @@ -78,6 +78,29 @@ + + + org.apache.maven.plugins + maven-antrun-plugin + + + quiet-period-before-stop + + run + + post-integration-test + + + + + + + + + org.springframework.boot spring-boot-maven-plugin