DevOps Testing

Salesforce Testing with GitHub Actions

Salesforce testing with GitHub Actions means using workflow files in your repository to authenticate to Salesforce orgs, validate metadata deployments with the sf CLI, run Apex tests and trigger functional regression, then report results as checks that protect branches. GitHub Actions supplies the events, runners and secrets; the workflow decides which Salesforce validation runs, against which org, and what blocks a merge or release.

SyntraFlow is designed to be called from a workflow job and return a result the job can act on; this pattern is available for demonstration and proof-of-concept validation.

Why teams build Salesforce pipelines on GitHub Actions

GitHub Actions is the automation service built into GitHub. Workflows are YAML files stored under the .github/workflows directory, triggered by repository events such as pull_request, push, schedule or a manual workflow_dispatch. Each workflow contains jobs that run on GitHub-hosted or self-hosted runners, and each job is a sequence of steps that run shell commands or reusable actions. For Salesforce teams already keeping source-format metadata in GitHub, it removes the need for a separate CI server.

The trade-off is that GitHub Actions knows nothing about Salesforce. Every Salesforce concept, from org authentication to test levels to deployment IDs, has to be expressed through sf CLI commands and scripts the team maintains. That flexibility is useful: the same workflow can run a check-only deploy, collect Apex coverage, call an external functional testing service and upload an evidence file. This page focuses on those workflow mechanics. The broader question of which stages a Salesforce pipeline needs is covered on CI/CD testing, and teams on Azure Pipelines will find the equivalent on Azure DevOps.

Anatomy of a Salesforce validation workflow

A typical pull request workflow for a Salesforce repository follows this sequence of jobs and steps.

1

Trigger on the right event

Listen for pull_request events targeting the integration or main branch, filtered with paths to the force-app directory so documentation changes do not start a Salesforce run.

2

Install the sf CLI and authenticate

Install the CLI on the runner and log in with the JWT bearer flow using a connected app, a consumer key and a private key stored as encrypted secrets, never a username and password.

3

Build a delta package

Compare the pull request head with its base and produce a package of only changed metadata, commonly with a delta-generation plugin such as sfdx-git-delta, plus any destructive changes.

4

Run a check-only deployment

Use sf project deploy validate against a validation sandbox or production with an appropriate test level, capturing the job ID for a later quick deploy.

5

Trigger functional regression

Call the functional testing service with the org alias, the changed component list and the pull request number, then wait for or poll the result.

6

Publish results and evidence

Write a job summary, upload JUnit results and the evidence bundle with the upload-artifact action, and let the job's exit code set the check status.

Choosing events and test depth per workflow

Not every event deserves the same Salesforce validation. Matching depth to trigger keeps runner minutes and sandbox contention under control.

Workflow triggerSalesforce validationTypical target org
pull_request to a feature integration branchDelta validate deploy with RunSpecifiedTests, targeted functional packScratch org or shared developer sandbox
pull_request to mainValidate deploy with RunLocalTests, impact-selected regression packsFull or partial copy staging sandbox
push to main after mergeDeploy to UAT sandbox, broader regression and access checksUAT sandbox
workflow_dispatch for releaseQuick deploy of a validated job ID inside the deployment windowProduction
deployment job completionProduction-safe smoke pack and evidence captureProduction
schedule nightlyFull regression and org drift checks independent of any changeStaging or UAT sandbox
release branch createdSeasonal release preview regression on preview sandboxesSandbox on the preview instance

Workflow design decisions that matter for Salesforce

These GitHub Actions features solve problems that are specific to validating Salesforce metadata.

Concurrency groups

Two workflows deploying to the same sandbox at once corrupt each other's results. A concurrency group keyed on the target org queues runs instead of interleaving them.

Environments with reviewers

A GitHub environment named for production can require approval before the job that runs a quick deploy starts, keeping human sign-off in the workflow.

Secrets scoped by environment

Store the production connected app key only in the production environment so pull request workflows cannot reach it, especially from forks.

Required status checks

Branch protection or rulesets make the validation job a required check, which turns a workflow result into an enforceable merge gate.

Reusable workflows

A single called workflow for authenticate, validate and test keeps many repositories or package directories consistent without copying YAML.

Timeouts and retries

Salesforce deploy queues and long Apex runs can stall. Explicit job timeouts and a bounded retry on transient API errors prevent hung runners and silent passes.

Calling a functional testing service from a job

Apex tests and a validate deploy answer whether the metadata compiles, deploys and satisfies code coverage. They say little about a Screen Flow, a Lightning record page, or what a user with a particular permission set can see. That is why a workflow typically adds a functional step after the check-only deploy or after deployment to a test sandbox.

