Andrea Azzola

Technology, Personal Development and Financial Independence

Automate SVN/Git Backups of Entire Salesforce.com Organizations

Posted on [Permalink]

The following solution involves two popolar SCM (SVN and Git), an always-on server (I use Windows, you may want to opt for the cloud) and a few free tools. You will need the Force.com Migration Tool, Apache Ant, and Java JDK. Start by setting things up with the following checklist:

  1. Java JDK - http://www.oracle.com/technetwork/java/javase/downloads/index.html
  2. Apache Ant - http://ant.apache.org/manual/install.html
  3. Force.com Migration Tool - http://www.salesforce.com/us/developer/docs/daas/Content/forcemigrationtool_install.htm
  4. Shell (or the Git Bash) - http://cygwin.com/install.html

I'm using SVN, so an SVN command line client that support the server version (which is above 1.7) is also necessary.

  1. SVN Client - http://www.sliksvn.com/en/download

The next things is setting up working folder and scripts, you'll have:

myWorkingFolder
  build.properties - Connection info
  build.xml - Retrieve instructions
  myScript.sh

build.properties content:

# build.properties

sf.serverurl = https://www.salesforce.com
sf.username = usr@domain.ext
sf.password = F4ncy!Pwd
sf.directory = Org

build.xml content:

<project name="MyProject" default="test" basedir="." xmlns:sf="antlib:com.salesforce">
    <property file="build.properties"/>
    <property environment="env"/>
    <target name="getOrg">
      <mkdir dir="Org"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" 
                metadataType="AccountCriteriaBasedSharingRule" 
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}"
                serverurl="${sf.serverurl}" metadataType="AccountOwnerSharingRule"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="ApexClass"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="ApexComponent"
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="ApexPage"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}"
                serverurl="${sf.serverurl}" metadataType="ApexTrigger"
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="AssignmentRule"
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="CallCenter"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" 
                metadataType="CampaignCriteriaBasedSharingRule"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="CampaignOwnerSharingRule"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="CaseCriteriaBasedSharingRule"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="CaseOwnerSharingRule"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="Community"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" 
                metadataType="ContactCriteriaBasedSharingRule"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="ContactOwnerSharingRule"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="CustomApplication"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="CustomApplicationComponent"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="CustomLabels"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="CustomObject"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" 
                metadataType="CustomObjectOwnerSharingRule"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="CustomObjectTranslation"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="CustomPageWebLink"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="CustomSite"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="CustomTab"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="Dashboard"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="Document"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="EmailTemplate"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="Flow"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="Group"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="HomePageComponent"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="HomePageLayout"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="Layout"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" 
                metadataType="LeadCriteriaBasedSharingRule"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="LeadOwnerSharingRule"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="Letterhead"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" 
                metadataType="OpportunityCriteriaBasedSharingRule"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" 
                metadataType="OpportunityOwnerSharingRule"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="PermissionSet"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="Portal"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="Profile"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="Queue"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="RemoteSiteSetting"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="Report"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="ReportType"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="Role"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="Scontrol"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="StaticResource"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="Workflow"  
                retrieveTarget="${sf.directory}"/>
        <sf:bulkRetrieve  username="${sf.username}" password="${sf.password}" 
                serverurl="${sf.serverurl}" metadataType="Settings"  
                retrieveTarget="${sf.directory}"/>
    </target>
</project>

run.cmd content:

svn checkout https://localhost:81/svn/myorg/trunk/ Org --depth=infinity --username bot 
                --password POOr+9jC --non-interactive --trust-server-cert
call ant getOrg
cd Org
svn propedit svn:ignore *.xml .
svn add --depth=infinity *
svn commit -m "Scheduled commit" --username bot --password B0tP4$$:)

Open the bash, run the the scripts, the results should be the following:

myWorkingFolder/
  myOrg/ - Project
  myOrg/.svn - SVN stuff (or .git for git stuff)
  myOrg/*.* - Versioned metadata

If you want to schedule the script in Windows, all you need to do is open the command prompt; and run the bash executable passing the script path as parameter, note that the whole process takes place in the working directory.

Please note: the script is for demonstration purpose only and comes with no guarantees. Also, this may be out of date or I could have made mistakes Please leave a comment below and I'll be happy to fix it for you.

Categories: Salesforce.com