Converting yGuard Ant task to gradle - ant

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" ) {
...
}
}

Related

jenkins dsl job script: How to access environment variable, (which is injected via propertiesFile, ) in downstreamParameterized step

my dsl job script in brief
job('test') {
steps {
shell('echo VERSION=$VERSION > version.txt\n' +
'echo VERSION_SUFFIX=$VERSION_SUFFIX >> version.txt\n' +
'echo GROUP_ID=$GROUP_ID >> version.txt')
// EnvInject Plugin
environmentVariables {
propertiesFile('version.txt')
}
}
publishers {
postBuildScripts {
steps {
shell('echo ${VERSION}')
}
onlyIfBuildSucceeds(false)
onlyIfBuildFails(false)
}
downstreamParameterized {
trigger('next-job') {
parameters {
predefinedProp('relVersion', '${VERSION}')
}
}
}
}
}
I need $VERSION number to pass to the downstream job a parameter.
I tried, ${env.VERSION} and also tried many options, but i couldn't catch the VERSION . any help is appreciated, thanks in advance.
You can use the option Prepare an environment for the run which is executed before SCM.
Option Prepare an environment for the run is not belongs pre-build/ build /post build, but job properties.
There is no job DSL API supports to configure this option. But we can use configure block.
job('next-job') {
configure { project ->
project / 'properties' << 'EnvInjectJobProperty' {
info {
loadFilesFromMaster false
propertiesContent 'Branch=${relVersion}'
}
keepBuildVariables true
keepJenkinsSystemVariables true
overrideBuildParameters false
on true
}
} // end of configure block
scm {
git {
remote {
url("ssh://git#bitbucket.rl.git")
}
branches('${branch}')
}
} // end of scm
steps {}
publishers {}
}
Above job DSL can generate following xml as the content of seed job's config.xml
<project>
<actions></actions>
<description></description>
<keepDependencies>false</keepDependencies>
<properties>
<EnvInjectJobProperty>
<info>
<loadFilesFromMaster>false</loadFilesFromMaster>
<propertiesContent>Branch=${relVersion}</propertiesContent>
</info>
<keepBuildVariables>true</keepBuildVariables>
<keepJenkinsSystemVariables>true</keepJenkinsSystemVariables>
<overrideBuildParameters>false</overrideBuildParameters>
<on>true</on>
</EnvInjectJobProperty>
</properties>
<canRoam>true</canRoam>
<disabled>false</disabled>
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
<triggers></triggers>
<concurrentBuild>false</concurrentBuild>
<builders></builders>
<publishers></publishers>
<buildWrappers></buildWrappers>
<scm class='hudson.plugins.git.GitSCM'>
<userRemoteConfigs>
<hudson.plugins.git.UserRemoteConfig>
<url>ssh://git#bitbucket.rl.git</url>
</hudson.plugins.git.UserRemoteConfig>
</userRemoteConfigs>
<branches>
<hudson.plugins.git.BranchSpec>
<name>${branch}</name>
</hudson.plugins.git.BranchSpec>
</branches>
<configVersion>2</configVersion>
<doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
<gitTool>Default</gitTool>
</scm>
</project>
You can try jod DSL on http://job-dsl.herokuapp.com/ to check generated xml from it as expect or not.

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') {
}
}
}

How can you use custom Ant PropertyExpander from within script

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));
}

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.

Resources