Ant’s Role in Enhancing Enterprise Capabilities with EWM & EWM EE

Getting Started What is Ant?

Ant is a build tool that is implemented as a scripting language, which is based on the JavaTM platform. Using Java as its platform allows Ant to be run on any system that supports Java in a variety of ways. Ant can be run via the command line, from a shell script or batch job, or from other applications like EclipseTM, a Jazz Build Engine (JBE), or a Rational Build Forge Agent (BFA). Ant scripts can be written such that they can be run in multiple environments without alteration or they can be written and customized for a specific target environment. Engineering Workflow ManagementTM (EWM) builds use Ant as the basic build tool. The flexibility of Ant allows you to customize how the EWM build is processed and how it is integrated into your software development workflow.

The scripting language implementation allows Ant to be extended to provide services beyond a simple build. In the case of EWM, Ant has been extended to allow for process automation – updating work items, checking work item conditions, triggering process actions based on build results – source control automation – updating files, delivering changes, flowing changes downstream, promoting changes from test to production – deployment automation – packaging build artifacts, deploying packages to other systems – and more.

Ant scripts are written in XML in a pseudo-programming language format. Each Ant script starts with an XML project element. The project element contains a top-level section, which is always executed when the script begins, and 0-n target elements, which can be required or optional, that are executed in a user-defined order. In a well-designed script a target will accomplish a defined unit of work: fetch files for a build; compile source files into an executable; publish the build results.

The basic building blocks used to complete a unit of work in an Ant build script target element are tasks. Each Ant task performs a specific function and is referenced by a unique name: copy to copy a file; delete to delete a file; and so on. There is an extensive list of built-in Ant tasks, and an even more extensive collection of tasks that have been contributed to Ant including those provided by the EWM.

The Engineering Workflow Management Ant tasks offer a variety of services that can be included in a build:

Controlling the build life cycle
Updating build progress monitoring
Publishing build results and contributions
Packaging and deployment of build results
Creating and maintaining build definitions
Working with EWM work items
Working with EWM source control
Creating and maintaining Enterprise Extensions system definitions  and more…

To use the EWM Ant tasks a general understanding of the Ant build environment and Ant build scripts is needed. For a general overview and introduction to Ant refer to the Apache Ant Manual that is appropriate for the version of Ant that you are running. The “Introduction”, “Using Apache Ant”, and “Running Apache Ant” sections provide an excellent overview. Refer to the “Ant Tasks” and “Concepts and Types” sections for more in-depth reference material.

Ant build environment

Ant runs in a Java JVM. It can be started from the command line via the ant command or directly using Java with one of the following Java command argument sequences:

java -Dant.home=c:\ant org.apache.tools.ant.Main [options] [target]
                              -or-
java -Dant.home=c:\ant org.apache.tools.ant.launch.Launcher [options] [target]

For more information on running Ant from either the command line or directly using Java, see Running Apache Ant. This documentation also provides a full list of arguments and options for the Ant application. Also note that the EWM extensions to Ant can be included in a stand-alone environment like this by including the “-lib /path_to_Build_Toolkit” option on the Java command.

Under Eclipse, Ant can be invoked by right-clicking on an Ant script file and choosing the “Run As -> Ant Build” option. Numerous extensions to Ant are available under Eclipse including those provided by the EWM.

A JBE or RBA build invokes Ant via Java. The EWM extensions to Ant are identified by a -lib argument on the Java command that points to the Build Toolkit folder where all the EWM extensions to Ant are housed.

Ant build scripts

In all environments, the primary argument for Ant is a path to the build script (-f), the script to run for the invocation, which defaults to the build.xml file in the current directory. The build script describes a list of steps to perform, called targets, and the order in which they should be performed. The format of an Ant build script is an XML document that is bounded by a project element containing top-level tasks and typically at least one target element.1 A target element consists of a set of Ant tasks that are executed sequentially to perform a unit of work.

For example, the following excerpt defines a target named “compile” which creates an output directory, compiles a set of Java source code, and creates a jar from the compiled output (the details for each of the following Ant tasks have been omitted for clarity):

