Environment Variables (In Gradle)
Environment Variables:
- These are properties defined outside of Gradle (in the environment) and can be accessed using
System.getenv()
. Note: Environment Variables are #not-tracked-by-gradle .
Example:
export MY_ENV_VAR="some_value"
gradle build
Access in build script:
val envVar = System.getenv("MY_ENV_VAR")
println("Environment variable: $envVar")
Not tracked by gradle
Not tracked by gradle
Environment variables are NOT automatically tracked by Gradle. This means that changes to environment variables won’t trigger tasks to be re-executed, and they won’t be considered in Gradle’s up-to-date checking or incremental build system.
Why Environment Variables Aren’t Tracked:
- Gradle’s incremental build support is based on its ability to track task inputs and outputs, such as files or task properties explicitly defined within the build script.
- Environment variables exist outside of Gradle’s scope, so it doesn’t automatically know about changes to them. As a result, tasks depending on environment variables can still be considered up-to-date even if the environment variables change.
Example: Environment Variable is not Tracked
Glass thought Sandbox Snapshot & Explanation
In this example we will run the following shell, which will vary the environment variable MY_ENV_VAR
between two values and run the task saveEnvVarToFile
which writes the environment variable to a file.
export MY_ENV_VAR=HI4 \
&& ./gradlew saveEnvVarToFile --console=plain \
&& cat ${GLASSTHOUGHT_SANDBOX:?}/lib/build/output.txt \
&& export MY_ENV_VAR=HI5 \
&& ./gradlew saveEnvVarToFile --console=plain \
&& cat ${GLASSTHOUGHT_SANDBOX:?}/lib/build/output.txt
This is the gradle task that writes the environment variable to a file:
tasks.register("saveEnvVarToFile") {
val envVar = System.getenv("MY_ENV_VAR")
// Without declaring the property as input and relying on env variable.
// inputs.property("MY_ENV_VAR", envVar)
outputs.file("build/output.txt") // Output file
doLast {
val outputFile = file("build/output.txt")
outputFile.writeText("Environment property: $envVar \n")
println("Environment variable: $envVar")
}
}
Notice that we have explicitly commented out the inputs.property("MY_ENV_VAR", envVar)
line, which would have declared the environment variable as a task input. Now when we run the 2nd run even though the environment variable has changed, the task is still considered up-to-date.
Command to reproduce:
gt.sandbox.checkout.commit 5b726c5 \
&& cd "${GT_SANDBOX_REPO}" \
&& cmd.run.announce "export MY_ENV_VAR=HI4 && ./gradlew saveEnvVarToFile --console=plain && cat ${GLASSTHOUGHT_SANDBOX:?}/lib/build/output.txt && export MY_ENV_VAR=HI5 && ./gradlew saveEnvVarToFile --console=plain && cat ${GLASSTHOUGHT_SANDBOX:?}/lib/build/output.txt"
Recorded output of command:
> Task :lib:saveEnvVarToFile UP-TO-DATE
BUILD SUCCESSFUL in 424ms
1 actionable task: 1 up-to-date
Environment property: HI4
> Task :lib:saveEnvVarToFile UP-TO-DATE
BUILD SUCCESSFUL in 337ms
1 actionable task: 1 up-to-date
Environment property: HI4
Workaround: Manually Declare Environment Variables as Inputs
If you want Gradle to consider environment variables when determining whether a task is up-to-date, you can declare them as task inputs. This way, Gradle will re-execute the task when the environment variable changes.
Example: Tracking an Environment Variable as a Task Input
tasks.register("saveEnvVarToFile") {
val envVar = System.getenv("MY_ENV_VAR")
// Declare the environment variable as input:
inputs.property("MY_ENV_VAR", envVar)
outputs.file("build/output.txt") // Output file
doLast {
val outputFile = file("build/output.txt")
outputFile.writeText("Environment variable saved in file: $envVar \n")
println("Environment variable: $envVar")
}
}
Glass thought Sandbox Snapshot & Explanation
Now when we run
export MY_ENV_VAR=HI4 \
&& ./gradlew saveEnvVarToFile --console=plain \
&& cat ${GLASSTHOUGHT_SANDBOX:?}/lib/build/output.txt \
&& export MY_ENV_VAR=HI5 \
&& ./gradlew saveEnvVarToFile --console=plain \
&& cat ${GLASSTHOUGHT_SANDBOX:?}/lib/build/output.txt
The task will re-execute when the environment variable changes.
Command to reproduce:
gt.sandbox.checkout.commit 18b8810 \
&& cd "${GT_SANDBOX_REPO}" \
&& cmd.run.announce "export MY_ENV_VAR=HI4 && ./gradlew saveEnvVarToFile --console=plain && cat ${GLASSTHOUGHT_SANDBOX:?}/lib/build/output.txt && export MY_ENV_VAR=HI5 && ./gradlew saveEnvVarToFile --console=plain && cat ${GLASSTHOUGHT_SANDBOX:?}/lib/build/output.txt"
Recorded output of command:
> Task :lib:saveEnvVarToFile
Environment variable: HI4
BUILD SUCCESSFUL in 350ms
1 actionable task: 1 executed
Environment variable saved in file: HI4
> Task :lib:saveEnvVarToFile
Environment variable: HI5
BUILD SUCCESSFUL in 342ms
1 actionable task: 1 executed
Environment variable saved in file: HI5
Gotcha
The gotcha with this approach is that we need to know which tasks depend on which environment variables and declare them as inputs manually.
Key Points:
- Environment variables are not tracked by default, so changes to them won’t trigger task re-execution.
- To ensure a task re-executes when an environment variable changes, declare the environment variable as a task input using
inputs.property()
. - By declaring it as an input, Gradle will treat the environment variable as part of the task’s state and include it in the up-to-date checks.
Conclusion:
While Gradle doesn’t automatically track environment variables, you can make Gradle aware of them by manually declaring them as task inputs. This ensures that tasks depending on environment variables will re-run when those variables change.
Children
Backlinks