|
1 |
| -# Develocity Build Processor |
| 1 | +# Develocity™ Build Processor |
2 | 2 |
|
3 |
| -A library to process Develocity™ build data with built-in caching and retry mechanisms. |
| 3 | +A library for fetching, processing, and analyzing Develocity build data with a fluent API, built-in caching, and retry mechanisms. |
| 4 | + |
| 5 | +The library aims to simplify interactions with the `/api/builds/**` endpoints of the Develocity API by providing a high level API with proper typed classes for each build tool. |
| 6 | +When using this library, you'll focus less on how to interact with the Develocity API and more on the processing and analysis of build data. |
| 7 | + |
| 8 | +Learn more about how to get started and leverage the full potential of Develocity and your build data below. |
| 9 | + |
| 10 | +## Getting started |
| 11 | + |
| 12 | +### Gradle |
| 13 | + |
| 14 | +Add the following to your `build.gradle(.kts)` file. |
| 15 | + |
| 16 | +```kotlin |
| 17 | +dependencies { |
| 18 | + implementation("dev.erichaag:develocity-build-processor:0.0.1") |
| 19 | +} |
| 20 | +``` |
| 21 | + |
| 22 | +### Example |
| 23 | + |
| 24 | +```java |
| 25 | +final var numberOfBuilds = new AtomicInteger(); |
| 26 | +final var numberOfGradleBuilds = new AtomicInteger(); |
| 27 | + |
| 28 | +BuildProcessor.forServer("https://develocity.example.com") |
| 29 | + .onBuild(__ -> numberOfBuilds.incrementAndGet()) |
| 30 | + .onGradleBuild(__ -> numberOfGradleBuilds.incrementAndGet()) |
| 31 | + .process(Duration.ofDays(1)); |
| 32 | + |
| 33 | +System.out.println("Processed " + numberOfBuilds.get() + " total builds"); |
| 34 | +System.out.println(numberOfGradleBuilds.get() + " were Gradle builds"); |
| 35 | +``` |
| 36 | + |
| 37 | +## Usage |
| 38 | + |
| 39 | +The main entry point is the `BuildProcessor` class. |
| 40 | +You can create an instance using one of the static constructors. |
| 41 | +Which one you use depends on your authentication requirements. |
| 42 | + |
| 43 | +```java |
| 44 | +// Use this if an access key is required to call the Develocity API |
| 45 | +// Will search the environment for an appropriate access key, failing if one can't be found |
| 46 | +BuildProcessor.forServer("https://develocity.example.com"); |
| 47 | + |
| 48 | +// Use this if you use anonymous access to call the Develocity API |
| 49 | +BuildProcessor.forServerWithAnonymousAccess("https://develocity.example.com"); |
| 50 | +``` |
| 51 | + |
| 52 | +### Processing build data |
| 53 | + |
| 54 | +A `BuildProcessor` works much like a Java `Stream` in that it has both *intermediate operations* and *terminal operations*. |
| 55 | + |
| 56 | +#### Intermediate operations |
| 57 | + |
| 58 | +A `BuildProcessor` has several _intermediate operations_ used for the actual processing of data. |
| 59 | +There are several operators for use depending on your use case. |
| 60 | + |
| 61 | +```java |
| 62 | +// Print the ID of any build |
| 63 | +processor.onBuild(build -> System.out.println(build.getId())); |
| 64 | + |
| 65 | +// Print the ID of each Gradle build |
| 66 | +processor.onGradleBuild(gradleBuild -> System.out.println(gradleBuild.getId())); |
| 67 | + |
| 68 | +// Print the ID of each Maven build |
| 69 | +processor.onMavenBuild(mavenBuild -> System.out.println(mavenBuild.getId())); |
| 70 | + |
| 71 | +// "Meta" operators to report on the processing itself |
| 72 | +processor.onProcessingStarted(e -> System.out.println("Started at " + e.triggeredAt())); |
| 73 | +processor.onProcessingFinished(e -> System.out.println("Finished at " + e.triggeredAt())); |
| 74 | +``` |
| 75 | + |
| 76 | +#### Terminal operations |
| 77 | + |
| 78 | +Just like a `Stream`, a `BuildProcessor` won't begin processing data until a _terminal operation_ is used. |
| 79 | +For a `BuildProcessor`, there is only one terminal operation named "`process`", though it has several overloaded variations for convenience. |
| 80 | + |
| 81 | +```java |
| 82 | +// Process builds from the last 7 days |
| 83 | +processor.process(Duration.ofDays(7)); |
| 84 | + |
| 85 | +// Process builds since Oct 5, 2024 |
| 86 | +processor.process(LocalDate.parse("2024-10-05")); |
| 87 | + |
| 88 | +// Process just Gradle builds since Oct 5, 2024 at 10:15:30 AM |
| 89 | +processor.process(LocalDateTime.parse("2024-10-05T10:15:30"), "buildTool:gradle"); |
| 90 | +``` |
| 91 | + |
| 92 | +#### Build models |
| 93 | + |
| 94 | +By default, the Develocity API returns a very limited amount of data about each build. |
| 95 | +To get more details, you need to define the *build models* to be returned. |
| 96 | +The more build models that are requested, the longer the query will take. |
| 97 | + |
| 98 | +This library works similarly. |
| 99 | +To use the additional data from the requested build models, cast the returned `Build` into a `BazelBuild`, `GradleBuild`, `MavenBuild`, or `SbtBuild`. |
| 100 | + |
| 101 | +```java |
| 102 | +processor.withRequiredBuildModels(GRADLE_ATTRIBUTES, MAVEN_ATTRIBUTES); |
| 103 | + |
| 104 | +processor.onBuild(build -> { |
| 105 | + switch(build) { |
| 106 | + case GradleBuild b -> b.getAttributes() |
| 107 | + .map(GradleAttributes::getRequestedTasks) |
| 108 | + .ifPresent(System.out::println); |
| 109 | + case MavenBuild b -> b.getAttributes() |
| 110 | + .map(MavenAttributes::getRequestedGoals) |
| 111 | + .ifPresent(System.out::println); |
| 112 | + default -> {} |
| 113 | + } |
| 114 | +}); |
| 115 | + |
| 116 | +// When using a build tool specific callback, no casting is required |
| 117 | +processor.onGradleBuild(gradleBuild -> { |
| 118 | + gradleBuild.getAttributes() |
| 119 | + .map(GradleAttributes::getGradleVersion) |
| 120 | + .ifPresent(System.out::println); |
| 121 | +}); |
| 122 | +``` |
| 123 | + |
| 124 | +Given requesting the *attributes* build models is so common, typically because this is the build model containing the custom values and tags, it's possible to query for these directly through the top-level `Build` object without casting. |
| 125 | + |
| 126 | +```java |
| 127 | +processor.withRequiredBuildModels(GRADLE_ATTRIBUTES, MAVEN_ATTRIBUTES); |
| 128 | + |
| 129 | +final var gitRepositories = new HashSet<String>(); |
| 130 | + |
| 131 | +processor.onBuild(build -> { |
| 132 | + if (build.getTags().contains("CI")) { |
| 133 | + build.getFirstValue("Git repository") |
| 134 | + .map(this::normalize) |
| 135 | + .ifPresent(gitRepositories::add); |
| 136 | + } |
| 137 | +}); |
| 138 | + |
| 139 | +// Ensure returned build data only contains Gradle or Maven builds |
| 140 | +processor.process(LocalDate.parse("2024-10-05"), "buildTool:gradle or buildTool:maven"); |
| 141 | + |
| 142 | +System.out.println("Detected " + gitRepositories.size() + " repositories using Develocity"); |
| 143 | +gitRepositories.forEach(System.out::println); |
| 144 | +``` |
| 145 | + |
| 146 | +### Caching build data for faster queries |
| 147 | + |
| 148 | +todo |
| 149 | + |
| 150 | +### Configuring retries and backoffs |
| 151 | + |
| 152 | +todo |
| 153 | + |
| 154 | +## License |
| 155 | + |
| 156 | +Develocity Build Processor is released under the [`MIT License`](LICENSE) and is not an official Gradle, Inc. product. |
0 commit comments