Skip to content

Appendix A: Sample GitHub Actions Workflow YAML

This appendix provides annotated example GitHub Actions workflow files and composite actions implementing the pipeline architecture described throughout this whitepaper. They are examples to adapt, not files promised to run unchanged. The files follow a modular design: each quality gate lives in its own reusable workflow under .github/workflows/, and repeated step sequences (authentication, environment setup, PR commenting, result parsing) are extracted into composite actions under .github/actions/.

All workflow files follow the conventions established in this whitepaper: Conventional Commits-compatible job naming, structured PR comment output via $GITHUB_STEP_SUMMARY and dedicated PR comment composite actions, and jq for parsing JSON output.

With a release management tool

An organisation that deploys with a Salesforce release management tool, such as AutoRABIT ARM, Gearset, Copado, Flosum, or Salesforce DevOps Center, does not need most of the deployment workflows in this appendix. The tool moves each change from org to org itself, and most such tools also validate the change and run its tests. The gates that check the repository before a change is merged, such as Prettier, static analysis, and the secret scan, can still run as GitHub workflows beside the tool.

Action version note: every uses: reference on this page names the version that was current at the time of writing. Where a page references the organisation's own reusable workflows and composite actions by tag, the tag is an immutable release tag; third-party actions are shown at their floating major tag, a choice many organisations make for highly trusted actions such as actions/checkout (the trade-off is explained in Appendix G). Newer major versions may introduce breaking changes: review the release notes for an action before upgrading, and validate in a non-production pipeline before promoting to protected branches. Dependabot and Renovate (Section 7) open PRs when new versions are published, providing a structured upgrade path.

The sfdx-git-delta plugin (GitHub) is used throughout for delta package generation, scoping analysis and test execution to changed files rather than the full workspace. The delta package is the folder that sfdx-git-delta writes for a change: a package.xml that lists the changed metadata, and a copy of each changed file. It is not a Salesforce package. The delta package is generated once per PR run by a dedicated reusable workflow and uploaded as a GitHub Actions artifact, then downloaded by every downstream job that needs it: code analysis, Apex tests, Jest tests, and deployment validation. This avoids the cost and inconsistency of regenerating the delta independently in each job.

The Gates at a Glance

Each table lists the gates that one kind of trigger runs: the tool behind each gate, what the gate does, and what happens when it finds a violation. The tools a developer runs before any of this, on their own machine, are in Section 4.

On a Pull Request

The gates of the pull request callers (A.1.2 and A.1.3), in the order they run. The run has four stages. In stage 1 the seven quick gates run in parallel, each a checkout and a short script, or Prettier. Stage 2 builds the delta package, and it starts only when every stage 1 gate has passed, so a pull request that fails a quick gate ends in seconds, before any org is touched. Stage 3 works on the delta package, with its three gates in parallel. Stage 4 validates the delta package against the org. Stage 5 is the Quality Gates job, the one required check, which waits for every job before it. A Variables job, which is not a gate, runs beside stage 1 and passes the thresholds from the top of the file to the gates that take them. The diagram shows which job waits for which, with each job under the name it has in the callers.

---
config:
  layout: dagre
---
flowchart TB
    accTitle: The stages of a pull request run
    accDescr: Stage 1 runs seven quick gates in parallel: formatting, the pull request title, secrets, prohibited metadata, destructive changes, the risk tier, and the changelog. Stage 2, the delta package, waits for all seven. Stage 3 runs code analysis, the Jest tests, and the Apex test selection in parallel, each on the delta package. Stage 4, the validation against the org, waits for code analysis and the Apex test selection. Stage 5, the Quality Gates job, is the one required check, and it waits for every job.
    subgraph s1 ["Stage 1: the quick gates, in parallel"]
        prettier["Formatting"]
        title["PR Title"]
        secrets["Secrets"]
        tier0["Prohibited Metadata"]
        destructive["Destructive Changes"]
        risk["Risk Tier"]
        changelog["Changelog"]
    end
    subgraph s2 ["Stage 2: the delta package, once every stage 1 gate has passed"]
        delta["Delta Package"]
    end
    subgraph s3 ["Stage 3: the gates on the delta package, in parallel"]
        sca["Code Analysis"]
        jest["Jest Tests"]
        apexsel["Apex Test Selection"]
    end
    subgraph s4 ["Stage 4: the validation against the org"]
        validate["Validation"]
    end
    subgraph s5 ["Stage 5: the one required check"]
        gates["Quality Gates"]
    end
    tier0 ~~~ delta
    s1 --> delta
    delta --> sca
    delta --> jest
    delta --> apexsel
    sca --> validate
    apexsel --> validate
    jest --> gates
    validate --> gates
