This README documents best practices around using Gradle in Gitpod. For the orignal Elasticseatch readme, see README-es.
Gradle may take some time to build your project. IntelliJ may take some time to index your project. To not wait for either, you may want to run Gradle and "IntelliJ warmup" in Gitpod's prebuild. Do do so:
- Create "Repository Settings" for you repo in Gitpod and enable prebuild.
- Run Gradle as
init
task and enabled intellij prebuilds via.gitpod.yaml
:
tasks:
- init: |
./gradlew build
jetbrains:
intellij:
prebuilds:
version: stable
While this generally enables prebuilds, please read the following sections of this document to ensure everything runs smoothly.
Context: Gitpod backs up all files from /workspace
when a workspace stops or when a prebuild finishes. Files outside this directly are not persisted. This affects Gradle, because, by default, Gradle persists files (e.g. downloaded dependencies) outside /workspace
.
# Ensure that Gradle saves all files in /workspace, because files outside that folder are not being backed up when a prebuild finishes or a workspace stops.
ENV GRADLE_USER_HOME=/workspace/.gradle/
# Ensure that Maven dependencies are saved in /workspace, because files outside that folder are not being backed up when a prebuild finishes or a workspace stops.
RUN mkdir /home/gitpod/.m2 && \
printf '<settings>\n <localRepository>/workspace/m2-repository/</localRepository>\n</settings>\n' > /home/gitpod/.m2/settings.xml
Gitpod's workspace-*
images already contain this configuration. If you use your own base image, please add it to your Dockerfile.
To find files are are being created or modified outside /workspace
, you can use the following method:
- First, we create a marker file. This is helpful to later find all files that are newer than this file. Example:
touch /workspace/starttime.txt
- Run your scripts or Gradle Build.
- List all files that are newer than than marker file:
find / -xdev -type f -newer /workspace/starttime.txt > /workspace/lostfiles_$(date +"%Y%m%d_%H%M%S").txt
The above example stores the resulting list in a file. This is hepful to run the command at the end of a prebuild and inspect the result in a debug workspace.
See here for the full example.
Context: By default, Gitpod simulates and interactive terminal for processes during prebuilds. However, For Gradle there can be compatibility issues that lead display errors. To avoid these troubles, please use this easy way as marking the terminal as non-interactive when the init task runs in a prebuid. Example:
if [ "$GITPOD_HEADLESS" = "true" ]; then
export TERM=dumb
fi
# run standard gradle build
./gradlew build
See here for the full example.
Context: IntelliJ may automatically trigger a "Gradle Sync" to import all Gradle projects on workspace start. For large projects this can slow down the workspace start. The "Gradle Sync" on workspce start should be unnecessary if you have IntelliJ "Warmup" running in your prebuilds.
To not have the Gradle Sync running on workpsace start, please:
- Ensure that your prebuild generates the
.idea/gradle.xml
file so IntelliJ is aware of your Gradle projects. This should happend during "IntelliJ warmup" in your prebuild, or you have the file committed to git. - Add code that temporarily disables "Reload project changes in the build scripts" under "Settings" -> "Build, Execution, Deployment" -> Build Tools". Example
.gitpod.yml
:
tasks:
- init: |
# disable Gradle auto-reload in IntelliJ
xmlstarlet ed --inplace -u '//option[@name="autoReloadType"]/@value' -v 'NONE' .idea/workspace.xml
# run standard gradle build
./gradlew localDistro
command: |
# re-enable Gradle auto-reload in IntelliJ
xmlstarlet ed --inplace -u '//option[@name="autoReloadType"]/@value' -v 'SELECTIVE' .idea/workspace.xml
See here for full example.
Sometimes the log output of Gradle is not enough to understand what really happend. This is particualrly true when Gradle is being invoked automatically, for example from a Gitpod prebuild or from IntelliJ during sync or warmup.
Gradle build scans provide a trove of insights: Gradle will upload a detailed report of the build to gradle.com and provide you with a URL to inspect the repos. yes, you'll need to accept Gradle's ToS to give permission to upload the report to gradle.com. Giving permission is usually an interactive process, but with the following confuguration you can enabled build scans by default, so that you'll get scans for prebuilds and IntelliJ warmups:
gradleEnterprise {
buildScan {
// Accept the terms of service automatically
termsOfServiceUrl = 'https://gradle.com/terms-of-service'
termsOfServiceAgree = 'yes'
// Always publish a build scan without requiring --scan
publishAlways()
}
}
See here for the full example.
Unfortunately, we've had cases in which the IntelliJ warmup process never finished and thus the Gitpod prebuild timed out after one hour. Here are scripts to troubleshoot this situation:
- tracer.sh: Dump Java Stack traces and Linux Process Tree. This helps to understand what process Gitpod waits for, and, if it's a Java process, what the process is doing.
- record.sh: Automatically run Java Flight Recorder on JVM processes.
- timeout.sh: Terminate processes at a defined timepout to avoid running into the Prebuild timeout.
See this example on how to add the scripts to your .gitpod.yaml
:
# configure Gradle and start tracing scripts
mkdir -p /workspace/.gradle
printf "org.gradle.jvmargs=-Xmx6g\norg.gradle.daemon=true\norg.gradle.parallel=true\n" > /workspace/.gradle/gradle.properties
mkdir -p /workspace/jvm_debug
nohup ./tracer.sh > /workspace/jvm_debug/tracer.log 2>&1 &
nohup ./record.sh > /workspace/jvm_debug/record.log 2>&1 &
nohup ./timeout.sh> /workspace/jvm_debug/timeout.log 2>&1 &
Once a prebuild has finished, we should be able to open a “debug workspace” on the prebuild and find detailed tracing in /workspace/jvm_debug/.