Specify Groovy AntBuilder execution directory - maven

I can execute a pom.xml with goals using AntBuilder like so.
def ant = new AntBuilder()
ant.sequential {
exec(executable:'mvn') {
arg(value:'clean')
arg(value:'install')
}
}
But how do I specify the execution directory to the AntBuilder? I'd like to just pass an absolute path.
For the record I've tried.
ant.project.setProperty('basedir', "${serviceRootDir}/")
and
ant.sequential {
mkdir(dir:"${serviceRootDir}/")...
You'd think this would be clear in the doc.

This works for me:
ant.exec(executable:"ls", dir:"/your/desired/directory")
It executes ls in the given directory, so mvn should work.

Related

Parallel execution 'mvn test' in Jenkins

I try to create jenkinsfile for parallel execution command mvn test with different arguments. On the first stage of jenkinsfile I create *.csv file where are will be future arguments for mvn test command. Also I don't know the quantity of parallel stages (it depends on first stage where I get data from DB). So, summarize it again. Logic:
First stage for getting data from DB over command mvn test (with args). On this test I save data into csv file.
In loop of jenkinsfile I read every string, parse it and get args for arallel execution mvn test (with args based on the parsed data).
Now it looks like this (only necessary fragments of jenkinsfile):
def buildProject = { a, b, c ->
node {
stage(a) {
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
sh "mvn -Dtest=test2 test -Darg1=${b} -Darg2=${c}"
}
}
}
}
stages {
stage('Preparation of file.csv') {
steps {
sh 'mvn -Dtest=test1 test'
}
}
stage('Parallel stage') {
steps {
script {
file = readFile "file.csv"
lines = file.readLines()
def branches = [:]
for(i = 0; i < lines.size(); i++) {
values = lines[i].split(';')
branches["${values[0]}"] = { buildProject(values[0], values[1], values[2]) }
}
parallel branches
}
}
}
}
So, which problems do I face now with?
I see in log following error:
[ERROR] The goal you specified requires a project to execute but there is no POM in this directory (/Data/jenkins/workspace//#2)
I look at workspaces of Jenkins and see that there were created several empty(!!!) directories (quantity equals to quantity of parallel stages). And therefore mvn command could be executed because of absence of pom.xml and other files.
In branches the same data are saved on every iteration of loop and in 'stage(a)' I see the same title (but every iteration of loop has unique 'values[0]').
Can you help me with this issue?
Thank you in advance!
So, regarding this jenkins issue issues.jenkins.io/browse/JENKINS-50307 and workaround which could be found there, task could be closed!

Setting file permissions dynamically in a gradle Copy task

I'm trying to get around a problem where a dependency in my build is a zip file that contains some read only files. When I extract that zip as part of my build I end out with read only files in a staging folder and they prevent the task running in the future since they cannot be overwritten.
Until there's a way to force overwrite in a gradle copy task I've been trying to find a way to change the file mode of the read-only files in a way that doesn't remove the execute bit from those files that need it.
I've come up with this:
task stageZip(type: Copy) {
from({ zipTree(zipFile) })
into stagingFolder
eachFile {
println "${it.name}, oldMode: ${Integer.toOctalString(it.mode)}, newMode: ${Integer.toOctalString(it.mode | 0200)}"
fileMode it.mode | 0200
}
}
But this doesn't work. If I comment out the fileMode line then the println correctly lists the old and new file modes with the write bit enabled for all files. If I leave the code as is, then all the files in the zip get extracted with the newMode of the first file.
This doesn't seem like this is an unreasonable thing to try and do, but I'm obviously doing something wrong. Any suggestions?
Based on this thread, consider the Sync task. Specifically:
task stageZip(type: Sync) {
from zipTree('data/data.zip')
into 'staging'
fileMode 0644
}
I've put a working example (as I understand the question) here.
Here is a method that answers the question about file permissions. The example is posted to GitHub here.
First, consider a method to add w to a file:
import java.nio.file.*
import java.nio.file.attribute.PosixFilePermission
def addWritePerm = { file ->
println "TRACER adding 'w' to : " + file.absolutePath
def path = Paths.get(file.absolutePath)
def perms = Files.getPosixFilePermissions(path)
perms << PosixFilePermission.OWNER_WRITE
Files.setPosixFilePermissions(path, perms)
}
then, the Gradle task could be as follows:
project.ext.stagingFolder = 'staging'
project.ext.zipFile = 'data/data.zip'
task stageZip(type: Copy) {
from({ zipTree(project.ext.zipFile) })
into project.ext.stagingFolder
doLast {
new File(project.ext.stagingFolder).eachFileRecurse { def file ->
if (! file.canWrite()) {
addWritePerm(file)
}
}
}
}
eachFile {
file -> file.setMode(file.getMode() | 0200)
}
Worked for me in an rpm task which works with copyspec

jenkinsfile - How do I access custom properties in my pom.xml?

Let's say I have a custom property in my pom.xml set like this:
<properties>
<app>com.myProject.app</app>
</properties>
How can I access it in my jenkinsfile?
This:
def pom = readMavenPom file: 'pom.xml'
def appName = pom.app
returns
org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: unclassified field org.apache.maven.model.Model app
Thanks in advance!
I know two approaches:
Use properties-maven-plugin to write the properties to a file. Use readProperties in the Jenkinsfile to read the properties.
Works only if properties aren't needed until after Maven ran.
Also, with the right circumstances, the properties file may be the stale one from a previous run, which is insiduous because the property values will be right anyway 99.9% of the time.
Use pom = readMavenPom 'path/to/pom.xml'. Afterwards, access the property like this: pom.properties['com.myProject.app'].
I like approach 2 much better: No extra plugin configuration in the POM, no file written, less sequencing constraints, less fragilities.
In pipeline style, inside Jenkinsfile you can access the value as follows
pipeline {
environment {
POM_APP = readMavenPom().getProperties().getProperty('app')
}
stages{
stage('app stage'){
steps{
script{
sh """
echo ${POM_APP}
"""
}
}
}
}
Read a maven project file
try this:
IMAGE = readMavenPom().getArtifactId()
VERSION = readMavenPom().getVersion()
jenkins pipeline add this stage.
more see
stage('info')
{
steps
{
script
{
def version = sh script: 'mvn help:evaluate -Dexpression=project.version -q -DforceStdout', returnStdout: true
def artifactId = sh script: 'mvn help:evaluate -Dexpression=project.artifactId -q -DforceStdout', returnStdout: true
}
}
}

What is the proper way to refer to resource directory path in one source set in gradle?

In my build.gradle file, I have defined a separate sourceSet for integration tests:
sourceSets {
integtest {
java.srcDir 'src/integtest/java/io/attil/integration'
resources.srcDir 'src/integtest/resources'
}
}
I would like to use the path to resources of the integration tests in one of my manually defined tasks (a task that prefills the data-base for integration tests; the sql script is located in the mentioned resource folder).
I have now the following solution:
task prefillDatabase {
// ... snip!
String sqlString = new File(sourceSets.integtest.resources.srcDirs.iterator().next().toString() + '/setup_integration_tests.sql').text
// ... snip!
}
While this works, it is quite cumbersome.
Is there a better, shorter way to achieve the same? (I'm looking for something like sourceSets.integtest.resources.srcDir.)
I'm not sure this is less verbose, but I'd argue it's more correct
File file = sourceSets.integtest.resources.matching {
include 'setup_integration_tests.sql'
}.singleFile
String sqlString = file.text
See FileTree.matching(Closure) and FileCollection.getSingleFile()
Also, this looks wrong to me
java.srcDir 'src/integtest/java/io/attil/integration'
I'd think it would be
java.srcDir 'src/integtest/java'
java.include 'io/attil/integration/**'

Path to project on which Gradle task is executed

I have parent and child project. Parent's build.gradle is empty, settings.xml contains include 'child' and
in build.gradle of child I have a task
task('executionPath') << {
println projectDir
}
This task is supposed to print the path to project on which the build was started.
If I invoke it in root by ./gradlew executionPath I expect it to show path of the root project, e.g. C:\projects\parent.
If I invoke it in root by ./gradlew child:executionPath I expect it to show path of the child project, e.g. C:\projects\parent\child.
I've tried the following:
projectDir always path to child
new File('.') always path to parent
System.getProperty("user.dir") always path to parent
Answer Gradle: get folder from which "gradle" was executed is not helpful in my case. How can I achieve the above?
It's not very straightforward solution, but you can use start parameters to find out, whether the task was called for the root project or for the current. Something like this:
task('executionPath') << {
//find the argument representing current task
String calledTaskName = null;
for (String taskArgument : project.getGradle().startParameter.taskRequests.get(0).args) {
if (taskArgument.equals(name) || taskArgument.endsWith(':'+name)) {
calledTaskName = taskArgument;
}
}
if (calledTaskName == null) {
println 'Task was not called via arguments'
return;
}
//check, whether task was called on root project or for subproject only
if (calledTaskName.startsWith(project.getPath())) {
println projectDir
} else {
println System.getProperty("user.dir")
}
}
This task is looking within start parameters for the current task name. If it was called via start parameters, it checks, whether task name contains current project name as a prefix and according to it prints out current project path or root project path.
Unfortunately, I don't know any other solution for your case. Sure, you may need to modify it for your exact purposes.

Resources