We are trying to implement our CI/CD with Azure DevOps (Pipelines) but we are facing a couple errors.

Basically we were trying to created just one build.xml and one build.properties files and dynamically change the values within these files based on the variables declared for each Pipeline.

Below are the files we are currently using:

enter image description here


<project name="Sample usage of Salesforce Ant tasks" default="deployCodeCheckOnly" basedir="." xmlns:sf="antlib:com.salesforce">

    <property file="build-sb.properties"/>
    <property environment="env"/>

    <!-- Setting default value for username, password and session id properties to empty string 
         so unset values are treated as empty. Without this, ant expressions such as ${sf.username}
         will be treated literally.
    <condition property="sf.username" value="${sf.username}"> <not> <isset property="sf.username"/> </not> </condition>
    <condition property="sf.password" value="${sf.password}"> <not> <isset property="sf.password"/> </not> </condition>

    <taskdef resource="com/salesforce/antlib.xml" uri="antlib:com.salesforce">
            <pathelement location="ant-salesforce.jar" />           

    <!-- Shows check only; never actually saves to the server -->
    <target name="deployCodeCheckOnly">
      <sf:deploy username="${sf.username}" password="${sf.password}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" pollWaitMillis="10000" deployRoot="../src" checkOnly="true"/>



# build.properties

# Specify the login credentials for the desired Salesforce organization
sf.username = usernamehere
sf.password = passwordhere
#sf.sessionId = <Insert your Salesforce session id here.  Use this or username/password above.  Cannot use both>
#sf.pkgName = <Insert comma separated package names to be retrieved>
#sf.zipFile = <Insert path of the zipfile to be retrieved>
#sf.metadataType = <Insert metadata type name for which listMetadata or bulkRetrieve operations are to be performed>

# Use 'https://login.salesforce.com' for production or developer edition (the default if not specified).
# Use 'https://test.salesforce.com for sandbox.
sf.serverurl = https://test.salesforce.com

sf.maxPoll = 2000
# If your network requires an HTTP proxy, see http://ant.apache.org/manual/proxy.html for configuration.

These are the variables defined for the Pipeline. The value for the password is pwd + token:

enter image description here

And here is our Ant Build script:

# Ant
# Build your Java projects and run tests with Apache Ant.
# Add steps that save build artifacts and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/java

  vmImage: 'ubuntu-latest'

- task: Ant@1
    workingDirectory: ''
    buildFile: 'build/build-sb.xml'
    options: -verbose -Dsalesforce.loginurl=$SF.LOGINURL -Dsalesforce.password=$SF.PASSWORD -Dsalesforce.testLevel=$SF.TESTLEVEL -Dsalesforce.username=$SF.USERNAME
    javaHomeOption: 'JDKVersion'
    jdkVersionOption: '1.8'
    jdkArchitectureOption: 'x64'
    publishJUnitResults: false
    testResultsFiles: '**/TEST-*.xml'

The problem happens if we don't explicitly enter the username/password and url in the build-sb.properties. We would like to dynamically populate these values based on the values declared for each Pipeline.

Here is what we get back from the logs if we don't enter these values:

##[section]Starting: Ant
Task         : Ant
Description  : Build with Apache Ant
Version      : 1.155.0
Author       : Microsoft Corporation
Help         : https://docs.microsoft.com/azure/devops/pipelines/tasks/build/ant
[command]/usr/bin/ant -version
Apache Ant(TM) version 1.9.6 compiled on July 20 2018
[command]/usr/bin/ant -buildfile /home/vsts/work/1/s/build/build-sb.xml -verbose -Dsalesforce.loginurl=$SF.LOGINURL -Dsalesforce.password=$SF.PASSWORD -Dsalesforce.testLevel=$SF.TESTLEVEL -Dsalesforce.username=$SF.USERNAME
Apache Ant(TM) version 1.9.6 compiled on July 20 2018
Buildfile: /home/vsts/work/1/s/build/build-sb.xml
Detected Java version: 1.8 in: /usr/lib/jvm/zulu-8-azure-amd64/jre
Detected OS: Linux
parsing buildfile /home/vsts/work/1/s/build/build-sb.xml with URI = file:/home/vsts/work/1/s/build/build-sb.xml
Project base dir set to: /home/vsts/work/1/s/build
parsing buildfile jar:file:/usr/share/ant/lib/ant.jar!/org/apache/tools/ant/antlib.xml with URI = jar:file:/usr/share/ant/lib/ant.jar!/org/apache/tools/ant/antlib.xml from a zip file
 [property] Loading /home/vsts/work/1/s/build/build-sb.properties
 [property] Loading Environment env.
