Calling Ant targets dynamically in Jenkins - ant

Is there a way to call Ant targets in 'Invoke Ant' build step dynamically? Say you have a build.xml with:
<target name="1" description="1">
<exec executable="${RES_DIR}/1.sh" failonerror="true">
</exec>
</target>
<target name="2" description="2">
<exec executable="${RES_DIR}/2.sh" failonerror="true">
</exec>
</target>
<target name="3" description="3">
<exec executable="${RES_DIR}/3.sh" failonerror="true">
</exec>
</target>
And want your Jenkins builds to all use this same build.xml, but to be able to call certain targets for each build. I don't want to hardcode these targets everytime a project needs to be created because I want it to be done automatically. Is this possible or do you have to create a project beforehand and manually set your Ant targets?

A simple trick can be to use the if attribute on targets.
For instance:
<target name="run" depends="1,2,3" />
<target name="1" description="1" if="run1">
<exec executable="${RES_DIR}/1.sh" failonerror="true">
</exec>
</target>
<target name="2" description="2" if="run2">
<exec executable="${RES_DIR}/2.sh" failonerror="true">
</exec>
</target>
<target name="3" description="3" if="run3">
<exec executable="${RES_DIR}/3.sh" failonerror="true">
</exec>
</target>
That way, you call the target run and set the property runX to an arbitrary value (true is generally a good choice). Only the target X will actually run.

That would probably work OK but it is a bit of an inconvenient to change your build just to satisfy a Jenkins build interface requirement.
The way I usually do it is to set a build parameter say a 'choice' and give the user the possibility to choose which target they want to invoke from that drop down list.
Say that choice parameter is called target then all you need to do in the 'invoke ant' build section is to refer to %target% and Jenkins will make the substitution for you.
Whether you go with a 'choice' or other types of build parameters (e.g. text) would depend on your specific needs.

Related

How to execute custom ant target using exec task?

In our project we are using a proprietary product which contains its own custom ant executable to build the deployment artifact.
So, we have two build files 'build-artifcat.xml' and 'build.xml'.
Here,
'build-artifcat.xml' - contains ant targets which can be executed with this products custom ant executable.
'build.xml' - contains ant targets which can be executed by Apache Ant.
We are using Bamboo CICD tool and this tool provides facility to execute only Apache Ant targets.
So, we are planning to use task to invoke ant targets from 'build-artifcat.xml' using this products custom ant executable.
I found below code while checking older projects but here I am not sure how can I specify the target to be executed from from 'build-artifcat.xml'.
Can you please help.
<target name="buildArtifact">
<echo>Running ant exec: ${run.custom.ant.exec}</echo>
<exec dir="${run.ant.exec.dir}" executable="${run.custom.ant.exec}" error="${basedir}/${error.log.file}">
<arg value="-f" />
<arg file="${basedir}/build-artifcat.xml" />
<arg value="-DimportDir=${import.location}" />
<arg value="-DartifactDir=${artifact.dir}" />
<arg value="-data" />
<arg value="${temp.workspace}" />
<arg value="-vmargs" />
<arg value="-Xmx1024m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./crashes/my-heap-dump.hprof -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:./crashes/gc.log" />
<arg value="-verbose" />
</exec>
</target>

How to specify lib directory for ant task?

I'm currently running an exec task in my build like this:
<target name="bar">
<exec executable="ant">
<arg value="-f"/>
<arg value="/path/to/my/build.xml"/>
<arg value="-lib"/>
<arg value="/path/to/my/libs"/>
</exec>
</target>
I don't really like it and want to replace the exec task with an ant task:
<target name="bar">
<ant antfile="/path/to/my/build.xml"/>
</target>
However, I don't know how to specify the lib directory in this case. Is this possible somehow?
What are you trying to achieve, by launching ANT from within ANT in this manner?
For example if you need custom ANT extensions, the path to these jars can be specified at runtime within the code as follows:
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="${lib.dir}/ant-contrib-0.3.jar"/>
</classpath>
</taskdef>
Better again, you could integrate a dependency management system like Apache ivy to manage 3rd party jar dependencies.
You can call ant script inside an ant script like below.
If you use the attribute inheritrefs="true" any Ids that are set in the parent build script will be passed to child build script as well.
Eg:
<ant antfile="subbuild.xml" inheritrefs="true"/>

how to use exec exit status in ant target and other targets also

