Defines some macros around sf:deploy to install and uninstall packages.
<!-- TODO: Review Ant v1.8 local properties --> | |
<project xmlns:sf="antlib:com.salesforce"> | |
<!-- Download from Salesforce Tools page under Setup --> | |
<typedef | |
uri="antlib:com.salesforce" | |
resource="com/salesforce/antlib.xml" | |
classpath="${basedir}/lib/ant-salesforce.jar"/> | |
<!-- Download from http://sourceforge.net/projects/ant-contrib/files/ant-contrib/1.0b3/ --> | |
<taskdef | |
resource="net/sf/antcontrib/antlib.xml" | |
classpath="${basedir}/lib/ant-contrib-1.0b3.jar" | |
/> | |
<!-- Download from https://code.google.com/p/missing-link/ --> | |
<taskdef | |
name="http" | |
classname="org.missinglink.ant.task.http.HttpClientTask" | |
classpath="${basedir}/lib/ml-ant-http-1.1.3.jar"/> | |
<!-- Download from http://www.oopsconsultancy.com/software/xmltask/ --> | |
<taskdef | |
name="xmltask" | |
classname="com.oopsconsultancy.xmltask.ant.XmlTask" | |
classpath="${basedir}/lib/xmltask.jar"/> | |
<macrodef name="installPackage" description="Installs the given managed package"> | |
<attribute name="namespace" description="Namespace of managed package to install."/> | |
<attribute name="version" description="Version of managed package to install."/> | |
<attribute name="packagePassword" description="Password used to install the pacakge. Optional." default=""/> | |
<attribute name="username" description="Salesforce user name."/> | |
<attribute name="password" description="Salesforce password."/> | |
<sequential> | |
<!-- Generate optional <password> element? --> | |
<if><equals arg1="@{packagePassword}" arg2=""/> | |
<then><property name="passwordElement" value=""/></then> | |
<else><property name="passwordElement" value="<password>@{packagePassword}</password>"/></else> | |
</if> | |
<!-- Generate working folder and metadata files representing the package to install --> | |
<delete dir="${basedir}/installdeploy"/> | |
<mkdir dir="${basedir}/installdeploy"/> | |
<mkdir dir="${basedir}/installdeploy"/> | |
<mkdir dir="${basedir}/installdeploy/installedPackages"/> | |
<echo file="${basedir}/installdeploy/package.xml"><![CDATA[<Package xmlns="http://soap.sforce.com/2006/04/metadata"><types><members>@{namespace}</members><name>InstalledPackage</name></types><version>28.0</version></Package>]]></echo> | |
<echo file="${basedir}/installdeploy/installedPackages/@{namespace}.installedPackage"><![CDATA[<InstalledPackage xmlns="http://soap.sforce.com/2006/04/metadata"><versionNumber>@{version}</versionNumber>${passwordElement}</InstalledPackage>]]></echo> | |
<sf:deploy deployRoot="${basedir}/installdeploy" username="@{username}" password="@{password}"/> | |
</sequential> | |
</macrodef> | |
<macrodef name="uninstallPackage" description="Uninstalls the given managed package"> | |
<attribute name="namespace" description="Namespace of managed package to install."/> | |
<attribute name="username" description="Salesforce user name."/> | |
<attribute name="password" description="Salesforce password."/> | |
<sequential> | |
<!-- Generate working folder and metadata files representing the package to uninstall --> | |
<delete dir="${basedir}/installdeploy"/> | |
<mkdir dir="${basedir}/installdeploy"/> | |
<mkdir dir="${basedir}/installdeploy"/> | |
<mkdir dir="${basedir}/installdeploy/installedPackages"/> | |
<echo file="${basedir}/installdeploy/package.xml"><![CDATA[<Package xmlns="http://soap.sforce.com/2006/04/metadata"><version>28.0</version></Package>]]></echo> | |
<echo file="${basedir}/installdeploy/destructiveChanges.xml"><![CDATA[<Package xmlns="http://soap.sforce.com/2006/04/metadata"><types><members>@{namespace}</members><name>InstalledPackage</name></types><version>28.0</version></Package>]]></echo> | |
<echo file="${basedir}/installdeploy/installedPackages/@{namespace}.installedPackage"><![CDATA[<InstalledPackage xmlns="http://soap.sforce.com/2006/04/metadata"><versionNumber>@{version}</versionNumber></InstalledPackage>]]></echo> | |
<sf:deploy deployRoot="${basedir}/installdeploy" username="@{username}" password="@{password}"/> | |
</sequential> | |
</macrodef> | |
<!-- Deploys the given file as a static resource via the sf:deploy Ant task (Metadata API) --> | |
<macrodef name="staticResource"> | |
<attribute name="username" description="Salesforce user name."/> | |
<attribute name="password" description="Salesforce password."/> | |
<attribute name="developername" description="Developer name for the Static Resource."/> | |
<attribute name="file" description="Source file for the static resource."/> | |
<attribute name="contenttype" description="Content type of the Static Resource."/> | |
<sequential> | |
<!-- Generate working folder and metadata files representing the package to uninstall --> | |
<delete dir="${basedir}/staticresourcedeploy"/> | |
<mkdir dir="${basedir}/staticresourcedeploy"/> | |
<mkdir dir="${basedir}/staticresourcedeploy"/> | |
<mkdir dir="${basedir}/staticresourcedeploy/staticresources"/> | |
<echo file="${basedir}/staticresourcedeploy/package.xml"><![CDATA[<Package xmlns="http://soap.sforce.com/2006/04/metadata"><types><members>*</members><name>StaticResource</name></types><version>29.0</version></Package>]]></echo> | |
<copy file="@{file}" tofile="${basedir}/staticresourcedeploy/staticresources/@{developername}.resource"/> | |
<echo file="${basedir}/staticresourcedeploy/staticresources/@{developername}.resource-meta.xml"><![CDATA[<StaticResource xmlns="http://soap.sforce.com/2006/04/metadata"><cacheControl>Private</cacheControl><contentType>@{contentType}</contentType></StaticResource>]]></echo> | |
<sf:deploy deployRoot="${basedir}/staticresourcedeploy" username="@{username}" password="@{password}"/> | |
</sequential> | |
</macrodef> | |
<!-- Provides access to the Salesforce Tooling REST API ExecuteAnnoynmous resource --> | |
<macrodef name="executeApex" description="Provides access to the Salesforce Tooling REST API ExecuteAnnoynmous resource"> | |
<attribute name="username" description="Salesforce user name."/> | |
<attribute name="password" description="Salesforce password."/> | |
<attribute name="resultprefix" description="Property name prefix used for properties containing response data" default="executeAnonymousResponse"/> | |
<attribute name="failonerror" description="If the execute fails then fail the Ant script" default="true"/> | |
<text name="apexcode"/> | |
<sequential> | |
<!-- Login --> | |
<login username="@{username}" password="@{password}" serverurl="serverUrl" sessionId="sessionId"/> | |
<!-- Execute Apex via Tooling API /executeAnonymous resource --> | |
<http url="https://na11.salesforce.com/services/data/v29.0/tooling/executeAnonymous" method="GET" entityProperty="executeAnonymousResponse" statusProperty="loginResponseStatus"> | |
<headers> | |
<header name="Authorization" value="Bearer ${sessionId}"/> | |
</headers> | |
<query> | |
<parameter name="anonymousBody" value="@{apexcode}"/> | |
</query> | |
</http> | |
<!-- Parse JSON response and set properites --> | |
<script language="javascript"> | |
var response = eval('('+project.getProperty('executeAnonymousResponse')+')'); | |
for(field in response) | |
project.setProperty('@{resultprefix}.' + field, response[field]); | |
</script> | |
<!-- Fail on error?--> | |
<if> | |
<and> | |
<equals arg1="@{failonerror}" arg2="true"/> | |
<equals arg1="${@{resultprefix}.success}" arg2="false"/> | |
</and> | |
<then> | |
<if> | |
<equals arg1="${@{resultprefix}.compiled}" arg2="false"/> | |
<then> | |
<fail message="${@{resultprefix}.line}:${@{resultprefix}.column} ${@{resultprefix}.compileProblem}"/> | |
</then> | |
<else> | |
<fail message="${@{resultprefix}.exceptionMessage} ${@{resultprefix}.exceptionStackTrace}"/> | |
</else> | |
</if> | |
</then> | |
</if> | |
</sequential> | |
</macrodef> | |
<!-- Provides access to the Salesforce Tooling REST API StaticResource resource --> | |
<macrodef name="staticResource.toolingapi" description="Provides access to the Salesforce Tooling REST API StaticResource resource"> | |
<attribute name="username" description="Salesforce user name."/> | |
<attribute name="password" description="Salesforce password."/> | |
<attribute name="developername" description="Developer name for the Static Resource."/> | |
<attribute name="body" description="Base64 encoded data for the Static Resource."/> | |
<attribute name="contenttype" description="Content type of the Static Resource."/> | |
<sequential> | |
<!-- Login --> | |
<login username="@{username}" password="@{password}" serverurl="serverUrl" sessionId="sessionId"/> | |
<!-- Create the StaticResource (later versions of this macro can support other operations) --> | |
<http url="https://na11.salesforce.com/services/data/v29.0/tooling/sobjects/StaticResource/" printresponse="true" printrequest="true" expected="201" method="POST" entityProperty="executeAnonymousResponse" statusProperty="loginResponseStatus"> | |
<headers> | |
<header name="Content-Type" value="application/json"/> | |
<header name="Authorization" value="Bearer ${sessionId}"/> | |
</headers> | |
<entity> | |
{ | |
"Name": "@{developerName}", | |
"Body": "@{body}", | |
"ContentType" : "@{contentType}" | |
} | |
</entity> | |
</http> | |
</sequential> | |
</macrodef> | |
<!-- Login into Salesforce and return the session Id and serverUrl --> | |
<macrodef name="login"> | |
<attribute name="username" description="Salesforce user name."/> | |
<attribute name="password" description="Salesforce password."/> | |
<attribute name="serverurl" description="Server Url property."/> | |
<attribute name="sessionId" description="Session Id property."/> | |
<sequential> | |
<!-- Obtain Session Id via Login SOAP service --> | |
<http url="https://login.salesforce.com/services/Soap/c/29.0" method="POST" failonunexpected="false" entityProperty="loginResponse" statusProperty="loginResponseStatus"> | |
<headers> | |
<header name="Content-Type" value="text/xml"/> | |
<header name="SOAPAction" value="login"/> | |
</headers> | |
<entity> | |
<![CDATA[ | |
<env:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'> | |
<env:Body> | |
<sf:login xmlns:sf='urn:enterprise.soap.sforce.com'> | |
<sf:username>@{username}</sf:username> | |
<sf:password>@{password}</sf:password> | |
</sf:login> | |
</env:Body> | |
</env:Envelope> | |
]]> | |
</entity> | |
</http> | |
<!-- Parse response --> | |
<xmltask destbuffer="loginResponseBuffer"> | |
<insert path="/">${loginResponse}</insert> | |
</xmltask> | |
<if> | |
<!-- Success? --> | |
<equals arg1="${loginResponseStatus}" arg2="200"/> | |
<then> | |
<!-- Parse sessionId and serverUrl --> | |
<xmltask sourcebuffer="loginResponseBuffer" failWithoutMatch="true"> | |
<copy path="/*[local-name()='Envelope']/*[local-name()='Body']/:loginResponse/:result/:sessionId/text()" property="@{sessionId}"/> | |
<copy path="/*[local-name()='Envelope']/*[local-name()='Body']/:loginResponse/:result/:serverUrl/text()" property="@{serverUrl}"/> | |
</xmltask> | |
</then> | |
<else> | |
<!-- Parse login error message and fail build --> | |
<xmltask sourcebuffer="loginResponseBuffer" failWithoutMatch="true"> | |
<copy path="/*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='Fault']/*[local-name()='faultstring']/text()" property="faultString"/> | |
</xmltask> | |
<fail message="${faultString}"/> | |
</else> | |
</if> | |
</sequential> | |
</macrodef> | |
<!-- Base64 encode a files data --> | |
<macrodef name="base64encode"> | |
<attribute name="file" description="File to base 64 encode."/> | |
<attribute name="base64" description="Property to store the base 64 encoded data."/> | |
<sequential> | |
<loadfile property="filedata" srcFile="@{file}"/> | |
<script language="javascript"> | |
importClass(javax.xml.bind.DatatypeConverter); | |
project.setProperty('@{base64}', | |
DatatypeConverter.printBase64Binary( | |
new java.lang.String(project.getProperty('filedata')).getBytes("UTF-8"))); | |
</script> | |
</sequential> | |
</macrodef> | |
<!-- Provides access to the Salesforce REST API for a SOQL query --> | |
<macrodef name="runQuery" description="Run database query"> | |
<attribute name="sessionId" description="Salesforce user name."/> | |
<attribute name="serverUrl" description="Salesforce url."/> | |
<attribute name="query" description="Salesforce password."/> | |
<attribute name="queryResult" description="Query result property name"/> | |
<sequential> | |
<!-- Extract host/instance name from the serverUrl returned from the login response --> | |
<propertyregex property="host" | |
input="${serverUrl}" | |
regexp="^((http[s]?|ftp):\/)?\/?([^:\/\s]+)((\/\w+)*\/)([\w\-\.]+[^#?\s]+)(.*)?(#[\w\-]+)?$" | |
select="\3" | |
casesensitive="false" /> | |
<!-- Execute Apex via REST API /query resource --> | |
<http url="https://${host}/services/data/v29.0/query" method="GET" entityProperty="queryResultResponse" statusProperty="loginResponseStatus" printrequestheaders="false" printresponseheaders="false"> | |
<headers> | |
<header name="Authorization" value="Bearer ${sessionId}"/> | |
</headers> | |
<query> | |
<parameter name="q" value="@{query}"/> | |
</query> | |
</http> | |
<property name="@{queryResult}" value="${queryResultResponse}"/> | |
</sequential> | |
</macrodef> | |
</project> |
This comment has been minimized.
This comment has been minimized.
Is it possible to use sessionid only for deployment ??? <sf:deploy deployRoot="${basedir}/installdeploy" sessionId ="@{sessionId}"/> |
This comment has been minimized.
This comment has been minimized.
Ye sessionId does work in sf:deploy. However if providing a session id. 'serverurl' attribute should be a specific app server instance (e.g. na1, na2) and can't be login.salesforce.com or test.salesforce.com, it needs to be na14.salesforce.com or so. |
This comment has been minimized.
This comment has been minimized.
Thats really interesting, i didn't know sf:deploy supported sessionId cool! |
This comment has been minimized.
This comment has been minimized.
Though i don't see any reference in the Ant migration tool docs? |
This comment has been minimized.
This comment has been minimized.
I tried it and I'm using it too, it works like a charm :) <sf:deploy serverurl="${sf.destinationserverurl}" sessionId="${sf.destinationsessionId}" maxPoll="${sf.maxPoll}" deployRoot="exported_foldername" rollbackOnError="true"/> |
This comment has been minimized.
This comment has been minimized.
Hello! Thanks for this script. i am using this script for deploying dependency tree before start working. however I am not able to define that the dependent package should be deployed for everyone, instead of only single user. how would i do that? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
Is it possible to turn
${serverUrl}
into${instance}
on line 99 and line 145?