Gradle for Java and Kotlin
Prerequisites
Eligible images
|
Typically, all you need to build a project and run tests is execute the gradle build
command in the root directory of the project. There are three ways to do this in Automation:
(Basic) Build the project and run tests using the Gradle wrapper.
(Complex build scripts) Build the project and run tests using a Kotlin script.
The next task after building the project is, typically, publishing build artifacts.
(Basic) Build the project and run tests with the Gradle wrapper
The easiest way to build a Gradle project is to use the Gradle wrapper in the project root. Note that the container image must have JRE/JDK 11 or later. For example:
If the wrapper is not found, the job will fail.
Build the project and run tests with a Kotlin script
If your build script contains complex logic written in Kotlin, you should run Gradle commands using the Space Gradle API. The best practice is to use the Gradle wrapper by calling the gradlew()
function. This lets you use container images with no Gradle included (JRE/JDK is still required).
Build the project and run tests in a custom container image
In some cases, you may need to use a custom Docker image (e.g. stored in Packages) to perform the build. This scenario requires you to understand how Automation works under the hood. The main trick is to receive test run results and pass them to Automation. If you use gradlew
command to run the build (as described above), this is solved by the special test results listener initialized in init.gradle
. Thus, the bootstrap job gets an additional step: It initializes Gradle using this init.gradle
file. When you run a custom Docker container, you have to do this manually, i.e. add Gradle initialization to your Automation script:
Publish Maven artifacts to Space Packages
Open the project's
build.gradle
file.Add the reference to the Maven plugin:
apply plugin: 'maven-publish'In the
publishing
section, specify the package properties (the generated package name will begroupId:artifactId
). For example, we want to publish a .jar file (for the sake of length, the section content is reduced):publishing { publications { maven(MavenPublication) { groupId = 'org.company' artifactId = 'sample' version = "0.9-SNAPSHOT" from components.java pom { name = 'My Library' description = 'A description of my library' ... } } } }In the
publishing
section, inrepositories
, specify the repository URL and credentials using the environment variables:publishing { repositories { maven { credentials { // Automation has a special account for authentication in Space // account credentials are accessible via env vars username = "$System.env.JB_SPACE_CLIENT_ID" password = "$System.env.JB_SPACE_CLIENT_SECRET" } url = "https://maven.pkg.jetbrains.space/mycompany/p/projectkey/my-maven-repo" } } }Edit the project's
.space.kts
file. For example:job("Build and publish") { container(displayName = "Run publish script", image = "gradle") { kotlinScript { api -> api.gradle("build") api.gradle("publish") } } }
Publish Maven artifacts to external repositories
Publishing artifacts to external Maven repositories is almost the same as publishing to a Space Packages repository. The only difference is that you should store credentials to the repository in the Secrets&Parameters storage.
Repeat steps 1 – 3 from Publish Maven artifacts to Space Packages.
Create a parameter and a secret for storing the username and password that the script must use to access the external repository.
In
build.gradle
, in thepublishing
,repositories
, specify the URL of the external repository and credentials using the environment variables:publishing { repositories { maven { credentials { // we'll set these env vars in .space.kts username = "$System.env.USERNAME" password = "$System.env.PASSWORD" } url = "https://externalrepo.example.com/my-maven-repo" } } }Edit the project's
.space.kts
file. For example:job("Build and publish") { container(displayName = "Run publish script", image = "gradle") { // env vars for build.gradle env["USERNAME"] = "{{ project:repo_user }}" env["PASSWORD"] = "{{ project:repo_password }}" kotlinScript { api -> api.gradle("build") api.gradle("publish") } } }
Gradle wrapper in a custom location
By default, the project's gradlew
wrapper is located in the project's root directory. To be able to run the wrapper, Automation sets the execute flag for the gradlew
file during the job execution. If in your project, the gradlew
file is located in a different directory (for example, ./subfolder/gradlew
), Automation doesn't set the flag automatically. As a result, when Automation tries to run the wrapper, the job fails with Permission denied
. To solve the issue, follow the instructions below.
Set the execute flag for the
gradlew
file in the project sources. For example, by usinggit
(run commands in the project root):git update-index --chmod=+x ./subfolder/gradlew git commit -m "Make gradlew executable" git push origin mainIn the project's
.space.kts
file, set the location of thegradlew
wrapper as a working directory. For example:job("Run gradle build") { container(displayName = "Run gradlew from another dir", image = "gradle") { // path to gradlew relative to project root workDir = "subfolder" kotlinScript { api -> api.gradlew("build") } } }