Mark the build result as Failed OR Successful - ant

I want to mark the build as successful when the file exist(when I mark ) OR failed when file does not exist (when I mark var name="build-result" value="FAILED" />).
I want to update build status after reading build-result OR by using "build.status" which I am updating depending on build-result as
<var name="build-result" value="SUCCEEDED" />
<echo message="Sending mail status- ${build-result}"/>
<propertyfile file="${build-status.file}">
<entry key="build.status" value="${build-result}" />
</propertyfile>
Currently I am doing in the way:
<isset variable="build-result" value="FAILED" />
</condition>
</fail>
But is giving the message as: BUILD FAILED
D:\projects\Self\AntExample\build.xml:51: isset doesn't support the "variable" attribute
which I want should be like "Build Failed as File Does not Exist"

Always refer to the on line documentation. <isset> takes the parameter property and not variable. Ant doesn't have the concept of variables -- just properties. What the <var/> task does is that it allows you to change a property once it is set. You should not be using <var> except in rare circumstances. As it says on the <var> task's page: In general, use of this task is DISCOURAGED, and the standard Ant Property should be used if possible.
In fact, now that you have <local/> in the list of standard Ant tasks, I find that you no longer really need <var/>.
If you want to fail your build if a file does not exist, look at the <available> test:
<fail message="This build is an utter and complete failure".>
<condition>
<not>
<available file="${result.file}" type="file"/>
</not>
</condition>
</fail>
<echo message="This build is a smashing success! We're so proud!"/>
The <fail> task will execute if the file ${result.file} is not found. Otherwise, the <echo> message will print.

<isset> accepts only one attribute- property and checks whether the specified property has been set or not (i.e. has been provided a value, including null)
See HERE for <isset>
what you may use is <equals> which compares the values of two arguments:
<equals arg1="${build-result}" arg2="FAILED">
See HERE for <equals>
as you've mentioned: I want to mark the build as successful when the file exist you may also want to look at the <available> task,
<available property="result" file="your_file_location" />
See HERE for <available>

Related

Removing absent entries from an ant path

I've got a situation where we're generating an Ant <path> which may contain some directories which don't actually exist. Unfortunately this is being fed into bnd, which blows up if anything in the path is missing.
So what I want is a way to filter a <path> to keep only those path elements which actually exist.
Is there a simple way to say this in Ant, or do I have to write a task?
I believe I have found an answer:
<path id="bnd.cp.existing">
<restrict>
<path refid="bnd.cp"/>
<exists/>
</restrict>
</path>
<!-- To see when it happens, add the following: -->
<echo message="bnd classpath is: ${toString:bnd.cp.existing}"/>
<iff>
<not>
<equals arg1="${toString:bnd.cp.existing}"
arg2="${toString:bnd.cp}"/>
</not>
<then>
<echo message=" trimmed from: ${toString:bnd.cp}"/>
</then>
</iff>
The restrict operation can take a path-like structure as input and return a version of it with the requested filtering applied -- in this case keep only the path elements which actually exist. This is then re-bound to a new ID for use by the <bnd> operation.

Ant target calling

