How can I reference a Travis secure variable in my build.gradle? - gradle

One of my project dependencies sits on a private Bintray repo, which requires a username and password to access. Locally, I have these set in my gradle.properties:
bintrayUsername=<myUserName>
bintrayPassword=<myPass>
This works (locally), where hasProperty(X) resolves true and it uses this property:
allprojects {
repositories {
jcenter()
def mahBintrayUsername = hasProperty(bintrayUsername) ? bintrayUsername : System.getenv('bintrayUsername')
def mahBintrayPassword = hasProperty(bintrayPassword) ? bintrayPassword : System.getenv('bintrayPassword')
maven {
credentials {
username mahBintrayUsername
password mahBintrayPassword
}
url 'http://dl.bintray.com/my-repo-org/maven-private'
}
}
}
On Travis, I use secure variables so I don't have to expose these values in my public repo, but with the aim of being able to build directly from my public repo. When the build starts, you can see that the variables are exported:
Setting environment variables from .travis.yml
$ export bintrayUsername=[secure]
$ export bintrayPassword=[secure]
$ export TERM=dumb
...
FAILURE: Build failed with an exception.
* Where:
Build file '/home/travis/build/ataulm/wutson/build.gradle' line: 15
* What went wrong:
A problem occurred evaluating root project 'wutson'.
> Could not find property 'bintrayUsername' on repository container.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
I'm unsure how to reference the exported environment variables in my build.gradle such that they would be found.
I've checked this answer which doesn't seem to work (as above), as well as this comment which results in the same build failure.
The series of commits I've tried can be seen here, with the latest: https://github.com/ataulm/wutson/commit/9331b8d91b4acf11fd3e286ff8ba1a24ed527177

The error is a result of your ternary statement attempting to evaluate bintrayUsername as part of the condition.
The hasProperty() method takes a String argument so you should use hasProperty('bintrayUsername'), instead of hasProperty(bintrayUsername). Doing the latter will attempt to evaluate a property that may not exist, leading to the MissingPropertyException.
Simply remember that trying to evaluate any symbol that doesn't exist will typically result in a MissingPropertyException.

Below an example to define a project property -not a local variable- if it is not defined, by getting the value from the Environment, i.e. where Travis puts your secure variable.
project.ext {
if (! project.hasProperty('some_prop')) {
some_prop = System.getenv('some_prop')
}
}
If you never set it as a property (not using gradle.properties files) and you always want to set it from the environment, just remove the IF part. :)
Note: I wanted a project property so I can use it also to set values in my spring-boot YAML file... both locally and in CI.

Related

How to configure Dokka for package documentation using Gradle?

I am unable to configure Dokka to include the documentation of my packages without using a full absolute path from the root of the file system. I have in my Gradle file (the includes line is the one in problem):
dokka {
outputFormat = 'html'
outputDirectory = "$projectDir/../doc"
configuration {
// Use to include or exclude non public members.
includeNonPublic = false
// Do not output deprecated members. Applies globally, can be overridden by packageOptions
skipDeprecated = false
// Emit warnings about not documented members. Applies globally, also can be overridden by packageOptions
reportUndocumented = true
// Do not create index pages for empty packages
skipEmptyPackages = true
includes = ["${projectDir}/app/src/main/kotlin/com/biexpertise/simplewebview/packages.md"]
}
}
When, I run ./gradlew dokka if I have this error:
> Task :app:dokka FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:dokka'.
> org.codehaus.groovy.runtime.GStringImpl cannot be cast to java.lang.String
If I remove $projectDir and use an absolute path, things are working. It is possible to use a relative path instead?
So that's in fact a problem with dokka's Gradle plugin, or to be more specific, with Groovy String implementation. Groovy uses it's own GStringImpl for strings, instead of the String class, which leads to a problem when casting a List<GStringImpl> to List<String> (this cast doesn't succeed).
The easiest solution is to call .toString() on your include, like this:
includes = ["${projectDir}/app/src/main/kotlin/com/biexpertise/simplewebview/packages.md".toString()]
This should be fixed on the dokka side though, you can file a bug report on GitHub

