Salesforce Backup Made Easy: Daily Automation with GitHub Actions

Steps to implement daily backups of a Salesforce org with GitHub Actions:

1) Preparing the GitHub repository

Decide the project name and whether to use production (login) or sandbox (test).

Create a repository in GitHub.

2) In the GitHub repository root, create the file sfdx-project.json below, change the project name and URL and commit:

(you can copy this file and modify it)

{

  "packageDirectories": [     {

       "path": "force-app",

      "default": true

     }  ],

  "name": "PROJECT_NAME_HERE",

  "namespace": "",

  "sfdcLoginUrl": "https://login_or_test_here.salesforce.com/",

  "sourceApiVersion": "55.0"

}

3) In the GitHub repository root, create the file package.xml below and commit:

(you can copy this file)

<?xml version=”1.0″ encoding=”UTF-8″?> <Package xmlns=”http://soap.sforce.com/2006/04/metadata”> <types> <members>*</members> <name>ApexClass</name> </types> <types> <members>*</members> <name>ApexComponent</name> </types> <types> <members>*</members> <name>ApexPage</name> </types> <types> <members>*</members> <name>ApexTrigger</name> </types> <types> <members>*</members> <name>AuraDefinitionBundle</name> </types> <types> <members>*</members> <name>CustomField</name> </types> <types> <members>*</members> <name>CustomLabels</name> </types> <types> <members>*</members> <name>CustomMetadata</name> </types> <types> <members>*</members> <name>CustomObject</name> </types> <types> <members>*</members> <name>FieldSet</name> </types> <types> <members>*</members> <name>FlexiPage</name> </types> <types> <members>*</members> <name>Flow</name> </types> <types> <members>*</members> <name>FlowCategory</name> </types> <types> <members>*</members> <name>FlowDefinition</name> </types> <types> <members>*</members> <name>LightningComponentBundle</name> </types> <types> <members>*</members> <name>LightningMessageChannel</name> </types> <types> <members>*</members> <name>NamedCredential</name> </types> <types> <members>*</members> <name>PermissionSet</name> </types> <types> <members>*</members> <name>RemoteSiteSetting</name> </types> <types> <members>*</members> <name>StaticResource</name> </types> <types> <members>*</members> <name>ValidationRule</name> </types> <types> <members>*</members> <name>Workflow</name> </types> <types> <members>*</members> <name>WorkflowFieldUpdate</name> </types> <types> <members>*</members> <name>WorkflowRule</name> </types> <types> <members>*</members> <name>WorkflowTask</name> </types> <version>54.0</version> </Package>

4) Getting authentication URL from the org

With SFDX installed, on Terminal, execute this command after changing the project name and URL (single line, no breaks):

sfdx force:auth:web:login --setalias PROJECT_NAME_HERE --instanceurl https://login_or_test_here.salesforce.com --setdefaultusername

5) It will prompt to login on the browser, then execute on Terminal:

sfdx force:org:display -u PROJECT_NAME_HERE --verbose

6) Copy to the Clipboard the entry immediately after “Sfdx Auth Url“. It should be something like force://PlatformCLI::6Bep…3ad@instancename.sandbox.my.salesforce.com

7) Storing authentication URL in GitHub safely

On GitHub, go to Settings / Secrets / Actions and create a new repository secret with the name “ORG_SFDX_URL” and paste the content copied in the previous step.

8) On GitHub, go to Actions, configure a simple workflow and name the script file “syncRepositoryToOrg.yml“.

(you can copy this file)

9) Setting up GitHub Action to backup the org

Copy the contents below into the new YML script and press “Start commit” (green button at top right).

(you can copy this file)

name: Detect changes in the org and sync into the repository

# When the workflow will run

on:

schedule:

# Runs at 12:00 UTC every day.

– cron: ‘0 12 * * *’

# Allows you to run this workflow manually from the Actions tab

workflow_dispatch:

inputs:

# this will be refered to as ${{ github.event.inputs.commit_text }}

commit_text:

description: ‘Commit text to use’

required: true

default: ‘New Manual Sync commit’

jobs:

sync_job:

runs-on: ubuntu-latest

steps:

– name: Install Salesforce CLI

run: |

wget https://developer.salesforce.com/media/salesforce-cli/sfdx/channels/stable/sfdx-linux-x64.tar.xz

mkdir ~/sfdx

tar xJf sfdx-linux-x64.tar.xz -C ~/sfdx –strip-components 1

echo “$HOME/sfdx/bin” >> $GITHUB_PATH

~/sfdx/bin/sfdx version

– name: ‘Checkout source code’

uses: actions/checkout@main

– name: ‘Create file to authenticate to the org via SFDX’

run: echo ${{ secrets.ORG_SFDX_URL }} > DEV-LOGIN.txt

– name: ‘Authenticate to the org using SFDX’

run: sfdx force:auth:sfdxurl:store -f DEV-LOGIN.txt -d -a backupfiles

– name: ‘Create project with manifest, Copy package.xml, Navigate to the project folder, Download metadata using SFDX’

run: |

rm DEV-LOGIN.txt

if test -d “./backupfiles/force-app”; then

echo force-app folder exists

else

sfdx force:project:create –projectname backupfiles –manifest

fi

if test -f “./backupfiles/sfdx-project.json”; then

echo sfdx-project.json file exists

else

cp ./sfdx-project.json ./backupfiles/sfdx-project.json

fi

if test -f “./backupfiles/manifest/package.xml”; then

echo package.xml file exists

else

cp ./package.xml ./backupfiles/manifest

# below causes ERROR running force:source:manifest:create: This directory does not contain a valid Salesforce DX project.

#sfdx force:source:manifest:create -m ApexClass,ApexComponent,ApexPage,ApexTrigger,AuraDefinitionBundle,CustomField,CustomLabels,CustomMetadata,CustomObject,FieldSet,FlexiPage,Flow,FlowCategory,FlowDefinition,LightningComponentBundle,LightningMessageChannel,NamedCredential,PermissionSet,RemoteSiteSetting,StaticResource,ValidationRule,Workflow,WorkflowFieldUpdate,WorkflowRule,WorkflowTask -o ./backupfiles/manifest

fi

cd ./backupfiles

sfdx force:source:retrieve -u backupfiles -x manifest/package.xml

– name: Save repository owner email

run: |

echo “owner_email=$(git log -n 1 –pretty=format:%ae )” >> $GITHUB_ENV

– name: Stage files and check for modified files

id: git-check

run: |

git init

git config user.email “${{ env.owner_email }}”

git config user.name “${{ github.repository_owner }}”

git add .

echo “modified=$(if git diff-index –quiet HEAD –; then echo “false”; else echo “true”; fi)” >> $GITHUB_OUTPUT

– name: Commit and push if there modified files

if: steps.git-check.outputs.modified == ‘true’

run: |

git commit -m “${{ github.event.inputs.commit_text }} on ${{ github.event.repository.updated_at }}”

echo “git-push=$(git push -u origin main)\n” >> $GITHUB_OUTPUT

10) Running the backup for the first time

Go to Actions and click “Detect changes in the org and backup…”, then click “Run workflow”. It will ask what branch to run the workflow from and the commit text to use (enter your choices). Click the green button “Run workflow”.

11) The workflow will be queued. You can click on it to see it being executed. The source code will be stored in the “backupfiles” folder.

12) In addition, the workflow will check your org every day at midnight (UTC) and backup any changes.


Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *