Skip to content

Commit

Permalink
Disable injection when custom extensions are detected (#398)
Browse files Browse the repository at this point in the history
  • Loading branch information
alextu authored Feb 27, 2024
1 parent 92f796e commit 6439fd2
Show file tree
Hide file tree
Showing 22 changed files with 700 additions and 106 deletions.
65 changes: 20 additions & 45 deletions src/main/java/hudson/plugins/gradle/injection/GitScmListener.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package hudson.plugins.gradle.injection;

import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import hudson.EnvVars;
import hudson.Extension;
import hudson.FilePath;
Expand All @@ -21,23 +20,20 @@
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import static hudson.plugins.gradle.injection.GradleInjectionAware.JENKINSGRADLEPLUGIN_GRADLE_ENTERPRISE_GRADLE_INJECTION_ENABLED;
import static hudson.plugins.gradle.injection.MavenInjectionAware.JENKINSGRADLEPLUGIN_MAVEN_PLUGIN_CONFIG_EXT_CLASSPATH;
import static hudson.plugins.gradle.injection.MavenInjectionAware.MAVEN_OPTS_HANDLER;
import static hudson.plugins.gradle.injection.MavenExtensionsDetector.detect;
import static hudson.plugins.gradle.injection.MavenExtClasspathUtils.*;
import static hudson.plugins.gradle.injection.MavenInjectionAware.*;
import static hudson.plugins.gradle.injection.MavenOptsHandler.MAVEN_OPTS;

@Extension
public class GitScmListener extends SCMListener {

private static final Logger LOGGER = LoggerFactory.getLogger(GitScmListener.class);

private static final MavenCoordinates DEVELOCITY_EXTENSION_MAVEN_COORDINATES = new MavenCoordinates("com.gradle", "gradle-enterprise-maven-extension");

@Override
public void onCheckout(
Run<?, ?> build,
Expand All @@ -61,19 +57,17 @@ public void onCheckout(
}

// Check .mvn/extensions.xml for already applied Develocity extension for maven injection only
if (mavenExtensionAlreadyApplied(config, workspace)) {
disableMavenAutoInjection(build, workspace, config, listener);
}
disableMavenAutoInjectionIfAlreadyApplied(build, workspace, config, listener);
} catch (Exception e) {
LOGGER.error("Error occurred when processing onCheckout notification", e);
}
}

private static void disableAutoInjection(
Run<?, ?> build,
FilePath workspace,
InjectionConfig config,
TaskListener listener
Run<?, ?> build,
FilePath workspace,
InjectionConfig config,
TaskListener listener
) throws Exception {
Computer computer = workspace.toComputer();
if (computer == null) {
Expand All @@ -96,11 +90,11 @@ private static void disableAutoInjection(
}
}

private static void disableMavenAutoInjection(
Run<?, ?> build,
FilePath workspace,
InjectionConfig config,
TaskListener listener
private static void disableMavenAutoInjectionIfAlreadyApplied(
Run<?, ?> build,
FilePath workspace,
InjectionConfig config,
TaskListener listener
) throws Exception {
Computer computer = workspace.toComputer();
if (computer == null) {
Expand All @@ -111,13 +105,13 @@ private static void disableMavenAutoInjection(

String currentMavenOpts = envVars.get(MavenOptsHandler.MAVEN_OPTS);
if (currentMavenOpts != null) {
Set<String> keepUrl = config.isEnforceUrl()
? Sets.newHashSet(MavenInjectionAware.GRADLE_ENTERPRISE_URL_PROPERTY_KEY.name)
: Collections.emptySet();

String mavenOpts = Strings.nullToEmpty(MAVEN_OPTS_HANDLER.removeIfNeeded(currentMavenOpts, keepUrl));

build.addAction(new MavenInjectionDisabledAction(mavenOpts));
Set<MavenExtension> knownExtensions = detect(config, workspace);
if (!knownExtensions.isEmpty()) {
build.addAction(
new MavenInjectionDisabledAction(
new MavenOptsDevelocityFilter(knownExtensions, isUnix(computer))
.filter(currentMavenOpts, config.isEnforceUrl())));
}
}
}

Expand Down Expand Up @@ -156,25 +150,6 @@ private static boolean shouldDisableMavenInjection(InjectionConfig config) {
return config.isInjectMavenExtension();
}

private static boolean mavenExtensionAlreadyApplied(InjectionConfig config, FilePath workspace) throws IOException, InterruptedException {
if (!config.isInjectMavenExtension()) {
return false;
}

FilePath extensionsFile = workspace.child(".mvn/extensions.xml");

if (extensionsFile.exists()) {
LOGGER.debug("Found extensions file: {}", extensionsFile);

MavenExtensions mavenExtensions = MavenExtensions.fromFilePath(extensionsFile);

return mavenExtensions.hasExtension(DEVELOCITY_EXTENSION_MAVEN_COORDINATES);
} else {
LOGGER.debug("Extensions file not found: {}", extensionsFile);
return false;
}
}

/**
* Action that disables Gradle Plugin injection by setting a flag to be read by the init script.
*/
Expand Down
39 changes: 39 additions & 0 deletions src/main/java/hudson/plugins/gradle/injection/InjectionConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ public class InjectionConfig extends GlobalConfiguration {

private boolean injectMavenExtension;
private boolean injectCcudExtension;
private String mavenExtensionCustomCoordinates;
private String ccudExtensionCustomCoordinates;
private ImmutableList<NodeLabelItem> mavenInjectionEnabledNodes;
private ImmutableList<NodeLabelItem> mavenInjectionDisabledNodes;

Expand Down Expand Up @@ -235,6 +237,26 @@ public void setInjectMavenExtension(boolean injectMavenExtension) {
this.injectMavenExtension = injectMavenExtension;
}

@CheckForNull
public String getMavenExtensionCustomCoordinates() {
return mavenExtensionCustomCoordinates;
}

@DataBoundSetter
public void setMavenExtensionCustomCoordinates(String mavenExtensionCustomCoordinates) {
this.mavenExtensionCustomCoordinates = Util.fixEmptyAndTrim(mavenExtensionCustomCoordinates);
}

@CheckForNull
public String getCcudExtensionCustomCoordinates() {
return ccudExtensionCustomCoordinates;
}

@DataBoundSetter
public void setCcudExtensionCustomCoordinates(String ccudExtensionCustomCoordinates) {
this.ccudExtensionCustomCoordinates = Util.fixEmptyAndTrim(ccudExtensionCustomCoordinates);
}

public boolean isInjectCcudExtension() {
return injectCcudExtension;
}
Expand Down Expand Up @@ -359,6 +381,23 @@ public FormValidation doCheckAccessKey(@QueryParameter String value) {
: FormValidation.error(Messages.InjectionConfig_InvalidAccessKey());
}

@Restricted(NoExternalUse.class)
@POST
public FormValidation doCheckMavenExtensionCustomCoordinates(@QueryParameter String value) {
return validateMavenCoordinates(value);
}

@Restricted(NoExternalUse.class)
@POST
public FormValidation doCheckCcudExtensionCustomCoordinates(@QueryParameter String value) {
return validateMavenCoordinates(value);
}

private static FormValidation validateMavenCoordinates(String value) {
String coord = Util.fixEmptyAndTrim(value);
return coord == null || MavenCoordinates.isValid(coord) ? FormValidation.ok() : FormValidation.error(Messages.InjectionConfig_InvalidMavenExtensionCustomCoordinates());
}

public static FormValidation checkRequiredUrl(String value) {
return checkUrl(value, true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

import hudson.EnvVars;
import hudson.FilePath;
import hudson.model.Computer;
import hudson.model.Node;
import hudson.plugins.gradle.injection.MavenExtensionsHandler.MavenExtension;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import static hudson.plugins.gradle.injection.MavenExtClasspathUtils.constructExtClasspath;
import static hudson.plugins.gradle.injection.MavenExtClasspathUtils.isUnix;

public class MavenBuildScanInjection implements BuildScanInjection, MavenInjectionAware {

Expand Down Expand Up @@ -112,21 +112,6 @@ private void cleanup(Node node, FilePath rootPath) {
}
}

private static String constructExtClasspath(List<FilePath> extensions, boolean isUnix) {
return extensions
.stream()
.map(FilePath::getRemote)
.collect(Collectors.joining(getDelimiter(isUnix)));
}

private static String getDelimiter(boolean isUnix) {
return isUnix ? ":" : ";";
}

private static boolean isUnix(Node node) {
Computer computer = node.toComputer();

return computer == null || Boolean.TRUE.equals(computer.isUnix());
}

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package hudson.plugins.gradle.injection;

import java.io.Serializable;
import java.util.Objects;

/**
* Describes a set of Maven coordinates, represented as a GAV.
*/
public final class MavenCoordinates {
public final class MavenCoordinates implements Serializable {

private final String groupId;
private final String artifactId;
Expand All @@ -19,6 +22,38 @@ public MavenCoordinates(String groupId, String artifactId, String version) {
this.version = version;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MavenCoordinates that = (MavenCoordinates) o;
return Objects.equals(groupId, that.groupId) && Objects.equals(artifactId, that.artifactId) && Objects.equals(version, that.version);
}

@Override
public int hashCode() {
return Objects.hash(groupId, artifactId, version);
}

static MavenCoordinates parseCoordinates(String groupAndArtifact) {
if (groupAndArtifact == null || groupAndArtifact.trim().isEmpty()) {
return null;
} else {
String[] ga = groupAndArtifact.split(":");
if (ga.length == 2) {
return new MavenCoordinates(ga[0], ga[1]);
} else if (ga.length == 3) {
return new MavenCoordinates(ga[0], ga[1], ga[2]);
} else {
return null;
}
}
}

static boolean isValid(String value) {
return MavenCoordinates.parseCoordinates(value) != null;
}

String groupId() {
return groupId;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package hudson.plugins.gradle.injection;

import hudson.FilePath;
import hudson.model.Computer;
import hudson.model.Node;

import java.util.List;
import java.util.stream.Collectors;

final class MavenExtClasspathUtils {
static final String SPACE = " ";

private MavenExtClasspathUtils() {
}

static String constructExtClasspath(List<FilePath> extensions, boolean isUnix) {
return extensions
.stream()
.map(FilePath::getRemote)
.collect(Collectors.joining(getDelimiter(isUnix)));
}

static String getDelimiter(boolean isUnix) {
return isUnix ? ":" : ";";
}

static boolean isUnix(Node node) {
Computer computer = node.toComputer();
return isUnix(computer);
}

static boolean isUnix(Computer computer) {
return computer == null || Boolean.TRUE.equals(computer.isUnix());
}
}
32 changes: 32 additions & 0 deletions src/main/java/hudson/plugins/gradle/injection/MavenExtension.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package hudson.plugins.gradle.injection;

public enum MavenExtension {
GRADLE_ENTERPRISE("gradle-enterprise-maven-extension", ExtensionsVersions.GE_EXTENSION_VERSION, new MavenCoordinates("com.gradle", "gradle-enterprise-maven-extension")),
CCUD("common-custom-user-data-maven-extension", ExtensionsVersions.CCUD_EXTENSION_VERSION, new MavenCoordinates("com.gradle", "common-custom-user-data-maven-extension")),
CONFIGURATION("configuration-maven-extension", "1.0.0", new MavenCoordinates("com.gradle", "configuration-maven-extension"));

private static final String JAR_EXTENSION = ".jar";

private final String name;
private final String version;

private final MavenCoordinates coordinates;

MavenExtension(String name, String version, MavenCoordinates coordinates) {
this.name = name;
this.version = version;
this.coordinates = coordinates;
}

public String getTargetJarName() {
return name + JAR_EXTENSION;
}

public String getEmbeddedJarName() {
return name + "-" + version + JAR_EXTENSION;
}

public MavenCoordinates getCoordinates() {
return coordinates;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ static MavenExtensions fromFilePath(FilePath extensionsFile) {
document.normalizeDocument();

return new MavenExtensions(document);
} catch (ParserConfigurationException | IOException | InterruptedException| SAXException e) {
} catch (ParserConfigurationException | IOException | InterruptedException | SAXException e) {
LOGGER.warn("Failed to parse extensions file: {}", extensionsFile, e);
return MavenExtensions.empty();
}
Expand Down
Loading

0 comments on commit 6439fd2

Please sign in to comment.