How to define Gradle project properties with Kotlin DSL

I'd like to check if two project properties are set and if not, set them to empty values in order to avoid a build failure. These properties are supposed come from ~/.gradle/gradle.properties (if configured).
The goal is to have credentials to a Maven repository in S3 defined in that local file. Every user has to put his own data there, but I want the build to just output a warning and continue if these are not set. Chances are high it will still be successful even without contacting S3.
I have got it running with Groovy DSL, but I am now switching to Kotlin and I just can't get the syntax right.
This is how ~/.gradle/gradle.properties looks like:
s3AccessKeyId=ABCDEFGHIJKLMNOPQRST
s3SecretKey=abcdefghijklmnopqrstuvwxyz1234567890abcd
And here are the relevant sections of the build.gradle.kts
if (!project.hasProperty("s3AccessKeyId") || !project.hasProperty("s3SecretKey")) {
logger.lifecycle("WARNING: s3AccessKeyId and s3SecretKey not set!")
project.extra["s3AccessKeyId"] = ""
project.extra["s3SecretKey"] = ""
}
repositories {
mavenLocal()
maven {
url = uri("s3://maven-repo.mycompany.com.s3.eu-central-1.amazonaws.com/")
credentials(AwsCredentials::class) {
accessKey = project.extra["s3AccessKeyId"].toString()
secretKey = project.extra["s3SecretKey"].toString()
}
}
}
No matter how I write the s3AccessKeyId="" lines, I am always getting the error:
Cannot get property 's3AccessKeyId' on extra properties extension as it does not exist
If all artifacts are found in the local Maven repository, I expect the build to work, even without gradle.properties. Only if some artifact is missing, the build should abort with some "credentials wrong" error.
As I said, it already worked with Groovy.
For that you need to use the properties attibute which is different from the extra like:
project.properties["s3SecretKey"].toString()
And then you need to have in your gradle.properties:
s3AccessKeyId=ABCDEFGHIJKLMNOPQRST
If the value is not there it might return null so you can do:
(project.properties["s3SecretKey"] ?: "default value").toString()
And it should work

Build Gradle getProperties before running already made task

