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

Add option to record commit hashes for Launchable #464

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
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
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,11 @@
<artifactId>version-number</artifactId>
<version>1.11</version>
</dependency>
<dependency>
<groupId>org.kohsuke</groupId>
<artifactId>github-api</artifactId>
<version>1.314</version>
</dependency>
<dependency>
<groupId>org.kohsuke.stapler</groupId>
<artifactId>stapler-groovy</artifactId>
Expand Down
104 changes: 104 additions & 0 deletions src/main/java/org/jenkinsci/maven/plugins/hpi/TestDependencyMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
Expand Down Expand Up @@ -43,6 +44,7 @@
import org.apache.maven.lifecycle.internal.LifecycleDependencyResolver;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.DependencyManagement;
import org.apache.maven.model.Scm;
import org.apache.maven.plugin.BuildPluginManager;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
Expand All @@ -56,6 +58,7 @@
import org.apache.maven.project.DependencyResolutionRequest;
import org.apache.maven.project.DependencyResolutionResult;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.project.ProjectDependenciesResolver;
import org.apache.maven.shared.dependency.graph.DependencyCollectorBuilder;
Expand All @@ -71,6 +74,10 @@
import org.eclipse.aether.resolution.ArtifactRequest;
import org.eclipse.aether.resolution.ArtifactResolutionException;
import org.eclipse.aether.resolution.ArtifactResult;
import org.kohsuke.github.GHRef;
import org.kohsuke.github.GHRepository;
import org.kohsuke.github.GHTagObject;
import org.kohsuke.github.GitHub;
import org.twdata.maven.mojoexecutor.MojoExecutor;

/**
Expand All @@ -90,6 +97,10 @@ public class TestDependencyMojo extends AbstractHpiMojo {
private static final Pattern PLUGIN_REGEX = Pattern.compile("WEB-INF/plugins/([^/.]+)[.][hj]pi");
private static final Pattern OVERRIDE_REGEX = Pattern.compile("([^:]+:[^:]+):([^:]+)");

private static final String PREFIX = "scm:git:https://github.com/";
private static final String SUFFIX = ".git";
private static final Pattern SHA1_HASH = Pattern.compile("^[a-f0-9]{40}$");

@Component private BuildPluginManager pluginManager;

@Component private DependencyCollectorBuilder dependencyCollectorBuilder;
Expand Down Expand Up @@ -131,6 +142,12 @@ public class TestDependencyMojo extends AbstractHpiMojo {
@Parameter(property = "upperBoundsExcludes")
private List<String> upperBoundsExcludes;

/**
* Path to a file to print commit hashes for Jenkins project dependencies.
*/
@Parameter(property = "commitHashes")
private File commitHashes;

@Override
public void execute() throws MojoExecutionException {
Map<String, String> overrides = overrideVersions != null ? parseOverrides(overrideVersions) : Map.of();
Expand Down Expand Up @@ -314,6 +331,8 @@ public void execute() throws MojoExecutionException {

copyTestDependencies(effectiveArtifacts);

printCommitHashes(effectiveArtifacts, commitHashes);

if (!additions.isEmpty() || !deletions.isEmpty() || !updates.isEmpty()) {
List<String> additionalClasspathElements = new LinkedList<>();
NavigableMap<String, String> includes = new TreeMap<>();
Expand Down Expand Up @@ -465,6 +484,91 @@ private void copyTestDependencies(Set<MavenArtifact> mavenArtifacts) throws Mojo
}
}

private void printCommitHashes(Set<MavenArtifact> mavenArtifacts, File commitHashes) throws MojoExecutionException {
if (commitHashes == null) {
return;
}
NavigableMap<String, String> nameToTag = new TreeMap<>();
GitHub github;
try {
github = GitHub.connect();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
for (MavenArtifact mavenArtifact : mavenArtifacts) {
Scm scm;
try {
getLog().info("Resolving POM for " + mavenArtifact.getId());
scm = mavenArtifact.resolvePom().getScm();
} catch (ProjectBuildingException e) {
throw new MojoExecutionException("Failed to resolve POM for artifact " + mavenArtifact, e);
}
String org = null;
String repo = null;
String tag = null;
if (scm != null) {
String gitHubRepo = scm.getConnection();
if (gitHubRepo != null && gitHubRepo.startsWith(PREFIX)) {
gitHubRepo = gitHubRepo.substring(gitHubRepo.indexOf(PREFIX) + PREFIX.length());
if (gitHubRepo.endsWith(SUFFIX)) {
gitHubRepo = gitHubRepo.substring(0, gitHubRepo.indexOf(SUFFIX));
}
String[] parts = gitHubRepo.split("/", 2);
if (parts.length == 2) {
org = parts[0];
repo = parts[1];
}
}
if (scm.getTag() != null && !scm.getTag().equals("HEAD")) {
tag = scm.getTag();
}
}
// TODO add support for incremental PR builds from a fork
if ("jenkinsci".equals(org) && repo != null && tag != null) {
String name = org + "/" + repo;
nameToTag.put(name, tag);
}
}
NavigableMap<String, String> nameToHash = new TreeMap<>();
for (Map.Entry<String, String> entry : nameToTag.entrySet()) {
String name = entry.getKey();
String tag = entry.getValue();
String hash;
if (SHA1_HASH.matcher(tag).matches()) {
hash = tag;
} else {
hash = tagToHash(name, tag, github);
}
if (!SHA1_HASH.matcher(hash).matches()) {
throw new IllegalStateException("Illegal hash for " + name + ": " + hash);
}
nameToHash.put(name, hash);
}
List<String> output = new ArrayList<>();
for (Map.Entry<String, String> entry : nameToHash.entrySet()) {
getLog().info(String.format("Component %s has hash %s", entry.getKey(), entry.getValue()));
output.add("--commit " + entry.getKey() + "=" + entry.getValue());
}
try (BufferedWriter w = Files.newBufferedWriter(commitHashes.toPath(), StandardCharsets.UTF_8)) {
w.write(String.join(" ", output));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

private String tagToHash(String name, String tag, GitHub github) {
getLog().info("Resolving tag for " + name);
try {
GHRepository repo = github.getRepository(name);
GHRef ref = repo.getRef("tags/" + tag);
String sha = ref.getObject().getSha();
GHTagObject tagObject = repo.getTagObject(sha);
return tagObject.getObject().getSha();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

private static void appendEntries(String property, Collection<String> additions, Properties properties) {
String existing = properties.getProperty(property);
List<String> newEntries = new ArrayList<>();
Expand Down