I am calling one target(targetCalled) from some other target(targetCaller), as follows:
<target depends="local.init"
description="creating application jar file of the classes dir"
name="run_check_server_client_jar_gen">
<antcall target="run_check_server_client_jar_callExec"/>
<if>
<isset property="result"/>
<then>
<echo>Result: ${result}</echo>
</then>
<else>
<echo>Propert result is not set yet !! </echo>
</else>
</if>
</target>
Now I call one exec from targetCalled as follows:
<target depends="local.init"
description="Running check for all classes in
client jar should also be present in server jar"
name="run_check_server_client_jar_callExec">
<exec executable="/bin/bash" resultproperty="${result}" failonerror="false">
<arg value="count_client_server_inner_classes.sh"/>
<arg value="gjf1common_client_classes.jar"/>
<arg value="gjf1common_classes.jar"/>
</exec>
<if>
<isset property="result"/>
<then>
<echo>Inside::Result: ${result}</echo>
</then>
<else>
<echo>Inside::Property result is not set yet !!!! </echo>
</else>
</if>
</target>
In my count_client_server_inner_classes.sh, i am exiting the status as:
exit "$result"
it is giving me ": numeric argument required"
i want that executable should return me a string, is that possible ??
I want to use this returned value in my targetCalled and targetCaller.
but when i am echoing the result property.. it is giving me 255.
Can anybody points out where i am going wrong ?
Ant isn't a scripting language. It's not a very good way to describe a build - but it's an awful scripting language. Trying to script in ant with pseudo-function calls and if/else like this is going to suck. In generally, stay away from if/else - if you find you need them you likely want to reevaluate your tool choice. Avoid antcall at all costs - it spins up a new jvm and makes for some crazy spaghetti - use depends to control the execution flow between targets.
To answer one of your question - the result property is always going to be the exit code, in the case of bash it's always goign to be an int 0-255.
The interesting part is in the bash script... post that. It's returning 255, which is a special code - means it's out of range. I suspect you're having it return a string?
You could simplify the whole mess by simply failing on error:
<target name="run-check-server-client-jar-gen" depends="local-init"
description="creating application jar file of the classes dir">
<exec executable="/bin/bash" failonerror="true">
<arg value="count_client_server_inner_classes.sh"/>
<arg value="gjf1common_client_classes.jar"/>
<arg value="gjf1common_classes.jar"/>
</exec>
</target>
If you really must give custom error status you can set the result property as you where and then you could:
<target name="run-check-server-client-jar-gen" depends="local-init"
description="creating application jar file of the classes dir">
<exec executable="/bin/bash" resultproperty="${return.code}">
<arg value="count_client_server_inner_classes.sh"/>
<arg value="gjf1common_client_classes.jar"/>
<arg value="gjf1common_classes.jar"/>
</exec>
<fail message="crazy shell script madness terminated abnormally.">
<condition>
<isfailure code="${return.code}"/>
</condition>
</fail>
</target>
I admit I didn't actually run the snippets above, you may have to massage a bit, but I'm pretty sure they'll go.
another editorial note on style: targets generally use - rather than _ or . to delimit word, where properties use .

How to correctly setup a conditional task with Maven-Ant?

New Ant user here. I've created a conditional task, which is run inside as a Maven Ant plugin. The issue I'm facing is the condition target: "ui-test-condition" is not being found during a build.
The error returned is:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-antrun-plugin:1.6:run (uitests) on project myProject: An Ant BuildException has occured: Target "ui-test-condition" does not exist in the project "maven-antrun-". It is used from target "ui-test-run". -> [Help 1]
This would suggest a syntax error in the code below, however I'm unable to identify the issue. Any assistance is greatly appreciated.
<target name="ui-test" depends="ui-test-run,ui-test-skip"/>
<target name="ui-test-condition">
<condition property="ui-test-condition-run">
<and>
<istrue value="${ui.test}"/>
</and>
</condition>
</target>
<target name="ui-test-run" depends="ui-test-condition" if="ui-test-condition-run">
<echo>Running tests</echo>
<exec dir="src/main/webapp/ui" executable="src/main/webapp/ui/${some.executable}"
resolveexecutable="true" failonerror="true">
<arg value="-e" />
<arg value="foo/run" />
</exec>
</target>
<target name="ui-test-skip" depends="ui-test-condition" unless="ui-test-condition-run">
<echo>Tests are skipped</echo>
</target>
I had the exact same problem and I found the answer is that the depends property of a target is not supported by maven-antrun-plugin.
Excerpt of http://maven.apache.org/plugins/maven-antrun-plugin/usage.html
Ultimately, you could specify some Ant <target/> attributes in the <target/> tag. Only depends attribute in Ant <target/> is not wrapped.
That does not prevent the feature from working, at least not from experience; by just removing the depends property and ordering the targets properly, it works.
Moreover, only the last target is considered by maven-antrun-plugin. You therefore need to find a way to evaluate your condition directly in that target.

