dotenv-gradle
dotenv-gradle copied to clipboard
Problem with use cases of executing subproject's task with dotenv option by using CLI arguments
Forked from https://github.com/uzzu/dotenv-gradle/issues/39#issuecomment-1827020991
refs: https://github.com/uzzu/dotenv-gradle/issues/39#issuecomment-1466671706
I'm still working on how to make the use cases of executing subproject's task with dotenv option by using CLI arguments, but I think the following tests would be good to pass.
Now failing test case
@Test
fun changeFileWithIgnoringParentByUsingCliOptionWithCallSubProject() {
RootProject(projectDir) {
settingsGradle(
"""
include("sub")
""".trimIndent()
)
buildGradle(
"""
plugins {
id("base")
id("co.uzzu.dotenv.gradle")
}
println("[root] FOO: ${'$'}{env.FOO.value}")
""".trimIndent()
)
file(
".env.template",
"""
FOO=
""".trimIndent()
)
file(
".env",
"""
FOO=100
""".trimIndent()
)
directory("sub")
file(
"sub/build.gradle",
"""
plugins {
id("base")
}
println("[sub] BAR: ${'$'}{env.BAR.value}")
""".trimIndent()
)
file(
"sub/.env.template",
"""
BAR=
""".trimIndent()
)
file(
"sub/.env",
"""
BAR=200
""".trimIndent()
)
file(
"sub/.env.local",
"""
BAR=2000
""".trimIndent()
)
}
val result = GradleRunner.create()
.withPluginClasspath()
.withProjectDir(projectDir)
.withArguments(":sub:clean", "-Pdotenv.filename=.env.local")
.build()
assertAll {
assertThat(result.output).contains("[root] FOO: 100")
assertThat(result.output).contains("[sub] BAR: 2000")
}
}
execution log
FAILURE: Build failed with an exception.
* Where:
Build file '/private/var/folders/xxx/build.gradle.kts' line: 1
* What went wrong:
An exception occurred applying plugin request [id: 'co.uzzu.dotenv.gradle']
> Failed to apply plugin 'co.uzzu.dotenv.gradle'.
> Could not read the dotenv file specified in the gradle.properties. dotenv.filename: .env.local, path: /private/var/folders/xxx/.env.local
workaround: Use gradle.properties
(memo) Perhaps the plugin can be resolved all command line arguments by using StartParameter
logs
println(target.gradle.startParameter.toString())
StartParameter{taskRequests=[DefaultTaskExecutionRequest{args=[:sub:clean],projectPath='null',rootDir='null'}], excludedTaskNames=[], currentDir=<<omitted>>, projectProperties={dotenv.filename=.env.local}, systemPropertiesArgs={}, gradleUserHomeDir=<<omitted>>/dotenv-gradle/plugin/build/tmp/test/work/.gradle-test-kit, gradleHome=<<omitted>>, logLevel=LIFECYCLE, showStacktrace=INTERNAL_EXCEPTIONS, buildFile=null, initScripts=[], dryRun=false, rerunTasks=false, offline=false, refreshDependencies=false, parallelProjectExecution=false, configureOnDemand=false, maxWorkerCount=8, buildCacheEnabled=false, writeDependencyLocks=false, verificationMode=STRICT, refreshKeys=false}
I have created a prototype, but it has a lot of problem to resolve this plugins cofigurations.
When executing Gradle from the CLI, it's possible to specify tasks for multiple subprojects, but you can't specify -P options for each task individually. This means that you cannot specify different .env file names for each subproject you execute.
Determining the expected behavior when CLI arguments are provided is extremely challenging. Seriously, in this plugin, deciding not to support CLI arguments (like -Pdotenv.xyz=aaa) is crucial for sustainable maintenance.
I could consider supporting local.properties, but there hasn't been a demand for that so far.
I think the root cause is the use of Gradle Properties for configuration. However, it's currently unavoidable, as it provides an understandable and minimally necessary functionality for many users. The use of CLI options was unexpected.
Apart from this, until I decide to stop using Gradle Properties for configuring this plugin by facing other issues, CLI options will not be supported.
I have followed this issue and I am a bit unsure how to realize the following:
I want to develop a library that will be built in different variants. These variants all use different .env files (e.g., different server configurations or default API keys).
It used to be possible to simply set ENV_FILE=.env.variant1 ./gradlew …, with an older version of this plugin.
How else can one set a different env file to use? Editing gradle.properties is not a solution since that file is also committed to the repository; I cannot change it every time I want to build a different variant.
I have a workaround that is not very clean, but here it goes.
In my build.gradle for the library, I define some defaults:
def envLookup() {
def defaults = [
'API_ENDPOINT': 'http://10.0.2.2:3001/api/v1',
'API_KEY' : 'test',
'VARIANT' : 'default',
'SERVICE' : 'default'
]
def envLookup = [:]
defaults.each { key, value ->
envLookup[key] = env.fetch(key, value)
}
return envLookup
}
I can use this, e.g., like:
buildConfigField "String", "API_ENDPOINT", "\"${envLookup()['API_ENDPOINT']}\""
For actually building the library, I have a Bash script:
#!/bin/bash
# trap exit by restoring the original gradle.properties from Git
function cleanup {
echo "Restoring gradle.properties"
git checkout gradle.properties
}
trap cleanup EXIT
# set the envfile to use for building
envFile=$1
gradleOpts="dotenv.filename=$envFile"
# temporarily write the filename setting into gradle.properties (see: https://github.com/uzzu/dotenv-gradle/issues/39)
echo >> gradle.properties
echo "$gradleOpts" >> gradle.properties
# build
./gradlew clean
./gradlew example:assembleRelease
# any other build steps as necessary
This will overwrite the gradle.properties on the fly and restore it to the default after completion.
I'll reopen the issue aside from how to solve it.