Custom Wrapper Distribution with gradle.properties


(Seoras Ray) #1

I have created a custom wrapper distribution and inserted an init.gradle script into it. This works as expected, however I also need to include a gradle.properties file and this is not working as expected. It doesn’t seem to matter where I place the properties file within the wrapper distribution zip, it never gets processed when the wrapper runs.

Could someone tell me how to include properties files in the distribution?

Thanks!


(Dmitriy Voronin) #2

Bump!
Still no answer here. I’m also interested in this case.
Also, is there any way to share some property between init.scripts in custom gradle wrapper? For example: company repository url.


(Seoras Ray) #3

I’ll share my workaround, but it’s hardly ideal:

In my init.gradle script I use an allprojects block to set properties on all projects. Something like the following:

allprojects { project ->
    project.ext.local_artifactory_contextUrl = 'http://something.something'
    ...
}

Unfortunately that is not good enough for the properties used by the credentials plugin. This looks for an actual file that it reads in on launch. So I still needed to in include an actual gradle.properties file with my distribution. For that I included the following code in my init.gradle:

import java.nio.file.Files
import java.nio.file.Paths
import java.nio.file.StandardCopyOption

def params = gradle.getStartParameter()
def gradleDir = params.getGradleUserHomeDir()
def files = [
  ['gradle.encrypted.properties.in', "${gradleDir}/gradle.encrypted.properties"]
]

// Check bundled files with any previously deployed files. If they don't exist of they aren't the same
// then copy the bundled files over and replace them.
files.each { pair ->
  def source = new File(pair[0])
  def target = new File(pair[1])

  def sourcePath = Paths.get(uri(source))
  def targetPath = Paths.get(target.getAbsolutePath())
 
  source = new File(sourcePath.toString())
  if (source.exists() && (! target.exists() || ! Arrays.equals(Files.readAllBytes(sourcePath), Files.readAllBytes(targetPath)))) {
    println "Copying ${source} to ${target}"
    Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING)
  }
}

This code block looks in an Array for files to copy and copies them into the Gradle Home Directory if they don’t already exist or if they exist but don’t match (i.e. there is an updated version in a newer distribution).

It works, but it’s ugly as sin. Hopefully there will be a Gradle native mechanism for doing this soon, or somebody will chime in with a better method.

Seoras.


(Stefan Oehme) #4

Putting property files in the distribution is not supported. Instead, you can use extension properties as you showed. Property files are meant for things that vary from project to project or from user to user. If it’s the same on every invocation, then hardcoding them in the init script works just as well.

As for the credentials plugin (which is a community plugin, not part of Gradle core): Sharing credentials as part of a Gradle distribution seems like a big security risk to me. They are placed in the user home for good reason.


(Seoras Ray) #5

Thanks for the response Stefan, much appreciated.

I don’t disagree with your note on security risks, but in our case the user home directory is part of an ephemeral Docker container. We could have embedded the files in the Docker image but having them in the Gradle distribution made them easier to update and guarantee that the devs wouldn’t be involved. We have had to work really hard on getting the Gradle barrier to entry down as we are a native shop and people are used to cmake/make. I am open to better suggestions though!


(Stefan Oehme) #6

I understand your concern, but the plugin you are referring to is not part of Gradle, so we couldn’t change it even if we wanted to. You could of course open a feature request for that plugin, but I doubt whether that would be considered a valid use case. Putting this property file in a docker image sounds like a perfectly fine solution. What’s the downside?


(Seoras Ray) #7

Hi Stefan,

The biggest downside was getting users to update their Docker images (manually or via bundled ‘build’ shell script). By bundling the properties file inside the distribution they don’t have to do anything to get the latest creds.

The secondary issue was that we don’t set a USER in the image. Users did not like having to continually chown the build artifacts or source files. Setting --gradle-user-home caused the distribution to get downloaded twice, as gradlew ignores it and uses ~/.gradle and then gradle proper uses it but there is nothing there.

I think ultimately I was hoping Gradle would simply take whatever files were bundled in the distribution and dump them into the home directory, without limiting these to .gradle or .properties etc.


(Stefan Oehme) #8

I don’t quite understand that. The distribution should only be downloaded once.

There’s a big difference here: The Gradle home (where the distribution lives) and the Gradle User Home (where properties, caches etc. live). If those were somehow mixed together, users could no longer use different versions of Gradle with the same settings.

As for your concrete problem: You might want to create a feature request to control the location of the encrypted properties in the credentials plugin. That would be more flexible than a hardcoded “look in the distribution dir”.