I would like to call target backup.yes only if the condition is true.
<condition property="directory.found.yes">
<equals arg1="${directory.found}" arg2="true"/>
</condition>
<antcall target="update.backup"/>
Is there any way to do this.
Instead of <antcall/>, do the following:
Imagine you're calling target foo, and you want to do a backup before, but only if that condition exists:
<target name="foo"
depends="update.backup">
<..../>
</target>
<target name="update.backup.test">
<condition property="directory.found.yes">
<equals arg1="${directory.found}" arg2="true"/>
</condition>
</target>
<target name="update.backup"
depends="update.backup.test"
if="directory.found.yes">
<.../>
</target>
The problem with <antcall/> is that it is used when the dependency matrix Ant uses is broken, and it's used to force a task to be done before another task is complete. When really abused, you'll end up calling the same task multiple times. I had a project here that literally called each target between 10 to 14 times, and there were over two dozen targets. I rewrote the entire build sans <antcall/> and by using true dependency setup, cut the build time by 75%.
From my experience 90% of <antcall/> is due to poor target dependency management.
Let's say you want to execute target foo. (The target the user wants to really execute), and before foo is called, you want to do your backup, but only if the directory actually exists.
In the above, foo is called. It depends upon update.backaup. The target update.backup is called, but it depends upon update.backup.test which will test whether or not the directory actually exists.
If the directory exists, the if clause on the update.backup task is true, and the task will actually execute. Otherwise, if the directory isn't there, it won't execute.
Note that update.backup first calls any dependencies before it checks whether the property on the if or unless parameter for the target entity is checked. This allows the target to call a test before it attempts to execute.
This is not a mere side effect, but built into the design of Ant. In fact, the Ant Manual on Targets](http://ant.apache.org/manual/targets.html) specifically gives a very similar example:
<target name="myTarget" depends="myTarget.check" if="myTarget.run">
<echo>Files foo.txt and bar.txt are present.</echo>
</target>
<target name="myTarget.check">
<condition property="myTarget.run">
<and>
<available file="foo.txt"/>
<available file="bar.txt"/>
</and>
</condition>
</target>
And states:
Important: the if and unless attributes only enable or disable the target to which they are attached. They do not control whether or not targets that a conditional target depends upon get executed. In fact, they do not even get evaluated until the target is about to be executed, and all its predecessors have already run.
You can do the following
In the other target:
<antcall target="update.back">
<param name="ok" value="${directory.found.yes}"/>
</antcall>
And in the update.backup target:
<target name="update.backup" if="ok">
But I think you can also do the following using the if statement from ant-contrib:
<if>
<equals arg1="${directory.found.yes}" arg2="true" />
<then>
<antcall target="update.back" />
</then>
</if>

Ant using waitfor to run task until a porperty is set

I'm running the following code:
<target name="_queryForRunningJobs">
<ac:trycatch property="NODE_Reboot.failed">
<try>
<queryForRunningJob action="queryForRunningJob" jenkinsbaseURL="${targetRSSURL}" property="isRunningJobs" ignoreJobsLike="${ignore.jobs.like}"/>
<echo message="${isRunningJobs}"/>
<fail message="There is at least one job currently running on ${targetRSSURL}">
<condition>
<isset property="isRunningJobs"/>
</condition>
</fail>
</try>
<catch>
<echo message="NODE_Reboot EXCEPTION: ${NODE_Reboot.failed}"/>
<property name="reboot.failed.execution" value="${NODE_Reboot.failed"/>
<ac:var name="isRunningJobs" unset="true"/>
</catch>
<finally>
</finally>
</ac:trycatch>
</target>
I'd like to change the try block so that queryForRunningJob happens every hour for say 6 hours until isRunningJobs is NOT set, if it is I unset it and wait an hour.
I've been trying to use waitFor, but I can't get it to run the custom task and also check that the property is not set.
Does anyone know how to do this?
You can use the not and isset conditions in the waitfor to make sure the variable is unset.
As for checking whether isRunningJobs is set or not, you can create a separate thread using parallel.

ANT: How to read property setted in a foreach loop

Dear, I currently face some problem to retrieve the value of a property setted in a foreach loop. Maybe one of you could help me...
The purpose is to check if one file of a folder has been modified since the corresponding jar has been generated. This way I know if I have to generate the jar again.
What I do is to go through the folder with a foreach loop and if one file match my test, set a property to true.
The problem is that my variable doesn't seems to exist after my loop... Here is a simplified code example that has the same problem:
<target name="target">
<taskdef resource="net/sf/antcontrib/antlib.xml" classpath="${lib.dir}/ant-contrib.jar"></taskdef>
<foreach target="setVar" param="var" list="a,b"/>
<echo>myreturn in target: ${env.myreturn}</echo>
<property name="env.myreturn" value="c"/>
<echo>myreturn in second: ${env.myreturn}</echo>
</target>
<target name="setVar">
<property name="env.myreturn" value="${var}"/>
<echo>myreturn in setVar: ${env.myreturn}</echo>
</target>
The result of this code is:
target:
setVar:
[echo] myreturn in setVar: a
setVar:
[echo] myreturn in setVar: b
[echo] myreturn in target: ${env.myreturn}
[echo] myreturn in second: c
BUILD SUCCESSFUL
It seems that the variable is correctly set as it could be printed in the "setVar" target but no way to retrieve value from the calling target.
I also know it's not possible to assign a value to a property twice. But the problem doesn't even occurs... When it'll be the case I could add a check on the value of the property before to assign it to be sure it is not already initialized...
Do you have a clue on the way I can solve my problem ???
Many thanks in advance for your help :)
Try <for> task from ant-contrib instead of <foreach>. The <for> task takes advantage of Ant macro facility that came later. It works faster and is more flexible than the older <foreach> task. You are in the same project context when using <for>. That means properties set in the loop will be visible outside of the loop. Of course, normal rules for properties apply... you only get to set it once... unless you use <var> task from ant-contrib to overwrite or unset previously set properties.
Ah the joys of Ant hacking.
Not sure about your foreach problem, but can you not use the uptodate task for your requirement?
Even if I don't need it anymore thanks to sudocode, I found a solution for my question. Maybe it could be useful for someone else...
A collegue talked about the "antcallback" target of ant-contrib: it allows to return a result from a called target to the calling one. With a combination of "for" target and "antcallback" it is possible to do what I wanted to do:
<target name="target">
<taskdef resource="net/sf/antcontrib/antlib.xml" classpath="${lib.dir}/ant-contrib.jar"></taskdef>
<for param="file">
<path>
<fileset dir="../myDirectory" includes="**/*" />
</path>
<sequential>
<antcallback target="setVar" return="retValue">
<param name="file" value="#{file}"/>
</antcallback>
</sequential>
</for>
<echo>result: ${retValue}</echo>
</target>
<target name="setVar">
<property name="retValue" value="${file}"/>
</target>
"file" contains the name of the file in the directory. It is given to the called target as parameter with value "#{file}" ('#' necessary due to "for" target implementation).
At the end of the main target, ${retValue} contains the first value setted by the "setVar" target. No error is thrown when trying to set it multiple times, so it's not necessary to check if variable has already been instantiated before to set it in "setVar" target.
The <foreach> task uses the same logic as <antcall> under the covers, and any proprrties set inside a target invoked by <antcall> do not have scope beyond the execution of that target.
In other words, the env.myreturn property that you define in the setVar target is lost as soon as execution of that target completes.
This sort of scripting really isn't what Ant is designed for. The Ant-contrib library tries to patch up the holes, but it's still bending it way out of shape.
If you need to write such scripts, and want to use Ant tasks to achieve them, have a look at Gradle instead. It's a rather lovely blend of Groovy (for scripting) and Ant (for the tasks).
The other approaches here (<for>, <var>, <groovy>properties.put(....)</groovy>, <property>, <antcallback>) did not work with ANT 1.9.4, so I used the file system similar to this (pseudocode):
<target name="outer">
<for> <antcall target="inner" /> </for>
<loadproperties srcfile="tmpfile.properties" />
<echo message="${outerprop}" />
</target>
<target name="inner">
<!-- did not work: -->
<!--
<property name="outerprop" value="true" />
<var name="outerprop" value="true" />
<groovy>properties.put('outerprop','true')</groovy>
<antcallback target="setouterprop" />
-->
<echo message="outerprop=true" file="tmpfile.properties" />
</target>
Maybe the other approaches did not work because of my <antcall>, but I need it here. (outerprop is initially unset)

Using ant, check if a particular string is found in a file

My requirement is that, using waitfor condition, ant should periodically check if string "Build Successful" is displayed in log file. If the string is found, then particular action should be performed.
Here's an example of one way you might do this:
<target name="wait-for">
<waitfor maxwait="15" maxwaitunit="second" timeoutproperty="build.timeout">
<resourcecontains resource="build.log" substring="Build Successful" />
</waitfor>
<antcall target="build-success" />
</target>
<target name="build-success" depends="build-fail" unless="build.timeout">
<echo message="Success" />
</target>
<target name="build-fail" if="build.timeout">
<echo message="Fail" />
</target>
Use the resourcecontains condition to look for the string in the named resource - in this case the file 'build.log'.
If it's not found in the allotted time, the build.timeout property is set. There are two targets, one that is to be run
if the string is found, the other if not. The 'target' attributes if, unless, and depends are used to make the if-else logic need. If you only need to take an action in the case of success or failure, you can simplify slightly.

Resources