Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
Grahame Grieve committed Jun 29, 2023
2 parents 4546948 + 95e2a5d commit 3ec28ae
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.hl7.fhir.igtools.publisher;

import com.google.common.collect.ImmutableList;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteWatchdog;
import org.apache.commons.exec.PumpStreamHandler;
Expand All @@ -10,12 +12,15 @@
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.settings.FhirSettings;

import javax.annotation.Nonnull;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;

public class FSHRunner {

Expand Down Expand Up @@ -64,25 +69,22 @@ protected void runFsh(File file, Publisher.IGBuildMode mode) throws IOException
exec.setWorkingDirectory(file);
ExecuteWatchdog watchdog = new ExecuteWatchdog(fshTimeout);
exec.setWatchdog(watchdog);

//FIXME This construction is a mess, and should use CommandLine(...).addArgument(...) construction. -Dotasek
String cmd = fshVersion == null ? "sushi" : "npx fsh-sushi@"+fshVersion;
if (mode == Publisher.IGBuildMode.PUBLICATION || mode == Publisher.IGBuildMode.AUTOBUILD) {
cmd += " --require-latest";
}

try {
final String execString;
if (SystemUtils.IS_OS_WINDOWS) {
exec.execute(org.apache.commons.exec.CommandLine.parse("cmd /C "+cmd+" . -o ."));
exec.execute(getWindowsCommandLine(fshVersion, mode));
} else if (FhirSettings.hasNpmPath()) {
ProcessBuilder processBuilder = new ProcessBuilder(new String("bash -c "+cmd));
ProcessBuilder processBuilder = new ProcessBuilder(new String("bash -c "+ getSushiCommandString(fshVersion,mode)));
Map<String, String> env = processBuilder.environment();
Map<String, String> vars = new HashMap<>();
vars.putAll(env);
String path = FhirSettings.getNpmPath()+":"+env.get("PATH");
vars.put("PATH", path);
exec.execute(org.apache.commons.exec.CommandLine.parse("bash -c "+cmd+" . -o ."), vars);

exec.execute(getNpmPathCommandLine(fshVersion, mode), vars);
} else {
exec.execute(org.apache.commons.exec.CommandLine.parse(cmd+" . -o ."));
exec.execute(getDefaultCommandLine(fshVersion, mode));
}
} catch (IOException ioex) {
log("Sushi couldn't be run. Complete output from running Sushi : " + pumpHandler.getBufferString());
Expand All @@ -99,6 +101,52 @@ protected void runFsh(File file, Publisher.IGBuildMode mode) throws IOException
}
}

@Nonnull
protected CommandLine getDefaultCommandLine(String fshVersion, Publisher.IGBuildMode mode) {
final List<String> sushiCommandList = getSushiCommandList(fshVersion, mode);
CommandLine commandLine = new CommandLine(sushiCommandList.get(0));
for (int i = 1; i < sushiCommandList.size(); i++) {
commandLine.addArgument(sushiCommandList.get(i));
}
commandLine.addArgument(".").addArgument("-o").addArgument(".");
return commandLine;
}

@Nonnull
protected CommandLine getNpmPathCommandLine(String fshVersion, Publisher.IGBuildMode mode) {
CommandLine commandLine = new CommandLine("bash").addArgument("-c");
for (String argument : getSushiCommandList(fshVersion,mode)) {
commandLine.addArgument(argument);
}
commandLine.addArgument(".").addArgument("-o").addArgument(".");
return commandLine;
}

@Nonnull
protected CommandLine getWindowsCommandLine(String fshVersion, Publisher.IGBuildMode mode) {
CommandLine commandLine = new CommandLine("cmd").addArgument("/C");
for (String argument : getSushiCommandList(fshVersion,mode)) {
commandLine.addArgument(argument);
}
commandLine.addArgument(".").addArgument("-o").addArgument(".");
return commandLine;
}

