Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[JENKINS-49898] maven-invoker-plugin add support for relative path in…
… "reportsDirectory", "projectsDirectory" and "cloneProjectsTo"
  • Loading branch information
Cyrille Le Clerc committed Mar 6, 2018
1 parent 1cfc35a commit 90d7474
Show file tree
Hide file tree
Showing 6 changed files with 833 additions and 30 deletions.
Expand Up @@ -35,6 +35,7 @@
import org.jenkinsci.plugins.pipeline.maven.MavenSpyLogProcessor;
import org.jenkinsci.plugins.maveninvoker.MavenInvokerRecorder;
import org.jenkinsci.plugins.pipeline.maven.MavenPublisher;
import org.jenkinsci.plugins.pipeline.maven.util.FileUtils;
import org.jenkinsci.plugins.pipeline.maven.util.XmlUtils;
import org.jenkinsci.plugins.workflow.steps.StepContext;
import org.kohsuke.stapler.DataBoundConstructor;
Expand All @@ -47,12 +48,13 @@
import java.util.logging.Logger;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class InvokerRunsPublisher extends MavenPublisher {
private static final Logger LOGGER = Logger.getLogger(InvokerRunsPublisher.class.getName());
private static final String GROUP_ID = "org.apache.maven.plugins";
private static final String ARTIFACT_ID = "maven-invoker-plugin";
private static final String GOAL = "run";
protected static final String GROUP_ID = "org.apache.maven.plugins";
protected static final String ARTIFACT_ID = "maven-invoker-plugin";
protected static final String RUN_GOAL = "run";

private static final long serialVersionUID = 1L;

Expand Down Expand Up @@ -82,11 +84,11 @@ public void process(@Nonnull StepContext context, @Nonnull Element mavenSpyLogsE
listener = new StreamBuildListener((OutputStream) System.err);
}

List<Element> sureFireTestEvents = XmlUtils.getExecutionEvents(mavenSpyLogsElt, GROUP_ID, ARTIFACT_ID, GOAL);
List<Element> invokerRunEvents = XmlUtils.getExecutionEvents(mavenSpyLogsElt, GROUP_ID, ARTIFACT_ID, RUN_GOAL);

if (sureFireTestEvents.isEmpty()) {
if (invokerRunEvents.isEmpty()) {
if (LOGGER.isLoggable(Level.FINE)) {
listener.getLogger().println("[withMaven] invokerPublisher - No " + GROUP_ID + ":" + ARTIFACT_ID + ":" + GOAL + " execution found");
listener.getLogger().println("[withMaven] invokerPublisher - No " + GROUP_ID + ":" + ARTIFACT_ID + ":" + RUN_GOAL + " execution found");
}
return;
}
Expand All @@ -96,12 +98,12 @@ public void process(@Nonnull StepContext context, @Nonnull Element mavenSpyLogsE
} catch (ClassNotFoundException e) {
listener.getLogger().print("[withMaven] invokerPublisher - Jenkins ");
listener.hyperlink("https://wiki.jenkins.io/display/JENKINS/Maven+Invoker+Plugin", "Maven Invoker Plugin");
listener.getLogger().println(" not found, don't display " + GROUP_ID + ":" + ARTIFACT_ID + ":" + GOAL + " results in pipeline screen.");
listener.getLogger().println(" not found, don't display " + GROUP_ID + ":" + ARTIFACT_ID + ":" + RUN_GOAL + " results in pipeline screen.");
return;
}


executeReporter(context, listener, sureFireTestEvents);
executeReporter(context, listener, invokerRunEvents);
}

private void executeReporter(StepContext context, TaskListener listener, List<Element> testEvents) throws IOException, InterruptedException {
Expand Down Expand Up @@ -143,7 +145,8 @@ private void executeReporter(StepContext context, TaskListener listener, List<El
}
}

private String expandAndRelativize(Element element, String name, Element testEvent, Element projectElt, FilePath workspace, TaskListener listener) {
@Nullable
protected String expandAndRelativize(@Nullable Element element, @Nullable String name, Element testEvent, Element projectElt, FilePath workspace, TaskListener listener) {
if (element == null) {
listener.getLogger().println("[withMaven] invokerPublisher - No <" + name + "> element found for <plugin> in " + XmlUtils.toString(testEvent));
return null;
Expand All @@ -169,11 +172,19 @@ private String expandAndRelativize(Element element, String name, Element testEve
} else if (result.contains("${basedir}")) {
String baseDir = projectElt.getAttribute("baseDir");
if (baseDir.isEmpty()) {
listener.getLogger().println("[withMaven] invokerPublisher - '${basedir}' found for <project> in " + XmlUtils.toString(testEvent));
listener.getLogger().println("[withMaven] invokerPublisher - '${basedir}' NOT found for <project> in " + XmlUtils.toString(testEvent));
return null;
}

result = result.replace("${basedir}", baseDir);
} else if (!FileUtils.isAbsolutePath(result)) {
char separator = FileUtils.isWindows(result) ? '\\' : '/';
String baseDir = projectElt.getAttribute("baseDir");
if (baseDir.isEmpty()) {
listener.getLogger().println("[withMaven] invokerPublisher - '${basedir}' NOT found for <project> in " + XmlUtils.toString(testEvent));
return null;
}
result = baseDir + separator + result;
}

return XmlUtils.getPathInWorkspace(result, workspace);
Expand Down
@@ -0,0 +1,60 @@
package org.jenkinsci.plugins.pipeline.maven.util;

import hudson.FilePath;

import javax.annotation.Nonnull;

/**
* @author <a href="mailto:cleclerc@cloudbees.com">Cyrille Le Clerc</a>
*/
public class FileUtils {

public static boolean isAbsolutePath(@Nonnull String path) {
if (isWindows(path)) {
if (path.length() > 3 && path.charAt(1) == ':' && path.charAt(2) == '\\') {
// windows path such as "C:\path\to\..."
return true;
} else if (path.length() > 3 && path.charAt(1) == ':' && path.charAt(2) == '/') {
// nasty windows path such as "C:/path/to/...". See JENKINS-44088
return true;
} else if (path.length() > 2 && path.charAt(0) == '\\' && path.charAt(1) == '\\') {
// Microsoft Windows UNC mount ("\\myserver\myfolder")
return true;
} else {
return false;
}
} else {
// see java.io.UnixFileSystem.prefixLength()
return path.charAt(0) == '/';
}

}

public static boolean isWindows(@Nonnull FilePath path) {
return isWindows(path.getRemote());
}

public static boolean isWindows(@Nonnull String path) {
if (path.length() > 3 && path.charAt(1) == ':' && path.charAt(2) == '\\') {
// windows path such as "C:\path\to\..."
return true;
} else if (path.length() > 3 && path.charAt(1) == ':' && path.charAt(2) == '/') {
// nasty windows path such as "C:/path/to/...". See JENKINS-44088
return true;
} else if (path.length() > 2 && path.charAt(0) == '\\' && path.charAt(1) == '\\') {
// Microsoft Windows UNC mount ("\\myserver\myfolder")
return true;
}
int indexOfSlash = path.indexOf('/');
int indexOfBackSlash = path.indexOf('\\');
if (indexOfSlash == -1) {
return true;
} else if (indexOfBackSlash == -1) {
return false;
} else if (indexOfSlash < indexOfBackSlash) {
return false;
} else {
return true;
}
}
}
Expand Up @@ -358,7 +358,7 @@ public static List<String> getExecutedLifecyclePhases(@Nonnull Element mavenSpyL
*/
@Nonnull
public static String getPathInWorkspace(@Nonnull final String absoluteFilePath, @Nonnull FilePath workspace) {
boolean windows = isWindows(workspace);
boolean windows = FileUtils.isWindows(workspace);

final String workspaceRemote = workspace.getRemote();

Expand Down Expand Up @@ -406,26 +406,12 @@ public static String getPathInWorkspace(@Nonnull final String absoluteFilePath,
return relativePath;
}

/**
* @deprecated use {@link FileUtils#isWindows(FilePath)}
*/
@Deprecated
public static boolean isWindows(@Nonnull FilePath path) {
String remote = path.getRemote();
if (remote.length() > 3 && remote.charAt(1) == ':' && remote.charAt(2) == '\\') {
// windows path such as "C:\path\to\..."
return true;
} else if (remote.length() > 3 && remote.charAt(1) == ':' && remote.charAt(2) == '/') {
// nasty windows path such as "C:/path/to/...". See JENKINS-44088
return true;
}
int indexOfSlash = path.getRemote().indexOf('/');
int indexOfBackSlash = path.getRemote().indexOf('\\');
if (indexOfSlash == -1) {
return true;
} else if (indexOfBackSlash == -1) {
return false;
} else if (indexOfSlash < indexOfBackSlash) {
return false;
} else {
return true;
}
return FileUtils.isWindows(path);
}

/**
Expand Down
@@ -0,0 +1,85 @@
package org.jenkinsci.plugins.pipeline.maven.publishers;

import hudson.FilePath;
import hudson.model.TaskListener;
import hudson.util.StreamTaskListener;
import org.hamcrest.Matchers;
import org.jenkinsci.plugins.pipeline.maven.util.XmlUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import java.io.File;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilderFactory;

/**
* @author <a href="mailto:cleclerc@cloudbees.com">Cyrille Le Clerc</a>
*/
public class InvokerRunsPublisherTest {
Document doc;

@Before
public void before() throws Exception {
String mavenSpyLogs = "org/jenkinsci/plugins/pipeline/maven/maven-spy-maven-invoker-plugin-integration-tests.xml";
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(mavenSpyLogs);
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(in);
}

/*
<ExecutionEvent type="MojoSucceeded" class="org.apache.maven.lifecycle.internal.DefaultExecutionEvent" _time="2018-03-06 23:49:30.662">
<project baseDir="/path/to/khmarbaise/maui/src/main/resources/mp-it-1" file="/path/to/khmarbaise/maui/src/main/resources/mp-it-1/pom.xml" groupId="com.soebes.maven.guide.mp.it" name="Maven Plugin Integration Test" artifactId="mp-it-1" version="0.1-SNAPSHOT">
<build sourceDirectory="/path/to/khmarbaise/maui/src/main/resources/mp-it-1/src/main/java" directory="/path/to/khmarbaise/maui/src/main/resources/mp-it-1/target"/>
</project>
<plugin executionId="integration-test" goal="run" lifecyclePhase="integration-test" groupId="org.apache.maven.plugins" artifactId="maven-invoker-plugin" version="3.0.1">
<projectsDirectory>src/it</projectsDirectory>
<cloneProjectsTo>/path/to/khmarbaise/maui/src/main/resources/mp-it-1/target/it</cloneProjectsTo>
<reportsDirectory>${invoker.reportsDirectory}</reportsDirectory>
</plugin>
</ExecutionEvent>
*/

/**
* projectsDirectory = src/it -> relative path
* cloneProjectsTo = /path/to/khmarbaise/maui/src/main/resources/mp-it-1/target/it -> absolute path
* reportsDirectory = ${invoker.reportsDirectory} -> variabilized path
*/
@Test
public void test_relative_path_and_absolute_path_and_variabilized_path() {
InvokerRunsPublisher invokerRunsPublisher = new InvokerRunsPublisher();
List<Element> invokerRunEvents = XmlUtils.getExecutionEvents(doc.getDocumentElement(), InvokerRunsPublisher.GROUP_ID, InvokerRunsPublisher.ARTIFACT_ID, InvokerRunsPublisher.RUN_GOAL);

FilePath workspace = new FilePath(new File("/path/to/khmarbaise/maui/src/main/resources/mp-it-1"));
TaskListener listener = new StreamTaskListener(System.out, StandardCharsets.UTF_8);

System.out.println(invokerRunEvents.size());
List<Element> invokerRunSucceededEvents = new ArrayList<>();
for (Element invokerRunEvent : invokerRunEvents) {
String eventType = invokerRunEvent.getAttribute("type");
if (eventType.equals("MojoSucceeded")) {
invokerRunSucceededEvents.add(invokerRunEvent);
}
}
Assert.assertThat(invokerRunSucceededEvents.size(), Matchers.is(1));
Element invokerRunSucceedEvent = invokerRunSucceededEvents.get(0);

Element projectElt = XmlUtils.getUniqueChildElement(invokerRunSucceedEvent, "project");
Element pluginElt = XmlUtils.getUniqueChildElement(invokerRunSucceedEvent, "plugin");
Element reportsDirectoryElt = XmlUtils.getUniqueChildElementOrNull(pluginElt, "reportsDirectory");
Element cloneProjectsToElt = XmlUtils.getUniqueChildElementOrNull(pluginElt, "cloneProjectsTo");
Element projectsDirectoryElt = XmlUtils.getUniqueChildElementOrNull(pluginElt, "projectsDirectory");

String reportsDirectory = invokerRunsPublisher.expandAndRelativize(reportsDirectoryElt, "reportsDirectory", invokerRunSucceedEvent, projectElt, workspace, listener);
Assert.assertThat(reportsDirectory, Matchers.is("target/invoker-reports"));
String projectsDirectory = invokerRunsPublisher.expandAndRelativize(projectsDirectoryElt, "projectsDirectory", invokerRunSucceedEvent, projectElt, workspace, listener);
Assert.assertThat(projectsDirectory, Matchers.is("src/it"));
String cloneProjectsTo = invokerRunsPublisher.expandAndRelativize(cloneProjectsToElt, "cloneProjectsTo", invokerRunSucceedEvent, projectElt, workspace, listener);
Assert.assertThat(cloneProjectsTo, Matchers.is("target/it"));
}
}
@@ -0,0 +1,37 @@
package org.jenkinsci.plugins.pipeline.maven.util;

import org.hamcrest.CoreMatchers;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Test;

/**
* @author <a href="mailto:cleclerc@cloudbees.com">Cyrille Le Clerc</a>
*/
public class FileUtilsTest {

@Test
public void test_isAbsolutePath_with_windows_absolute_path() {
Assert.assertThat(FileUtils.isAbsolutePath("c:\\jenkins\\workspace\\"), Matchers.is(true));
}

@Test
public void test_isAbsolutePath_with_windows_relative_path() {
Assert.assertThat(FileUtils.isAbsolutePath("jenkins\\workspace\\"), Matchers.is(false));
}

@Test
public void test_isAbsolutePath_with_linux_absolute_path() {
Assert.assertThat(FileUtils.isAbsolutePath("/var/lib/jenkins/workspace"), Matchers.is(true));
}

@Test
public void test_isAbsolutePath_with_linux_relative_path() {
Assert.assertThat(FileUtils.isAbsolutePath("jenkins/workspace"), Matchers.is(false));
}

@Test
public void test_isAbsolutePath_with_windows_unc_absolute_path() {
Assert.assertThat(FileUtils.isAbsolutePath("\\\\myserver\\jenkins\\workspace\\"), Matchers.is(true));
}
}

0 comments on commit 90d7474

Please sign in to comment.