Skip to content

Commit

Permalink
DCA11Y-1145: Add support for mise config files
Browse files Browse the repository at this point in the history
  • Loading branch information
atl-mk committed Sep 20, 2024
1 parent 589f352 commit 9429520
Show file tree
Hide file tree
Showing 14 changed files with 279 additions and 1 deletion.
6 changes: 6 additions & 0 deletions frontend-maven-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@
<goal>run</goal>
<goal>verify</goal>
</goals>
<configuration>
<environmentVariables>
<MISE_CONFIG_DIR>TESTDIR</MISE_CONFIG_DIR>
<MISE_ENV>TESTPROFILE</MISE_ENV>
</environmentVariables>
</configuration>
</execution>
</executions>
</plugin>
Expand Down
10 changes: 10 additions & 0 deletions frontend-maven-plugin/src/it/mise-config-file/.mise.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[tools]
java = "temurin-21"
maven = "3.9"
pre-commit = "latest"
ktlint = "latest"
python = "3.12"
# node 22.5.1
node = "22.5.1"
# node 22.5.1
yarn = "1.22.22"
12 changes: 12 additions & 0 deletions frontend-maven-plugin/src/it/mise-config-file/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions frontend-maven-plugin/src/it/mise-config-file/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "example",
"version": "0.0.1"
}
34 changes: 34 additions & 0 deletions frontend-maven-plugin/src/it/mise-config-file/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?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>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
5 changes: 5 additions & 0 deletions frontend-maven-plugin/src/it/mise-config-file/verify.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
assert new File(basedir, 'target/node').exists() : "Node was not installed in the custom install directory";

String buildLog = new File(basedir, 'build.log').text
assert buildLog.contains('.mise.toml') : 'The wrong file was used'
assert buildLog.contains('Installing node version v22.5.1') : 'The correct node version was not detected'
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[tools]
java = "temurin-21"
maven = "3.9"
pre-commit = "latest"
ktlint = "latest"
python = "3.12"
# node 22.5.1
node = "22.5.1"
# node 22.5.1
yarn = "1.22.22"

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "example",
"version": "0.0.1"
}
34 changes: 34 additions & 0 deletions frontend-maven-plugin/src/it/mise-env-config-file/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?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>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
assert new File(basedir, 'target/node').exists() : "Node was not installed in the custom install directory";

String buildLog = new File(basedir, 'build.log').text
assert buildLog.contains('TESTDIR/mise.TESTPROFILE.toml') : 'The wrong file was used'
assert buildLog.contains('Installing node version v22.5.1') : 'The correct node version was not detected'
6 changes: 6 additions & 0 deletions frontend-plugin-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@
<version>33.1.0-jre</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-lambda</artifactId>
<version>1.2.1</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static java.lang.String.format;
import static java.util.Objects.isNull;
import static java.util.Optional.empty;
import static org.slf4j.LoggerFactory.getLogger;

