Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support installing node,npm,yarn version from package.json engines #999

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,13 @@
{
"name": "example",
"version": "0.0.1",
"engines": {
"node": ">=10.3 <15"
},
"dependencies": {
"less": "~3.0.2"
},
"scripts": {
"prebuild": "npm install"
}
}
49 changes: 49 additions & 0 deletions frontend-maven-plugin/src/it/node-version-from-engines/pom.xml
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.github.eirslett</groupId>
<artifactId>example</artifactId>
<version>0</version>
<packaging>pom</packaging>

<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<!-- NB! Set <version> to the latest released version of frontend-maven-plugin, like in README.md -->
<version>@project.version@</version>

<configuration>
<installDirectory>target</installDirectory>
</configuration>

<executions>

<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>engines</nodeVersion>
</configuration>
</execution>

<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<!-- Optional configuration which provides for running any npm command -->
<configuration>
<arguments>install</arguments>
</configuration>
</execution>

</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,9 @@
assert new File(basedir, 'target/node').exists() : "Node was not installed in the custom install directory";
assert new File(basedir, 'node_modules').exists() : "Node modules were not installed in the base directory";
assert new File(basedir, 'target/node/npm').exists() : "npm was not copied to the node directory";

import org.codehaus.plexus.util.FileUtils;

String buildLog = FileUtils.fileRead(new File(basedir, 'build.log'));

assert buildLog.contains('BUILD SUCCESS') : 'build was not successful'
13 changes: 13 additions & 0 deletions frontend-maven-plugin/src/it/npm-version-from-engines/package.json
@@ -0,0 +1,13 @@
{
"name": "example",
"version": "0.0.1",
"engines": {
"npm": ">=7 <8"
},
"dependencies": {
"less": "~3.0.2"
},
"scripts": {
"prebuild": "npm install"
}
}
50 changes: 50 additions & 0 deletions frontend-maven-plugin/src/it/npm-version-from-engines/pom.xml
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.github.eirslett</groupId>
<artifactId>example</artifactId>
<version>0</version>
<packaging>pom</packaging>

<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<!-- NB! Set <version> to the latest released version of frontend-maven-plugin, like in README.md -->
<version>@project.version@</version>

<configuration>
<installDirectory>target</installDirectory>
</configuration>

<executions>

<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>v16.0.0</nodeVersion>
<npmVersion>engines</npmVersion>
</configuration>
</execution>

<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<!-- Optional configuration which provides for running any npm command -->
<configuration>
<arguments>install</arguments>
</configuration>
</execution>

</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,9 @@
assert new File(basedir, 'target/node').exists() : "Node was not installed in the custom install directory";
assert new File(basedir, 'node_modules').exists() : "Node modules were not installed in the base directory";
assert new File(basedir, 'target/node/npm').exists() : "npm was not copied to the node directory";

import org.codehaus.plexus.util.FileUtils;

String buildLog = FileUtils.fileRead(new File(basedir, 'build.log'));

assert buildLog.contains('BUILD SUCCESS') : 'build was not successful'
@@ -0,0 +1,13 @@
{
"name": "example",
"version": "0.0.1",
"engines": {
"yarn": "^1.10"
},
"dependencies": {
"less": "~3.0.2"
},
"scripts": {
"prebuild": "npm install"
}
}
50 changes: 50 additions & 0 deletions frontend-maven-plugin/src/it/yarn-version-from-engines/pom.xml
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.github.eirslett</groupId>
<artifactId>example</artifactId>
<version>0</version>
<packaging>pom</packaging>

<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<!-- NB! Set <version> to the latest released version of frontend-maven-plugin, like in README.md -->
<version>@project.version@</version>

<configuration>
<installDirectory>target</installDirectory>
</configuration>

<executions>

<execution>
<id>install node and yarn</id>
<goals>
<goal>install-node-and-yarn</goal>
</goals>
<configuration>
<nodeVersion>v16.0.0</nodeVersion>
<yarnVersion>engines</yarnVersion>
</configuration>
</execution>

<execution>
<id>yarn install</id>
<goals>
<goal>yarn</goal>
</goals>
<!-- Optional configuration which provides for running any npm command -->
<configuration>
<arguments>install</arguments>
</configuration>
</execution>

</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,6 @@
assert new File(basedir, 'target/node').exists() : "Node was not installed in the custom install directory";
assert new File(basedir, 'node_modules').exists() : "Node modules were not installed in the base directory";
assert new File(basedir, 'node_modules/less/package.json').exists() : "Less dependency has not been installed successfully";

