Skip to content

Commit

Permalink
fix: yarn berry detection in case working directory is changed
Browse files Browse the repository at this point in the history
Furthermore, prevent errors in case of berry usage
and attempt to add arguments, which are not supported
by berry.
  • Loading branch information
holomekc authored and eirslett committed May 12, 2024
1 parent 5ad126f commit edca7a1
Show file tree
Hide file tree
Showing 14 changed files with 1,040 additions and 32 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ jobs:

steps:
- name: Git checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Use cache
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ~/.m2
key: "${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}"
restore-keys: |
${{ runner.os }}-maven3-
- name: Configure Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: "8"
java-version: "21"
distribution: temurin
- name: "Run Maven"
shell: bash
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
cacheFolder: .yarn/cache

enableGlobalCache: false

nodeLinker: node-modules

yarnPath: .yarn/releases/yarn-4.1.1.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "example",
"version": "0.0.1",
"dependencies": {
"less": "~3.0.2"
},
"packageManager": "[email protected]"
}
49 changes: 49 additions & 0 deletions frontend-maven-plugin/src/it/yarn-berry-integration/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http:https://maven.apache.org/POM/4.0.0" xmlns:xsi="http:https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http:https://maven.apache.org/POM/4.0.0 http:https://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>v20.12.2</nodeVersion>
<yarnVersion>v1.22.22</yarnVersion>
</configuration>
</execution>

<execution>
<id>yarn install</id>
<goals>
<goal>yarn</goal>
</goals>
<configuration>
<arguments>install --no-immutable</arguments>
</configuration>
</execution>

</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
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'
//TODO: Find a suitable replacement for this if it's necessary.
//assert buildLog.replace(File.separatorChar, '/' as char).matches('(?s).+Unpacking .+\\Q/local-repo/com/github/eirslett/yarn/[1-9\\.]*/yarn-[1-9\\.]*.tar.gz\\E into .+/target/node/yarn.+') : 'incorrect local repository location'
4 changes: 2 additions & 2 deletions frontend-maven-plugin/src/it/yarn-integration/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
<goal>install-node-and-yarn</goal>
</goals>
<configuration>
<nodeVersion>v8.11.1</nodeVersion>
<yarnVersion>v1.6.0</yarnVersion>
<nodeVersion>v20.12.2</nodeVersion>
<yarnVersion>v1.22.22</yarnVersion>
</configuration>
</execution>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.github.eirslett.maven.plugins.frontend.mojo;

import static com.github.eirslett.maven.plugins.frontend.mojo.YarnUtils.isYarnrcYamlFilePresent;

import java.io.File;
import java.util.stream.Stream;
import org.apache.maven.execution.MavenSession;
Expand Down Expand Up @@ -69,38 +71,25 @@ protected boolean skipExecution() {
return this.skip;
}

/**
* Checks whether a .yarnrc.yml file exists at the project root (in multi-module builds, it will be the Reactor project)
*
* @return true if the .yarnrc.yml file exists, false otherwise
*/
private boolean isYarnrcYamlFilePresent() {
Stream<File> filesToCheck = Stream.of(
new File(session.getCurrentProject().getBasedir(), YARNRC_YAML_FILE_NAME),
new File(session.getRequest().getMultiModuleProjectDirectory(), YARNRC_YAML_FILE_NAME),
new File(session.getExecutionRootDirectory(), YARNRC_YAML_FILE_NAME)
);

return filesToCheck
.anyMatch(File::exists);
}

