How can you use custom Ant PropertyExpander from within script - ant

Sample script:
<property name="foo" value="bar" />
<script language="javascript"> <![CDATA[
var echoTest = project.createTask("echo");
echoTest.setMessage("${toString:foo}");
echoTest.perform();
echoTest = project.createTask("echo");
echoTest.setMessage("${foo}");
echoTest.perform();
</script>
Expected Output:
[echo] bar
[echo] bar
Actual Output:
[echo] ${toString:foo}
[echo] ${foo}
....
So how can I perform the string expansion which Ant does?

Found the solution.
function antResolveProperty(value) {
var propertyHelper = Packages.org.apache.tools.ant.PropertyHelper.getPropertyHelper(project);
return String(propertyHelper.replaceProperties(value));
}

Related

How to update batch of Jenkins job's parameter in the folder using plugin/API/code?

I have a Jenkins folder "testFolder", a view "test_view" in the folder, n job pipelines in "test_view".One parameter named "exclude" in n jobs, how to update the value of parameter "exclude" in batch of the pipelines under "test_view"? Is there any plugin / API / code can do it?
I refer to this blog and execute the groovy script in the Jenkins script console
Update default values of Jenkins Job Parameters but the solution will delete all existing parameters and add the parameter back which is quite risky. If I remove this line
((Job) job).removeProperty(ParametersDefinitionProperty.class);
It can override the default value of the parameter but it will keep the old parameter in the config.xml. Is there any function that can update specific parameters, maybe something like
((Job) job).updateProperty(new ParametersDefinitionProperty(newParameters));
Groovy script
Jenkins instance = Jenkins.getInstance();
List items = instance.getAllItems();
String folderPath = "test_folder";
String viewNameInFolder = "test_view";
String parameterNameInPipelines = "exclude";
String parameterValue = "exclude.json";
String parameterDescription = "";
for (Item item: items) {
if (item instanceof com.cloudbees.hudson.plugins.folder.Folder) {
if (item.getFullName().trim().equals((folderPath).trim())) {
//locate the expected folder
Object[] viewsArray = item.getAllViews().toArray();
for(Object view: viewsArray){
if(view.getViewName().trim().equals(viewNameInFolder)){
// locate the expected view under folder
Object[] jobsArray = view.getAllItems().toArray();
for (Object job: jobsArray) { // Loop though all pipelines job
if(job instanceof org.jenkinsci.plugins.workflow.job.WorkflowJob) {
StringParameterDefinition param1 = new StringParameterDefinition(parameterNameInPipelines , parameterValue, parameterDescription);
ParameterDefinition[] newParameters = [param1];
((Job) job).addProperty(new ParametersDefinitionProperty(newParameters));
}
}
}
}
}
}
}
config.xml
<flow-definition plugin="workflow-job#2.40">
<actions/>
<description/>
<keepDependencies>false</keepDependencies>
<properties>
<hudson.plugins.jira.JiraProjectProperty plugin="jira#3.2.1">
<siteName>https://$sitename.com/</siteName>
</hudson.plugins.jira.JiraProjectProperty>
<com.sonyericsson.jenkins.plugins.bfa.model.ScannerJobProperty plugin="build-failure-analyzer#1.20.0">
<doNotScan>false</doNotScan>
</com.sonyericsson.jenkins.plugins.bfa.model.ScannerJobProperty>
<com.sonyericsson.rebuild.RebuildSettings plugin="rebuild#1.28">
<autoRebuild>false</autoRebuild>
<rebuildDisabled>false</rebuildDisabled>
</com.sonyericsson.rebuild.RebuildSettings>
<hudson.model.ParametersDefinitionProperty>
<parameterDefinitions class="java.util.Arrays$ArrayList">
<a class="hudson.model.ParameterDefinition-array">
<hudson.model.StringParameterDefinition>
<name>exclude</name>
<description/>
<defaultValue>exclude.json</defaultValue>
<trim>false</trim>
</hudson.model.StringParameterDefinition>
</a>
</parameterDefinitions>
</hudson.model.ParametersDefinitionProperty>
<hudson.model.ParametersDefinitionProperty>
<parameterDefinitions class="java.util.Arrays$ArrayList">
<a class="hudson.model.ParameterDefinition-array">
<hudson.model.StringParameterDefinition>
<name>exclude</name>
<description/>
<defaultValue>exclude2.json</defaultValue>
<trim>false</trim>
</hudson.model.StringParameterDefinition>
</a>
</parameterDefinitions>
</hudson.model.ParametersDefinitionProperty>
</properties>
<definition class="org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition" plugin="workflow-cps#2.90">
<script>pipeline { agent any stages { stage('Hello') { steps { echo 'Hello World' } } } } </script>
<sandbox>true</sandbox>
</definition>
<triggers/>
<disabled>false</disabled>
</flow-definition>

Reuse maven step in Jenkins Job DSL

I am using the Job DSL to define a job that requires multiple maven steps to be run. This is an example:
def mavenInst = 'maven-3x'
job('test') {
steps{
maven {
mavenInstallation(mavenInst)
goals('fuu')
}
maven {
mavenInstallation(mavenInst)
goals('bar')
}
// more steps of the same form.
maven {
mavenInstallation(mavenInst)
goals('fuu bar')
}
}
}
So, much of code is repeated quite often.
Is it possible to extract the respective parts of the job description and call them from within the Job DSL? I imagine something like this:
def mavenInst = 'maven-3x'
job('test') {
steps{
myCustomStep('fuu')
myCustomStep('bar')
// more steps of the same form.
myCustomStep('fuu bar')
}
}
This would result in significantly less code and would be easier to change in the future.
I have read that the steps need some sort of context but I can not figure out how to do it. I tried to extract the block into a configure closure as this:
def fuubar = { it ->
mavenInstallation(mavenInst)
goals('fuu bar')
}
But when I call the element with configure fuubar, nothing is shown in the resulting job configure.xml.
Any help would be appreciated.
I would think you can do this
job('test') {
steps {
maven {
mavenInstallation('maven-3x')
goals('fuu')
goals('bar')
goals('fuu bar')
}
}
}
based on the excellent help
and also in the dsl playground
which gives you this
<!-- 1. test -->
<project>
<actions></actions>
<description></description>
<keepDependencies>false</keepDependencies>
<properties></properties>
<scm class='hudson.scm.NullSCM'></scm>
<canRoam>true</canRoam>
<disabled>false</disabled>
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
<triggers class='vector'></triggers>
<concurrentBuild>false</concurrentBuild>
<builders>
<hudson.tasks.Maven>
<targets>fuu bar fuu bar</targets>
<mavenName>maven-3x</mavenName>
<jvmOptions></jvmOptions>
<usePrivateRepository>false</usePrivateRepository>
</hudson.tasks.Maven>
</builders>
<publishers></publishers>
<buildWrappers></buildWrappers>
</project>
EDIT
Rereading your question it seems this is an example.
The above could also be written
def goal_names = ['fuu', 'bar', 'fuu bar']
job('test') {
steps {
maven {
mavenInstallation('maven-3x')
goal_names.each { goal ->
goals(goal)
}
}
}
}
EDIT 2 to use separate steps
def goal_names = ['fuu', 'bar', 'fuu bar']
job('test') {
steps {
goal_names.each { goal ->
maven {
mavenInstallation('maven-3x')
goals(goal)
}
}
}
}
XML
<!-- 1. test -->
<project>
<actions></actions>
<description></description>
<keepDependencies>false</keepDependencies>
<properties></properties>
<scm class='hudson.scm.NullSCM'></scm>
<canRoam>true</canRoam>
<disabled>false</disabled>
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
<triggers class='vector'></triggers>
<concurrentBuild>false</concurrentBuild>
<builders>
<hudson.tasks.Maven>
<targets>fuu</targets>
<mavenName>maven-3x</mavenName>
<jvmOptions></jvmOptions>
<usePrivateRepository>false</usePrivateRepository>
</hudson.tasks.Maven>
<hudson.tasks.Maven>
<targets>bar</targets>
<mavenName>maven-3x</mavenName>
<jvmOptions></jvmOptions>
<usePrivateRepository>false</usePrivateRepository>
</hudson.tasks.Maven>
<hudson.tasks.Maven>
<targets>fuu bar</targets>
<mavenName>maven-3x</mavenName>
<jvmOptions></jvmOptions>
<usePrivateRepository>false</usePrivateRepository>
</hudson.tasks.Maven>
</builders>
<publishers></publishers>
<buildWrappers></buildWrappers>
</project>
I managed to tackle that since I got similar issue and I wanted to have reusable methods with customization. I am not sure whether it is possible to encapsulate multiples steps in a method but you can encapsulate closure like this:
Closure runInLatestInstallation(String moduleName, String mavenGoals) {
return {
rootPOM("${moduleName}/pom.xml")
goals(mavenGoals)
mavenInstallation('Latest')
}
}
and you can call it like this:
maven runInLatestInstallation(moduleName, 'versions:update-parent')

Jenkins Job DSL: how to build particular node in Configure block?

The particular thing I want is to prevent some steps from execution in Flexible Publish section. I use a condition of strings (not) matching and I don't want something to be executed after check fails.
Being configured manually, expected step looks like this:
Expected postbuild step
As I have not found an appropriate method in Jenkins Jobs DSL API I've tried to reproduce it using the Configure block. The reference says that I can use 'project' for root element of the job and 'node' for particular node to append a child to them. It says also that new nodes won't be created again if pointed nodes exist. So here's my config:
job("flexible_condition") {
publishers {
flexiblePublish {
configure { node ->
node / publishers /
'org.jenkins__ci.plugins.flexible__publish.ConditionalPublisher' << 'runner'(class:
'org.jenkins_ci.plugins.run_condition.BuildStepRunner$DontRun')
}
condition {
not { stringsMatch('string_placeholder', '', false) }
}
publisher {
debianPackage('common') {
commitMessage('new feature')
}
}
publisher {
git {
pushOnlyIfSuccess(true)
branch('origin', 'master')
}
}
}
}
}
In spite of the reference desirable xml aren't generated in my jenkins neither in the Playground. I've got nodes duplicated instead and it seems that 'node' is interpreted as 'project' and is always put to the root.
<!-- 1. flexible_condition -->
<project>
<actions></actions>
<description></description>
<keepDependencies>false</keepDependencies>
<properties></properties>
<scm class='hudson.scm.NullSCM'></scm>
<canRoam>true</canRoam>
<disabled>false</disabled>
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
<triggers class='vector'></triggers>
<concurrentBuild>false</concurrentBuild>
<builders></builders>
<publishers>
<org.jenkins__ci.plugins.flexible__publish.ConditionalPublisher>
<runner class='org.jenkins_ci.plugins.run_condition.BuildStepRunner$DontRun'></runner>
</org.jenkins__ci.plugins.flexible__publish.ConditionalPublisher>
<org.jenkins__ci.plugins.flexible__publish.FlexiblePublisher>
<publishers>
<org.jenkins__ci.plugins.flexible__publish.ConditionalPublisher>
<condition class='org.jenkins_ci.plugins.run_condition.logic.Not'>
<condition class='org.jenkins_ci.plugins.run_condition.core.StringsMatchCondition'>
<arg1>string_placeholder</arg1>
<arg2></arg2>
<ignoreCase>false</ignoreCase>
</condition>
</condition>
<publisherList>
<ru.yandex.jenkins.plugins.debuilder.DebianPackagePublisher>
<repoId>common</repoId>
<commitMessage>new feature</commitMessage>
<commitChanges>true</commitChanges>
</ru.yandex.jenkins.plugins.debuilder.DebianPackagePublisher>
<hudson.plugins.git.GitPublisher>
<configVersion>2</configVersion>
<pushMerge>false</pushMerge>
<pushOnlyIfSuccess>true</pushOnlyIfSuccess>
<forcePush>false</forcePush>
<tagsToPush></tagsToPush>
<branchesToPush>
<hudson.plugins.git.GitPublisher_-BranchToPush>
<targetRepoName>origin</targetRepoName>
<branchName>master</branchName>
</hudson.plugins.git.GitPublisher_-BranchToPush>
</branchesToPush>
</hudson.plugins.git.GitPublisher>
</publisherList>
<runner class='org.jenkins_ci.plugins.run_condition.BuildStepRunner$Fail'></runner>
</org.jenkins__ci.plugins.flexible__publish.ConditionalPublisher>
</publishers>
</org.jenkins__ci.plugins.flexible__publish.FlexiblePublisher>
</publishers>
<buildWrappers></buildWrappers>
</project>
I've been checking this example in the Playground via Job DSL version 1.40 but 1.39 in my jenkins gives the same result.
What am doing wrong?
Thank you.
UPD I've put the configure block below as SevenEleven suggested and it almost helped. The runner node is on the right place now but is still duplicated.
<publishers>
<org.jenkins__ci.plugins.flexible__publish.ConditionalPublisher>
<condition .../>
<publisherList>
...
</publisherList>
<runner class='org.jenkins_ci.plugins.run_condition.BuildStepRunner$Fail'></runner>
<runner class='org.jenkins_ci.plugins.run_condition.BuildStepRunner$DontRun'></runner>
</org.jenkins__ci.plugins.flexible__publish.ConditionalPublisher>
</publishers>
UPD 2 Although there are two different lines in the xml, the newer runner replaces the default one in generated job. So I've got the expected result. Thanks.
UPD 3. Yay! Found out that now one can simply use JobDSL syntax and it works.
publishers {
flexiblePublish {
conditionalAction {
condition {
not { stringsMatch('string_placeholder', '', false) }
}
publishers {
debianPackage('common') {
commitMessage('Automatic Commit')
}
git {
pushOnlyIfSuccess(true)
branch('origin', '$GIT_BRANCH')
}
}
runner('DontRun')
}
}
}
To edit the configuration, you have to place the configure-block below, not inside the publishers configuration:
job("flexible_condition") {
publishers {
flexiblePublish {
//...
}
}
configure {
it / publishers / 'org.jenkins__ci.plugins.flexible__publish.FlexiblePublisher' / publishers / 'org.jenkins__ci.plugins.flexible__publish.ConditionalPublisher' / 'runner'(class:'org.jenkins_ci.plugins.run_condition.BuildStepRunner$DontRun') {
}
}
}

Use PMD's Copy/Paste Detector with Gradle

I'd like to use Copy/Paste Detector in my Gradle build.
This is why I've decided to translate the following Ant task (which I've found here) into Gradle syntax:
<target name="cpd">
<taskdef name="cpd" classname="net.sourceforge.pmd.cpd.CPDTask" />
<cpd minimumTokenCount="100" outputFile="/home/tom/cpd.txt">
<fileset dir="/home/tom/tmp/ant">
<include name="**/*.java"/>
</fileset>
</cpd>
</target>
This is how the translation looks currently:
check << {
ant.taskdef(name: 'cpd', classname: 'net.sourceforge.pmd.cpd.CPDTask', classpath: configurations.pmd.asPath)
ant.cpd(minimumTokenCount: '100', outputFile: file('build/reports/pmd/copyPasteDetector.txt').toURI().toString()) {
fileset(dir: 'src'){
include(name: '**.java')
}
}
}
Unfortunately calling gradle check yields an net.sourceforge.pmd.cpd.ReportException, the stacktrace is here.
How can I scan my source code with the Copy/Paste Detector using Gradle 1.9?
Thanks!
You can also use my gradle-cpd-plugin. See https://github.com/aaschmid/gradle-cpd-plugin for further informationen. Applying the cpd plugin automatically adds it the cpd as dependency of check task.
Note: I am not very happy with the name cpd for extension (see toolVersion) and task, suggestions welcome ;-)
Currently, it is version 0.1 but I am on it to switch from using CPD's ant task internally to directly call it. This will include support of all parameters etc. Here is a usage example:
apply plugin: 'cpd'
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'de.aaschmid.gradle.plugins:gradle-cpd-plugin:0.1'
}
}
// optional - default is 5.1.0
cpd {
toolVersion = '5.0.5'
}
tasks.cpd {
reports {
text.enabled = true
xml.enabled = false
}
source = files('src/main/java')
}
Guys from gradle forums suggest that you use CPD in gradle like that:
task cpd(dependsOn: ':pmdSetup') {
// Combine all source sets
allSource = files {
allprojects.findAll { proj ->
proj.hasProperty("sourceSets")
}.collect { proj ->
proj.sourceSets.collect { ss ->
ss.java
}
}
}
// Declare this task's inputs and outputs.
inputs.files allSource
outDir = file("$buildDirName/cpd")
outputs.dir outDir
// outputs.files file("$outDir.path/cpd.xml")
doLast {
outDir.mkdirs()
// Keep a reference to the gradle project for use inside the
// ant closure, where "project" refers to the ant project.
gproj = project
ant {
cpd(minimumTokenCount: '100', format: 'xml',
outputFile: outDir.path + '/cpd.xml') {
fileset(dir: projectDir.getPath()) {
// Convert the gradle sourceSet to an ant
// fileset.
allSource.each { file ->
include(name: gproj.relativePath(file))
}
}
}
}
}
}
and, of course, apply plugin: 'pmd' before.
The definition of my outputFile caused the problem.
I adapted this build.gradle and I'm now happy with the following solution:
check << {
File outDir = new File('build/reports/pmd/')
// Make sure the output dir exists to prevent a ReportException
outDir.mkdirs()
ant.taskdef(name: 'cpd', classname: 'net.sourceforge.pmd.cpd.CPDTask',
classpath: configurations.pmd.asPath)
ant.cpd(minimumTokenCount: '100', format: 'text',
outputFile: new File(outDir , 'cpd.txt')) {
fileset(dir: "src/main/java") {
include(name: '**/*.java')
}
}
}
Thanks Andrey Regentov and Perryn Fowler for their input.

