Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable injection when custom extensions are detected #398

Merged
merged 3 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
36 changes: 36 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,20 @@ public FormValidation doCheckAccessKey(@QueryParameter String value) {
: FormValidation.error(Messages.InjectionConfig_InvalidAccessKey());
}

@Restricted(NoExternalUse.class)
@POST
public FormValidation doCheckMavenExtensionCustomCoordinates(@QueryParameter String value) {
String coord = Util.fixEmptyAndTrim(value);
return coord == null || MavenCoordinates.isValid(coord) ? FormValidation.ok() : FormValidation.error(Messages.InjectionConfig_InvalidMavenExtensionCustomCoordinates());
}

@Restricted(NoExternalUse.class)
@POST
public FormValidation doCheckCcudExtensionCustomCoordinates(@QueryParameter String value) {
String coord = Util.fixEmptyAndTrim(value);
return coord == null || MavenCoordinates.isValid(coord) ? FormValidation.ok() : FormValidation.error(Messages.InjectionConfig_InvalidMavenExtensionCustomCoordinates());
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we can extract the logic of both of these methods into a private method and reuse it


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,5 +1,7 @@
package hudson.plugins.gradle.injection;

import java.util.Objects;

/**
* Describes a set of Maven coordinates, represented as a GAV.
*/
Expand All @@ -19,6 +21,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,32 @@
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;

class MavenExtClasspathUtils {
static final String SPACE = " ";

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());
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also make this class final and add private constructor

}
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package hudson.plugins.gradle.injection;

import hudson.FilePath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

public class MavenExtensionsDetector {
private static final Logger LOGGER = LoggerFactory.getLogger(MavenExtensionsDetector.class);

static Set<MavenExtension> detect(InjectionConfig config, FilePath workspace) throws IOException, InterruptedException {
if (!config.isInjectMavenExtension()) {
return Collections.emptySet();
}

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

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

MavenExtensions mavenExtensions = MavenExtensions.fromFilePath(extensionsFile);

Set<MavenExtension> knownExtensions = new HashSet<>();
if (mavenExtensions.hasExtension(MavenExtension.GRADLE_ENTERPRISE.getCoordinates()) ||
mavenExtensions.hasExtension(MavenCoordinates.parseCoordinates(config.getMavenExtensionCustomCoordinates()))) {
knownExtensions.add(MavenExtension.GRADLE_ENTERPRISE);
}
if (mavenExtensions.hasExtension(MavenExtension.CCUD.getCoordinates()) ||
mavenExtensions.hasExtension(MavenCoordinates.parseCoordinates(config.getCcudExtensionCustomCoordinates()))
) {
knownExtensions.add(MavenExtension.CCUD);
}
return knownExtensions;
} else {
LOGGER.debug("Extensions file not found: {}", extensionsFile);
return Collections.emptySet();
}
}
}
Loading
Loading