<target name="compile">
    <mkdir> - create a directory
    <javac> - compile Java code
    <jar>   - create a jar file

</target>
1Note: A build script can consist of just the top-level area of the project element. This is a common format for imported definition files for macros, tasks, and types, but an uncommon format for a typical build script.

The following is an example build script.

The script starts with an XML declaration on line 1.

Lines 2-9 contain a copyright in the form of a comment; comments start with “<!–” and end with “–>”.

Lines 10-14 define the start of the project element. The project element declares the default target – “all” on line 47, the name of the project – “CreateWorkspace”, and an antlib namespace which will be covered later.

The top-level section of the script is between line 14 and line 21. Top-level sections and the tasks they contain will always be executed, regardless of what targets are executed. In the top-level section a description is defined, as well as Ant properties, via a loadProperties task and a set of property tasks.

There are three main targets defined – init, main, and term – on lines 25, 30-39, and 44.
The last target on line 47 is the default target which in this case defines the order in which the other targets will be executed. !”Finally, line 48 completes the project element.

 

Ant tasks and types

Ant tasks perform the actions to complete a unit of work. Each task is identified by a unique element name, which usually describes the action the task performs. Attributes specified on the task element provide the information necessary for the task to perform the action; a path to a file to copy, the name of the directory to make, the ID of the work item to fetch, and so on. Ant types are used to provide extended information to a task when a single attribute is insufficient; a list of file paths to include in a jar, a list of work item properties to fetch, conditions when an action should be taken, and so on.

In the following example a target named “main” is defined. Within the main target a deleteBuildResults task is defined with attributes that specify the EWM repository URL, the userid and password to use to login to the server, and the ID of the build whose results should be processed. In the example the actual values for the attributes are held in properties – ${propertyName} – that will be resolved before being passed to the deleteBuildResults task. Within the deleteBuildResults task element an includeResult type is defined which limits the results to be deleted to personal builds older than 2 days.



Using EWM tasks and types

To start working with the EWM Ant tasks you must first define the tasks and types to Ant. Unlike the built-in tasks described in the Ant documentation, Ant Tasks, the EWM tasks are contributions to the Ant platform and need to be identified to be used. There are numerous ways to define the tasks to Ant, here we will discuss the six most common in order of preference:

1. Define an antlib namespace in the project element.
2. Use the loadBuildExtensions task to identify additional participating tasks.
3. Use the taskdef and typedef resource attribute and the built-in property files.
4. Run the build script under the EWM Eclipse client where all tasks and types have been identified.
5. Run the supplied Ant script which includes a taskdef for each task and typedef for each type.
6. Code individual taskdef and typedef tasks for the tasks/types needed in the top-level section of your script.

The following table describes the support that each toolkit provides for each of the task definition methods. Any column marked with a “•” signifies that that toolkit supports that definition method.

 

[1] z/OS environment only
[2] IBMi environment only
[3] Code shared between z/OS and IBMi environments and included in system-specific Enterprise Build Toolkits
[4] Code shared between z/OS and IBMi environments and included in system-specific Enterprise System Definition Toolkits
[5] These tasks are accessible using the Load Build Extensions methodology when the iItems=”true” is specified when loadBuildExtensions is invoked [6] These tasks are accessible using the Load Build Extensions methodology when the zItems=”true” is specified when loadBuildExtensions is invoked [7] Due to naming conflicts between z/OS and IBMi tasks and Eclipse limitations, some IBMi tasks names have been prefixed with “ibmi.”

The following toolkits include common tasks and types from the Enterprise Build Toolkit (com.ibm.team.enterprise.build.ant): !”Enterprise Build Toolkit – z/OS (com.ibm.team.enterprise.zos.build.ant)

Enterprise Build Toolkit – IBMi (com.ibm.teamp.build.toolkit)
The following toolkits include common tasks and types from the Enterprise System Definition Toolkit (com.ibm.team.enterprise.systemdefinition.toolkit):

Enterprise System Definition Toolkit – z/OS (com.ibm.team.enterprise.zos.systemdefinition.toolkit) !”Enterprise System Definition Toolkit – IBMi (com.ibm.team.enterprise.ibmi.systemdefinition.toolkit)

