Skip to content

Commit

Permalink
produce version report on outgoing configurations (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
ferozco authored Mar 3, 2022
1 parent d4d9b61 commit 572205d
Show file tree
Hide file tree
Showing 14 changed files with 245 additions and 99 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ build
*.iws
out
generated_*
.idea
1 change: 0 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ allprojects {

dependencies {
"errorprone"("com.google.errorprone:error_prone_core")
"errorprone"("com.jakewharton.nopen:nopen-checker")
"compileOnly"("com.jakewharton.nopen:nopen-annotations")
}

Expand Down
5 changes: 4 additions & 1 deletion gradle-versions/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import java.net.URI

plugins {
`groovy`
`java-gradle-plugin`
`maven-publish`
id("com.gradle.plugin-publish") version "0.20.0"
Expand All @@ -17,9 +18,11 @@ dependencies {
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")
implementation("com.google.guava:guava")

testImplementation(gradleTestKit())
testImplementation(platform("org.junit:junit-bom"))
testImplementation("org.assertj:assertj-core")
testImplementation("org.junit.jupiter:junit-jupiter-engine")
testImplementation("com.netflix.nebula:nebula-test")
}

tasks.test {
Expand All @@ -33,7 +36,7 @@ gradlePlugin {
plugins {
create("versions") {
id = "com.markelliot.versions"
implementationClass = "com.markelliot.gradle.versions.UpdateVersionsPlugin"
implementationClass = "com.markelliot.gradle.versions.RootUpdateVersionsPlugin"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@

package com.markelliot.gradle.versions;

import com.jakewharton.nopen.annotation.Open;
import com.markelliot.gradle.versions.api.DependencyUpdateRec;
import com.markelliot.gradle.versions.api.ImmutableDependencyUpdateRec;
import com.markelliot.gradle.versions.api.ImmutableUpdateReport;
import com.markelliot.gradle.versions.api.UpdateReport;
import com.markelliot.gradle.versions.api.YamlSerDe;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
Expand All @@ -32,20 +33,31 @@
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.LenientConfiguration;
import org.gradle.api.artifacts.ResolvedDependency;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.specs.Specs;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;

@Open
public class CheckNewVersionsTask extends DefaultTask {
public abstract class CheckNewVersionsTask extends DefaultTask {
// TODO(markelliot): make these configurable
private static final Set<String> DISALLOWED_QUALIFIERS =
Set.of("-alpha", "-beta", "-ea", "-rc");

@OutputFile
abstract RegularFileProperty getReportFile();

@TaskAction
public final void taskAction() {
public final void taskAction() throws IOException {
Set<DependencyUpdateRec> dependencyUpdates = getDependencyUpdates();
Set<DependencyUpdateRec> pluginUpdates = getPluginUpdates();
writeReports(dependencyUpdates, pluginUpdates);

YamlSerDe.mapper.writeValue(
getReportFile().getAsFile().get(),
UpdateReport.builder()
.project(getProject().getPath())
.addAllDependencyUpdates(dependencyUpdates)
.addAllPluginUpdates(pluginUpdates)
.build());
}

private Set<DependencyUpdateRec> getDependencyUpdates() {
Expand Down Expand Up @@ -82,17 +94,6 @@ private Set<DependencyUpdateRec> getPluginUpdates() {
return pluginUpdates;
}

private void writeReports(
Set<DependencyUpdateRec> dependencyUpdates, Set<DependencyUpdateRec> pluginUpdates) {
Reports.writeUpdateReport(
getProject().getBuildDir(),
ImmutableUpdateReport.builder()
.project(getProject().getPath())
.addAllDependencyUpdates(dependencyUpdates)
.addAllPluginUpdates(pluginUpdates)
.build());
}

private static String render(DependencyUpdateRec detail) {
return detail.group()
+ ":"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@ public final class Reports {

private Reports() {}

public static void writeUpdateReport(File projectBuildDir, UpdateReport report) {
writeReport(projectBuildDir, REPORT_YML, report);
}

public static void writeGradleUpdateReport(File projectBuildDir, GradleUpdateReport report) {
writeReport(projectBuildDir, GRADLE_REPORT_YML, report);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.markelliot.gradle.versions;

import java.util.Map;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;

public final class RootUpdateVersionsPlugin implements Plugin<Project> {
private static final String VERSIONS_PROPS = "versions.props";
private static final String ALL_REPORTS = "allReports";

@Override
public void apply(Project project) {
if (!project.equals(project.getRootProject())) {
throw new IllegalStateException("Plugin must be applied onto root project");
}

Configuration reportConfiguration = createReportConfiguration(project);
project.getAllprojects()
.forEach(
subProject -> {
subProject.getPluginManager().apply(UpdateVersionsPlugin.class);
Dependency dependency =
project.getDependencies()
.project(
Map.of(
"path",
subProject.getPath(),
"configuration",
UpdateVersionsPlugin.NEW_VERSIONS));
project.getDependencies()
.add(reportConfiguration.getName(), dependency);
});

project.getTasks()
.register(
"updateVersionsProps",
UpdateVersionsPropsTask.class,
task -> {
task.setDescription(
"Uses result of checkNewVersions task to update versions.props");

task.getVersionsProps().set(project.file(VERSIONS_PROPS));
task.getReports().from(reportConfiguration);
});

project.getTasks()
.register(
"updatePlugins",
UpdatePluginsTask.class,
task -> {
task.getReports().from(reportConfiguration);
task.setDescription(
"Uses result of checkNewVersions task to update buildscript plugin blocks");
});
project.getTasks()
.create("updateGradleWrapper", UpdateGradleWrapperTask.class)
.setDescription("Uses result of checkNewGradleVersion to update Gradle wrapper");

Task gradleTask =
project.getTasks().create("checkNewGradleVersion", CheckNewGradleVersionTask.class);
gradleTask.setDescription("Checks for and reports on existence of a new Gradle version");
project.getTasks().getByName("checkNewVersions").dependsOn(gradleTask);
}

private static Configuration createReportConfiguration(Project project) {
return project.getConfigurations()
.create(
ALL_REPORTS,
conf -> {
conf.setCanBeResolved(true);
conf.setCanBeConsumed(true);
conf.setVisible(false);
});
}
}
Original file line number Diff line number Diff line change
@@ -1,42 +1,38 @@
package com.markelliot.gradle.versions;

import com.google.common.annotations.VisibleForTesting;
import com.jakewharton.nopen.annotation.Open;
import com.markelliot.gradle.versions.api.UpdateReport;
import com.markelliot.gradle.versions.api.YamlSerDe;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.gradle.api.DefaultTask;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.TaskAction;

@Open
public class UpdatePluginsTask extends DefaultTask {
public abstract class UpdatePluginsTask extends DefaultTask {

@InputFiles
abstract ConfigurableFileCollection getReports();

@TaskAction
public void taskAction() {
if (!getProject().equals(getProject().getRootProject())) {
getLogger().warn("updatePluginsTask task may only be called from the root project");
return;
}

// collect all the update recommendations.
List<UpdateReport> reports = new ArrayList<>();
getProject()
.allprojects(
proj ->
Reports.loadUpdateReport(proj.getBuildDir())
.ifPresent(
r -> {
getLogger()
.info("Found reports.yml for " + proj);
reports.add(r);
}));
List<UpdateReport> reports =
getReports().getFiles().stream()
.flatMap(
file ->
Stream.of(
YamlSerDe.deserialize(
file.toPath(), UpdateReport.class)))
.collect(Collectors.toUnmodifiableList());

Map<String, String> pluginUpdates = mergePluginUpdates(reports);
getProject()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,45 +16,50 @@

package com.markelliot.gradle.versions;

import com.jakewharton.nopen.annotation.Open;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.tasks.TaskProvider;

public final class UpdateVersionsPlugin implements Plugin<Project> {
public static final String NEW_VERSIONS = "newVersions";

@Open
public class UpdateVersionsPlugin implements Plugin<Project> {
@Override
public final void apply(Project project) {
if (project.getTasks().findByName("checkNewVersions") == null) {
project.getTasks()
.create("checkNewVersions", CheckNewVersionsTask.class)
.setDescription(
"Checks for and reports on existence of newer versions of dependencies and plugins");
} else {
System.out.println(
"Project '" + project.getName() + "' already has checkNewVersions task.");
}
TaskProvider<CheckNewVersionsTask> checkNewVersions =
project.getTasks()
.register(
"checkNewVersions",
CheckNewVersionsTask.class,
task -> {
task.getReportFile()
.set(
project.getLayout()
.getBuildDirectory()
.file("versions-report.yml"));
task.setDescription(
"Checks for and reports on existence of newer versions of dependencies and plugins");
});

createOutgoingConfiguration(project, checkNewVersions);
}

if (project.equals(project.getRootProject())) {
project.getTasks()
.create("updateVersionsProps", UpdateVersionsPropsTask.class)
.setDescription(
"Uses result of checkNewVersions task to update versions.props");
project.getTasks()
.create("updatePlugins", UpdatePluginsTask.class)
.setDescription(
"Uses result of checkNewVersions task to update buildscript plugin blocks");
project.getTasks()
.create("updateGradleWrapper", UpdateGradleWrapperTask.class)
.setDescription(
"Uses result of checkNewGradleVersion to update Gradle wrapper");
private static void createOutgoingConfiguration(
Project project, TaskProvider<CheckNewVersionsTask> task) {
Configuration outgoingConfiguration =
project.getConfigurations()
.create(
NEW_VERSIONS,
conf -> {
conf.setCanBeResolved(false);
conf.setCanBeConsumed(true);
conf.setVisible(true);
});

Task gradleTask =
project.getTasks()
.create("checkNewGradleVersion", CheckNewGradleVersionTask.class);
gradleTask.setDescription(
"Checks for and reports on existence of a new Gradle version");
project.getTasks().getByName("checkNewVersions").dependsOn(gradleTask);
}
project.getArtifacts()
.add(
outgoingConfiguration.getName(),
task.flatMap(CheckNewVersionsTask::getReportFile),
artifact -> artifact.builtBy(task));
}
}
Loading

0 comments on commit 572205d

Please sign in to comment.