Skip to content

Commit 5213373

Browse files
committed
Add incremental backoff, customizable retries, and many convenience methods
1 parent 5178e38 commit 5213373

31 files changed

+1113
-266
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Develocity Build Processor
22

3-
wip
3+
A library to process Develocity™ build data with built-in caching and retry mechanisms.

build.gradle.kts

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
@file:Suppress("UnstableApiUsage")
22

33
plugins {
4-
alias(libs.plugins.develocity.api.models)
5-
alias(libs.plugins.java.test.fixtures)
6-
alias(libs.plugins.java.library)
4+
alias(libs.plugins.conventions.develocity.api)
5+
alias(libs.plugins.conventions.release)
6+
alias(libs.plugins.gradle.java.library)
7+
alias(libs.plugins.gradle.java.test.fixtures)
78
}
89

910
group = "dev.erichaag"
@@ -30,3 +31,30 @@ develocityApi {
3031
val test by testing.suites.getting(JvmTestSuite::class) {
3132
useJUnitJupiter(libs.versions.junit)
3233
}
34+
35+
val mavenJava by publishing.publications.getting(MavenPublication::class) {
36+
pom {
37+
name = "Develocity Build Processor"
38+
description = "A library to process Develocity™ build data with built-in caching and retry mechanisms."
39+
url = "https://github.com/erichaagdev/develocity-build-processor"
40+
licenses {
41+
license {
42+
name = "MIT License"
43+
url = "https://raw.githubusercontent.com/erichaagdev/develocity-build-processor/main/LICENSE"
44+
distribution = "repo"
45+
}
46+
}
47+
developers {
48+
developer {
49+
id = "erichaagdev"
50+
name = "Eric Haag"
51+
52+
}
53+
}
54+
scm {
55+
connection = "scm:git:git://github.com/erichaagdev/develocity-build-processor.git"
56+
developerConnection = "scm:git:ssh://github.com/erichaagdev/develocity-build-processor.git"
57+
url = "https://github.com/erichaagdev/develocity-build-processor"
58+
}
59+
}
60+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
plugins {
2+
id("java")
3+
id("maven-publish")
4+
id("signing")
5+
}
6+
7+
java {
8+
withJavadocJar()
9+
withSourcesJar()
10+
}
11+
12+
publishing.repositories.maven {
13+
name = "distribution"
14+
url = uri(layout.buildDirectory.dir("distributionRepository"))
15+
}
16+
17+
tasks.javadoc {
18+
(options as StandardJavadocDocletOptions).addBooleanOption("html5", true)
19+
}
20+
21+
val mavenJava by publishing.publications.creating(MavenPublication::class) {
22+
from(components["java"])
23+
}
24+
25+
signing {
26+
val signingSecretKey = providers.gradleProperty("signingSecretKey")
27+
val signingPassword = providers.gradleProperty("signingPassword")
28+
if (signingSecretKey.isPresent && signingPassword.isPresent) {
29+
sign(mavenJava)
30+
useInMemoryPgpKeys(signingSecretKey.get(), signingPassword.get())
31+
isRequired = true
32+
}
33+
}
34+
35+
val verifySigningCredentials by tasks.registering {
36+
val signingSecretKey = providers.gradleProperty("signingSecretKey")
37+
val signingPassword = providers.gradleProperty("signingPassword")
38+
doFirst {
39+
if (!signingSecretKey.isPresent && !signingPassword.isPresent) throw GradleException("'signingSecretKey' and 'signingPassword' properties must be set")
40+
if (!signingSecretKey.isPresent) throw GradleException("'signingSecretKey' property must be set")
41+
if (!signingPassword.isPresent) throw GradleException("'signingPassword' property must be set")
42+
}
43+
}
44+
45+
val publishMavenJavaPublicationToDistributionRepository = tasks.named<PublishToMavenRepository>("publishMavenJavaPublicationToDistributionRepository") {
46+
dependsOn(verifySigningCredentials)
47+
val repositoryUrl = repository.url
48+
doFirst {
49+
File(repositoryUrl.toURL().file).deleteRecursively()
50+
}
51+
}
52+
53+
val packageDistribution by tasks.registering(Zip::class) {
54+
destinationDirectory = layout.buildDirectory.dir("packageDistribution")
55+
from(publishMavenJavaPublicationToDistributionRepository.map { it.repository.url })
56+
exclude("**/*.asc.*")
57+
}

gradle/libs.versions.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ jakarta-annotation-api = { module = "jakarta.annotation:jakarta.annotation-api",
1111
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }
1212

1313
[plugins]
14-
develocity-api-models = { id = "conventions.develocity-api-models" }
15-
java-library = { id = "java-library" }
16-
java-test-fixtures = { id = "java-test-fixtures" }
14+
conventions-develocity-api = { id = "conventions.develocity-api" }
15+
conventions-release = { id = "conventions.release" }
16+
gradle-java-library = { id = "java-library" }
17+
gradle-java-test-fixtures = { id = "java-test-fixtures" }
1718
openapi-generator = { id = "org.openapi.generator", version.ref = "openapi-generator" }

settings.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ plugins {
77
develocity {
88
buildScan {
99
termsOfUseAgree = "yes"
10-
termsOfUseUrl = "https://gradle.com/terms-of-service"
10+
termsOfUseUrl = "https://gradle.com/help/legal-terms-of-use"
1111
}
1212
}
1313

14-
rootProject.name = "develocity-build-scan-processor"
14+
rootProject.name = "develocity-build-processor"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package dev.erichaag.develocity.api;
2+
3+
import java.util.function.Supplier;
4+
5+
public class AttributesNotPresentException extends RuntimeException {
6+
7+
AttributesNotPresentException(String methodName) {
8+
super("'" + methodName + "' may only be called when attributes are present.");
9+
}
10+
11+
static Supplier<AttributesNotPresentException> attributesNotPresent(String methodName) {
12+
return () -> new AttributesNotPresentException(methodName);
13+
}
14+
15+
}

src/main/java/dev/erichaag/develocity/api/BazelBuild.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
package dev.erichaag.develocity.api;
22

3+
import java.time.Duration;
4+
import java.time.Instant;
5+
import java.util.List;
36
import java.util.Objects;
47
import java.util.Set;
58

9+
import static dev.erichaag.develocity.api.MethodNotSupportedException.methodNotSupportedForBazel;
610
import static java.util.Collections.emptySet;
711

812
public final class BazelBuild implements Build {
@@ -33,6 +37,46 @@ public String getBuildAgentVersion() {
3337
return build.getBuildAgentVersion();
3438
}
3539

40+
@Override
41+
public Instant getStartTime() {
42+
throw methodNotSupportedForBazel("getStartTime()");
43+
}
44+
45+
@Override
46+
public Duration getDuration() {
47+
throw methodNotSupportedForBazel("getDuration()");
48+
}
49+
50+
@Override
51+
public String getProjectName() {
52+
throw methodNotSupportedForBazel("getProjectName()");
53+
}
54+
55+
@Override
56+
public List<String> getRequestedWorkUnits() {
57+
throw methodNotSupportedForBazel("getRequestedWorkUnits()");
58+
}
59+
60+
@Override
61+
public boolean hasFailed() {
62+
throw methodNotSupportedForBazel("hasFailed()");
63+
}
64+
65+
@Override
66+
public String getUser() {
67+
throw methodNotSupportedForBazel("getUser()");
68+
}
69+
70+
@Override
71+
public List<String> getTags() {
72+
throw methodNotSupportedForBazel("getTags()");
73+
}
74+
75+
@Override
76+
public List<Value> getValues() {
77+
throw methodNotSupportedForBazel("getValues()");
78+
}
79+
3680
@Override
3781
public Set<BuildModel> getAvailableBuildModels() {
3882
return emptySet();

src/main/java/dev/erichaag/develocity/api/Build.java

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
package dev.erichaag.develocity.api;
22

3+
import java.time.Duration;
4+
import java.time.Instant;
5+
import java.util.Collection;
6+
import java.util.List;
7+
import java.util.Optional;
38
import java.util.Set;
49

10+
import static java.util.stream.Collectors.toUnmodifiableSet;
11+
512
public sealed interface Build permits GradleBuild, MavenBuild, BazelBuild, SbtBuild {
613

714
String getId();
@@ -12,10 +19,58 @@ public sealed interface Build permits GradleBuild, MavenBuild, BazelBuild, SbtBu
1219

1320
String getBuildAgentVersion();
1421

15-
Set<BuildModel> getAvailableBuildModels();
22+
Instant getStartTime();
23+
24+
Duration getDuration();
25+
26+
String getProjectName();
27+
28+
List<String> getRequestedWorkUnits();
29+
30+
boolean hasFailed();
31+
32+
String getUser();
33+
34+
List<String> getTags();
35+
36+
default boolean hasTag(String tag) {
37+
return getTags().contains(tag);
38+
}
39+
40+
List<Value> getValues();
41+
42+
default boolean hasValue(String key) {
43+
return getValues().stream().anyMatch(it -> it.name().equals(key));
44+
}
45+
46+
default List<String> getValues(String key) {
47+
return getValues().stream()
48+
.filter(it -> it.name().equals(key))
49+
.map(Value::value)
50+
.toList();
51+
}
52+
53+
default Optional<String> getValue(String key) {
54+
final var values = getValues(key);
55+
if (values.size() > 1) throw new IllegalStateException("Multiple values for key '" + key + "'");
56+
return values.stream().findFirst();
57+
}
58+
59+
default Optional<String> getFirstValue(String key) {
60+
return getValues(key).stream().findFirst();
61+
}
1662

1763
ApiBuild getBuild();
1864

65+
Set<BuildModel> getAvailableBuildModels();
66+
67+
default boolean containsAllRelevantBuildModelsFrom(Collection<BuildModel> requiredBuildModels) {
68+
return getAvailableBuildModels()
69+
.containsAll(requiredBuildModels.stream()
70+
.filter(it -> it.isModelFor(this))
71+
.collect(toUnmodifiableSet()));
72+
}
73+
1974
static Build from(ApiBuild build) {
2075
return switch (build.getBuildToolType()) {
2176
case "gradle" -> new GradleBuild(build);

src/main/java/dev/erichaag/develocity/api/BuildModel.java

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,32 @@
22

33
public enum BuildModel {
44

5-
ALL_MODELS("*"),
6-
GRADLE_ARTIFACT_TRANSFORM_EXECUTIONS("gradle-artifact-transform-executions"),
7-
GRADLE_ATTRIBUTES("gradle-attributes"),
8-
GRADLE_BUILD_CACHE_PERFORMANCE("gradle-build-cache-performance"),
9-
GRADLE_DEPRECATIONS("gradle-deprecations"),
10-
GRADLE_NETWORK_ACTIVITY("gradle-network-activity"),
11-
GRADLE_PROJECTS("gradle-projects"),
12-
MAVEN_ATTRIBUTES("maven-attributes"),
13-
MAVEN_BUILD_CACHE_PERFORMANCE("maven-build-cache-performance"),
14-
MAVEN_DEPENDENCY_RESOLUTION("maven-dependency-resolution"),
15-
MAVEN_MODULES("maven-modules");
5+
ALL_MODELS("*", null),
6+
GRADLE_ARTIFACT_TRANSFORM_EXECUTIONS("gradle-artifact-transform-executions", GradleBuild.class),
7+
GRADLE_ATTRIBUTES("gradle-attributes", GradleBuild.class),
8+
GRADLE_BUILD_CACHE_PERFORMANCE("gradle-build-cache-performance", GradleBuild.class),
9+
GRADLE_DEPRECATIONS("gradle-deprecations", GradleBuild.class),
10+
GRADLE_NETWORK_ACTIVITY("gradle-network-activity", GradleBuild.class),
11+
GRADLE_PROJECTS("gradle-projects", GradleBuild.class),
12+
MAVEN_ATTRIBUTES("maven-attributes", MavenBuild.class),
13+
MAVEN_BUILD_CACHE_PERFORMANCE("maven-build-cache-performance", MavenBuild.class),
14+
MAVEN_DEPENDENCY_RESOLUTION("maven-dependency-resolution", MavenBuild.class),
15+
MAVEN_MODULES("maven-modules", MavenBuild.class);
1616

17-
final String modelName;
17+
private final String modelName;
18+
private final Class<? extends Build> modelFor;
1819

19-
BuildModel(String modelName) {
20+
BuildModel(String modelName, Class<? extends Build> modelFor) {
2021
this.modelName = modelName;
22+
this.modelFor = modelFor;
23+
}
24+
25+
boolean isModelFor(Build build) {
26+
return modelFor == null || modelFor.isInstance(build);
27+
}
28+
29+
public String modelName() {
30+
return modelName;
2131
}
2232

2333
}

0 commit comments

Comments
 (0)