diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 364e4f7..a3f7f3a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,4 +1,5 @@ import org.springframework.boot.gradle.tasks.run.BootRun +import java.io.ByteArrayOutputStream plugins { `java-convention` @@ -30,13 +31,21 @@ tasks.getByName("bootRun") { args = listOf("--spring.profiles.active=dev") } +val shortCommitHash by tasks.registering(Exec::class) { + commandLine("git", "rev-parse", "--short", "HEAD") + standardOutput = ByteArrayOutputStream() +} + springBoot { buildInfo { properties { + additional = mapOf("commit" to DelegatingProvider(shortCommitHash.map { it.standardOutput.toString().trim() })) time = null artifact = "" group = "" name = "" } + + dependsOn(shortCommitHash) } } diff --git a/buildSrc/src/main/java/DelegatingProvider.java b/buildSrc/src/main/java/DelegatingProvider.java new file mode 100644 index 0000000..9b730f5 --- /dev/null +++ b/buildSrc/src/main/java/DelegatingProvider.java @@ -0,0 +1,93 @@ +import java.io.Serializable; +import java.util.function.BiFunction; + +import org.gradle.api.Transformer; +import org.gradle.api.provider.Provider; +import org.jetbrains.annotations.Nullable; + +/** + * Spring Boot's {@code BuildInfo} Task calls the {@link Object#toString() toString} Method on every value present in + * the Map of the additional build information properties at task execution time. Therefore, a normal Gradle + * {@link Provider} does not work, since the {@link Object#toString() toString} method does not return the String + * representation of the provided value. + * + * @implNote Instances of this class must be serializable. Gradle will reject unserializable input properties when + * calculating the input's fingerprint. + */ +public class DelegatingProvider implements Provider, Serializable { + + /** + * @implNote Marking this property as transient is not an ideal solution, but the only type-safe one, since + * {@link Provider} does not implement {@link Serializable}. + */ + private final transient Provider delegate; + + /** + * @param delegate + * The provider all operations are delegated to, not {@code null}. + */ + public DelegatingProvider(Provider delegate) { + this.delegate = delegate; + } + + /** + * @return The string representation of the contained value. + */ + @Override + public String toString() { + return delegate.get().toString(); + } + + @Override + public T get() { + return delegate.get(); + } + + @Nullable + @Override + public T getOrNull() { + return delegate.getOrNull(); + } + + @Override + public T getOrElse(T defaultValue) { + return delegate.getOrElse(defaultValue); + } + + @Override + public Provider map(Transformer transformer) { + return delegate.map(transformer); + } + + @Override + public Provider flatMap(Transformer, ? super T> transformer) { + return delegate.flatMap(transformer); + } + + @Override + public boolean isPresent() { + return delegate.isPresent(); + } + + @Override + public Provider orElse(T value) { + return delegate.orElse(value); + } + + @Override + public Provider orElse(Provider provider) { + return delegate.orElse(provider); + } + + @Override + @Deprecated + public Provider forUseAtConfigurationTime() { + return delegate.forUseAtConfigurationTime(); + } + + @Override + public Provider zip(Provider provider, BiFunction biFunction) { + return delegate.zip(provider, biFunction); + } + +} diff --git a/buildSrc/src/main/kotlin/java-convention.gradle.kts b/buildSrc/src/main/kotlin/java-convention.gradle.kts index bfd80de..74c70aa 100644 --- a/buildSrc/src/main/kotlin/java-convention.gradle.kts +++ b/buildSrc/src/main/kotlin/java-convention.gradle.kts @@ -11,7 +11,6 @@ repositories { java { sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 } val integrationTestImplementation by configurations.creating @@ -40,19 +39,17 @@ dependencies { testImplementation("org.mockito:mockito-junit-jupiter") } -sourceSets { - create("integrationTest") { - compileClasspath += sourceSets.main.get().output - runtimeClasspath += sourceSets.main.get().output - } +val integrationTestSourceSet by sourceSets.creating { + compileClasspath += sourceSets.main.get().output + runtimeClasspath += sourceSets.main.get().output } -val integrationTest = task("integrationTest") { +val integrationTest by tasks.registering(Test::class) { group = "verification" - testClassesDirs = sourceSets["integrationTest"].output.classesDirs - classpath = sourceSets["integrationTest"].runtimeClasspath - shouldRunAfter("test") + testClassesDirs = integrationTestSourceSet.output.classesDirs + classpath = integrationTestSourceSet.runtimeClasspath + shouldRunAfter(tasks.test) } tasks.withType {