Due to naming conflicts between z/OS and IBMi tasks, the following IBMi tasks have been prefaced with “ibmi.”.

export
fileMetadata !”fileMetadataDelete !”folderMetadata !”folderMetadataDelete !”init
langDef !”resolveMetadata !”sourceCodeData !”toolkitInit !”toolkitTerm !”translator

For example, the export task for IBMi system definitions is ibmi.export. This only affects access to these tasks using the Eclipse plugin methodology. All other methods use the standard names for these tasks.


Antlib namespace

The antlib namespace is the easiest, and thus most preferred, method for defining contributed tasks to Ant. It is a built-in feature of XML parsers and fully supported by Ant. This method uses an attribute of the project element, xmlns, to signal Ant and its XML parsing routines to define all of the tasks and types defined in the antlib.xml file in the top-level directory of the specified jar. For example, the following project element defines two antlib namespaces, one for the AntContrib tasks and one for the Build Extensions tasks:

<project
    basedir="."
    default="all"
    name="FindWorkItemIdForWorkItemType"
    xmlns:ac="antlib:net.sf.antcontrib"
    xmlns:xt="antlib:com.ibm.team.build.extensions.toolkit">

In the example, the first xmlns defines the “ac” namespace – xmlns:ac – to the tasks and types defined in the antlib.xml file in the primary, or top-level, package of the AntContrib jar you are using: net.sf.antcontrib. At this point all of the AntContrib tasks are accessible to the script by prefacing the task element name with “ac:” as in the following AntContrib switch clause example (notice that both tasks, switch, and types, case and default, are prefaced with the “ac:” namespace:

<ac:switch value="${tmp.authenticationPolicy}">
    <ac:case value="CERTIFICATEFILE">
        <startBuildActivity
                repositoryAddress="@{repositoryAddress}"
                userId="@{userId}"
                certificateFile="@{certificateFile}"
                autoComplete="true"
                buildResultUUID="@{buildResultUUID}"
                label="@{label}"/>
    </ac:case>
    <ac:case value="INTEGRATEDWINDOWS">
        <startBuildActivity
                repositoryAddress="@{repositoryAddress}"
                integratedWindows="@{integratedWindows}"
                autoComplete="true"
                buildResultUUID="@{buildResultUUID}"
                label="@{label}"/>
    </ac:case>
    <ac:default>
        <startBuildActivity
                repositoryAddress="@{repositoryAddress}"
                userId="@{userId}"
                password="@{password}"
                autoComplete="true"
                buildResultUUID="@{buildResultUUID}"
                label="@{label}"/>
    </ac:default>
</ac:switch>

The second xmlns defines the “xt” namespace to the tasks and types defined in the antlib.xml file in the primary, or top-level, package in the Build Extensions jar you are using: com.ibm.team.build.extensions.toolkit. Notice that the version information in the jar file name is not a factor when using this method; any version of the jar file will satisfy this namespace definition. At this point, all of the Build Extensions tasks are accessible to the script by prefacing the task element name with “xt:” as in the following example:

<xt:deleteBuildResults
    repositoryAddress="${repositoryAddress}"
    userId="${userId}"
    password="${password}"
    buildId="${buildDefinition}">
    <xt:includeResult>
        <xt:buildProperty name="buildDefinitionId" value="${buildDefinition}"/>
    </xt:includeResult>
</xt:deleteBuildResults>

The namespace value can be anything that you choose, but it is always best to choose something short, descriptive, and memorable. One more word to the wise, once you have decided on a namespace value, be consistent and use the same value in all of your Ant scripts. For more information on Ant namespace support, refer to XML Namespace Support.

Load build extensions task

The loadBuildExtensions task is used to register participating EWM and Enterprise Extensions Ant tasks and types under the Build Extensions toolkit namespace. This function allows all participating tasks and types to be referenced by a common namespace. The idea behind this task is to make referencing the various Ant tasks spread across the numerous jars described above easier by using a single namespace, that of the Build Extensions tasks, instead of a namespace for each individual jar. See the loadBuildExtensions documentation for more information on the task.

There are two requirements to use this method for defining contributed tasks to Ant. First, you must include a namespace definition for the Build Extensions toolkit. Second, you must include the loadBuildExtensions task in the script. The most common location for the task is in the top-level section of the script as in the following example:

 

Immediately following the loadBuildExtensions task all tasks and types from all participating jars are accessible using the namespace defined for the Build Extensions toolkit, “xt” in the example.

Property files

Another way to define contributed tasks to Ant is with a property file included in the jar. The AntContrib toolkit and the EWM toolkits identified in the Toolkit Support for Task/Type Definition Methods support this method. To use this method you include a taskdef task in the top-level section of the build script that identifies the path to the properties file in the appropriate jar and a path to the jar. Any of the following examples can be used as a template for the taskdef task:

!”Define AntContrib tasks when the jar location is known:
<taskdef resource=”net/sf/antcontrib/antcontrib.properties”

         classpath="${path_to_jar}/ant-contrib-1.0b3.jar"/>

Define AntContrib tasks when the jar location or name is unknown:

     <taskdef resource="net/sf/antcontrib/antcontrib.properties">
         <classpath>
             <fileset dir="${commonPath}/external_libs" includes="**/*.jar"/>
         </classpath>

</taskdef>

Define Build Extensions tasks when the jar location is known:

     <taskdef
         resource="com/ibm/team/build/extensions/toolkit/antTasks.properties"
         classpath="${path_to_jar}/com.ibm.team.build.extensions.toolkit_1.1.600.v20200807_1702.jar"/>
     <typedef
         resource="com/ibm/team/build/extensions/toolkit/antTypes.properties"
         classpath="${path_to_jar}/com.ibm.team.build.extensions.toolkit_1.1.600.v20200807_1702.jar"/>

Define Build Extensions tasks when the jar location or name is unknown:

     <taskdef resource="com/ibm/team/build/extensions/toolkit/antTasks.properties"
         <classpath>
             <fileset dir="${installPath}/jazz/buildsystem/buildtoolkit"
                 includes="**/com.ibm.team.build.extensions.toolkit*.jar"/>
         </classpath>
     </taskdef>
     <typedef resource="com/ibm/team/build/extensions/toolkit/antTypes.properties"
         <classpath>
             <fileset dir="${installPath}/jazz/buildsystem/buildtoolkit"
                 includes="**/com.ibm.team.build.extensions.toolkit*.jar"/>
         </classpath>
     </typedef>

Note that the EWM toolkits have two properties files, “antTasks.properties” for tasks and “antTypes.properties” for types, and that each needs to be identified to define all the pieces in that toolkit. Also note that the jar file name for EWM toolkits will include version information, and therefore, the jar file names will change with new releases. It is recommended to use the more generic method for an unknown jar file name so that code need not be updated when a new version of EWM is installed.

Immediately following the taskdef task all tasks and types from the jars are accessible using just the name of the task. The following example assumes that the AntContrib tasks have been defined as above. Note that the AntContrib propertyregex task is not prefaced by a namespace, but instead identified by just its name:

<macrodef name="GetExportCreateBuild">
    <attribute name="property"/>
    <attribute name="testcase"/>
    <sequential>
<local name="lcl.buildType"/>

 

 <propertyregex
            property="lcl.buildType"
            input="@{testcase}"
            regexp="^ExportBuildDefinition(.*)"
            select="\1" override="true"/>
        <property name="@{property}"
            value="CreateBuildDefinition${lcl.buildType}.xml"/>
        <echo>createBuild: ${@{property}}</echo>
    </sequential>

</macrodef>

Eclipse plugin

The fourth way to define contributed tasks to Ant is supplied by EWM when definitions for the tasks and types are included in the toolkit’s plugin definition. The Toolkit Support for Task/Type Definition Methods table identifies which toolkits support this method. To run one of the EWM Ant tasks identified in this manner, run the build script under Eclipse and specify just the name of the task in the script. The tasks are automatically available in the Ant environment created by Eclipse to run the script. The following explains how to run an Ant script under Eclipse:

 




Supplied script

Some of the EWM toolkits described above supply a pre-written Ant script that uses the taskdef and typedef tasks described below to define contributed tasks to Ant. The Toolkit Support for Task/Type Definition Methods table identifies which toolkits support this method. To use this method in your script you simply import the script in the top-level section of your script. It has no targets, just a top-level section of its own that contains only taskdef and typedef statements. The following is an example of the code you will need:

<project>
    <import file="/path_to_file/BuildToolkitTaskDefs.xml"/>
    ...

</project>

The preferred method for importing the supplied scripts is shown in the following example. With this method the need to maintain the path to the supplied script is avoided thereby reducing maintenance activity when EWM is upgraded:

<import>
    <javaresource name="scripts/imports/BuildExtensionsToolkitTaskDefs.xml"/>

</import>

Supplied script locations

The following table can be used as a reference for the name and location of the supplied scripts for the EWM toolkits:

 

Taskdef and Typedef

The most basic means of defining contributed tasks to Ant is to include a taskdef task for each task that will be used by a script and a typedef task for all of the types that are used by the identified task. Using this method produces the most efficient code; no processing time is wasted defining tasks and types that will not be used by the script. The tradeoff for this efficiency is that it may take more effort to maintain the script as time passes and newer versions of underlying software are installed. All toolkits support this method.

To define a task using the taskdef task include a taskdef statement specifying the name and classname for the required Ant task. A taskdef statement is typically located in the top-level section of the Ant script, but may appear elsewhere if needed. For example:

<taskdef name="artifactFilePublisher" classname="com.ibm.team.build.ant.task.ArtifactFilePublisherTask"/>

Task names can be found in EWM documentation. You may actually use any name you choose, but it may make code maintenance difficult if different names are used for the same task in a large library of code. Classnames can be found within the target jar file by converting the path to the executable class to the classname format. For example:

/com/ibm/team/build/extensions/toolkit/ant/builddefinition/task/CreateBuildDefinitionTask.class


becomes

com.ibm.team.build.extensions.toolkit.ant.builddefinition.task.CreateBuildDefinitionTask

For more information and a completed description refer to the Taskdef and Typedef Ant documentation.

Examples

Pre-Build script to check approvals

The goal of this Ant script is to ensure that all “Code review” approvals have been completed before a build is processed. This means that the build workspace contains change sets to be built, that the change sets have been associated with, or linked to, one or more work items, that the work items have a “Code review” approval defined, and that the “Code review” must be approved before the build can proceed.

Workspace

The build workspace, “Test Workspace”, contains change sets to be built and the change sets have been associated with work items, “7,8”:






CheckApprovals script

The CheckApprovals Ant script satisfies the requirements described above assuming that the workspace and work items have been set up as described. A simplified version of the script is included below to illustrate the details of how the script accomplishes its task. The following discussion describes the meaning of critical aspects of the code using line number references:

 



 

CheckApprovals build Log

The following is a typical build log for the CheckApprovals Ant script with debugging information enabled. It shows the work items found when examining the workspace – 7,8 – the raw JSON output – one JSON array entry for each approval and five JSON object name-value pairs for the information associated with the approval – that the “cumstate” of the approval is “Approved” and that the “approvals” property was set to true:

CheckApprovals implementation

The CheckApprovals Ant script is supplied with EWM. A copy of it is located in the install_location/buildsystem/buildtoolkit/examples/build folder. You can use this example as is or modify it to suit your needs. If you modify the example it is highly recommended that you copy it to another location so that your modifications are not overlaid when applying maintenance. To implement the script, update your Enterprise Extensions Dependency Build definition and specify the path to the script in the “Pre-build script” field on the Dependency Build tab. To implement the script for a simple Jazz Build Engine Ant build, insert a call to the script at the beginning of your existing build script.

CheckApprovals.xml Source

The following is the source for the CheckApprovals.xml Ant script which can be downloaded here:

<?xml version="1.0" encoding="UTF-8"?>
<!--
    Licensed Materials - Property of IBM
    (c) Copyright IBM Corporation 2021. All Rights Reserved.
    Note to U.S. Government Users Restricted Rights:
    Use, duplication or disclosure restricted by GSA ADP Schedule
    Contract with IBM Corp.

–> <project

    basedir="."
    default="all"
    name="CheckApprovals"
    xmlns:ac="antlib:net.sf.antcontrib"
    xmlns:xt="antlib:com.ibm.team.build.extensions.toolkit">
    <description>CheckApprovals</description>
    <loadproperties srcFile="login.properties"/>
<import>
        <javaresource name="scripts/extensions/imports/WorkItemMacros.xml"/>

</import>

    <!-- - - - - - - - - - - - - - - - - - - *
    *  CheckApprovals init                   *
    *- - - - - - - - - - - - - - - - - - - -->
    <target name="init" description="init"/>
    <!-- - - - - - - - - - - - - - - - - - - *
    *  CheckApprovals main                   *
    *- - - - - - - - - - - - - - - - - - - -->
    <target name="main" description="main">
        <xt:getchangesetworkitems
            repositoryAddress="${repositoryAddress}"
            userId="${userId}"
            password="${password}"
            workspaceUUID="${workspaceUUID}"
            property="workItems"
        />
        <echo>${workItems}</echo>
        <ac:for list="${workItems}" param="workItem" delimiter="," trim="true">
            <sequential>
                <local name="approved"/>
                <CheckForApprovals
                    repositoryAddress="${repositoryAddress}"
                    userId="${userId}"
                    password="${password}"
                    approval="Code review"
                    property="approved"
                    workItemId="@{workItem}"
                />
                <echo>${approved}</echo>
                <fail message="Build failed: Code review approvals are not complete">
                    <condition>
                        <not>
                            <istrue value="${approved}"/>
                        </not>
                    </condition>
                </fail>
            </sequential>
        </ac:for>
    </target>
    <!-- - - - - - - - - - - - - - - - - - - *
    *  CheckApprovals term                   *
    *- - - - - - - - - - - - - - - - - - - -->
    <target name="term" description="term"/>
    <target depends="init,main,term" description="all" name="all"/>
</project>

CheckForApprovals Ant Macro

The CheckForApprovals macro is supplied with EWM. You do not need to install, duplicate, or update this macro. It is made available by the import task described previously. It is presented here for information purposes only. If you wish to copy and modify this macro for your own purposes in your own locally maintained source, feel free to do so.

The CheckForApprovals macro retrieves approvals information for the specified work item in JSON format. It calls the CheckForApprovalsScript script which searches for the specified approval. The following discussion describes the meaning of critical aspects of the code using line number references:





CheckForApprovals macro

The following is the source for the CheckForApprovals macro which can be downloaded here:

<!-- CheckForApprovals -->
<macrodef name="CheckForApprovals">
    <!-- TeamTask common -->
    <attribute name="repositoryAddress" default="${repositoryAddress}"/>
    <attribute name="userId" default="${userId}"/>
    <attribute name="password" default="${password}"/>
    <attribute name="certificateFile" default=""/>
    <attribute name="integratedWindows" default=""/>
    <attribute name="kerberos" default=""/>
    <attribute name="passwordFile" default="${valueFor:passwordFile}"/>
    <attribute name="repositoriesFile" default=""/>
    <attribute name="smartCard" default=""/>
    <attribute name="failOnError" default="true"/>
    <attribute name="reuseLoginOption" default="true"/>
    <attribute name="verbose" default="false"/>
    <!-- Macro specifics -->
    <attribute name="approval"/>
    <attribute name="property"/>
    <attribute name="workItemId"/>
    <sequential>
        <local name="lcl.approvals"/>
        <xt:addReference>
            <xt:getWorkItem id="getWorkItemTaskReference"/>
        </xt:addReference>
<TeamTask
                refid="getWorkItemTaskReference"
                repositoryAddress="@{repositoryAddress}"
                userId="@{userId}"
password="@{password}"
                certificateFile="@{certificateFile}"
                integratedWindows="@{integratedWindows}"
                kerberos="@{kerberos}"
                passwordFile="@{passwordFile}"
                repositoriesFile="@{repositoriesFile}"
                smartCard="@{smartCard}"
                failOnError="@{failOnError}"
                reuseLoginOption="@{reuseLoginOption}"
                verbose="@{verbose}"
            >
            <taskAttribute name="workItemId" value="@{workItemId}"/>
            <taskElement>
                <xt:fetch name="approvals" property="lcl.approvals" ApprovalsJson="true"/>
            </taskElement>

</TeamTask>

        <CheckForApprovalsScript approval="@{approval}" input="${lcl.approvals}" property="@{property}"/>
    </sequential>

</macrodef>

CheckForApprovalsScript script

The CheckForApprovalsScript script is supplied with the EWM. You do not need to install, duplicate, or update this script. It is made available by the import tasks described previously. It is presented here for information purposes only. If you wish to copy and modify this script for your own purposes in your own locally maintained source, feel free to do so.

The CheckForApprovalsScript script is written in JavaScript which has better facilities for parsing the getWorkItem JSON output. This script searches the JSON output for the specified approval. If the approval is found, and if it has a cumulative state of “Approved”, the “approved” property will be set to true. The following discussion describes the meaning of critical aspects of the code using line number references:

Line: Description:

These attributes are passed from the CheckForApprovals macro. The approval attribute specifies the text of the approval to search for; 97-99 “Code review” in this example. The input attribute passes the JSON output for the work item. The property attribute specifies the name of

the property to create with the result.

125-149 The traverse() function parses the JSON output which is a JSON array of JSON objects; one array entry for each approval and one object in each array entry for each approval name-value pair.

143-145 When the target array entry is processed and the target approval name-value pair is encountered, if the “cumstate” is set to “Approved” the result is set to true.

162 The specified property is set to the result of the search.

CheckForApprovalsScript source

The following is the source for the CheckForApprovalsScript script which can be downloaded here:

<!-- CheckForApprovalsScript -->
<scriptdef name="CheckForApprovalsScript" language="javascript">
    <attribute name="approval"/>
    <attribute name="input"/>
    <attribute name="property"/>
    <![CDATA[
    // Get input attributes
    var approval  = attributes.get("approval");
    var input     = attributes.get("input");
    var property  = attributes.get("property");
    // Get debug attributes
    var debugOn   = project.getProperty("debugOn");
    var debug     = project.getProperty("debug");
    // Set global variables
    var approved = "false";
    // Echo task for debugging
    echo = project.createTask("echo");
    function debugMsg(msg) {
        if (debugOn == "true" && debug == "true") {
            echo.setMessage(msg);
            echo.perform();

}

}

    // Function to traverse JSON
    var json = eval("(" + input + ")");
    function traverse(obj,lastkey) {
        var type = typeof obj;
        if (type == "object") {
            for (var key in obj) {
                var type = typeof obj[key];
                if (lastkey === undefined || lastkey == "" || lastkey == key) {
                    newkey = key;
                } else {
                    newkey = lastkey + ’.’ + key;
                }
                if (type == "object") {
                    traverse(obj[key],newkey);
                } else {
                    // Complete value
                    debugMsg("key=" + newkey + " " + "value=" + obj[key]);
                    // Check approvals
                    if (newkey.indexOf(approval) != -1 && newkey.indexOf("cumstate") != -1 && obj[key] == "Approved") {
                        approved = "true";
                    }

} }

} }

    // Debug messages
    debugMsg("approval=" + approval);
    debugMsg("input=" + input);
    // Main Processing
    traverse(json);
    // Debug messages
    debugMsg("property=" + property);
    debugMsg("approved=" + approved);
    project.setProperty(property,approved);
    ]]>
</scriptdef>


For more information



About the author

Arun K Sriramaiah has more than 15 years of experience in IBM Tools and DevOps. Can be contacted at arusrira@in.ibm.com and Daniel Reilly EWM Enterprice Extension development Can be contacted at djreilly@us.ibm.com

Dashboards and work items are no longer publicly available, so some links may be invalid. We now provide similar information through other means. Learn more here.
Feedback
Was this information helpful? Yes No 0 people rated this as helpful.