Skip to content

Create Scratch Org ​

Reusable workflow that provisions a ready-to-use scratch org as a self-service task: it authenticates to the Dev Hub, creates a scratch org, optionally installs dependency packages, deploys the source, assigns permissions, imports sample data, runs anonymous Apex setup scripts, and generates a login password so the org can be handed over to a project member. Designed to be called from a workflow_dispatch caller (see examples/create-scratch-org.yml) so that even non-technical team members can request a fresh org straight from the GitHub Actions tab.

Reusable workflow - call it from your own repository with uses:. View source

Inputs ​

InputDescriptionTypeRequiredDefault
org-nameHuman-readable name for the scratch org.stringno-
descriptionDescription stored on the scratch org.stringno-
admin-emailEmail address of the scratch org admin user.stringno-
duration-daysNumber of days before the scratch org expires (1-30).stringno7
source-dirSource directory to deploy to the scratch org.stringnoforce-app
definition-filePath to the scratch org definition file.stringnoconfig/project-scratch-def.json
deploy-metadataDeploy the project source after the org is created.booleannotrue
install-packagesInstall dependency packages before deploying.booleannofalse
packagesComma-separated or multi-line list of dependency packages (aliases or IDs) to install, e.g. "04t...,04t...".stringno-
permission-setsComma-separated or multi-line list of permission sets to assign to the scratch org admin user after the deployment. Leave empty to skip.stringno-
permission-set-groupsComma-separated or multi-line list of permission set groups to assign to the scratch org admin user. Leave empty to skip.stringno-
permission-set-licensesComma-separated or multi-line list of permission set licenses to assign to the scratch org admin user. Leave empty to skip.stringno-
import-dataImport sample data after the deployment.booleannofalse
csv-file-pathPath to a CSV file imported via the Bulk API 2.0. Leave empty to skip.stringno-
csv-object-typesObject type of the records in the CSV file (required when csv-file-path is set).stringno-
json-file-pathComma-separated or multi-line list of sObject Tree JSON file(s) to import, in order. Leave empty to skip.stringno-
apex-file-pathComma-separated anonymous Apex file(s) or glob(s) to execute after the data import, e.g. "./scripts/apex/setup/*.apex". Leave empty to skip.stringno-

Secrets ​

SecretDescriptionRequired
SFDX_CONSUMER_KEYConsumer key (client ID) of the Dev Hub connected app used for the JWT flow.yes
SFDX_JWT_SECRET_KEYContents of the private server key (server.key) used for the JWT flow.yes
SFDX_USERNAMEUsername of the Dev Hub integration user to authenticate as.yes

Example usage ​

Copy this caller into your project's .github/workflows/ directory (source):

yaml
# Example: self-service scratch org creation.
# Copy this file into your project's .github/workflows/ directory. Team members
# then run it on demand from the Actions tab ("Run workflow") and fill in the
# form below - no local Salesforce CLI setup required.

name: Create Scratch Org

on:
  workflow_dispatch:
    inputs:
      org-name:
        description: Scratch org name
        type: string
      description:
        description: Scratch org description
        type: string
      admin-email:
        description: Admin user email
        type: string
      duration-days:
        description: Lifespan in days (1-30)
        type: string
        default: '7'
      install-packages:
        description: Install dependency packages?
        type: boolean
        default: false
      import-data:
        description: Import sample data?
        type: boolean
        default: true

# Least-privilege token: the called workflow only reads the repository and talks
# to Salesforce. A reusable workflow can never get more permissions than the
# caller grants here.
permissions:
  contents: read

jobs:
  create-scratch-org:
    uses: svierk/salesforce-devops-starter-kit/.github/workflows/create-scratch-org.yml@v1.5.0
    with:
      org-name: ${{ inputs.org-name }}
      description: ${{ inputs.description }}
      admin-email: ${{ inputs.admin-email }}
      duration-days: ${{ inputs.duration-days }}
      source-dir: force-app
      deploy-metadata: true
      install-packages: ${{ inputs.install-packages }}
      # Dependency packages to install when "Install dependency packages?" is checked:
      # packages: '04t...,04t...'
      # Permissions granted to the admin user after the deployment, so the
      # handed-over org (and the data import below) can use the deployed metadata:
      # permission-sets: 'My_App_Admin,My_App_User'
      # permission-set-groups: 'Sales_Manager'
      import-data: ${{ inputs.import-data }}
      # Sample data imported when "Import sample data?" is checked (CSV via Bulk API 2.0,
      # JSON via sObject Tree). Point these at files that exist in your repository:
      csv-file-path: ./data/accounts.csv
      csv-object-type: Account
      json-file-path: ./data/accounts.json,./data/contacts.json
      # Anonymous Apex setup scripts executed last, in alphabetical order:
      # apex-file-path: ./scripts/apex/setup/*.apex
    secrets:
      SFDX_CONSUMER_KEY: ${{ secrets.SFDX_CONSUMER_KEY }}
      SFDX_JWT_SECRET_KEY: ${{ secrets.SFDX_JWT_SECRET_KEY }}
      SFDX_USERNAME: ${{ secrets.SFDX_USERNAME }}

Released under the MIT License. · llms.txt for AI agents