Suppose you have different configuration files you need to include based on whether you have a local development build or a production build. Or that you want to exclude certain debug classes from the production. 1. Are there any best practices on how to organize the build? 2. What is the best way to tell gradle that it should do a dev/prod build?
The best practice (as recommended in the âContinuous Deliveryâ book) is to produce just one artifact and have a runtime switch for selecting the environment.
If you need to build different artifacts, you could do it as follows:
- Pass in the current environment as a project property (e.g. â-Penvironment=prodâ) * In the build script, first configure what is common between all environments * At the end of the build script, have a single if- or switch-statement for per-environment configuration
Taking this one step further, you could create an additional build script for each environment and apply the one for the current environment at the end of the main script. For example:
def envScript = file("gradle/$environment-env.gradle")
if (!envScript.exists()) {
throw new GradleException("Unknown environment: $environment")
}
apply from: envScript
Just came across this, also putting some dev vs prod logic in our build. There are a bunch of ways to skin this cat, but Iâm surprised how hacky they all feel. He was the evolution of my solution:
- Instead of using a project property, I wanted to create a task, called âproductionâ. If run, it would turn on/off all the stuff needed for a production build. Just add it to the list of tasks you are running. Isnât âââgradle build productionâââ nicer looking than âââgradle -Pproduction=true buildâââ? Plus, itâs easier to remember, self-documenting (âââgradle tasksâââ), etc.
Unfortunately I couldnât work out the order in which things were configured and executed. Right now, all the production build does is set a couple properties differently, but I couldnât find a clean way of having those properties set before all the other tasks.
- Next iteration, I tried using a plain project property, called âdebugâ. If debug is true, do some stuff, else do some other stuff. A couple things are inelegant about this though: first, to set a default value for debug, I canât just do:
debug :? true
âŚbecause you get âno such propertyâ errors. You have to do:
if(!hasProperty(âdebugâ)) debug = true else debug ?: true
or something like that. Sort of wordy.
The other issue is that in my scripts, I treat debug like a boolean. I assign it a boolean value as the default. But I canât pass booleans values on the command line. âââgradle -Pdebug=falseâââ results in debug getting set to the string âfalseâ, not to boolean false. So later, when I test the flag:
someVar = debug ? âdevâ : âprodâ
âŚthe test doesnât work. groovy truth for a string is non-null/empty, so âfalseâ is true.
Again, all easily solved problems, but it feels harder than it should be. I would think passing on/off flags to a build would be a pretty common use case.
I have another example that is quite probably related: Excludes by configuration donât work either with eclipse-wtp (using gradle version 1.2). For excludes by dependency (see commented lines below) eclipse-wtp behaves as expected.
With SpringSource inlining a class-incompatible spring-asm into spring-core with version 3.2.0.M2 pretty soon there might be a good amount of gradle-users interested in this:
apply plugin: 'java'
apply plugin: 'eclipse-wtp'
apply plugin: 'war'
repositories {
mavenCentral()
}
configurations {
runtime.exclude module:'spring-asm'
}
dependencies {
runtime
'org.springframework:spring-beans:3.1.2.RELEASE'
//
runtime
('org.springframework:spring-beans:3.1.2.RELEASE') {
//
exclude module:'spring-asm'
//
}
testCompile
'junit:junit:4.10'
}
All excludes in this example have an effect on .classpath. Only the commented exclude has an effect on .settings/org.eclipse.wst.common.component.
Iâm also interested in this.
While setting properties via command-line arguments works, Iâd echo Russâ first point. In my case, different environments involves slight alterations to compilation arguments. Iâd be interested in learning more about whatâs considered best practice is in this case, but a âruntime switchâ doesnât seem to be an option?
Looking at Gradleâs own build, it seems its now using its own solution to this using âBuildTypesâ. Thereâs some discussion around that here. Is that a forthcoming feature?
Iâm also interested in this.
While setting properties via command-line arguments works, Iâd echo Russâ first point. In my case, different environments involves slight alterations to compilation arguments. Iâd be interested in learning more about whatâs considered best practice is in this case, but a âruntime switchâ doesnât seem to be an option?
Looking at Gradleâs own build, it seems its now using its own solution to this using âBuildTypesâ. Thereâs some discussion around that here. Is that a forthcoming feature?
As to #1, canât you just check to see if the production task is enabled wherever youâre doing the production-dependent configuration?
You can use one of these plugins to solve this problem: https://bitbucket.org/AlexanderBartash/gradle-environments-plugin/wiki/Home https://github.com/marceloemanoel/gradle-environments-plugin