String buildLog = new File(basedir, 'build.log').text
assert buildLog.contains('BUILD SUCCESS') : 'build was not successful'
Expand Up @@ -78,28 +78,28 @@ public void execute(FrontendPluginFactory factory) throws InstallationException
String npmDownloadRoot = getNpmDownloadRoot();
Server server = MojoUtils.decryptServer(serverId, session, decrypter);
if (null != server) {
factory.getNodeInstaller(proxyConfig)
String installedNodeVersion=factory.getNodeInstaller(proxyConfig)
.setNodeVersion(nodeVersion)
.setNodeDownloadRoot(nodeDownloadRoot)
.setNpmVersion(npmVersion)
.setUserName(server.getUsername())
.setPassword(server.getPassword())
.install();
factory.getNPMInstaller(proxyConfig)
.setNodeVersion(nodeVersion)
.setNodeVersion(installedNodeVersion)
.setNpmVersion(npmVersion)
.setNpmDownloadRoot(npmDownloadRoot)
.setUserName(server.getUsername())
.setPassword(server.getPassword())
.install();
} else {
factory.getNodeInstaller(proxyConfig)
String installedNodeVersion=factory.getNodeInstaller(proxyConfig)
.setNodeVersion(nodeVersion)
.setNodeDownloadRoot(nodeDownloadRoot)
.setNpmVersion(npmVersion)
.install();
factory.getNPMInstaller(proxyConfig)
.setNodeVersion(this.nodeVersion)
.setNodeVersion(installedNodeVersion)
.setNpmVersion(this.npmVersion)
.setNpmDownloadRoot(npmDownloadRoot)
.install();
Expand Down
6 changes: 6 additions & 0 deletions frontend-plugin-core/pom.xml
Expand Up @@ -11,6 +11,12 @@
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>com.vdurmont</groupId>
<artifactId>semver4j</artifactId>
<version>3.1.0</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
Expand Down
Expand Up @@ -6,6 +6,10 @@
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import com.vdurmont.semver4j.Requirement;
import com.vdurmont.semver4j.Semver;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -28,6 +32,8 @@ public class NPMInstaller {

private final FileDownloader fileDownloader;

private Requirement npmVersionRequirement;

NPMInstaller(InstallConfig config, ArchiveExtractor archiveExtractor, FileDownloader fileDownloader) {
this.logger = LoggerFactory.getLogger(getClass());
this.config = config;
Expand Down Expand Up @@ -78,7 +84,53 @@ public void install() throws InstallationException {
if (this.npmDownloadRoot == null || this.npmDownloadRoot.isEmpty()) {
this.npmDownloadRoot = DEFAULT_NPM_DOWNLOAD_ROOT;
}
if ("engines".equals(this.npmVersion)) {
try {
File packageFile = new File(this.config.getWorkingDirectory(), "package.json");
HashMap<String, Object> data = new ObjectMapper().readValue(packageFile, HashMap.class);
if (data.containsKey("engines")) {
HashMap<String, Object> engines = (HashMap<String, Object>) data.get("engines");
if (engines.containsKey("npm")) {
this.npmVersionRequirement = Requirement.buildNPM((String) engines.get("npm"));
} else {
this.logger.info("Could not read npm from engines from package.json");
}
} else {
this.logger.info("Could not read engines from package.json");
}
} catch (IOException e) {
throw new InstallationException("Could not read npm engine version from package.json", e);
}
}

if (!npmProvided() && !npmIsAlreadyInstalled()) {
if (this.npmVersionRequirement != null) {
// download available node versions
try {
String downloadUrl = this.npmDownloadRoot
+ "..";

File archive = File.createTempFile("npm_versions", ".json");

downloadFile(downloadUrl, archive, this.userName, this.password);

HashMap<String, Object> data = new ObjectMapper().readValue(archive, HashMap.class);

List<String> npmVersions = new LinkedList<>();
if (data.containsKey("versions")) {
HashMap<String, Object> versions = (HashMap<String, Object>) data.get("versions");
npmVersions.addAll(versions.keySet());
} else {
this.logger.info("Could not read versions from NPM registry");
}

logger.debug("Available NPM versions: {}", npmVersions);
this.npmVersion = npmVersions.stream().filter(version -> npmVersionRequirement.isSatisfiedBy(new Semver(version, Semver.SemverType.NPM))).findFirst().orElseThrow(() -> new InstallationException("Could not find matching node version satisfying requirement " + this.npmVersionRequirement));
this.logger.info("Found matching NPM version {} satisfying requirement {}.", this.npmVersion, this.npmVersionRequirement);
} catch (IOException | DownloadException e) {
throw new InstallationException("Could not get available node versions.", e);
}
}
installNpm();
}
copyNpmScripts();
Expand All @@ -93,7 +145,12 @@ private boolean npmIsAlreadyInstalled() {
HashMap<String, Object> data = new ObjectMapper().readValue(npmPackageJson, HashMap.class);
if (data.containsKey(VERSION)) {
final String foundNpmVersion = data.get(VERSION).toString();
if (foundNpmVersion.equals(this.npmVersion)) {
if (npmVersionRequirement != null && npmVersionRequirement.isSatisfiedBy(new Semver(foundNpmVersion, Semver.SemverType.NPM))) {
//update version with installed version
this.nodeVersion = foundNpmVersion;
this.logger.info("NPM {} matches required version range {} installed.", foundNpmVersion, npmVersionRequirement);
return true;
} else if (foundNpmVersion.equals(this.npmVersion)) {
this.logger.info("NPM {} is already installed.", foundNpmVersion);
return true;
} else {
Expand Down