Converting yGuard Ant task to gradle

I am porting a project build from ANT to Gradle. Everything has been done exception the obfuscation part, the obfuscation task in build.xml is as:
<taskdef name="yguard" classname="com.yworks.yguard.YGuardTask" classpath="${ant.yguard.path}"/>
<target name="obfuscate-no-test" depends="no-test-jar">
<yguard>
<inoutpairs>
<fileset dir="${dir.dist}">
<include name="**/*.jar"/>
<exclude name="**/*_obf.jar"/>
<exclude name="**/*-doc.jar"/>
</fileset>
</inoutpairs>
<externalclasses>
<path refid="path.lib.biz"/>
<path refid="path.lib.share"/>
<path refid="path.lib.web"/>
</externalclasses>
<rename logfile="${rename.log}">
<property name="naming-scheme" value="best"/>
<keep>
<class classes="none" fields="none" methods="none">
<patternset>
<include name="com.payeshgaran.framework.internal.**.*"/>
</patternset>
</class>
<class classes="public" fields="protected" methods="protected">
<patternset>
<include name="com.payeshgaran.framework.**.*"/>
<exclude name="com.payeshgaran.framework.internal.**.*"/>
</patternset>
</class>
</keep>
<adjust replacecontent="true">
<include name="META-INF/*.tld"/>
</adjust>
</rename>
</yguard>
</target>
For porting this to gradle I did this:
task obfuscate(dependsOn: [":ext:build", ":biz:build", ":web:build"]) {
ant.taskdef(name: "yguard",
classname: "com.yworks.yguard.YGuardTask",
classpath: "$rootProject.projectDir/lib/ant/yguard-2.5.1.jar")
ant.yguard() {
inoutpairs {
fileset(dir: distFolder) {
include(name: "**/*.jar")
exclude(name: "**/*_obf.jar")
exclude(name: "**/*-doc.jar")
}
}
externalClasses {
fileset(dir: libsFolder) {
include(name: '**/*.jar')
}
}
rename(logFile: "$distFolder/rename.log") {
property(name: "naming-scheme", value: "best")
keep() {
}
adjust(replaceContent: "true") {
include(name: "META-INF/*.tld")
}
}
}
}
Well the things go fine except I can not define a class objects (inside the keep object) cause its a reserved word in groovy.
What can I do for that?
Try:
keep {
'class'( classes:"none", fields:"none", methods:"none" ) {
...
}
}

Resources