I’m trying to use a Java, Serenity-BDD project with gradle version 4.8+, but the application is not pulling the CLI arguments of -Denvironment and -Dservicebranches. I have these properties as blank values in my local.properties file, and they’re not getting assigned when my app runs.
./gradlew --build-cache build -Dwebdriver.remote.url=${SELENIUM_REMOTE_URL} -Denvironment=${ENVIRONMENT} -Dservicebranches=${SERVICE_BRANCHES} -Dtags=${TAGS}
I have a local.properties file with properties that are being successfully dependency injected into the project (through Serenity-Spring). I'm hoping that these CLI arguments will override these values:
servicebranches=
environment=local
But right now, anything specified in the CLI arguments are not being passed into the project. Either through DI, or through explicitly grabbing the environment variables in the build.gradle, which what I've tried hasn't been working.
Here's a few things which I have tried in the build.gradle:
//task integrationTests() {
// doFirst
// {
// def environment = System.getProperty('environment')
// def servicebranches = System.getProperty('servicebranches')
// }
// tasks.build.execute()
//}
//integrationTests.dependsOn(build)
//build.doFirst{
// systemProperties System.properties
// def environment = System.properties['environment']
// environment = environment //This actually flags with 'Silly assignment'
//}
build.doFirst{
def environment = System.getProperty('environment')
def servicebranches = System.getProperty('servicebranches')
}
The latest one seems to still be missing a step, because the program is still working, but the args are still not getting through. I've even tried -Denvironment=potato, and no errors have come up because I do not have a property or properties file named that.
I've also tried using the -P tag instead of -D tag, but that doesn't seem to be working either.
All I’m trying to do is use build.gradle to use System.getProperty(‘environment’) and System.getProperty(‘servicebranches’) before I use the already created ‘build’ task that comes with Serenity. How would I do this? Do I build a whole new task, where I use these getProperties, and then call the build task? Do I have to specify the assignment of these same named variables in the local.properties file?
-D is for system properties in Gradle. Try with -P instead (https://docs.gradle.org/current/userguide/build_environment.html#sec:project_properties)
I know this is a very old question but here's what I did to solve my problem, I got the idea from here: https://github.com/serenity-bdd/serenity-documentation/pull/120/files
Serenity was not pulling the environment from gradle to use EnvironmentSpecificProperties, it kept saying "undefined property for environment 'null" when I removed the default environment. I had to add this to my Gradle file:
test {
systemProperty 'environment', System.properties['environment']
}

Cloning a git repo in a task by providing authentication

I want to clone a private repository in my system. I am able to clone a public repo using:
def myrepo = org.ajoberstar.grgit.Grgit.clone(dir:'', uri:'')
but in case of a private repo, I need to provide credentials to clone. I have gone through this link, but the properties given here like Force, Hardcoded are not available in my gradle. So, I am not able to make use of the properties given here.
The following properties are available for me:
org.ajoberstar.grgit.auth.AuthConfig.FORCE_OPTION
org.ajoberstar.grgit.auth.AuthConfig.USERNAME_OPTION
org.ajoberstar.grgit.auth.AuthConfig.PASSWORD_OPTION
and if I give any value to these, I get error Cannot assign value to final fields
Can anybody help with the authentication part?
I am using dependency org.ajoberstar:grgit:1.3.0.
The link you provided clearly states that system properties need to be used to pass appropriate settings.
So you need to run gradle passing all the properties via command line. Assume this is build.gradle file:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.ajoberstar:grgit:1.3.0'
}
}
task cloneRepo << {
org.ajoberstar.grgit.Grgit.clone(dir: '', uri: '<link to private repo>')
}
Run it with:
gradle cloneRepo -Dorg.ajoberstar.grgit.auth.username=your_username -Dorg.ajoberstar.grgit.auth.password=your_pass -Dorg.ajoberstar.grgit.auth.force=sshagent

Passing properties to a gradle build

I admit I am quite new to gradle but I did not expect to be unable to understand something as simple as the example below. I can read the gradle documentation about checking whether a project property have been set or not using a hasProperty(String propertyName) call and I am sitting here and have no idea why something so basic does not work.
I believe my mind must be so much "ant like" oriented that for sure I am missing something ordinary basic
task printSystem() << {
println system
println "has property: " + hasProperty("system")
}
and invoking that task with the command below:
$gradle printSystem -Psystem=mySystem
mySystem
has property: null
So my questions would be:
Why system is printed out but hasProperty returns null?
How should I check for the existence of the project property called "system"?
Is there a different way for testing for a project property as opposed to a system property?
How would you pass a system property from the command line?
This is from, the gradle documentation and I believe I am reading it right
19.2.1. Checking for project properties
You can access a project property in your build script simply by using its name as you would use a variable. If this property does not exist, an exception will be thrown and the build will fail. If your build script relies on optional properties the user might set, perhaps in a gradle.properties file, you need to check for existence before you access them. You can do this by using the method hasProperty('propertyName') which returns true or false.
You need to explicitly invoke hasProperty on the project instance - without it, hasProperty is invoked on some local context. The following example works:
task printSystem() << {
println system
println "has property: " + project.hasProperty("system")
}
Because non-existing properties (system is not defined in the script) are taken from the project instance. If you won't pass the system property, an exception will be thrown on println.
project.hasProperty('propName')
Not sure if I understood right, but you can access project properties via the project instance and system properties via the System class.
Using -D switch - gradle -Dprop=value

Resources