Profiles - pford68/gradle-examples GitHub Wiki

Background

Gradle does not natively support profiles. They are easy to implement:

  1. You could use project properties, then if-thens applying different profile Gradle files.
  2. You could use domain objects in the Gradle file.1

However, especially in the case of plugins, Gradle is not really supposed to work that way. Instead of creating one configuration and making decisions or setting values based on profiles, you should configure plugins that do 90% of what you need, then create separate tasks for alternatives.

Plugins and Tasks

Plugins should be designed so that they can be configured for, say, 80% of the cases in one extension, then for the other 20% of cases, create separate tasks with different configurations.2 This does not neessarily negate the need for profiles, but a cleaner way to approach the problem is to have one base plugin configuration in your Gradle file, which you override in various tasks geared toward various environments:

libertyDeployer {
    trustStore = "/users/functionalUser/local/ssl-key.jks"
    trustStorePassword = "${project.trustStorePassword}"
    user = "****"
    password = "${project.libertyPassword}"
    hostName = "****"

    deploy {
        artifact = file("${libsDir}/${app}.war")
        contextRoot = "/${app}"
    }
}
task local(type: DeployTask){
    description 'Deploys to a local server.  Edit for your environment.'
    trustStore = "/Users/paford/local/my-ssl-key.jks"
    hostName = "localhost"
    httpsPort = 12443
}
task dev(type: DeployTask){
    description 'Deploys to the integration server'
    httpsPort = 12443
}
task productionWest(type: DeployTask){
    description 'Deploys to production instance on the west zone'
    httpsPort = 10443
}
task productionEast(type: DeployTask){
    description 'Deploys to production instance on the east zone'
    httpsPort = 20443
}

There may be cases, however, with 3pty plugins where the task/plugin design does not allows this. In cases where you have one extension or one configuration, you do have to use profiles.

Notes

  1. See this article and this one.

    • The importance of this technique transcends profiles.

    • I like the implementation in the second article best of all.

      // File: build.gradle
      loadConfiguration()
      
      task printProps << {
         println "serverName:  $config.serverName"
         println "mail.server: $config.mail.server"
         println "mail.port:   $config.mail.port"
      }
      
      def loadConfiguration() {
         def environment = hasProperty('env') ? env : 'dev'
         setProperty 'environment', environment
         println "Environment is set to $environment"
      
         def configFile = file('config.groovy')
         def config = new ConfigSlurper(environment).parse(configFile.toURL())
         setProperty 'config', config
      }
      
      // File: config.groovy
      mail {
        server = 'localhost'
        port = 25
      }
      
      environments {
          dev {
              serverName = 'http://localhost:9090'       
          }
      
          test {
              serverName = 'http://testserver'
              mail {
                  server = 'mail.testserver'
              }
          }
      
          prod {
              serverName = 'http://www.mrhaki.com'
              mail {
                  port = 552
                  server = 'mail.host.com'
              }
          }
      }
      
  2. https://discuss.gradle.org/t/can-multiple-extensions-be-used-to-configure-additional-instance-of-a-task/5703

Often plugins target the 80% case where a behavior is just needed once. For the remaining 20%, users can drop down to the task level and configure another task manually.

References