Skip to content

Commit

Permalink
Merge pull request #1116 from jonkoops/fix-pnpm-bin
Browse files Browse the repository at this point in the history
Use a script to proxy PNPM executable on Windows
  • Loading branch information
eirslett authored Oct 23, 2023
2 parents b4738a7 + ceb0068 commit 436bd91
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 105 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
distribution: temurin
- name: "Run Maven"
shell: bash
run: mvn clean install --batch-mode -PintegrationTests -DintegrationTestProfiles=it-${{ runner.os }}
run: mvn clean install --batch-mode -PintegrationTests
- name: "Deploy"
if: github.repository_owner == 'eirslett' && github.ref == 'refs/heads/master' && matrix.os == 'ubuntu-latest'
shell: bash
Expand Down
5 changes: 0 additions & 5 deletions frontend-maven-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@
<maven>3.6.0</maven>
</prerequisites>

<properties>
<integrationTestProfiles>it-Linux</integrationTestProfiles>
</properties>

<description>
This Maven plugin lets you install Node/NPM locally
for your project, install dependencies with NPM,
Expand Down Expand Up @@ -134,7 +130,6 @@

<configuration>
<debug>true</debug>
<profiles>${integrationTestProfiles}</profiles>
<projectsDirectory>src/it</projectsDirectory>
<cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo>
<settingsFile>src/it/settings.xml</settingsFile>
Expand Down
68 changes: 11 additions & 57 deletions frontend-maven-plugin/src/it/pnpm-integration/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,65 +41,19 @@
<arguments>install</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

<profiles>
<profile>
<id>it-Linux</id>
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>

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

<executions>
<execution>
<id>pnpm test</id>
<goals>
<goal>pnpm</goal>
</goals>
<configuration>
<arguments>test</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>it-macOs</id>
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>

<execution>
<id>pnpm test</id>
<goals>
<goal>pnpm</goal>
</goals>
<configuration>
<installDirectory>target</installDirectory>
<arguments>test</arguments>
</configuration>
</execution>

<executions>
<execution>
<id>pnpm test</id>
<goals>
<goal>pnpm</goal>
</goals>
<configuration>
<arguments>test</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package com.github.eirslett.maven.plugins.frontend.lib;

import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.HashMap;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;

public class PnpmInstaller {

private static final String VERSION = "version";
Expand Down Expand Up @@ -69,7 +68,12 @@ public void install() throws InstallationException {
if (!pnpmIsAlreadyInstalled()) {
installPnpm();
}
copyPnpmScripts();

if (this.config.getPlatform().isWindows()) {
linkExecutableWindows();
} else {
linkExecutable();
}
}
}

Expand Down Expand Up @@ -169,42 +173,72 @@ private void installPnpm() throws InstallationException {
}
}

private void copyPnpmScripts() throws InstallationException{
File installDirectory = getNodeInstallDirectory();

File nodeModulesDirectory = new File(installDirectory, "node_modules");
File pnpmDirectory = new File(nodeModulesDirectory, "pnpm");
// create a copy of the pnpm scripts next to the node executable
for (String script : Arrays.asList("pnpm", "pnpm.cmd")) {
File scriptFile = new File(pnpmDirectory, "bin" + File.separator + script);
if (scriptFile.exists()) {
File copy = new File(installDirectory, script);
if (!copy.exists()) {
try
{
FileUtils.copyFile(scriptFile, copy);
}
catch (IOException e)
{
throw new InstallationException("Could not copy pnpm", e);
}
copy.setExecutable(true);
}
}
private void linkExecutable() throws InstallationException{
File nodeInstallDirectory = getNodeInstallDirectory();
File pnpmExecutable = new File(nodeInstallDirectory, "pnpm");

if (pnpmExecutable.exists()) {
this.logger.info("Existing pnpm executable found, skipping linking.");
return;
}
// On non-windows platforms, if no predefined executables exist, symlink the .cjs executable
File pnpmExecutable = new File(installDirectory, "pnpm");
if (!pnpmExecutable.exists() && !this.config.getPlatform().isWindows()) {

File pnpmJsExecutable = new File(pnpmDirectory, "bin" + File.separator + "pnpm.cjs");
if (pnpmJsExecutable.exists()) {
this.logger.info("No pnpm executable found, creating symlink to {}", pnpmJsExecutable.toPath());
try {
Files.createSymbolicLink(pnpmExecutable.toPath(), pnpmJsExecutable.toPath());
} catch (IOException e) {
throw new InstallationException("Could not copy pnpm", e);
}
}

NodeExecutorConfig executorConfig = new InstallNodeExecutorConfig(this.config);
File pnpmJsExecutable = executorConfig.getPnpmCjsPath();

if (!pnpmJsExecutable.exists()) {
throw new InstallationException("Could not link to pnpm executable, no pnpm installation found.");
}

this.logger.info("No pnpm executable found, creating symbolic link to {}.", pnpmJsExecutable.toPath());

try {
Files.createSymbolicLink(pnpmExecutable.toPath(), pnpmJsExecutable.toPath());
} catch (IOException e) {
throw new InstallationException("Could not create symbolic link for pnpm executable.", e);
}
}

private void linkExecutableWindows() throws InstallationException{
File nodeInstallDirectory = getNodeInstallDirectory();
File pnpmExecutable = new File(nodeInstallDirectory, "pnpm.cmd");

if (pnpmExecutable.exists()) {
this.logger.info("Existing pnpm executable found, skipping linking.");
return;
}

NodeExecutorConfig executorConfig = new InstallNodeExecutorConfig(this.config);
File pnpmJsExecutable = executorConfig.getPnpmCjsPath();

if (!pnpmJsExecutable.exists()) {
throw new InstallationException("Could not link to pnpm executable, no pnpm installation found.");
}

this.logger.info("No pnpm executable found, creating proxy script to {}.", pnpmJsExecutable.toPath());

Path nodePath = executorConfig.getNodePath().toPath();
Path relativeNodePath = nodeInstallDirectory.toPath().relativize(nodePath);
Path relativePnpmPath = nodeInstallDirectory.toPath().relativize(pnpmJsExecutable.toPath());

// Create a script that will proxy any commands passed into it to the pnpm executable.
String scriptContents = new StringBuilder()
.append(":: Created by frontend-maven-plugin, please don't edit manually.\r\n")
.append("@ECHO OFF\r\n")
.append("\r\n")
.append("SETLOCAL\r\n")
.append("\r\n")
.append(String.format("SET \"NODE_EXE=%%~dp0\\%s\"\r\n", relativeNodePath))
.append(String.format("SET \"PNPM_CLI_JS=%%~dp0\\%s\"\r\n", relativePnpmPath))
.append("\r\n")
.append("\"%NODE_EXE%\" \"%PNPM_CLI_JS%\" %*")
.toString();

try {
BufferedWriter writer = new BufferedWriter(new FileWriter(pnpmExecutable));
writer.write(scriptContents);
writer.close();
} catch (IOException e) {
throw new InstallationException("Could not create proxy script for pnpm executable.", e);
}
}

Expand Down

0 comments on commit 436bd91

Please sign in to comment.