How and when to access in Gradle a property? - gradle

I have the following in build.gradle:
PlatformUmbrella platformUmbrella = PlatformUmbrella.create(System.properties['module.status'])
task setClBeforePublish << platformUmbrella.beforePublish
project.tasks.publish.doLast platformUmbrella.afterPublish
and gradle.properties has module.status = snapshot``gradlew properties outputs:
module.status: snapshot
But when either System.properties['module.status'] or gradle.properties['module.status'] is retrieved, null is returned (presumably because properties haven't been processed yet). Accessing gradle.properties['module.status'] inside a gradle.taskGraph.whenReady closure also returns null. What's the right way to access the 'module.status' setting?

Contents of gradle.properties will be automatically loaded into the project's "extra" properties extension, which are accessed via project.ext.
In your case, try project.ext["module.status"] instead.

Related

Xamarin.Android - How do you set the MONO_GC_PARAMS environment variable

How do you set the value of this environment variable in Mac OSX? I tried creating an environment.txt file in my Xamarin.Android project with a build action of AndroidEnvironment, but when I check my diagnostic build output, I still see this:
MONO_GC_PARAMS = major=marksweep-conc
I didn't set that value - it must be the default, but I can't find where it's stored or how to change it. Thank you.
These items need to be on a single line with commas seperating the parameters. i.e. MONO_GC_PARAMS=bridge-implementation=tarjan,nursery-size=128‌​m,soft-heap-limit=51‌​2m,major=marksweep-c‌​onc
This will be picked up via the following code:
if (lineToWrite.StartsWith ("MONO_GC_PARAMS=", StringComparison.Ordinal))
haveMonoGCParams = true;
You should be able to set this item if you have the Use the concurrent garbage collector (Experimental) enabled in your project settings. This definition will be added to your .csproj:
<AndroidEnableSGenConcurrent>true</AndroidEnableSGenConcurrent>
This will set the following parameter to Mono:
if (!haveMonoGCParams) {
if (EnableSGenConcurrent)
environment.WriteLine ("MONO_GC_PARAMS=major=marksweep-conc");
else
environment.WriteLine ("MONO_GC_PARAMS=major=marksweep");
}
Source
However I believe only two options are available via this logic. Either marksweep or marksweep-conc.

Cannot have different system properties values for different tasks

I am trying to create 2 tasks to execute the sonarcube task. I want to be able to specify different properties depending on the task
task sonarqubePullRequest(type: Test){
System.setProperty( "sonar.projectName", "sonarqubePullRequest")
System.setProperty("sonar.projectKey", "sonarqubePullRequest")
System.setProperty("sonar.projectVersion", serviceVersion)
System.setProperty("sonar.jacoco.reportPath",
"${project.buildDir}/jacoco/test.exec")
tasks.sonarqube.execute()
}
task sonarqubeFullScan(type: Test){
System.setProperty("sonar.projectName", "sonarqubeFullScan")
System.setProperty("sonar.projectKey", "sonarqubeFullScan")
System.setProperty("sonar.projectVersion", serviceVersion)
System.setProperty("sonar.jacoco.reportPath",
"${project.buildDir}/jacoco/test.exec")
tasks.sonarqube.execute()
}
The tasks work but there seems to be an issue with the properties I am setting
if I run the first task which is sonarqubePullRequest then everything is fine, but if run sonarqubeFullScan then if uses the values specified in the sonarqubePullRequest. so the project name is set sonarqubePullRequest
it is as if those properties are set at run time and cannot be updated. I feel like I am missing something obvious any suggestions greatly received.
First of all: NEVER use execute() on tasks. The method is not part of the public Gradle API and therefor, its behaviour can change or be undefined. Gradle will execute the tasks on its own, either because you specified them (command line or settings.gradle) or as task dependencies.
The reason, why your code does not work, is the difference between the configuration phase and the execution phase. In the configuration phase, all the (configuration) code in your task closures is executed, but not the tasks. So, you'll always overwrite the system properties. Only (internal) task actions, doFirst and doLast closures are executed in the execution phase. Please note, that every task is only executed ONCE in a build, so your approach to parametrize a task twice will never work.
Also, I do not understand why you are using system properties to configure your sonarqube task. You can simply configure the task directly via:
sonarqube {
properties {
property 'sonar.projectName', 'sonarqubePullRequest'
// ...
}
}
Now you can configure the sonarqube task. To distinguish between your two cases, you can add a condition for different property values. The next example makes use of a project property as condition:
sonarqube {
properties {
// Same value for both cases
property 'sonar.projectVersion', serviceVersion
// Value based on condition
if (project.findProperty('fullScan') {
property 'sonar.projectName', 'sonarqubeFullScan'
} else {
property 'sonar.projectName', 'sonarqubePullRequest'
}
}
}
Alternatively, you can add another task of the type SonarQubeTask. This way, you could parametrize both tasks differently and call them (via command line or dependency) whenever you need them:
sonarqube {
// Generated by the plugin, parametrize like described above
}
task sonarqubeFull(type: org.sonarqube.gradle.SonarQubeTask) {
// Generated by your build script, parametrize in the same way
}

How to assign default values for ext based properties in gradle

I am working on a gradle plugin with a task where it accesses the extra params using the project object itself like
project.extraParam1
project.extraParam2
Now I can use this plugin from another project and pass the parameters in the build.gradle file as
ext {
extraParam1 value1
extraParam2 value2
}
I mean I apply this plugin in another project's build.gradle. Define the ext parameters and call the plugin task and it works. The task is able to access the extra properties. However, I want to set some default values to these, so that even though the project which is using the plugin doesn't define the ext parameter, it has some default values and works for default values.
In your plugin, you can do something like that :
def extraParam1 = project.hasProperty('extraParam1') ? project.extraParam1 : 'default value'

Dynamically changing 'teamcity.build.branch'

I want to set the value of 'teamcity.build.branch' dynamically according to the result of another TC build configuration part of the build pipeline.
Is that even possible? It looks like the value is evaluated and used at the start of the build pipeline.
UseCase:
I am executing a TC build configuration that will generate a unique number
in the connected TC build configuration part of the same pipeline I want the number to be used in the 'teamcity.build.branch' - just for visualization purposes
I am already using message service to overwrite the parameter, but the change is not taken into account. It looks like the value is read in the very early stage of the build process.
Check below reference containing build number and git branch name
https://octopus.com/blog/teamcity-version-numbers-based-on-branches
You could overwrite the value of the parameter by using a simple script that emits a "set parameter" service message.
By using a dedicated service message in your build script, you can dynamically update build parameters of the build right from a build step (...)
With that approach, here are the steps that you need to perform:
In the first build config, define a custom build parameter and set its value to the unique number you're generating. Do this directly from the script that generates the unique number by writing something like this to STDOUT:
##teamcity[setParameter name='magicNumber' value='1234']
In the dependent build config, you now have access to that parameter. Using a second build script, you can overwrite the teamcity.build.branch with the same mechanism:
##teamcity[setParameter name='teamcity.build.branch' value='the new value']
Note 1: I recommend against overwriting the built-in parameters, because this might have strange side-effects. Rather, define a custom parameter in the second build config and use that for your visualization purposes.
Note 2: In case you decide to ignore Note 1, it may be necessary to overwrite the build parameters by setting the dependency property as outlined in the docs in section "Overriding Dependencies Properties":
##teamcity[setParameter name='reverse.dep.*.teamcity.build.branch' value='the new value']

How do I use inputs.property on a Gradle task, but with a closure for a value?

I'm trying to add an installer builder to my build configuration and I'm having a little trouble getting task inputs set up properly. I have the configuration split into a separate .gradle file and I add it to my project by doing the following.
project.ext.i4jArgs = [ "--verbose" ]
apply from: rootProject.projectDir.absolutePath + "/gradle/install4j.gradle"
To build the installers I'm calling a command line tool via exec. Almost everything is based on convention, but I want to optionally add a couple arguments / switches to the command from my main build file. I do it using the project.ext.i4jArgs property (above).
If I set the project.ext.i4jArgs property before applying my install4j.gradle file, I can use the following for inputs and everything seems to work.
inputs.property("i4jArgs", project.ext.has('i4jArgs') ? project.ext.i4jArgs : null)
However, if I apply my install4j.gradle file first and set the project.ext.i4jArgs property second, the project.ext.i4jArgs property is always null when I'm declaring inputs in my task (obviously). The API for TaskInputs (here) says I can pass a closure as a value. Is there a way I can use a closure to delay the evaluation of the project.ext.i4jArgs long enough to guarantee it's been initialized? I though the following would work, but the closure never gets called.
inputs.property("i4jArgs", {
project.afterEvaluate {
println "has args ${project.ext.has('i4jArgs')}"
project.ext.has('i4jArgs') ? project.ext.i4jArgs : null
}
})
I know writing a plugin that supports all the configuration I want might be a better option for the specific example I've given, but I'd like to figure out what I'm misunderstanding here anyway.
I would remove project.afterEvaluate in the first closure. This is for adding a closure that gets executed after the project has been configured.
What is actually going on is when gradle resolves the inputs, it calls the first closure, which then calls project.afterEvaluate, which adds a closure to the list that will be called when the project is done configuring... which will never be called because it is now in the execution phase.

Resources