ForceFlow is a simple library to automate build and deployment-related tasks on the Force.com platform. It is built on top of Apache Ant, so it can be used in combination with the Force.com migration tool and with any continuous integration or build solutions, such as Atlassian Bamboo or Jenkins CI.
- Schedule and abort Apex jobs
- Manage remote site settings
- Execute Apex code
- Run Apex tests (with XML reports)
- Insert and delete records
- Support for flow deactivation and deletion (in conjunction with the Force.com migration tool)
If you are not familiar with Ant and you need a template for your script you can copy the one below.
<?xml version="1.0" encoding="UTF-8"?>
<project name="forceflow-sample" xmlns:ff="antlib:com.spaceheroes">
<!--
This assumes forceflow.jar is copied
in a folder named "lib"
====================================== -->
<path id="ant.additions.classpath">
<fileset dir="./lib/" includes="*.jar"/>
</path>
<taskdef resource="antlib.xml" uri="antlib:com.spaceheroes" classpathref="ant.additions.classpath" />
<!--
You can now define Ant targets and
use any ForceFlow tasks within.
====================================== -->
</project>
You can execute an Apex script as follows.
<ff:apex username="..." password="..." serverurl="...">
<![CDATA[
List<Contact> cts = [SELECT id,Email FROM Contact WHERE (Email<>null AND (NOT Email LIKE '%.nospam'))];
for (Contact ct : cts) {
ct.Email = ct.Email + '.nospam';
}
update cts;
]]>
</ff:apex>
Use this to create or update remote site settings.
<ff:remotesite name="Google_APIs" url="https://www.googleapis.com" disableProtocolSecurity="true" username="..." password="..." serverurl="...">
Allows queries to the Google Maps API
</ff:remotesite>
Use this tag to abort all the jobs that are currently scheduled.
<ff:clearschedule username="..." password="..." serverurl="..." />
Use this tag to abort specific jobs that are currently scheduled.
<ff:clearschedule scheduleName="..." username="..." password="..." serverurl="..." />
You can use this task to schedule the execution of a batch class.
<ff:scheduleapex username="..." password="..." serverurl="..." className="MySchedulableClass" cron="0 0 12 1/1 * ? *" />
or
<ff:scheduleapex username="..." password="..." serverurl="..." scheduleName="..." className="MySchedulableClass" cron="0 0 12 1/1 * ? *" />
Works with both objects and custom settings.
<ff:insert object="Contact" username="..." password="..." serverurl="...">
<property name="FirstName" value="Some"/>
<property name="LastName" value="Dude"/>
<property name="Email" value="[email protected]"/>
</ff:insert>
You can delete all the records from an object or a custom settings. It's bulkified, so it works also with very large tables.
<ff:deleteall object="Contact" username="..." password="..." serverurl="..."/>
Generates a full test report in the JUnit XML format (output file: test-report.xml). This report can be read by Atlassian Bamboo to display test results of a build.
<ff:runtests username="..." password="..." serverurl="..." />
It's possible to use ForceFlow in composition with the Force Migration Tool to deactivate all flows in a Salesforce organisation.
<target name="deactivateFlows">
<delete dir="temp"/>
<!-- Retrieve all the existing flows from the target org -->
<ff:createFlowRetrieveAllManifest
destinationPath="temp/existing" />
<sf:retrieve
username="${sf.username}"
password="${sf.password}"
serverurl="${sf.serverurl}"
retrieveTarget="temp/existing"
unpackaged="temp/existing/package.xml"/>
<!-- ForceFlow can then create an ad-hoc package to inactivate all the flows.
such package can be deployed using the Force.com migration tool -->
<ff:createFlowInactivateManifest
sourcePath="temp/existing"
destinationPath="temp/inactivation" />
<sf:deploy
username="${sf.username}"
password="${sf.password}"
serverurl="${sf.serverurl}"
deployRoot="temp/inactivation" />
<delete dir="temp"/>
</target>
It's possible to create an extra task that deletes flows. Bare in mind deactivation is required before deleting flows, so the two targets should be chained.
<target name="deleteFlows" depends="deactivateFlows">
<delete dir="temp"/>
<!-- Retrieve all the existing flows from the target org -->
<ff:createFlowRetrieveAllManifest destinationPath="temp/existing" />
<sf:retrieve
username="${sf.username}"
password="${sf.password}"
serverurl="${sf.serverurl}"
retrieveTarget="temp/existing"
unpackaged="temp/existing/package.xml" />
<!-- ForceFlow can then create an ad-hoc destructiveChanges to delete all the flows.
such destructive package can be deployed using the Force.com migration tool -->
<ff:createFlowDeleteManifest
sourcePath="temp/existing"
destinationPath="temp/delete" />
<sf:deploy
username="${sf.username}"
password="${sf.password}"
serverurl="${sf.serverurl}"
deployRoot="temp/delete"
ignoreWarnings="true" />
<delete dir="temp"/>
</target>
ForceFlow is available under the MIT license. Please see the LICENSE for details.