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

fix: yarn berry detection in case working directory is changed #1143

Merged
merged 3 commits into from
May 12, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"
eirslett marked this conversation as resolved.
Show resolved Hide resolved
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://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>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