Ask: Please provide the apiKey and apiSecret as options in the plugin-publish-plugin’s pluginBundle extension
Context:
Just integrated the plugin-publish plugin to upload my gradle plugin to the community plugin portal.
The way the plugin consumes the api key and secret makes it difficult to use on build machine line travis-ci.
Travis allows me to supply environment variables that can then be used securely in my build scripts. For example, i would add a BINTRAYKEY value in travis with the api key value. I would then supply this value to the bintray publish plugin configuration as System.env.BINTRAYKEY.
bintray {
key = System.env.BINTRAYTOKEN
.....
}
For the plugin-publish-plugin, i had to do the following due to the limitation
/**
* Grabs the values from the env and writes to a file that can be used by the plugin-publish plugin.
* This allows us define the API and secrete securely in travis-ci
*/
task setupPluginUpload << {
def file = file("build/plugin-publish-keys.properties")
def key=System.env.gradlePublishKey
def secret = System.env.gradlePublishSecret
if( !key || !secret)
{
throw new RuntimeException("gradlePublishKey and/or gradlePublishSecret are not defined environment variables")
}
def props = new Properties()
props.setProperty("gradle.publish.key", key)
props.setProperty("gradle.publish.secret", secret)
props.store(file.newWriter(), "Generated for use with plugin-publish-plugin")
// Used by the plugin-publish plugin to retrieve the keys.
System.properties.setProperty("com.gradle.login.properties.file", file.absolutePath)
}
tasks.publishPlugins.dependsOn tasks.setupPluginUpload
The Publishing Plugin is just looking for a project property with that name. If you want to use an environment variable instead you can set the property to the environment variable value using extra properties. No need to create a task to do this. In fact, this is considered configuration, which should never be done at execution time.
This is probably a better workaround for now, since it doesn’t involve creating a properties file. But it would be great if it was an option in the pluginBundle extension
task setupPluginUpload << {
def key=System.env.gradlePublishKey
def secret = System.env.gradlePublishSecret
if( !key || !secret)
{
throw new RuntimeException("gradlePublishKey and/or gradlePublishSecret are not defined environment variables")
}
System.properties.setProperty("gradle.publish.key", key)
System.properties.setProperty("gradle.publish.secret", secret)
}
tasks.publishPlugins.dependsOn tasks.setupPluginUpload
I agree that this should be settable in the pluginBundle DSL.
In the meantime, is there a reason why you can’t pass the variables through to your script using a -D argument in the .travis.yml to set the system properties? I can’t remember whether the Travis UI masks secure variables in the output. I thought it did, but can’t find an example of a build with that happening right now.
Another, much quicker way to create the properties file is to do it in the .travis.yml file itself - shell is built for this kind of thing:
This solution may work securely for Travis but not for all build systems. Jenkins, for example, provides full access to the job workspace post-build, even people without direct read-access to credential storage. From a corporate security standpoint, the credentials should never be written to any long term storage medium in unencrypted form. The easiest solution to satisfy everyone is to allow the gradle script to supply the credentials directly, then it is up to the user and their security requirements to figure out how to get them there. For many, that will be environment variables but it could be a database query or some other mechanism.