Skip to content

Commit ba2cef0

Browse files
authored
fix: Do not copy bundle lock for major upgrade (#22789)
Fixes #22775
1 parent 0381f3d commit ba2cef0

File tree

9 files changed

+388
-107
lines changed

9 files changed

+388
-107
lines changed

flow-server/src/main/java/com/vaadin/flow/server/frontend/BundleUtils.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,18 @@ private static Logger getLogger() {
167167
* task options
168168
*/
169169
public static void copyPackageLockFromBundle(Options options) {
170+
try {
171+
if (FrontendUtils.isPlatformMajorVersionUpdated(
172+
options.getClassFinder(), options.getNodeModulesFolder(),
173+
options.getNpmFolder(), options.getBuildDirectory())) {
174+
getLogger().info(
175+
"Platform version updated. Skipping bundle lock file copy.");
176+
return;
177+
}
178+
} catch (IOException ioe) {
179+
getLogger().debug("Failed to validate platform version change.",
180+
ioe);
181+
}
170182
String lockFile;
171183
if (options.isEnablePnpm()) {
172184
lockFile = Constants.PACKAGE_LOCK_YAML;

flow-server/src/main/java/com/vaadin/flow/server/frontend/FrontendUtils.java

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.io.InputStream;
2525
import java.io.UncheckedIOException;
2626
import java.net.URL;
27+
import java.nio.charset.StandardCharsets;
2728
import java.nio.file.Files;
2829
import java.nio.file.LinkOption;
2930
import java.nio.file.Path;
@@ -44,19 +45,22 @@
4445
import org.slf4j.Logger;
4546
import org.slf4j.LoggerFactory;
4647
import tools.jackson.databind.JsonNode;
48+
import tools.jackson.databind.node.ObjectNode;
4749

4850
import com.vaadin.experimental.CoreFeatureFlagProvider;
4951
import com.vaadin.flow.di.Lookup;
5052
import com.vaadin.flow.di.ResourceProvider;
5153
import com.vaadin.flow.function.DeploymentConfiguration;
5254
import com.vaadin.flow.internal.DevModeHandler;
5355
import com.vaadin.flow.internal.DevModeHandlerManager;
56+
import com.vaadin.flow.internal.JacksonUtils;
5457
import com.vaadin.flow.internal.Pair;
5558
import com.vaadin.flow.internal.StringUtil;
5659
import com.vaadin.flow.internal.hilla.EndpointRequestUtil;
5760
import com.vaadin.flow.internal.menu.MenuRegistry;
5861
import com.vaadin.flow.server.AbstractConfiguration;
5962
import com.vaadin.flow.server.Constants;
63+
import com.vaadin.flow.server.Platform;
6064
import com.vaadin.flow.server.VaadinService;
6165
import com.vaadin.flow.server.VaadinServlet;
6266
import com.vaadin.flow.server.frontend.scanner.ClassFinder;
@@ -1560,4 +1564,137 @@ public static boolean isTailwindCssEnabled(Options options) {
15601564
.isEnabled(CoreFeatureFlagProvider.TAILWIND_CSS);
15611565
}
15621566

1567+
/**
1568+
* Compares current platform version with the one last recorded as installed
1569+
* in node_modules/.vaadin/vaadin_version. In case there was no existing
1570+
* platform version recorder and node_modules exists, then platform is
1571+
* considered as staying on the same version.
1572+
*
1573+
* @param finder
1574+
* project execution class finder
1575+
* @param npmFolder
1576+
* npm root folder
1577+
* @param nodeModules
1578+
* node_modules folder
1579+
* @param buildDirectory
1580+
* project build directory, to find dev-bundle folder
1581+
* @return {@code true} if the version has changed, {@code false} if not
1582+
* @throws IOException
1583+
* when file reading fails
1584+
*/
1585+
protected static boolean isPlatformMajorVersionUpdated(ClassFinder finder,
1586+
File npmFolder, File nodeModules, File buildDirectory)
1587+
throws IOException {
1588+
// if no record of current version is present, version is not
1589+
// considered updated
1590+
Optional<String> platformVersion = getVaadinVersion(finder);
1591+
if (platformVersion.isPresent()) {
1592+
JsonNode vaadinJsonContents = getBundleVaadinContent(
1593+
buildDirectory);
1594+
if (!vaadinJsonContents.has(NodeUpdater.VAADIN_VERSION)
1595+
&& nodeModules.exists()) {
1596+
// Check for vaadin version from installed node_modules
1597+
vaadinJsonContents = getVaadinJsonContents(npmFolder);
1598+
}
1599+
// If no record of previous version, version is considered same
1600+
if (!vaadinJsonContents.has(NodeUpdater.VAADIN_VERSION)) {
1601+
return false;
1602+
}
1603+
FrontendVersion jsonVersion = new FrontendVersion(vaadinJsonContents
1604+
.get(NodeUpdater.VAADIN_VERSION).asString());
1605+
FrontendVersion platformsVersion = new FrontendVersion(
1606+
platformVersion.get());
1607+
return jsonVersion.getMajorVersion() != platformsVersion
1608+
.getMajorVersion();
1609+
}
1610+
return false;
1611+
}
1612+
1613+
private static JsonNode getBundleVaadinContent(File buildDirectory)
1614+
throws IOException {
1615+
JsonNode vaadinJsonContents;
1616+
File vaadinJsonFile = new File(
1617+
new File(buildDirectory, Constants.DEV_BUNDLE_LOCATION),
1618+
TaskRunDevBundleBuild.VAADIN_JSON);
1619+
if (!vaadinJsonFile.exists()) {
1620+
return JacksonUtils.createObjectNode();
1621+
}
1622+
String fileContent = Files.readString(vaadinJsonFile.toPath(),
1623+
StandardCharsets.UTF_8);
1624+
vaadinJsonContents = JacksonUtils.readTree(fileContent);
1625+
return vaadinJsonContents;
1626+
}
1627+
1628+
/**
1629+
* Compares current platform version with the one last recorded as installed
1630+
* in node_modules/.vaadin/vaadin_version. In case there was no existing
1631+
* platform version recorder and node_modules exists, then platform is
1632+
* considered updated.
1633+
*
1634+
* @param finder
1635+
* project execution class finder
1636+
* @param npmFolder
1637+
* npm root folder
1638+
* @param nodeModules
1639+
* node_modules folder
1640+
* @return {@code true} if the version has changed, {@code false} if not
1641+
* @throws IOException
1642+
* when file reading fails
1643+
*/
1644+
protected static boolean isPlatformVersionUpdated(ClassFinder finder,
1645+
File npmFolder, File nodeModules) throws IOException {
1646+
// if no record of current version is present, version is not
1647+
// considered updated
1648+
Optional<String> platformVersion = getVaadinVersion(finder);
1649+
if (platformVersion.isPresent() && nodeModules.exists()) {
1650+
JsonNode vaadinJsonContents = getVaadinJsonContents(npmFolder);
1651+
// If no record of previous version, version is considered updated
1652+
if (!vaadinJsonContents.has(NodeUpdater.VAADIN_VERSION)) {
1653+
return true;
1654+
}
1655+
return !Objects.equals(vaadinJsonContents
1656+
.get(NodeUpdater.VAADIN_VERSION).asString(),
1657+
platformVersion.get());
1658+
}
1659+
return false;
1660+
}
1661+
1662+
protected static Optional<String> getVaadinVersion(ClassFinder finder) {
1663+
URL coreVersionsResource = finder
1664+
.getResource(Constants.VAADIN_CORE_VERSIONS_JSON);
1665+
1666+
if (coreVersionsResource == null) {
1667+
return Optional.empty();
1668+
}
1669+
try (InputStream vaadinVersionsStream = coreVersionsResource
1670+
.openStream()) {
1671+
final JsonNode versionsJson = JacksonUtils
1672+
.readTree(StringUtil.toUTF8String(vaadinVersionsStream));
1673+
if (versionsJson.has("platform")) {
1674+
return Optional.of(versionsJson.get("platform").asString());
1675+
}
1676+
} catch (Exception e) {
1677+
LoggerFactory.getLogger(Platform.class)
1678+
.error("Unable to determine version information", e);
1679+
}
1680+
1681+
return Optional.empty();
1682+
}
1683+
1684+
static File getVaadinJsonFile(File npmFolder) {
1685+
return new File(new File(npmFolder, NODE_MODULES),
1686+
NodeUpdater.VAADIN_JSON);
1687+
}
1688+
1689+
static ObjectNode getVaadinJsonContents(File npmFolder) throws IOException {
1690+
File vaadinJsonFile = getVaadinJsonFile(npmFolder);
1691+
if (vaadinJsonFile.exists()) {
1692+
String fileContent = Files.readString(vaadinJsonFile.toPath(),
1693+
StandardCharsets.UTF_8);
1694+
return JacksonUtils.readTree(fileContent);
1695+
} else {
1696+
return JacksonUtils.createObjectNode();
1697+
}
1698+
}
1699+
15631700
}

flow-server/src/main/java/com/vaadin/flow/server/frontend/NodeUpdater.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747

4848
import static com.vaadin.flow.server.Constants.PACKAGE_JSON;
4949
import static com.vaadin.flow.server.Constants.PACKAGE_LOCK_JSON;
50-
import static com.vaadin.flow.server.frontend.FrontendUtils.NODE_MODULES;
5150
import static java.nio.charset.StandardCharsets.UTF_8;
5251

5352
/**
@@ -67,7 +66,7 @@ public abstract class NodeUpdater implements FallibleCommand {
6766
// .vaadin/vaadin.json contains local installation data inside node_modules
6867
// This will help us know to execute even when another developer has pushed
6968
// a new hash to the code repository.
70-
private static final String VAADIN_JSON = ".vaadin/vaadin.json";
69+
protected static final String VAADIN_JSON = ".vaadin/vaadin.json";
7170

7271
static final String DEPENDENCIES = "dependencies";
7372
static final String VAADIN_DEP_KEY = "vaadin";
@@ -542,7 +541,8 @@ String writePackageFile(JsonNode json, File packageFile)
542541
}
543542

544543
File getVaadinJsonFile() {
545-
return new File(new File(options.getNpmFolder(), NODE_MODULES),
544+
return new File(
545+
new File(options.getNpmFolder(), FrontendUtils.NODE_MODULES),
546546
VAADIN_JSON);
547547
}
548548

flow-server/src/main/java/com/vaadin/flow/server/frontend/TaskRunDevBundleBuild.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,14 @@
2525
import java.util.ArrayList;
2626
import java.util.Arrays;
2727
import java.util.List;
28+
import java.util.Optional;
2829
import java.util.stream.Collectors;
2930

3031
import org.slf4j.Logger;
3132
import org.slf4j.LoggerFactory;
33+
import tools.jackson.databind.node.ObjectNode;
3234

35+
import com.vaadin.flow.internal.JacksonUtils;
3336
import com.vaadin.flow.server.Constants;
3437
import com.vaadin.flow.server.ExecutionFailedException;
3538
import com.vaadin.flow.shared.util.SharedUtil;
@@ -75,6 +78,8 @@ public class TaskRunDevBundleBuild implements FallibleCommand {
7578
"Read more [about Vaadin development mode](https://vaadin.com/docs/next/flow/configuration/development-mode#precompiled-bundle).";
7679
//@formatter:on
7780

81+
public static final String VAADIN_JSON = "vaadin.json";
82+
7883
private final Options options;
7984

8085
/**
@@ -94,6 +99,7 @@ public void execute() throws ExecutionFailedException {
9499
runFrontendBuildTool("Vite", "vite", "vite", "build");
95100

96101
copyPackageLockToBundleFolder();
102+
addVaadinVersionToDevBundle();
97103

98104
addReadme();
99105

@@ -251,6 +257,29 @@ private void copyPackageLockToBundleFolder() {
251257
}
252258
}
253259

260+
private void addVaadinVersionToDevBundle() {
261+
File devBundleFolder = getDevBundleFolderInTarget();
262+
assert devBundleFolder.exists() : "No dev-bundle folder created";
263+
264+
Optional<String> vaadinVersion = FrontendUtils
265+
.getVaadinVersion(options.getClassFinder());
266+
if (vaadinVersion.isPresent()) {
267+
ObjectNode vaadinObject = JacksonUtils.createObjectNode();
268+
vaadinObject.put("version", vaadinVersion.get());
269+
270+
try {
271+
Files.writeString(
272+
new File(devBundleFolder, VAADIN_JSON).toPath(),
273+
vaadinObject.toPrettyString(), StandardCharsets.UTF_8);
274+
} catch (IOException e) {
275+
getLogger().error(
276+
"Failed to write vaadin version to '"
277+
+ new File(devBundleFolder, VAADIN_JSON) + "'",
278+
e);
279+
}
280+
}
281+
}
282+
254283
private void addReadme() {
255284
if (!options.isCompressBundle()) {
256285
return;

flow-server/src/main/java/com/vaadin/flow/server/frontend/TaskRunNpmInstall.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ private void updateLocalHash() {
157157

158158
final Map<String, String> updates = new HashMap<>();
159159
updates.put(HASH_KEY, hash);
160-
TaskUpdatePackages.getVaadinVersion(packageUpdater.finder)
160+
FrontendUtils.getVaadinVersion(packageUpdater.finder)
161161
.ifPresent(s -> updates.put(VAADIN_VERSION, s));
162162
updates.put(PROJECT_FOLDER,
163163
options.getNpmFolder().getAbsolutePath());

flow-server/src/main/java/com/vaadin/flow/server/frontend/TaskUpdatePackages.java

Lines changed: 3 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,16 @@
2626
import java.util.Map;
2727
import java.util.Map.Entry;
2828
import java.util.Objects;
29-
import java.util.Optional;
3029
import java.util.stream.Collectors;
3130
import java.util.stream.Stream;
3231

33-
import org.slf4j.LoggerFactory;
3432
import tools.jackson.databind.JsonNode;
3533
import tools.jackson.databind.node.ObjectNode;
3634

3735
import com.vaadin.flow.component.dependency.NpmPackage;
3836
import com.vaadin.flow.internal.JacksonUtils;
3937
import com.vaadin.flow.internal.StringUtil;
4038
import com.vaadin.flow.server.Constants;
41-
import com.vaadin.flow.server.Platform;
42-
import com.vaadin.flow.server.frontend.scanner.ClassFinder;
4339
import com.vaadin.flow.server.frontend.scanner.FrontendDependenciesScanner;
4440

4541
import static com.vaadin.flow.server.frontend.VersionsJsonConverter.JS_VERSION;
@@ -410,7 +406,9 @@ && pinPlatformDependency(packageJson,
410406

411407
// FIXME do not do cleanup of node_modules every time platform is
412408
// updated ?
413-
doCleanUp = doCleanUp || (!enablePnpm && isPlatformVersionUpdated());
409+
doCleanUp = doCleanUp || (!enablePnpm && FrontendUtils
410+
.isPlatformVersionUpdated(finder, options.getNpmFolder(),
411+
options.getNodeModulesFolder()));
414412

415413
// Remove obsolete devDependencies
416414
dependencyCollection = new ArrayList<>(
@@ -517,56 +515,6 @@ protected static boolean pinPlatformDependency(JsonNode packageJson,
517515
return true;
518516
}
519517

520-
/**
521-
* Compares current platform version with the one last recorded as installed
522-
* in node_modules/.vaadin/vaadin_version. In case there was no existing
523-
* platform version recorder and node_modules exists, then platform is
524-
* considered updated.
525-
*
526-
* @return {@code true} if the version has changed, {@code false} if not
527-
* @throws IOException
528-
* when file reading fails
529-
*/
530-
private boolean isPlatformVersionUpdated() throws IOException {
531-
// if no record of current version is present, version is not
532-
// considered updated
533-
Optional<String> platformVersion = getVaadinVersion(finder);
534-
if (platformVersion.isPresent()
535-
&& options.getNodeModulesFolder().exists()) {
536-
JsonNode vaadinJsonContents = getVaadinJsonContents();
537-
// If no record of previous version, version is considered updated
538-
if (!vaadinJsonContents.has(NodeUpdater.VAADIN_VERSION)) {
539-
return true;
540-
}
541-
return !Objects.equals(vaadinJsonContents
542-
.get(NodeUpdater.VAADIN_VERSION).asString(),
543-
platformVersion.get());
544-
}
545-
return false;
546-
}
547-
548-
static Optional<String> getVaadinVersion(ClassFinder finder) {
549-
URL coreVersionsResource = finder
550-
.getResource(Constants.VAADIN_CORE_VERSIONS_JSON);
551-
552-
if (coreVersionsResource == null) {
553-
return Optional.empty();
554-
}
555-
try (InputStream vaadinVersionsStream = coreVersionsResource
556-
.openStream()) {
557-
final JsonNode versionsJson = JacksonUtils
558-
.readTree(StringUtil.toUTF8String(vaadinVersionsStream));
559-
if (versionsJson.has("platform")) {
560-
return Optional.of(versionsJson.get("platform").asString());
561-
}
562-
} catch (Exception e) {
563-
LoggerFactory.getLogger(Platform.class)
564-
.error("Unable to determine version information", e);
565-
}
566-
567-
return Optional.empty();
568-
}
569-
570518
/**
571519
* Cleans up any previous version properties from the packageJson object if
572520
* present.

0 commit comments

Comments
 (0)