Skip to content

[8.19] [Build] Make DependenciesInfoPlugin configuration cache compatible (#129791) #129855

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

Open
wants to merge 1 commit into
base: 8.19
Choose a base branch
from
Open
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 @@ -10,7 +10,6 @@
package org.elasticsearch.gradle.internal;

import org.elasticsearch.gradle.dependencies.CompileOnlyResolvePlugin;
import org.elasticsearch.gradle.internal.precommit.DependencyLicensesTask;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
Expand All @@ -28,14 +27,14 @@ public void apply(final Project project) {
var depsInfo = project.getTasks().register("dependenciesInfo", DependenciesInfoTask.class);

depsInfo.configure(t -> {
t.setRuntimeConfiguration(project.getConfigurations().getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME));
t.setCompileOnlyConfiguration(
project.getConfigurations().getByName(CompileOnlyResolvePlugin.RESOLVEABLE_COMPILE_ONLY_CONFIGURATION_NAME)
);
t.getConventionMapping().map("mappings", () -> {
var depLic = project.getTasks().named("dependencyLicenses", DependencyLicensesTask.class);
return depLic.get().getMappings();
});
var runtimeConfiguration = project.getConfigurations().getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME);
t.getRuntimeArtifacts().set(project.getProviders().provider(() -> runtimeConfiguration.getIncoming().getArtifacts()));
t.getClasspath().from(runtimeConfiguration);
var compileOnlyConfiguration = project.getConfigurations()
.getByName(CompileOnlyResolvePlugin.RESOLVEABLE_COMPILE_ONLY_CONFIGURATION_NAME);
t.getCompileOnlyArtifacts().set(project.getProviders().provider(() -> compileOnlyConfiguration.getIncoming().getArtifacts()));
t.getClasspath().from(compileOnlyConfiguration);

});
Configuration dependenciesInfoFilesConfiguration = project.getConfigurations().create("dependenciesInfoFiles");
dependenciesInfoFilesConfiguration.setCanBeResolved(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,22 @@

import org.elasticsearch.gradle.internal.precommit.DependencyLicensesTask;
import org.elasticsearch.gradle.internal.precommit.LicenseAnalyzer;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.DependencySet;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.ArtifactCollection;
import org.gradle.api.artifacts.ProjectDependency;
import org.gradle.api.artifacts.component.ModuleComponentIdentifier;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.ProjectLayout;
import org.gradle.api.internal.ConventionTask;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.MapProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
import org.gradle.api.provider.ProviderFactory;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputDirectory;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
Expand All @@ -34,6 +37,7 @@
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
Expand All @@ -51,31 +55,58 @@
* <li>license: <a href="https://spdx.org/licenses/">SPDX license</a> identifier, custom license or UNKNOWN.</li>
* </ul>
*/
public class DependenciesInfoTask extends ConventionTask {
public abstract class DependenciesInfoTask extends ConventionTask {

private final DirectoryProperty licensesDir;
@Inject
public abstract ProviderFactory getProviderFactory();

@OutputFile
private File outputFile;
/**
* We have to use ArtifactCollection instead of ResolvedArtifactResult here as we're running
* into a an issue in Gradle: https://github.com/gradle/gradle/issues/27582
*/

private LinkedHashMap<String, String> mappings;
@Internal
abstract Property<ArtifactCollection> getRuntimeArtifacts();

public Configuration getRuntimeConfiguration() {
return runtimeConfiguration;
@Input
public Provider<Set<ModuleComponentIdentifier>> getRuntimeModules() {
return mapToModuleComponentIdentifiers(getRuntimeArtifacts().get());
}

public void setRuntimeConfiguration(Configuration runtimeConfiguration) {
this.runtimeConfiguration = runtimeConfiguration;
}
@Internal
abstract Property<ArtifactCollection> getCompileOnlyArtifacts();

public Configuration getCompileOnlyConfiguration() {
return compileOnlyConfiguration;
@Input
public Provider<Set<ModuleComponentIdentifier>> getCompileOnlyModules() {
return mapToModuleComponentIdentifiers(getCompileOnlyArtifacts().get());
}

public void setCompileOnlyConfiguration(Configuration compileOnlyConfiguration) {
this.compileOnlyConfiguration = compileOnlyConfiguration;
/**
* We need to track file inputs here from the configurations we inspect to ensure we dont miss any
* artifact transforms that might be applied and fail due to missing task dependency to jar
* generating tasks.
* */
@InputFiles
abstract ConfigurableFileCollection getClasspath();

private Provider<Set<ModuleComponentIdentifier>> mapToModuleComponentIdentifiers(ArtifactCollection artifacts) {
return getProviderFactory().provider(
() -> artifacts.getArtifacts()
.stream()
.map(r -> r.getId())
.filter(id -> id instanceof ModuleComponentIdentifier)
.map(id -> (ModuleComponentIdentifier) id)
.collect(Collectors.toSet())
);
}

private final DirectoryProperty licensesDir;

@OutputFile
private File outputFile;

private LinkedHashMap<String, String> mappings;

/**
* Directory to read license files
*/
Expand All @@ -102,17 +133,6 @@ public void setOutputFile(File outputFile) {
this.outputFile = outputFile;
}

/**
* Dependencies to gather information from.
*/
@InputFiles
private Configuration runtimeConfiguration;
/**
* We subtract compile-only dependencies.
*/
@InputFiles
private Configuration compileOnlyConfiguration;

@Inject
public DependenciesInfoTask(ProjectLayout projectLayout, ObjectFactory objectFactory, ProviderFactory providerFactory) {
this.licensesDir = objectFactory.directoryProperty();
Expand All @@ -123,22 +143,18 @@ public DependenciesInfoTask(ProjectLayout projectLayout, ObjectFactory objectFac

@TaskAction
public void generateDependenciesInfo() throws IOException {
final DependencySet runtimeDependencies = runtimeConfiguration.getAllDependencies();
// we have to resolve the transitive dependencies and create a group:artifactId:version map

final Set<String> compileOnlyArtifacts = compileOnlyConfiguration.getResolvedConfiguration()
.getResolvedArtifacts()
.stream()
.map(r -> {
ModuleVersionIdentifier id = r.getModuleVersion().getId();
return id.getGroup() + ":" + id.getName() + ":" + id.getVersion();
})
.collect(Collectors.toSet());

final Set<String> compileOnlyIds = getCompileOnlyModules().map(
set -> set.stream()
.map(id -> id.getModuleIdentifier().getGroup() + ":" + id.getModuleIdentifier().getName() + ":" + id.getVersion())
.collect(Collectors.toSet())
).get();
final StringBuilder output = new StringBuilder();
for (final Dependency dep : runtimeDependencies) {
Map<String, String> mappings = getMappings().get();
for (final ModuleComponentIdentifier dep : getRuntimeModules().get()) {
// we do not need compile-only dependencies here
if (compileOnlyArtifacts.contains(dep.getGroup() + ":" + dep.getName() + ":" + dep.getVersion())) {
String moduleName = dep.getModuleIdentifier().getName();
if (compileOnlyIds.contains(dep.getGroup() + ":" + moduleName + ":" + dep.getVersion())) {
continue;
}

Expand All @@ -147,25 +163,20 @@ public void generateDependenciesInfo() throws IOException {
continue;
}

final String url = createURL(dep.getGroup(), dep.getName(), dep.getVersion());
final String dependencyName = DependencyLicensesTask.getDependencyName(getMappings(), dep.getName());
getLogger().info("mapped dependency " + dep.getGroup() + ":" + dep.getName() + " to " + dependencyName + " for license info");
final String url = createURL(dep.getGroup(), moduleName, dep.getVersion());
final String dependencyName = DependencyLicensesTask.getDependencyName(mappings, moduleName);
getLogger().info("mapped dependency " + dep.getGroup() + ":" + moduleName + " to " + dependencyName + " for license info");

final String licenseType = getLicenseType(dep.getGroup(), dependencyName);
output.append(dep.getGroup() + ":" + dep.getName() + "," + dep.getVersion() + "," + url + "," + licenseType + "\n");
output.append(dep.getGroup() + ":" + moduleName + "," + dep.getVersion() + "," + url + "," + licenseType + "\n");
}

Files.write(outputFile.toPath(), output.toString().getBytes("UTF-8"), StandardOpenOption.CREATE);
}

@Input
public LinkedHashMap<String, String> getMappings() {
return mappings;
}

public void setMappings(LinkedHashMap<String, String> mappings) {
this.mappings = mappings;
}
@Optional
public abstract MapProperty<String, String> getMappings();

/**
* Create an URL on <a href="https://repo1.maven.org/maven2/">Maven Central</a>
Expand Down