Stage Gate Tool What It Does Violations Outcome
1 Prettier Formatting Verification Prettier Checks that the source files are formatted to the repository's Prettier configuration Blocks
1 Semantic PR Title Check amannn/action-semantic-pull-request Checks that the pull request title follows Conventional Commits, because the title becomes the commit on the protected branch Blocks
1 Secret Scanning The scanner the organisation chooses, such as Gitleaks, TruffleHog, or GitHub secret scanning; the sample's scan step is a placeholder Scans the change for committed credentials Blocks, once a scanner is in place
1 Prohibited Metadata Check (Tier 0) None: a script and the risk matrix Looks for any Tier 0 path that the pull request adds or changes Blocks
1 Destructive Change Detection None: a script Looks for destructiveChanges.xml in the diff Does not block. Labels the pull request destructive-change, so that branch protection holds it for a person's approval
1 Metadata Risk Tier None: a script and the risk matrix Labels the pull request with the highest metadata risk tier among its files Never blocks. Disables auto-merge on Tier 1
1 Changelog Check None: a script Looks for a change to CHANGELOG.md in any pull request but the release pull request of Release Please, which alone writes that file Blocks
2 Generate Delta Package sfdx-git-delta Builds the delta package of what the pull request changes, which the gates below work on None: it checks nothing. The gates below skip when the delta package is empty
3 Static Code Analysis Salesforce Code Analyzer and its engines (Appendix E) Scans the delta, uploads SARIF to GitHub code scanning, posts the violations as two tables, and stores the complete results as an artifact for 7 days Blocks at severity 1 and 2. Severity 3 to 5 is reported
3 LWC Jest Tests Jest, and Codecov Runs the Jest tests when Lightning Web Components changed, comments the result on the pull request, and uploads coverage Blocks on a failing test, and on a component that has a test and is below 80% line coverage; a component with no test is only named
3 Apex Test Selection None: a script Chooses the test level and the tests for the validation None: it only chooses
4 Metadata Validation and Apex Tests Salesforce CLI Validates the delta against the target org without deploying it, runs the chosen Apex tests, and posts the results as tables Blocks on a component that will not deploy, a failing test, or a changed class or trigger below 75% coverage
5 Quality Gates, the last job of each caller None Collects the result of every gate above. It is the one check the branch ruleset requires (Appendix C) Blocks when any gate failed or was cancelled. A skipped gate counts as passing

Two more workflows answer a pull request event. A.1.6 runs the Metadata Risk Tier gate again whenever auto-merge is enabled. A.1.8 gives a pull request from Dependabot a title that the Semantic PR Title Check accepts; it is not a gate.

On a Push

The gates of the push baseline (A.1.1), which runs on every push. On a branch whose name starts with feat, only the secret scan and the formatting check run. A push workflow cannot stop a commit that is already pushed, so a failed run flags the problem before a pull request is opened.

Gate Tool What It Does Violations Outcome
Prettier Formatting Verification Prettier Checks that the source files are formatted to the repository's Prettier configuration Fails the run
Secret Scanning The scanner the organisation chooses; the sample's scan step is a placeholder Scans for committed credentials Fails the run, once a scanner is in place
Static Code Analysis Salesforce Code Analyzer and its engines Scans only the files that the push changed, and writes violations to the job summary Never fails: on a push it is advisory
LWC Jest Tests Jest, and Codecov Runs every Jest test, since a push has no pull request diff to narrow them Fails the run for a failing test, and for a tested component below 80% line coverage

On a push to main the same workflow also runs Release Please, which is not a gate.

On Demand

One workflow runs only when a person starts it, from the "Run workflow" button (A.1.7). It is a report, not a gate.

Gate Tool What It Does Violations Outcome
Full Repository Scan Salesforce Code Analyzer and its engines Scans the whole repository, and stores every violation as a CSV file, a JSON file, and a SARIF file in one artifact to download Never fails. The job summary has the counts for each severity and a table of every blocking violation

On a Schedule

The checks of the two scheduled callers (A.1.4 and A.1.5), which look at the org and at the whole repository, and not at a change.

Gate Tool What It Does Violations Outcome Schedule
Full Code Analyzer Scan Salesforce Code Analyzer and its engines Scans the whole repository, as the on-demand scan does, so that a file that no change touches is still reported Never fails. The job summary has the counts for each severity and a table of every blocking violation, and every violation is in an artifact Weekly
Org Scan: Metadata Drift Detection Salesforce CLI, and git diff Retrieves the org's metadata over the checked-out source and compares it with the last commit Opens a GitHub issue; the run stays green, and Slack gets the report on every run, drift or none Weekly
Apex Compilation Check Salesforce CLI Retrieves every Apex class and trigger from the org and checks that all of it compiles Opens a GitHub issue, fails the run, and notifies Slack Weekly in production, and nightly in a pipeline sandbox
Apex Tests (Full Org) Salesforce CLI, and Codecov Runs every local test with RunLocalTests and uploads coverage Opens a GitHub issue and fails the run; Slack gets the report on every run, pass or fail Nightly
LWC Jest Tests Jest, and Codecov Runs every Jest test with coverage Fails the run for a failing test, and for a tested component below 80% line coverage; Slack gets the report on every run, with the number of components with no test Nightly