How do I pass an argument to an Ant task?

I'm not very good with Ant, but we're using it as a build tool. Right now, we can run "ant test" and it'll run through all the unit tests.
However, I'd love to be able to do something like ant test some_module and have it accept some_module as a parameter, and only test that.
I haven't been able to find how to pass command line args to Ant - any ideas?
One solution might be as follows. (I have a project that does this.)
Have a separate target similar to test with a fileset that restricts the test to one class only. Then pass the name of that class using -D at the ant command line:
ant -Dtest.module=MyClassUnderTest single_test
In the build.xml (highly reduced):
<target name="single_test" depends="compile" description="Run one unit test">
<junit>
<batchtest>
<fileset dir="${test.dir}" includes="**/${test.module}.class" />
</batchtest>
</junit>
</target>
You can also define a property with an optional default value that can be replaced via command line, e.g.
<target name="test">
<property name="moduleName" value="default-module" />
<echo message="Testing Module: ${moduleName}"/>
....
</target>
and run it as:
ant test -DmoduleName=ModuleX
What about using some conditional in your test target and the specifying -Dcondition=true?
<target name="test" depends="_test, _test_if_true>
...
</target>
<target name="_test_if_true" if="condition">
...
</target>
<target name="_test" unless="condition">
...
</target>
Adapted a bit from the ant faq.
You can define a property on commandline when invoking ant:
ant -Dtest.module=mymodulename
Then you can use it as any other ant property:
...
<fileset dir="${test.dir}" includes="**/${test.module}.class" />
...
Have a look at Ant's manual.
I tried the solutions posted here for the very same original question. Yes just use ant -D<arg_name>. THe -D is a "keyword" I guess. I'm no ant expert and have not read the manuals in detail. Then inside the ant XML files can be accessed like: ${arg_name}
For instance you can have an argument name like: arg.myarg, so in XML ${arg.myarg}.
Ant really doesn't have parameters_ for the build file. I can think of a few ways to do this:
Use a special target to specify the tests. You can use the <for/> task from AntContrib to allow you to specify multiple tests. You'll need to download the Ant-Contrib jar file. I recommend placing it inside your project under the `${basedir}/antlib/antcontrib" directory. That way, when others checkout your project, they get the needed Ant-Contrib jar file.
<property name="antlib.dir" value="${basedir}/antlib"/>
<property name="antcontrib.dir" value="${antlib}/antcontrib"/>
<!-- Set up the ant contrib tasks for your use -->
<taskdef resource="net/sf/antcontrib/antlib.xml">
<classpath>
<fileset dir="${antcontrib.dir}"/>
</classpath>
</taskdef>
<target name="select-test"
description="Select the tests to run"
depends="test-compile"
if="junit-tests">
<for parameter="module"
list="${junit-tests}"
delimiter=" ">
<sequential>
<junit
fork="true"
...>
<batchtest todir="$target/unit-tests">
<fileset dir="${test.destdir}">
<include name="**/#{module}.class"/>
</fileset>
</junit>
</sequential>
</for>
</target>
You cab now run multiple tests like this:
$ ant -D"test-one test-two test-three" select-test
You could try this to access one target at a time. Add these lines to your build.xml file :
<project name="whatever" default="default">
<input message="Please select module:" addproperty="mod" />
<target name="default" depends="${mod}/>
...
</project>
This allows you to enter the module you want to execute and execute that itself instead of running the whole build.xml
You might need to make a few more changes to your build.xml for this to work perfectly.
For the arguments , there is Facility called property. You need to set the property. As in ANT plain arguments is taken as target name.
Lest say you have two modules in your project ModuleX and ModuleY where ModuleX has 2 testcases to run and ModuleY with 10 testcases.
You could do something like this :
ant runTestsOnModule -Dtestmodule="ModuleX"
OR to test all modules by calling
ant tests
<target name="runTestsOnModule">
<antCall target="testcase${testmodule}"/>
</target>'
<! -- run single module -->
<target name="runTestsOnModule">
<antCall target="testcase${testmodule}"/>
</target>
<!--run all tests-->
<target name="tests">
<antcall target="testcaseModuleX">
<antcall target="testCaseModuleY">
</target>
<target name="testcaseModuleX">
..run junit task to call 2 testcase
</target>
<target name="testcaseModuleY">
....run junit task to call 10 testcase
</target>

Resources