public class NodeVersionDetector {

private static final List<String> MISE_CONFIG_FILENAMES = listMiseConfigFilenames();
private static final String TOOL_VERSIONS_FILENAME = ".tool-versions";

public static String getNodeVersion(File workingDir, String providedNodeVersion, String genericNodeVersionFile) throws Exception {
Expand All @@ -32,7 +35,9 @@ public static String getNodeVersion(File workingDir, String providedNodeVersion,
throw new Exception("The Node version file doesn't seem to exist: " + genericNodeVersionFileFile);
}

if (genericNodeVersionFile.endsWith(TOOL_VERSIONS_FILENAME)) {
if (genericNodeVersionFile.endsWith(".toml") && genericNodeVersionFile.contains("mise")) {
return readMiseConfigTomlFile(genericNodeVersionFileFile, genericNodeVersionFileFile.toPath(), logger);
} else if (genericNodeVersionFile.endsWith(TOOL_VERSIONS_FILENAME)) {
return readToolVersionsFile(genericNodeVersionFileFile, genericNodeVersionFileFile.toPath(), logger);
} else {
return readNvmrcFile(genericNodeVersionFileFile, genericNodeVersionFileFile.toPath(), logger);
Expand All @@ -48,6 +53,49 @@ public static String getNodeVersion(File workingDir, String providedNodeVersion,
}
}

/**
* Mise has way too many options, see:
* <a href="https://mise.jdx.dev/profiles.html">https://mise.jdx.dev/profiles.html</a>
* <a href="https://mise.jdx.dev/configuration.html#mise-toml">https://mise.jdx.dev/configuration.html#mise-toml</a>
*/
public static List<String> listMiseConfigFilenames() {
final String miseConfigDir = System.getenv("MISE_CONFIG_DIR");
final String miseEnv = System.getenv("MISE_ENV");

// The order is important and should respect mises' ordering
final List<String> allMiseConfigFilenames = new ArrayList<>();

allMiseConfigFilenames.add(format("%s/config.%s.toml", miseConfigDir, miseEnv));
allMiseConfigFilenames.add(format("%s/mise.%s.toml", miseConfigDir, miseEnv));

allMiseConfigFilenames.add(".config/mise/config.toml");
allMiseConfigFilenames.add("mise/config.toml");
allMiseConfigFilenames.add("mise.toml");
allMiseConfigFilenames.add(".mise/config.toml");
allMiseConfigFilenames.add(".mise.toml");
allMiseConfigFilenames.add(".config/mise/config.local.toml");
allMiseConfigFilenames.add("mise/config.local.toml");
allMiseConfigFilenames.add("mise.local.toml");
allMiseConfigFilenames.add(".mise/config.local.toml");
allMiseConfigFilenames.add(".mise.local.toml");

allMiseConfigFilenames.add(format(".config/mise/config.%s.toml", miseEnv));
allMiseConfigFilenames.add(format("mise/config.%s.toml", miseEnv));
allMiseConfigFilenames.add(format("mise.%s.toml", miseEnv));
allMiseConfigFilenames.add(format(".mise/config.%s.toml", miseEnv));
allMiseConfigFilenames.add(format(".mise.%s.toml", miseEnv));
allMiseConfigFilenames.add(format(".config/mise/config.%s.local.toml", miseEnv));
allMiseConfigFilenames.add(format("mise/config.%s.local.toml", miseEnv));
allMiseConfigFilenames.add(format(".mise/config.%s.local.toml", miseEnv));
allMiseConfigFilenames.add(format(".mise.%s.local.toml", miseEnv));

return allMiseConfigFilenames;
}

/**
* Ordering this hierarchy of reading the files isn't just the most idiomatic, it's also probably the best
* for performance.
*/
public static String recursivelyFindVersion(File directory) throws Exception {
Logger logger = getLogger(NodeVersionDetector.class);

Expand Down Expand Up @@ -79,6 +127,20 @@ public static String recursivelyFindVersion(File directory) throws Exception {
if (trimmedLine != null) return trimmedLine;
}

for (String miseConfigFilename: MISE_CONFIG_FILENAMES) {
// We don't know if MISE_CONFIG_DIR can result in absolute or relative file paths, try to do our best
String[] splitMiseConfigFilename = miseConfigFilename.split("/");
Path potentiallyAbsoluteFilepath = Paths.get("", splitMiseConfigFilename);
Path miseConfigFilePath = potentiallyAbsoluteFilepath.isAbsolute() ?
potentiallyAbsoluteFilepath : Paths.get(directoryPath, splitMiseConfigFilename);

File miseConfigFile = miseConfigFilePath.toFile();
if (miseConfigFile.exists()) {
String trimmedVersion = readMiseConfigTomlFile(miseConfigFile, miseConfigFilePath, logger);
if (trimmedVersion != null) return trimmedVersion;
}
}

File parent = directory.getParentFile();
if (isNull(parent) || directory.equals(parent)) {
throw new Exception("Reach root-level without finding a suitable file");
Expand Down Expand Up @@ -131,6 +193,41 @@ static Optional<String> readNvmrcFileLines(List<String> lines) {
return empty();
}

/**
* If this gets any more complicated we'll add a reader, not sure how strict mise is with the spec, we want to be
* at least as loose.
*/
@VisibleForTesting
static String readMiseConfigTomlFile(File miseTomlFile, Path miseTomlFilePath, Logger logger) throws Exception {
assertNodeVersionFileIsReadable(miseTomlFile);

List<String> lines = Files.readAllLines(miseTomlFilePath);
for (String line: lines) {
if (!isNull(line)) {
String trimmedLine = line.trim();

if (trimmedLine.isEmpty()) {
continue;
}

if (!trimmedLine.startsWith("node")) { // naturally skips over comments
continue;
}

logger.info("Found the version of Node in: " + miseTomlFilePath);

if (trimmedLine.contains("[")) {
throw new Exception("mise file support is limited to a single version");
}

return trimmedLine
.replaceAll("node(js)?\\s*=\\s*", "")
.replaceAll("\"", ""); // destringify the version
}
}
return null;
}

private static String readToolVersionsFile(File toolVersionsFile, Path toolVersionsFilePath, Logger logger) throws Exception {
assertNodeVersionFileIsReadable(toolVersionsFile);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
package com.github.eirslett.maven.plugins.frontend.lib;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import static com.github.eirslett.maven.plugins.frontend.lib.NodeVersionDetector.readNvmrcFileLines;
import static com.github.eirslett.maven.plugins.frontend.lib.NodeVersionDetector.recursivelyFindVersion;
import static com.github.stefanbirkner.systemlambda.SystemLambda.withEnvironmentVariable;
import static java.lang.String.format;
import static java.nio.charset.Charset.defaultCharset;
import static java.nio.file.StandardOpenOption.WRITE;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.assertEquals;
Expand Down Expand Up @@ -39,4 +49,33 @@ public void testNvmrcFileParsing_shouldIgnoreEmptyLines() {
""
)).get());
}

@Test
public void testAbsoluteMiseConfigFilePath(
@TempDir Path tempMiseConfigDir,
@TempDir Path tempUnrelatedDirectory
) throws Exception {
// setup
String expectedVersion = "9.8.7";
String miseProfile = "testabsolute";

Path tempMiseConfigDirAbsolutePath = tempMiseConfigDir.toAbsolutePath();
String tempMiseConfigFilename = format("mise.%s.toml", miseProfile);
Path tempMiseConfigFilePath = Paths.get(tempMiseConfigDirAbsolutePath.toString(), tempMiseConfigFilename);
Path tempMiseConfigFile = Files.createFile(tempMiseConfigFilePath);

// given
withEnvironmentVariable("MISE_CONFIG_DIR", tempMiseConfigDirAbsolutePath.toString())
.and("MISE_ENV", miseProfile)
.execute(() -> {
String miseConfigFileContents = format("node = \"%s\"", expectedVersion);
Files.write(tempMiseConfigFile, singletonList(miseConfigFileContents), defaultCharset(), WRITE);

// when
String readVersion = recursivelyFindVersion(tempUnrelatedDirectory.toFile());

// then
assertEquals(expectedVersion, readVersion, "versions didn't match");
});
}
}

0 comments on commit 9429520

Please sign in to comment.