Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ public enum BuildToolType {
@JsonProperty("gradle")
GRADLE,
@JsonProperty("maven")
MAVEN;
MAVEN,
@JsonProperty("npm")
NPM;

public String getAttributesUrlSuffix() {
return String.format("/%s-attributes", name().toLowerCase(Locale.ROOT));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSetter;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.plugins.gradle.BuildToolType;
import org.kohsuke.stapler.export.ExportedBean;

import java.util.List;
import java.util.Map;
import java.util.Objects;

@ExportedBean
Expand All @@ -15,7 +17,7 @@ public class ScanDetail {

private final String url;

@JsonAlias({"rootProjectName", "topLevelProjectName"})
@JsonAlias({"rootProjectName", "topLevelProjectName", "packageName"})
private String projectName;
@SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD")
private BuildToolType buildToolType;
Expand All @@ -26,6 +28,18 @@ public class ScanDetail {
@SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD")
private boolean hasFailed;

// Converts NpmCommand object into a list of tasks
@JsonSetter("command")
private void setCommand(Map<String, Object> npmCommand) {
if (npmCommand == null) {
return;
}
Object command = npmCommand.get("command");
if (command != null && (tasks == null || tasks.isEmpty())) {
tasks = List.of(command.toString());
}
}

ScanDetail(String url) {
this.url = url;
}
Expand Down Expand Up @@ -59,7 +73,12 @@ public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ScanDetail that = (ScanDetail) o;
return hasFailed == that.hasFailed && Objects.equals(url, that.url) && Objects.equals(projectName, that.projectName) && buildToolType == that.buildToolType && Objects.equals(buildToolVersion, that.buildToolVersion) && Objects.equals(tasks, that.tasks);
return hasFailed == that.hasFailed
&& Objects.equals(url, that.url)
&& Objects.equals(projectName, that.projectName)
&& buildToolType == that.buildToolType
&& Objects.equals(buildToolVersion, that.buildToolVersion)
&& Objects.equals(tasks, that.tasks);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package hudson.plugins.gradle.injection;

public record ArtifactDigest(String digest) {

public boolean matches(String otherDigest) {
return digest.equals(otherDigest);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package hudson.plugins.gradle.injection;

import javax.annotation.Nullable;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;

public record ArtifactMetadata(String version, ArtifactDigest digest) {

private static final String SEPARATOR = ",";

// Adapter from the old interface
public ArtifactMetadata(String version, String digest) {
this(version, new ArtifactDigest(digest));
}

public boolean isForVersion(@Nullable String requiredVersion) {
return version.equals(requiredVersion);
}

public void writeToFile(Path metadataFile) throws IOException {
String content = version + SEPARATOR + digest.digest();
Files.writeString(metadataFile, content);
}

public static Optional<ArtifactMetadata> readFromFile(Path metadataFile) throws IOException {
if (Files.exists(metadataFile)) {
String[] metadata = Files.readString(metadataFile).split(SEPARATOR);
if (metadata.length == 2) {
String version = metadata[0];
ArtifactDigest digest = new ArtifactDigest(metadata[1]);
return Optional.of(new ArtifactMetadata(version, digest));
}
}
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.cloudbees.plugins.credentials.CredentialsProvider;
import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials;
import com.google.common.annotations.VisibleForTesting;
import hudson.EnvVars;
import hudson.Extension;
import hudson.model.EnvironmentContributor;
Expand Down Expand Up @@ -33,12 +34,13 @@ public class BuildScanEnvironmentContributor extends EnvironmentContributor {

private final ShortLivedTokenClientFactory shortLivedTokenClientFactory;

@SuppressWarnings("unused")
public BuildScanEnvironmentContributor() {
this.shortLivedTokenClientFactory = new ShortLivedTokenClientFactory();
this(new ShortLivedTokenClientFactory());
}

// required for testing
public BuildScanEnvironmentContributor(ShortLivedTokenClientFactory shortLivedTokenClientFactory) {
@VisibleForTesting
BuildScanEnvironmentContributor(ShortLivedTokenClientFactory shortLivedTokenClientFactory) {
this.shortLivedTokenClientFactory = shortLivedTokenClientFactory;
}

Expand Down Expand Up @@ -67,10 +69,11 @@ public void buildEnvironmentFor(@Nonnull Run run, @Nonnull EnvVars envs, @Nonnul

Secret shortLivedToken = getShortLivedToken(secretKey, logger);

run.addAction(DevelocityParametersAction.of(logger, shortLivedToken, secretPassword));
run.addAction(DevelocityParametersAction.of(shortLivedToken, secretPassword));
}

private @Nullable Secret getShortLivedToken(Secret secretKey, DevelocityLogger logger) {
@Nullable
private Secret getShortLivedToken(Secret secretKey, DevelocityLogger logger) {
if (secretKey == null) {
return null;
}
Expand Down Expand Up @@ -143,7 +146,7 @@ static DevelocityParametersAction empty() {
return EMPTY;
}

private static DevelocityParametersAction of(DevelocityLogger logger, @Nullable Secret shortLivedToken, @Nullable Secret repoPassword) {
private static DevelocityParametersAction of(@Nullable Secret shortLivedToken, @Nullable Secret repoPassword) {
List<ParameterValue> values = new ArrayList<>();
if (shortLivedToken != null) {
values.add(new PasswordParameterValue(GRADLE_ENTERPRISE_ACCESS_KEY, shortLivedToken.getPlainText()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,9 @@

import hudson.FilePath;
import hudson.Util;
import jenkins.model.Jenkins;
import org.apache.commons.io.IOUtils;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public final class CopyUtil {

Expand All @@ -24,7 +19,7 @@ public static void copyResourceToNode(FilePath nodePath, String resourceName) th
}

public static void copyDownloadedResourceToNode(FilePath controllerRootPath, FilePath nodePath, String resourceName) throws IOException, InterruptedException {
nodePath.copyFrom(controllerRootPath.child(MavenExtensionDownloadHandler.DOWNLOAD_CACHE_DIR).child(resourceName));
nodePath.copyFrom(controllerRootPath.child(InjectionUtil.DOWNLOAD_CACHE_DIR).child(resourceName));
}

public static String unsafeResourceDigest(String resourceName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
import hudson.model.Computer;
import hudson.model.Node;
import hudson.model.TaskListener;
import hudson.plugins.gradle.injection.npm.NpmAgentDownloadHandler;
import hudson.plugins.gradle.injection.npm.NpmBuildScanInjection;
import hudson.slaves.ComputerListener;
import jenkins.model.Jenkins;

import java.io.File;
import java.util.Map;
import java.util.function.Supplier;
import java.util.logging.Level;
Expand All @@ -27,13 +30,18 @@ public class DevelocityComputerListener extends ComputerListener {
private final GradleBuildScanInjection gradleBuildScanInjection;
private final MavenBuildScanInjection mavenBuildScanInjection;
private final MavenExtensionDownloadHandler mavenExtensionDownloadHandler;
private final NpmBuildScanInjection npmBuildScanInjection;
private final NpmAgentDownloadHandler npmAgentDownloadHandler;
private final Supplier<InjectionConfig> injectionConfigSupplier;

@SuppressWarnings("unused")
public DevelocityComputerListener() {
this(
new GradleBuildScanInjection(),
new MavenBuildScanInjection(),
new MavenExtensionDownloadHandler(),
new NpmBuildScanInjection(),
new NpmAgentDownloadHandler(),
new JenkinsInjectionConfig()
);
}
Expand All @@ -43,11 +51,15 @@ public DevelocityComputerListener() {
GradleBuildScanInjection gradleBuildScanInjection,
MavenBuildScanInjection mavenBuildScanInjection,
MavenExtensionDownloadHandler mavenExtensionDownloadHandler,
NpmBuildScanInjection npmBuildScanInjection,
NpmAgentDownloadHandler npmAgentDownloadHandler,
Supplier<InjectionConfig> injectionConfigSupplier
) {
this.gradleBuildScanInjection = gradleBuildScanInjection;
this.mavenBuildScanInjection = mavenBuildScanInjection;
this.mavenExtensionDownloadHandler = mavenExtensionDownloadHandler;
this.npmBuildScanInjection = npmBuildScanInjection;
this.npmAgentDownloadHandler = npmAgentDownloadHandler;
this.injectionConfigSupplier = injectionConfigSupplier;
}

Expand All @@ -60,15 +72,20 @@ public void onOnline(Computer computer, TaskListener listener) {
return;
}

Map<MavenExtension, String> extensionsDigest = mavenExtensionDownloadHandler.getExtensionDigests(
() -> Jenkins.get().getRootDir(), injectionConfig
);
Supplier<File> root = () -> Jenkins.get().getRootDir();
// When the agent becomes online, all artifacts must be already downloaded on the controller.
Map<MavenExtension, String> extensionsDigest = mavenExtensionDownloadHandler.getExtensionDigests(root, injectionConfig);
ArtifactDigest npmAgentDigest =
npmBuildScanInjection
.ifInjectionEnabledGlobally(injectionConfig, () -> npmAgentDownloadHandler.getDownloadedNpmAgentDigest(root))
.orElse(null);

Node node = computer.getNode();
EnvVars computerEnvVars = computer.getEnvironment();

gradleBuildScanInjection.inject(node, globalEnvVars, computerEnvVars);
mavenBuildScanInjection.inject(node, extensionsDigest);
npmBuildScanInjection.inject(node, npmAgentDigest, computerEnvVars);
} catch (Throwable t) {
/*
* We should catch everything because this is not handled by {@link hudson.slaves.SlaveComputer#setChannel(Channel, OutputStream, Channel.Listener)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

@SuppressWarnings("unused")
@Extension
public class DevelocityErrorsAction implements RootAction, StaplerProxy {

@Override
public String getIconFileName() {
return isVisible() && Jenkins.get().hasPermission(Jenkins.ADMINISTER) ? "/plugin/gradle/images/svgs/gradle-build-scan.svg" : null;
Expand Down
21 changes: 12 additions & 9 deletions plugin/src/main/java/hudson/plugins/gradle/injection/EnvUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ public static EnvVars globalEnvironment() {
}

EnvironmentVariablesNodeProperty nodeProperty =
jenkins.getGlobalNodeProperties().get(EnvironmentVariablesNodeProperty.class);
jenkins.getGlobalNodeProperties().get(EnvironmentVariablesNodeProperty.class);

return nodeProperty != null ? nodeProperty.getEnvVars() : null;
}

@CheckForNull
public static String getEnv(Node node, String key) {
List<EnvironmentVariablesNodeProperty> all =
node.getNodeProperties().getAll(EnvironmentVariablesNodeProperty.class);
node.getNodeProperties().getAll(EnvironmentVariablesNodeProperty.class);

if (all.isEmpty()) {
return null;
Expand All @@ -51,31 +51,34 @@ public static String getEnv(EnvVars env, String key) {
public static void removeEnvVars(Node node, Collection<String> keys) {
keys.forEach(key -> removeEnvVar(node, key));
}
public static void removeEnvVars(Node node, InitScriptVariables[] keys) {
for (InitScriptVariables key : keys) {

public static void removeEnvVars(Node node, EnvVar[] keys) {
for (EnvVar key : keys) {
removeEnvVar(node, key);
}
}

public static void removeEnvVar(Node node, String key) {
setEnvVar(node, key, null);
}
public static void removeEnvVar(Node node, InitScriptVariables key) {

public static void removeEnvVar(Node node, EnvVar key) {
setEnvVar(node, key, null);
}

public static void setEnvVar(Node node, InitScriptVariables key, @Nullable String value) {
public static void setEnvVar(Node node, EnvVar key, @Nullable String value) {
setEnvVar(node, key.getEnvVar(), value);
}

public static void setEnvVar(Node node, String key, @Nullable String value) {
List<EnvironmentVariablesNodeProperty> all =
node.getNodeProperties().getAll(EnvironmentVariablesNodeProperty.class);
node.getNodeProperties().getAll(EnvironmentVariablesNodeProperty.class);

if (all.isEmpty()) {
if (value != null) {
node.getNodeProperties().add(
new EnvironmentVariablesNodeProperty(
new EnvironmentVariablesNodeProperty.Entry(key, value)));
new EnvironmentVariablesNodeProperty(
new EnvironmentVariablesNodeProperty.Entry(key, value)));
} // noop if null
return;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package hudson.plugins.gradle.injection;

public interface EnvVar {

String getEnvVar();
}
Loading
Loading