parsing buildfile jar:file:/home/vsts/work/1/s/build/ant-salesforce.jar!/com/salesforce/antlib.xml with URI = jar:file:/home/vsts/work/1/s/build/ant-salesforce.jar!/com/salesforce/antlib.xml from a zip file
Build sequence for target(s) `deployCodeCheckOnly' is [deployCodeCheckOnly]
Complete build sequence is [deployCodeCheckOnly, ]

[antlib:com.salesforce] Could not load definitions from resource com/salesforce/antlib.xml. It could not be found.

/home/vsts/work/1/s/build/build-sb.xml:21: Attribute 'username' cannot be an empty string
    at com.salesforce.ant.SFDCAntTask.validateAttribute(SFDCAntTask.java:130)
    at com.salesforce.ant.SFDCAntTask.validateAttributes(SFDCAntTask.java:38)
    at com.salesforce.ant.SFDCMDAPIAntTask.validateAttributes(SFDCMDAPIAntTask.java:41)
    at com.salesforce.ant.DeployTask.execute(DeployTask.java:57)
    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:293)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
    at org.apache.tools.ant.Task.perform(Task.java:348)
    at org.apache.tools.ant.Target.execute(Target.java:435)
    at org.apache.tools.ant.Target.performTasks(Target.java:456)
    at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1405)
    at org.apache.tools.ant.Project.executeTarget(Project.java:1376)
    at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
    at org.apache.tools.ant.Project.executeTargets(Project.java:1260)
    at org.apache.tools.ant.Main.runBuild(Main.java:853)
    at org.apache.tools.ant.Main.startAnt(Main.java:235)
    at org.apache.tools.ant.launch.Launcher.run(Launcher.java:285)
    at org.apache.tools.ant.launch.Launcher.main(Launcher.java:112)

Total time: 1 second
The process '/usr/bin/ant' failed with exit code 1
##[error]Error: The process '/usr/bin/ant' failed with exit code 1
##[section]Finishing: Ant

Here is the documentation about the Pipeline Variables:

To reference a variable in YAML, prefix it with a dollar sign and enclose it in parentheses. For example: $(variable-name)

To use a variable in a script, use environment variable syntax. Replace . and space with _, capitalize the letters, and then use your platform's syntax for referencing an environment variable. Examples:

Batch script: %VARIABLE-NAME%

PowerShell script: $env:VARIABLE-NAME

Bash script: $VARIABLE-NAME

We have tried every possible way of referencing these variables within build-sb.properties without success.

$SF.USERNAME, $SF_USERNAME, $(sf_username), $(sf.username), etc.....

Any ideas?

Also, even when it works, we always get this message in the log:

[antlib:com.salesforce] Could not load definitions from resource com/salesforce/antlib.xml. It could not be found.
[sf:deploy] Note: use ant -verbose to get more information on the failure

This is really driving us crazy...


  • what is there in your src folder , i want to know the directory structure
    – Hunt
    Mar 3, 2020 at 11:47

3 Answers 3


After more than a week working on this, we found the reason why we weren't able to pass the password to the build.properties. In Azure DevOps, in order to reference a variable, we need to start with the $ sign.

Our password we had created and stored for the password variable in Azure was $alesforce. This was for testing only :)

Because it started with $ it was been interpreted as a variable. After we switched to something else that didn't start with the $ it worked as expected!


Have you tried this inside your YAML file?

task: Ant@1
workingDirectory: ''
Options: -verbose -Dsalesforce.url=$(sf.url),Dsalesforce.password=$(sf.password),Dsalesforce.username=$(sf.username)

Check out the following video because it is using Ant Migration Tool with AzureDevOps as well and the YAML had the variable group options mentioned above. Link


Issue is with the below highlighted line

<taskdef resource="com/salesforce/antlib.xml" uri="antlib:com.salesforce">
        **<pathelement location="ant-salesforce.jar" />**           

Unable to find your ant-salesforce,jar reason being you .jar is under build folder. So in the script it should be

**<pathelement location="build/ant-salesforce.jar" />** 

it will solve your problem

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .