-
-
Notifications
You must be signed in to change notification settings - Fork 16
Adopt Gradle best practices #543
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
MartelliEnrico
wants to merge
5
commits into
main
Choose a base branch
from
gradle-9.7-best-practices
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
ff6f975
Gradle 9.7 best practices
MartelliEnrico 8539732
Convert to Kotlin script
MartelliEnrico 20a819e
Put archive generation inside jlink task
MartelliEnrico 1134b0c
Added random test runner
MartelliEnrico 9d44812
Added random seed for reproducible tests
MartelliEnrico File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| import com.github.stickerifier.stickerify.JlinkJavaLauncher | ||
| import com.github.stickerifier.stickerify.JlinkTask | ||
| import io.spring.gradle.nullability.NullabilityOptions | ||
| import org.gradle.internal.buildconfiguration.DaemonJvmPropertiesConfigurator | ||
| import org.gradle.kotlin.dsl.support.serviceOf | ||
|
|
||
| plugins { | ||
| java | ||
| application | ||
| alias(libs.plugins.spring.nullability) | ||
| } | ||
|
|
||
| repositories { | ||
| mavenCentral() | ||
| } | ||
|
|
||
| dependencies { | ||
| implementation(libs.gson) | ||
| implementation(libs.jspecify) | ||
| implementation(libs.logback.classic) | ||
| implementation(libs.logstash.logback.encoder) | ||
| implementation(libs.telegram.bot.api) | ||
| implementation(libs.tika) | ||
|
|
||
| constraints { | ||
| add("implementation", libs.jackson.core) | ||
| } | ||
|
|
||
| testImplementation(libs.hamcrest) | ||
| testImplementation(libs.junit.jupiter) | ||
| testImplementation(libs.mockwebserver) | ||
| testRuntimeOnly(libs.junit.platform) | ||
| } | ||
|
|
||
| group = "com.github.stickerifier" | ||
| version = "2.0" | ||
| description = "Telegram bot to convert medias into the format required to be used as Telegram stickers" | ||
|
|
||
| java.toolchain { | ||
| languageVersion = JavaLanguageVersion.of(26) | ||
| vendor = JvmVendorSpec.ADOPTIUM | ||
| } | ||
|
|
||
| tasks.named<UpdateDaemonJvm>(DaemonJvmPropertiesConfigurator.TASK_NAME) { | ||
| languageVersion = JavaLanguageVersion.of(26) | ||
| vendor = JvmVendorSpec.ADOPTIUM | ||
| } | ||
|
|
||
| val jlink = tasks.register<JlinkTask>("jlink") { | ||
| description = "Generates a minimal JRE for the project with compact object headers archive." | ||
|
|
||
| options = listOf("--strip-debug", "--no-header-files", "--no-man-pages", "--ignore-modified-runtime") | ||
| modules = listOf( | ||
| "java.instrument", // for junit | ||
| "java.naming", // for logback | ||
| "java.sql", // for tika | ||
| "jdk.unsupported" // for gson | ||
| ) | ||
| includeModulePath = false | ||
| javaCompiler = javaToolchains.compilerFor(java.toolchain) | ||
|
|
||
| val execOps = serviceOf<ExecOperations>() | ||
| doLast { | ||
| val javaExe = outputDirectory.file("jre/bin/java").get().asFile.absolutePath | ||
| execOps.exec { | ||
| commandLine(javaExe, "-XX:+UseCompactObjectHeaders", "-Xshare:dump") | ||
| } | ||
| } | ||
| } | ||
|
|
||
| val CompileOptions.nullability: NullabilityOptions | ||
| get() = (this as ExtensionAware).extensions["nullability"] as NullabilityOptions | ||
|
|
||
| tasks.named<JavaCompile>(JavaPlugin.COMPILE_TEST_JAVA_TASK_NAME) { | ||
| options.nullability.checking = "tests" | ||
| } | ||
|
|
||
| tasks.test { | ||
| inputs.dir(jlink.map { it.outputDirectory.get().asFile }) | ||
| javaLauncher = providers.provider { JlinkJavaLauncher(jlink.get()) } | ||
|
|
||
| useJUnitPlatform() | ||
| jvmArgs("--enable-final-field-mutation=ALL-UNNAMED") | ||
|
|
||
| testLogging { | ||
| events("started", "passed", "failed", "skipped") | ||
| } | ||
|
|
||
| val seedProvider = providers.gradleProperty("junitSeed").orElse(providers.provider { System.nanoTime().toString() }) | ||
| jvmArgumentProviders.add(CommandLineArgumentProvider { | ||
| val seed = seedProvider.get() | ||
| listOf("-Djunit.jupiter.execution.order.random.seed=$seed") | ||
| }) | ||
|
|
||
| doFirst { | ||
| println("Test seed: ${seedProvider.get()}") | ||
| } | ||
| } | ||
|
|
||
| application { | ||
| mainClass = "com.github.stickerifier.stickerify.runner.Main" | ||
| applicationDefaultJvmArgs = listOf("-XX:+UseCompactObjectHeaders", "-XX:+UseShenandoahGC", "-XX:ShenandoahGCMode=generational", "--enable-final-field-mutation=ALL-UNNAMED") | ||
| } | ||
|
|
||
| distributions { | ||
| main { | ||
| contents { | ||
| from(jlink) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| tasks.named<CreateStartScripts>(ApplicationPlugin.TASK_START_SCRIPTS_NAME) { | ||
| (unixStartScriptGenerator as TemplateBasedScriptGenerator).template = resources.text.fromFile("src/main/resources/customUnixStartScript.txt") | ||
| (windowsStartScriptGenerator as TemplateBasedScriptGenerator).template = resources.text.fromFile("src/main/resources/customWindowsStartScript.txt") | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| plugins { | ||
| id('java-library') | ||
| `java-library` | ||
| } | ||
|
|
||
| repositories { | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| org.gradle.cache=true | ||
| org.gradle.configuration-cache=true | ||
| org.gradle.isolated-projects=true | ||
| org.gradle.jvmargs=-Dfile.encoding=UTF-8 |
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| plugins { | ||
| id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" | ||
| } | ||
|
|
||
| rootProject.name = "Stickerify" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| junit.jupiter.testclass.order.default=org.junit.jupiter.api.ClassOrderer$Random | ||
| junit.jupiter.testmethod.order.default=org.junit.jupiter.api.MethodOrderer$Random |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: Stickerifier/Stickerify
Length of output: 932
🏁 Script executed:
Repository: Stickerifier/Stickerify
Length of output: 6218
🌐 Web query:
Gradle ProviderFactory.provider Callable value recalculated each time queried Provider API documentation💡 Result:
Yes, a Provider created via ProviderFactory.provider(Callable) is live, meaning its Callable is invoked every time the Provider's value is queried [1][2][3]. Key details regarding this behavior: - Live Evaluation: Because the provider is live, calling methods like get or getOrNull on the provider will re-execute the logic inside the provided Callable [1][4]. - Memoization Requirement: Since the Callable is not memoized by default, if your calculation is expensive, you must manually handle caching or memoization of the result if you wish to avoid repeated execution [4]. - Configuration Cache: While the provider itself is live, its usage within the Configuration Cache has specific behaviors. The provider is always computed and its value can be cached by the Configuration Cache when applicable; if created at configuration time, the Callable is permitted to use configuration-time-only APIs and capture objects of arbitrary types [1][2]. - Workarounds: To effectively cache or memoize the result of a provider created via a Callable, developers often use a Property object, set it with the provider, and apply configuration methods such as finalizeValueOnRead to ensure the value is fixed and no longer re-evaluated upon subsequent reads [5][4].
Citations:
Resolve the fallback seed once.
When
junitSeedis unset, the live provider can return a different value for the JVM argument and thedoFirstlog. Resolve the seed once and reuse it for both.Source: MCP tools