@Override
public void execute(FrontendPluginFactory factory) throws InstallationException {
ProxyConfig proxyConfig = MojoUtils.getProxyConfig(this.session, this.decrypter);
Server server = MojoUtils.decryptServer(this.serverId, this.session, this.decrypter);

boolean isYarnYamlFilePresent = isYarnrcYamlFilePresent(this.session, this.workingDirectory);

if (null != server) {
factory.getNodeInstaller(proxyConfig).setNodeDownloadRoot(this.nodeDownloadRoot)
.setNodeVersion(this.nodeVersion).setPassword(server.getPassword())
.setUserName(server.getUsername()).install();
factory.getYarnInstaller(proxyConfig).setYarnDownloadRoot(this.yarnDownloadRoot)
.setYarnVersion(this.yarnVersion).setUserName(server.getUsername())
.setPassword(server.getPassword()).setIsYarnBerry(isYarnrcYamlFilePresent()).install();
.setPassword(server.getPassword()).setIsYarnBerry(isYarnYamlFilePresent).install();
} else {
factory.getNodeInstaller(proxyConfig).setNodeDownloadRoot(this.nodeDownloadRoot)
.setNodeVersion(this.nodeVersion).install();
factory.getYarnInstaller(proxyConfig).setYarnDownloadRoot(this.yarnDownloadRoot)
.setYarnVersion(this.yarnVersion).setIsYarnBerry(isYarnrcYamlFilePresent()).install();
.setYarnVersion(this.yarnVersion).setIsYarnBerry(isYarnYamlFilePresent).install();
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.github.eirslett.maven.plugins.frontend.mojo;

import static com.github.eirslett.maven.plugins.frontend.mojo.YarnUtils.isYarnrcYamlFilePresent;

import java.io.File;
import java.util.Collections;

Expand Down Expand Up @@ -62,7 +64,8 @@ public synchronized void execute(FrontendPluginFactory factory) throws TaskRunne
if (this.buildContext == null || this.buildContext.hasDelta(packageJson)
|| !this.buildContext.isIncremental()) {
ProxyConfig proxyConfig = getProxyConfig();
factory.getYarnRunner(proxyConfig, getRegistryUrl()).execute(this.arguments,
boolean isYarnBerry = isYarnrcYamlFilePresent(this.session, this.workingDirectory);
factory.getYarnRunner(proxyConfig, getRegistryUrl(), isYarnBerry).execute(this.arguments,
this.environmentVariables);
} else {
getLog().info("Skipping yarn install as package.json unchanged");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.github.eirslett.maven.plugins.frontend.mojo;

import java.io.File;
import java.util.stream.Stream;

import org.apache.maven.execution.MavenSession;

public class YarnUtils {

private static final String YARNRC_YAML_FILE_NAME = ".yarnrc.yml";

/**
* Checks whether a .yarnrc.yml file exists at the project root
* (in multi-module builds, it will be the Reactor project)
*
* @param session
* the current maven session
* @param workingDirectory
* the configured working directory
*
* @return true if the .yarnrc.yml file exists, false otherwise
*/
public static boolean isYarnrcYamlFilePresent(MavenSession session, File workingDirectory) {
Stream<File> filesToCheck = Stream.of(
new File(session.getCurrentProject().getBasedir(), YARNRC_YAML_FILE_NAME),
new File(session.getRequest().getMultiModuleProjectDirectory(), YARNRC_YAML_FILE_NAME),
new File(session.getExecutionRootDirectory(), YARNRC_YAML_FILE_NAME),
new File(workingDirectory, YARNRC_YAML_FILE_NAME)
);

return filesToCheck
.anyMatch(File::exists);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ public NpxRunner getNpxRunner(ProxyConfig proxy, String npmRegistryURL) {
return new DefaultNpxRunner(getExecutorConfig(), proxy, npmRegistryURL);
}

public YarnRunner getYarnRunner(ProxyConfig proxy, String npmRegistryURL) {
return new DefaultYarnRunner(new InstallYarnExecutorConfig(getInstallConfig()), proxy, npmRegistryURL);
public YarnRunner getYarnRunner(ProxyConfig proxy, String npmRegistryURL, boolean isYarnBerry) {
return new DefaultYarnRunner(new InstallYarnExecutorConfig(getInstallConfig(), isYarnBerry), proxy, npmRegistryURL);
}

public GruntRunner getGruntRunner(){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public interface YarnExecutorConfig {
File getWorkingDirectory();

Platform getPlatform();

boolean isYarnBerry();
}

final class InstallYarnExecutorConfig implements YarnExecutorConfig {
Expand All @@ -20,13 +22,16 @@ final class InstallYarnExecutorConfig implements YarnExecutorConfig {

private static final String YARN_DEFAULT = YarnInstaller.INSTALL_PATH + "/dist/bin/yarn";

private File nodePath;
private final File nodePath;

private final InstallConfig installConfig;

public InstallYarnExecutorConfig(InstallConfig installConfig) {
private final boolean isYarnBerry;

public InstallYarnExecutorConfig(InstallConfig installConfig, final boolean isYarnBerry) {
this.installConfig = installConfig;
nodePath = new InstallNodeExecutorConfig(installConfig).getNodePath();
this.isYarnBerry = isYarnBerry;
}

@Override
Expand All @@ -49,4 +54,9 @@ public File getWorkingDirectory() {
public Platform getPlatform() {
return installConfig.getPlatform();
}

@Override
public boolean isYarnBerry() {
return isYarnBerry;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public void install() throws InstallationException {

private boolean yarnIsAlreadyInstalled() {
try {
YarnExecutorConfig executorConfig = new InstallYarnExecutorConfig(config);
YarnExecutorConfig executorConfig = new InstallYarnExecutorConfig(config, isYarnBerry);
File nodeFile = executorConfig.getYarnPath();
if (nodeFile.exists()) {
final String version =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,19 @@ final class DefaultYarnRunner extends YarnTaskExecutor implements YarnRunner {

public DefaultYarnRunner(YarnExecutorConfig config, ProxyConfig proxyConfig, String npmRegistryURL) {
super(config, TASK_NAME, config.getYarnPath().getAbsolutePath(),
buildArguments(proxyConfig, npmRegistryURL));
buildArguments(config, proxyConfig, npmRegistryURL));
}

private static List<String> buildArguments(ProxyConfig proxyConfig, String npmRegistryURL) {
private static List<String> buildArguments(final YarnExecutorConfig config, ProxyConfig proxyConfig,
String npmRegistryURL) {
List<String> arguments = new ArrayList<>();

if (config.isYarnBerry()) {
// Yarn berry does not support the additional arguments we try to set below.
// Setting those results in failures during yarn execution.
return arguments;
}

if (npmRegistryURL != null && !npmRegistryURL.isEmpty()) {
arguments.add("--registry=" + npmRegistryURL);
}
Expand Down

0 comments on commit edca7a1

Please sign in to comment.