protected List<String> getSushiCommandList(String fshVersion, Publisher.IGBuildMode mode) {
final List<String> cmd = fshVersion == null ? List.of("sushi"): List.of("npx", "fsh-sushi@"+fshVersion);
if (mode == Publisher.IGBuildMode.PUBLICATION || mode == Publisher.IGBuildMode.AUTOBUILD) {
return new ImmutableList.Builder<String>().addAll(cmd).add("--require-latest").build();
}
return cmd;
}
protected String getSushiCommandString(String fshVersion, Publisher.IGBuildMode mode) {

StringJoiner stringJoiner = new StringJoiner(" ");
for (String argument : getSushiCommandList(fshVersion,mode)) {
stringJoiner.add(argument);
}
return stringJoiner.toString();
}
public class MySushiHandler extends OutputStream {

private byte[] buffer;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package org.hl7.fhir.igtools.publisher;

import org.apache.commons.exec.CommandLine;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.Mockito;

import java.util.List;
import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;


public class FSHRunnerTests {



public static Stream<Arguments> defaultExecStringParams () {
List<Arguments> output = List.of(
Arguments.of(Publisher.IGBuildMode.PUBLICATION, null, "sushi --require-latest . -o ."),
Arguments.of(Publisher.IGBuildMode.AUTOBUILD, null, "sushi --require-latest . -o ."),
Arguments.of(Publisher.IGBuildMode.MANUAL, null, "sushi . -o ."),
Arguments.of(Publisher.IGBuildMode.PUBLICATION, "1.2.3", "npx [email protected] --require-latest . -o ."),
Arguments.of(Publisher.IGBuildMode.AUTOBUILD, "1.2.3", "npx [email protected] --require-latest . -o ."),
Arguments.of(Publisher.IGBuildMode.MANUAL, "1.2.3", "npx [email protected] . -o .")
);
return output.stream();
}

@ParameterizedTest
@MethodSource("defaultExecStringParams")
public void testDefaultExecString(Publisher.IGBuildMode mode, String fshVersion, String expectedExecString) {
FSHRunner fshRunner = new FSHRunner(Mockito.mock(IWorkerContext.ILoggingService.class));
final CommandLine actualCommandLine = fshRunner.getDefaultCommandLine(fshVersion, mode);
assertIsEqual(CommandLine.parse(expectedExecString), actualCommandLine);
}

public static Stream<Arguments> sushiCommandParams () {
List<Arguments> output = List.of(
Arguments.of(Publisher.IGBuildMode.PUBLICATION, null, "sushi --require-latest"),
Arguments.of(Publisher.IGBuildMode.AUTOBUILD, null, "sushi --require-latest"),
Arguments.of(Publisher.IGBuildMode.MANUAL, null, "sushi"),
Arguments.of(Publisher.IGBuildMode.PUBLICATION, "1.2.3", "npx [email protected] --require-latest"),
Arguments.of(Publisher.IGBuildMode.AUTOBUILD, "1.2.3", "npx [email protected] --require-latest"),
Arguments.of(Publisher.IGBuildMode.MANUAL, "1.2.3", "npx [email protected]")
);
return output.stream();
}

@ParameterizedTest
@MethodSource("sushiCommandParams")
public void testGetSushiCommand(Publisher.IGBuildMode mode, String fshVersion, String expectedSushiCommand) {
FSHRunner fshRunner = new FSHRunner(Mockito.mock(IWorkerContext.ILoggingService.class));
assertEquals(expectedSushiCommand, fshRunner.getSushiCommandString(fshVersion,mode));
}

private void assertIsEqual(CommandLine a, CommandLine b) {
assertEquals(a.getExecutable(), b.getExecutable());
assertArrayEquals(a.getArguments(), b.getArguments());
}

public static Stream<Arguments> windowsExecStringParams () {
List<Arguments> output = List.of(
Arguments.of(Publisher.IGBuildMode.PUBLICATION, null, "cmd /C sushi --require-latest . -o ."),
Arguments.of(Publisher.IGBuildMode.AUTOBUILD, null, "cmd /C sushi --require-latest . -o ."),
Arguments.of(Publisher.IGBuildMode.MANUAL, null, "cmd /C sushi . -o ."),
Arguments.of(Publisher.IGBuildMode.PUBLICATION, "1.2.3", "cmd /C npx [email protected] --require-latest . -o ."),
Arguments.of(Publisher.IGBuildMode.AUTOBUILD, "1.2.3", "cmd /C npx [email protected] --require-latest . -o ."),
Arguments.of(Publisher.IGBuildMode.MANUAL, "1.2.3", "cmd /C npx [email protected] . -o .")
);
return output.stream();
}
@ParameterizedTest
@MethodSource("windowsExecStringParams")
public void testWindowsExecString(Publisher.IGBuildMode mode, String fshVersion, String expectedExecString) {
FSHRunner fshRunner = new FSHRunner(Mockito.mock(IWorkerContext.ILoggingService.class));
final CommandLine actualCommandLine = fshRunner.getWindowsCommandLine(fshVersion, mode);
assertIsEqual(CommandLine.parse(expectedExecString), actualCommandLine);
}

public static Stream<Arguments> npmPathExecStringParams () {
List<Arguments> output = List.of(
Arguments.of(Publisher.IGBuildMode.PUBLICATION, null, "bash -c sushi --require-latest . -o ."),
Arguments.of(Publisher.IGBuildMode.AUTOBUILD, null, "bash -c sushi --require-latest . -o ."),
Arguments.of(Publisher.IGBuildMode.MANUAL, null, "bash -c sushi . -o ."),
Arguments.of(Publisher.IGBuildMode.PUBLICATION, "1.2.3", "bash -c npx [email protected] --require-latest . -o ."),
Arguments.of(Publisher.IGBuildMode.AUTOBUILD, "1.2.3", "bash -c npx [email protected] --require-latest . -o ."),
Arguments.of(Publisher.IGBuildMode.MANUAL, "1.2.3", "bash -c npx [email protected] . -o .")
);
return output.stream();
}
@ParameterizedTest
@MethodSource("npmPathExecStringParams")
public void testNpmPathExecString(Publisher.IGBuildMode mode, String fshVersion, String expectedExecString) {
FSHRunner fshRunner = new FSHRunner(Mockito.mock(IWorkerContext.ILoggingService.class));
final CommandLine actualCommandLine = fshRunner.getNpmPathCommandLine(fshVersion, mode);
assertIsEqual(CommandLine.parse(expectedExecString), actualCommandLine);
}
}
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,12 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
<!-- plantuml -->
<dependency>
<groupId>net.sourceforge.plantuml</groupId>
Expand Down

0 comments on commit 3ec28ae

Please sign in to comment.