diff --git a/README.md b/README.md index b3b489c0f..83f795966 100644 --- a/README.md +++ b/README.md @@ -140,7 +140,7 @@ present). Have a look at the example `POM` to see how it should be set up with Yarn: https://github.com/eirslett/frontend-maven-plugin/blob/master/frontend-maven-plugin/src/it/yarn-integration/pom.xml - +For standard default node and yarn location ```xml ... @@ -165,6 +165,16 @@ https://github.com/eirslett/frontend-maven-plugin/blob/master/frontend-maven-plu ``` +To specify a custom yarn dist tar ball location: +```xml + https://repository.xyz.com/content/repositories/public/yarn/ + 1.17.3 + tgz +``` +Then the program will look for a tar file at: +```/yarn-.tgz```, which translates to +```https://repository.xyz.com/content/repositories/public/yarn/yarn-1.17.3.tgz``` + ### Running npm All node packaged modules will be installed in the `node_modules` folder in your [working directory](#working-directory). diff --git a/frontend-maven-plugin/src/main/java/com/github/eirslett/maven/plugins/frontend/mojo/InstallNodeAndYarnMojo.java b/frontend-maven-plugin/src/main/java/com/github/eirslett/maven/plugins/frontend/mojo/InstallNodeAndYarnMojo.java index daae17c79..4c1cb921a 100644 --- a/frontend-maven-plugin/src/main/java/com/github/eirslett/maven/plugins/frontend/mojo/InstallNodeAndYarnMojo.java +++ b/frontend-maven-plugin/src/main/java/com/github/eirslett/maven/plugins/frontend/mojo/InstallNodeAndYarnMojo.java @@ -31,6 +31,14 @@ public final class InstallNodeAndYarnMojo extends AbstractFrontendMojo { defaultValue = YarnInstaller.DEFAULT_YARN_DOWNLOAD_ROOT) private String yarnDownloadRoot; + /** + * Full path minus version to download Yarn binary from. No default. Ends with slash. + * Example: https://a-host.a-domain/blah/blah/-/ of https://a-host.a-domain/blah/blah/-/yarn-1.17.3.tgz + */ + @Parameter(property = "yarnDownloadUrl", required = false, + defaultValue = "") + private String yarnDownloadUrl; + /** * The version of Node.js to install. IMPORTANT! Most Node.js version names start with 'v', for example * 'v0.10.18' @@ -44,6 +52,12 @@ public final class InstallNodeAndYarnMojo extends AbstractFrontendMojo { @Parameter(property = "yarnVersion", required = true) private String yarnVersion; + /** + * The tarball extension of Yarn to install, something like tgz, tar.gz, etc. + */ + @Parameter(property = "yarnExtension", required = false, defaultValue = "") + private String yarnExtension; + /** * Server Id for download username and password */ @@ -81,8 +95,13 @@ public void execute(FrontendPluginFactory factory) throws InstallationException } else { factory.getNodeInstaller(proxyConfig).setNodeDownloadRoot(this.nodeDownloadRoot) .setNodeVersion(this.nodeVersion).install(); - factory.getYarnInstaller(proxyConfig).setYarnDownloadRoot(this.yarnDownloadRoot) - .setYarnVersion(this.yarnVersion).install(); + if (this.yarnDownloadUrl != null && !this.yarnDownloadUrl.isEmpty()) { + factory.getYarnInstaller(proxyConfig).setYarnVersion(this.yarnVersion) + .install(this.yarnDownloadUrl, this.yarnExtension); + } else { + factory.getYarnInstaller(proxyConfig).setYarnDownloadRoot(this.yarnDownloadRoot) + .setYarnVersion(this.yarnVersion).install(); + } } } diff --git a/frontend-plugin-core/src/main/java/com/github/eirslett/maven/plugins/frontend/lib/YarnInstaller.java b/frontend-plugin-core/src/main/java/com/github/eirslett/maven/plugins/frontend/lib/YarnInstaller.java index 532439fb2..c6e4234c4 100644 --- a/frontend-plugin-core/src/main/java/com/github/eirslett/maven/plugins/frontend/lib/YarnInstaller.java +++ b/frontend-plugin-core/src/main/java/com/github/eirslett/maven/plugins/frontend/lib/YarnInstaller.java @@ -73,6 +73,21 @@ public void install() throws InstallationException { } } + public void install(String yarnDownloadUrl, String yarnExtension) throws InstallationException { + if (yarnVersion == null || yarnVersion.isEmpty()) { + throw new InstallationException("yarnVersion has to be provided."); + } + if (yarnExtension == null || yarnExtension.isEmpty()) { + throw new InstallationException("yarnExtension has to be provided."); + } + // use static lock object for a synchronized block + synchronized (LOCK) { + if (!yarnIsAlreadyInstalled()) { + installYarn(yarnDownloadUrl, yarnVersion, yarnExtension); + } + } + } + private boolean yarnIsAlreadyInstalled() { try { YarnExecutorConfig executorConfig = new InstallYarnExecutorConfig(config); @@ -97,15 +112,27 @@ private boolean yarnIsAlreadyInstalled() { } private void installYarn() throws InstallationException { + String downloadUrl = yarnDownloadRoot + yarnVersion; + String defaultYarnExtension = "tar.gz"; + + try { + File installDirectory = getInstallDirectory(); + ensureCorrectYarnRootDirectory(installDirectory, yarnVersion); + } catch (IOException e) { + throw new InstallationException("Could not extract the Yarn archive", e); + } + + installYarn(downloadUrl, yarnVersion, defaultYarnExtension); + } + + private void installYarn(String yarnDownloadUrl, String yarnVersion, String yarnExtension) throws InstallationException { try { logger.info("Installing Yarn version {}", yarnVersion); - String downloadUrl = yarnDownloadRoot + yarnVersion; - String extension = "tar.gz"; - String fileending = "/yarn-" + yarnVersion + "." + extension; + String fileEnding = "/yarn-" + yarnVersion + "." + yarnExtension; - downloadUrl += fileending; + String downloadUrl = yarnDownloadUrl + fileEnding; - CacheDescriptor cacheDescriptor = new CacheDescriptor("yarn", yarnVersion, extension); + CacheDescriptor cacheDescriptor = new CacheDescriptor("yarn", yarnVersion, yarnExtension); File archive = config.getCacheResolver().resolve(cacheDescriptor); @@ -141,8 +168,6 @@ private void installYarn() throws InstallationException { throw e; } - ensureCorrectYarnRootDirectory(installDirectory, yarnVersion); - logger.info("Installed Yarn locally."); } catch (DownloadException e) { throw new InstallationException("Could not download Yarn", e); @@ -160,9 +185,45 @@ private File getInstallDirectory() { return installDirectory; } - private void extractFile(File archive, File destinationDirectory) throws ArchiveExtractionException { + private File getDistDirectory(File destinationDirectory) throws IOException { + File distDirectory = new File(destinationDirectory, "dist"); + if (distDirectory.exists()) { + try { + FileUtils.deleteDirectory(distDirectory); + } catch (IOException e) { + throw new IOException("Could not clean up existing dist directory: " + distDirectory.getName()); + } + } + logger.info("Creating directory {}", distDirectory); + distDirectory.mkdir(); + return distDirectory; + } + + private void copyToDist(File destinationDirectory) throws IOException { + // Copying installed /node/yarn/yarn- to /node/yarn/dist for execution path. + // See this: https://github.com/eirslett/frontend-maven-plugin/issues/647 + File versionedDirectory = new File(destinationDirectory, "yarn-" + + (yarnVersion.startsWith("v") ? "" : "v") + + yarnVersion); + File distDirectory = getDistDirectory(destinationDirectory); + + if (versionedDirectory.exists()) { + try { + logger.info("Copying {} to {}", versionedDirectory, distDirectory); + FileUtils.copyDirectory(versionedDirectory, distDirectory, true); + File distYarn = new File(distDirectory, "bin/yarn"); + distYarn.setExecutable(true); + } catch (IOException e) { + logger.error("Failed to copy from {} to {}.", versionedDirectory, distDirectory); + } + } + } + + private void extractFile(File archive, File destinationDirectory) throws ArchiveExtractionException, IOException { logger.info("Unpacking {} into {}", archive, destinationDirectory); archiveExtractor.extract(archive.getPath(), destinationDirectory.getPath()); + copyToDist(destinationDirectory); + } private void ensureCorrectYarnRootDirectory(File installDirectory, String yarnVersion) throws IOException {