The pattern is generic. A step makes an authenticated HTTP call or runs a small CLI script that starts a run, passing context the service needs: the target org, the commit SHA, the pull request number and the list of changed components. The step then polls for completion within a timeout, downloads the result, writes a readable summary to the job summary, and exits non-zero on a failed critical test so the check turns red. The evidence file is uploaded as a workflow artifact and linked from the pull request comment. Keeping the call in its own job with an explicit dependency on the deploy job makes the ordering clear and lets a re-run repeat only the functional step when a sandbox hiccup caused the failure.

Common GitHub Actions pitfalls on Salesforce projects

These issues show up repeatedly when Salesforce teams first move validation into workflows.

  • Workflows triggered from forks do not receive repository secrets, so validation silently skips authentication unless the workflow handles that case explicitly.
  • A delta package omits a dependent component that exists in the target org, so the validate deploy passes but a later full deployment fails.
  • RunLocalTests on every pull request makes checks take so long that developers stop waiting for them and merge on partial results.
  • A quick deploy is attempted after the validation has expired or after another deployment changed the org, and the release job fails in the deployment window.
  • Parallel pull requests share one validation sandbox and overwrite each other's metadata, producing results that belong to neither change.
  • Functional tests run before the deploy job finishes because job dependencies were not declared with needs.
  • Test results are printed to logs only, so nobody can later show an auditor which checks ran for a given production release.

Scratch orgs, sandboxes and test data in workflows

Scratch orgs created from a Dev Hub with a scratch org definition file give each workflow run a clean, disposable environment and suit source-tracked, package-based projects. They are limited by daily and active scratch org allocations, start empty, and do not include every feature or setting of production, so functional tests that need realistic data or production-like configuration usually run in a sandbox instead. Many teams combine both: scratch orgs for fast pull request checks, a partial or full copy sandbox for merge-to-main regression.

Whichever environment is used, the workflow should prepare data deliberately. Loading reference records with a data import step or synthetic test data avoids tests that depend on whatever happens to exist in the org, and reserving records per run with data reservation stops parallel jobs from colliding on the same Account or Opportunity.

How SyntraFlow is designed to fit a workflow

SyntraFlow does not provide a published GitHub Action or a certified GitHub integration. It is designed to be driven from a workflow step using the generic pattern above.

Started by a step

A workflow step can start a SyntraFlow run with the target org and change context, keeping the trigger logic in the team's own YAML.

Impact-selected packs

The changed component list can be used to select relevant regression packs so pull request checks stay fast.

Machine-readable result

The run returns a pass or fail outcome the job converts into its exit code and a required status check.

Evidence for the release

Scope, results and timestamps can be saved as a workflow artifact or linked from the pull request for audit, with proof-of-concept validation available on request.

Related pages

Salesforce DevOps Testing

The hub for validation layers, quality gates and evidence across Salesforce pipelines.

Pull Request Testing

What to validate on a pull request, independent of which CI service runs it.

Azure DevOps

The equivalent pipeline pattern for teams on Azure Pipelines and release stages.

CI/CD Testing

Which validation stages a Salesforce delivery pipeline needs, from commit to production.

Quality Gates

How to turn workflow results into enforceable pass or fail decisions.

Data Reservation

Keep parallel workflow runs from colliding on the same Salesforce records.

GitHub Actions testing FAQs

What is Salesforce testing with GitHub Actions?

It is running Salesforce validation from GitHub Actions workflows: authenticating with the sf CLI, performing check-only deployments, running Apex tests and triggering functional regression when pull requests or pushes occur. Results are reported as checks so branch protection can block merges that fail.

Which sf CLI commands are typically used in the workflow?

Common ones are sf org login jwt for authentication, sf project deploy validate for a check-only deployment with a chosen test level, sf project deploy quick to deploy a previously validated job, and sf apex run test for standalone test runs. Exact flags depend on the project and target org.

Is there a SyntraFlow GitHub Action in the Marketplace?

No. SyntraFlow does not claim a published action or a native GitHub integration. It is designed to be started from a workflow step using a scripted call, returning a result and evidence the job can act on, and this is available for demonstration and proof-of-concept validation.

Should pull request workflows run all local Apex tests?

Usually not on every pull request to a feature branch, because RunLocalTests in a large org can take a long time. Many teams run specified tests on early pull requests and reserve RunLocalTests for merges toward main and for the production validation that enables quick deploy.

How do I stop two workflows deploying to the same sandbox at once?

Use a concurrency group keyed on the target org so runs queue rather than overlap. For higher throughput, give pull request checks disposable scratch orgs and keep the shared sandbox for merge-level regression.

How is this page different from pull request testing?

This page is about GitHub Actions mechanics: events, jobs, secrets, environments and status checks. Pull request testing covers what should be validated on a Salesforce pull request and how reviewers use the results, whichever CI service runs it.

Turn your workflows into Salesforce quality checks

See how SyntraFlow is designed to be triggered from a GitHub Actions job and return results your branch protection can enforce.