diff --git a/CHANGELOG.md b/CHANGELOG.md index 7925f88c..910529ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,8 @@ Last public release: [![Maven Central](https://maven-badges.herokuapp.com/maven- ## Changelog -### 1.11.2 - +### 1.11.4 +* Support node arm64 binaries since v16 major release ### 1.11.1 diff --git a/frontend-plugin-core/src/main/java/com/github/eirslett/maven/plugins/frontend/lib/NodeInstaller.java b/frontend-plugin-core/src/main/java/com/github/eirslett/maven/plugins/frontend/lib/NodeInstaller.java index 2ca05dc5..805c8901 100644 --- a/frontend-plugin-core/src/main/java/com/github/eirslett/maven/plugins/frontend/lib/NodeInstaller.java +++ b/frontend-plugin-core/src/main/java/com/github/eirslett/maven/plugins/frontend/lib/NodeInstaller.java @@ -128,7 +128,7 @@ private void installNodeDefault() throws InstallationException { this.config.getPlatform().getLongNodeFilename(this.nodeVersion, false); String downloadUrl = this.nodeDownloadRoot + this.config.getPlatform().getNodeDownloadFilename(this.nodeVersion, false); - String classifier = this.config.getPlatform().getNodeClassifier(); + String classifier = this.config.getPlatform().getNodeClassifier(this.nodeVersion); File tmpDirectory = getTempDirectory(); @@ -216,7 +216,7 @@ private void installNodeWithNpmForWindows() throws InstallationException { this.config.getPlatform().getLongNodeFilename(this.nodeVersion, true); String downloadUrl = this.nodeDownloadRoot + this.config.getPlatform().getNodeDownloadFilename(this.nodeVersion, true); - String classifier = this.config.getPlatform().getNodeClassifier(); + String classifier = this.config.getPlatform().getNodeClassifier(this.nodeVersion); File tmpDirectory = getTempDirectory(); @@ -274,7 +274,7 @@ private void installNodeForWindows() throws InstallationException { File destination = new File(destinationDirectory, "node.exe"); - String classifier = this.config.getPlatform().getNodeClassifier(); + String classifier = this.config.getPlatform().getNodeClassifier(this.nodeVersion); CacheDescriptor cacheDescriptor = new CacheDescriptor("node", this.nodeVersion, classifier, "exe"); diff --git a/frontend-plugin-core/src/main/java/com/github/eirslett/maven/plugins/frontend/lib/Platform.java b/frontend-plugin-core/src/main/java/com/github/eirslett/maven/plugins/frontend/lib/Platform.java index 68d38e43..39d93a98 100644 --- a/frontend-plugin-core/src/main/java/com/github/eirslett/maven/plugins/frontend/lib/Platform.java +++ b/frontend-plugin-core/src/main/java/com/github/eirslett/maven/plugins/frontend/lib/Platform.java @@ -1,6 +1,8 @@ package com.github.eirslett.maven.plugins.frontend.lib; import java.io.File; +import java.util.regex.Matcher; +import java.util.regex.Pattern; enum Architecture { x86, x64, ppc64le, s390x, arm64, armv7l, ppc, ppc64; public static Architecture guess(){ @@ -60,6 +62,13 @@ public String getCodename(){ } class Platform { + + /** + * Node.js supports Apple silicon since v16 + * https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V16.md#toolchain-and-compiler-upgrades + */ + private static final int NODE_VERSION_THRESHOLD_MAC_ARM64 = 16; + private final String nodeDownloadRoot; private final OS os; private final Architecture architecture; @@ -117,7 +126,7 @@ public String getLongNodeFilename(String nodeVersion, boolean archiveOnWindows) if(isWindows() && !archiveOnWindows){ return "node.exe"; } else { - return "node-" + nodeVersion + "-" + this.getNodeClassifier(); + return "node-" + nodeVersion + "-" + this.getNodeClassifier(nodeVersion); } } @@ -141,13 +150,30 @@ public String getNodeDownloadFilename(String nodeVersion, boolean archiveOnWindo } } - public String getNodeClassifier() { - final String result; - if(isMac() && architecture == Architecture.arm64) { // this check is required to download the x64 binary until there is an arm64 version available for macOS (darwin). - result = getCodename() + "-" + Architecture.x64.name(); + public String getNodeClassifier(String nodeVersion) { + String result = getCodename() + "-" + resolveArchitecture(nodeVersion).name(); + return classifier != null ? result + "-" + classifier : result; + } + + private Architecture resolveArchitecture(String nodeVersion) { + if (isMac() && architecture == Architecture.arm64) { + Integer nodeMajorVersion = getNodeMajorVersion(nodeVersion); + if (nodeMajorVersion == null || nodeMajorVersion < NODE_VERSION_THRESHOLD_MAC_ARM64) { + return Architecture.x64; + } + } + + return architecture; + } + + static Integer getNodeMajorVersion(String nodeVersion) { + Matcher matcher = Pattern.compile("^v(\\d+)\\..*$").matcher(nodeVersion); + if (matcher.matches()) { + return Integer.parseInt(matcher.group(1)); } else { - result = getCodename() + "-" + architecture.name(); + // malformed node version + return null; } - return classifier != null ? result + "-" + classifier : result; } + } diff --git a/frontend-plugin-core/src/test/java/com/github/eirslett/maven/plugins/frontend/lib/PlatformTest.java b/frontend-plugin-core/src/test/java/com/github/eirslett/maven/plugins/frontend/lib/PlatformTest.java index e9af5913..8a1bb218 100644 --- a/frontend-plugin-core/src/test/java/com/github/eirslett/maven/plugins/frontend/lib/PlatformTest.java +++ b/frontend-plugin-core/src/test/java/com/github/eirslett/maven/plugins/frontend/lib/PlatformTest.java @@ -17,6 +17,10 @@ @PrepareForTest({Platform.class, OS.class, Architecture.class, File.class}) public class PlatformTest { + private static final String NODE_VERSION_8 = "v8.17.2"; + private static final String NODE_VERSION_15 = "v15.14.0"; + private static final String NODE_VERSION_16 = "v16.1.0"; + @Test public void detect_win_doesntLookForAlpine() { mockStatic(OS.class); @@ -26,13 +30,13 @@ public void detect_win_doesntLookForAlpine() { when(Architecture.guess()).thenReturn(Architecture.x86); Platform platform = Platform.guess(); - assertEquals("win-x86", platform.getNodeClassifier()); + assertEquals("win-x86", platform.getNodeClassifier(NODE_VERSION_15)); verifyNoMoreInteractions(File.class); // doesn't look for a file path } @Test - public void detect_arm_mac_download_x64_binary() { + public void detect_arm_mac_download_x64_binary_node15() { mockStatic(OS.class); mockStatic(Architecture.class); @@ -40,7 +44,19 @@ public void detect_arm_mac_download_x64_binary() { when(Architecture.guess()).thenReturn(Architecture.arm64); Platform platform = Platform.guess(); - assertEquals("darwin-x64", platform.getNodeClassifier()); + assertEquals("darwin-x64", platform.getNodeClassifier(NODE_VERSION_15)); + } + + @Test + public void detect_arm_mac_download_x64_binary_node16() { + mockStatic(OS.class); + mockStatic(Architecture.class); + + when(OS.guess()).thenReturn(OS.Mac); + when(Architecture.guess()).thenReturn(Architecture.arm64); + + Platform platform = Platform.guess(); + assertEquals("darwin-arm64", platform.getNodeClassifier(NODE_VERSION_16)); } @Test @@ -58,7 +74,7 @@ public void detect_linux_notAlpine() throws Exception { when(alpineRelease.exists()).thenReturn(false); Platform platform = Platform.guess(); - assertEquals("linux-x86", platform.getNodeClassifier()); + assertEquals("linux-x86", platform.getNodeClassifier(NODE_VERSION_15)); assertEquals("https://nodejs.org/dist/", platform.getNodeDownloadRoot()); } @@ -77,7 +93,7 @@ public void detect_linux_alpine() throws Exception { when(alpineRelease.exists()).thenReturn(true); Platform platform = Platform.guess(); - assertEquals("linux-x86-musl", platform.getNodeClassifier()); + assertEquals("linux-x86-musl", platform.getNodeClassifier(NODE_VERSION_15)); assertEquals("https://unofficial-builds.nodejs.org/download/release/", platform.getNodeDownloadRoot()); } @@ -91,6 +107,14 @@ public void detect_aix_ppc64() { when(Architecture.guess()).thenReturn(Architecture.ppc64); Platform platform = Platform.guess(); - assertEquals("aix-ppc64", platform.getNodeClassifier()); + assertEquals("aix-ppc64", platform.getNodeClassifier(NODE_VERSION_15)); } + + @Test + public void getNodeMajorVersion() { + assertEquals(Integer.valueOf(8), Platform.getNodeMajorVersion(NODE_VERSION_8)); + assertEquals(Integer.valueOf(15), Platform.getNodeMajorVersion(NODE_VERSION_15)); + assertEquals(Integer.valueOf(16), Platform.getNodeMajorVersion(NODE_VERSION_16)); + } + }