A.1 - Caller Workflows¶
Caller workflows are the thin top-level files wired to GitHub Actions trigger events: push, pull_request, schedule, workflow_dispatch. Each caller composes one or more reusable workflows (defined in A.2) into a complete pipeline for that trigger. The caller is responsible for event filtering, concurrency scoping, and secret forwarding; it does not contain the quality gate logic itself.
A.1.1 - CI on Push¶
Lightweight push-time quality baseline. Runs on every push to every branch to provide immediate feedback before a PR is opened. On pushes to main, also triggers automated release management via release-please.
# .github/workflows/ci.yml
# Push Quality Baseline: runs lightweight quality checks on every push
# to any branch. On pushes to main, also triggers release management.
name: CI on Push
on:
push:
branches:
- '**'
concurrency:
group: push-${{ github.ref }}
cancel-in-progress: true
jobs:
# ── Formatting (runs first) ─────────────────────────────────
prettier-verify:
name: Formatting
uses: ./.github/workflows/sf-prettier-verify.yml
# ── Quality gates (run after formatting passes) ─────────────
secret-scan:
name: Secrets
needs: prettier-verify
uses: ./.github/workflows/sf-secret-scan.yml
code-analyzer:
name: Code Analysis
needs: prettier-verify
uses: ./.github/workflows/sf-code-analyzer.yml
with:
mode: ci
workspace: force-app
jest-tests:
name: Jest Tests
needs: prettier-verify
uses: ./.github/workflows/sf-jest-tests.yml
with:
skip-delta-check: true
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
# ── Release Management (main branch only, after all gates) ──
release-please:
name: Release
needs: [secret-scan, code-analyzer, jest-tests]
if: github.ref == 'refs/heads/main'
uses: ./.github/workflows/release-please.yml
secrets:
RELEASE_PLEASE_TOKEN: ${{ secrets.RELEASE_PLEASE_TOKEN }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
A.1.2 - PR to Production Branch¶
Full quality gate suite for pull requests targeting main. Authenticates to the production org for both Apex tests and deployment validation. The branch-specific split between this file and pr-staging.yml exists solely so that each caller can pass the correct credential secret; the underlying reusable workflows are identical.
# .github/workflows/pr-prod.yml
# PR Quality Gates (prod-bound): comprehensive quality gate suite for pull
# requests targeting `main`. Authenticates to the production org for both
# Apex tests and deployment validation.
name: CI on PR (prod)
on:
pull_request:
branches: [main]
types: [opened, synchronize, ready_for_review]
paths:
- 'force-app/**'
- '.github/**'
concurrency:
group: pr-prod-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
# ── Independent gates (run in parallel) ─────────────────────
semver-check:
name: PR Title
uses: ./.github/workflows/sf-semver-check.yml
secret-scan:
name: Secrets
uses: ./.github/workflows/sf-secret-scan.yml
prettier-verify:
name: Formatting
uses: ./.github/workflows/sf-prettier-verify.yml
destructive-check:
name: Destructive Changes
uses: ./.github/workflows/sf-destructive-check.yml
# ── Delta generation (prerequisite for analysis gates) ──────
generate-delta:
name: Delta Package
uses: ./.github/workflows/sf-generate-delta.yml
# ── Analysis gates (require delta) ──────────────────────────
code-analyzer:
name: Code Analysis
needs: generate-delta
if: needs.generate-delta.outputs.artifact-uploaded == 'true'
uses: ./.github/workflows/sf-code-analyzer.yml
with:
mode: pr
jest-tests:
name: Jest Tests
needs: generate-delta
if: needs.generate-delta.outputs.artifact-uploaded == 'true'
uses: ./.github/workflows/sf-jest-tests.yml
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
apex-tests:
name: Apex Tests
needs: generate-delta
if: needs.generate-delta.outputs.artifact-uploaded == 'true'
uses: ./.github/workflows/sf-apex-tests-pr.yml
secrets:
SFDX_AUTH_URL: ${{ secrets.SFDX_AUTH_URL_PROD }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
# ── Deployment validation (final gate) ──────────────────────
validate-deploy:
name: Validation
needs: [generate-delta, code-analyzer, apex-tests, destructive-check]
if: needs.generate-delta.outputs.artifact-uploaded == 'true' && !failure() && !cancelled()
uses: ./.github/workflows/sf-validate-deployment.yml
secrets:
SFDX_AUTH_URL_VALIDATION: ${{ secrets.SFDX_AUTH_URL_PROD }}
A.1.3 - PR to Staging Branches¶
Identical gate chain to A.1.2, targeted at non-prod long-lived branches (staging, uat, integration, full). Authenticates to the staging org rather than production.
# .github/workflows/pr-staging.yml
# PR Quality Gates (staging-bound): comprehensive quality gate suite for pull
# requests targeting non-prod long-lived branches. Authenticates to the
# staging org for both Apex tests and deployment validation.
name: CI on PR (staging)
on:
pull_request:
branches: [staging, uat, integration, full]
types: [opened, synchronize, ready_for_review]
paths:
- 'force-app/**'
- '.github/**'
concurrency:
group: pr-staging-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
# ── Independent gates (run in parallel) ─────────────────────
semver-check:
name: PR Title
uses: ./.github/workflows/sf-semver-check.yml
secret-scan:
name: Secrets
uses: ./.github/workflows/sf-secret-scan.yml
prettier-verify:
name: Formatting
uses: ./.github/workflows/sf-prettier-verify.yml
destructive-check:
name: Destructive Changes
uses: ./.github/workflows/sf-destructive-check.yml
# ── Delta generation (prerequisite for analysis gates) ──────
generate-delta:
name: Delta Package
uses: ./.github/workflows/sf-generate-delta.yml
# ── Analysis gates (require delta) ──────────────────────────
code-analyzer:
name: Code Analysis
needs: generate-delta
if: needs.generate-delta.outputs.artifact-uploaded == 'true'
uses: ./.github/workflows/sf-code-analyzer.yml
with:
mode: pr
jest-tests:
name: Jest Tests
needs: generate-delta
if: needs.generate-delta.outputs.artifact-uploaded == 'true'
uses: ./.github/workflows/sf-jest-tests.yml
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
apex-tests:
name: Apex Tests
needs: generate-delta
if: needs.generate-delta.outputs.artifact-uploaded == 'true'
uses: ./.github/workflows/sf-apex-tests-pr.yml
secrets:
SFDX_AUTH_URL: ${{ secrets.SFDX_AUTH_URL_STAGING }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
# ── Deployment validation (final gate) ──────────────────────
validate-deploy:
name: Validation
needs: [generate-delta, code-analyzer, apex-tests, destructive-check]
if: needs.generate-delta.outputs.artifact-uploaded == 'true' && !failure() && !cancelled()
uses: ./.github/workflows/sf-validate-deployment.yml
secrets:
SFDX_AUTH_URL_VALIDATION: ${{ secrets.SFDX_AUTH_URL_STAGING }}
A.1.4 - Scheduled Drift Detection¶
Weekly org surveillance. Runs metadata drift detection, Apex compilation, and a full-org Apex test run against production. Slack-notifies on any failure.
# .github/workflows/scheduled-drift-detection.yml
# Weekly Surveillance: scheduled monitoring of org health.
# Runs drift detection, compilation check, then full-org Apex tests.
# Creates GitHub issues on failures and notifies Slack.
name: Weekly Org Surveillance
on:
schedule:
- cron: '0 22 * * 2' # Tuesdays at 10:00 PM UTC
workflow_dispatch: # Allow manual trigger
jobs:
# ── Drift detection (parallel with compilation) ─────────────
drift-detection:
name: Drift Detection
uses: ./.github/workflows/sf-drift-detection.yml
secrets:
SFDX_AUTH_URL: ${{ secrets.SFDX_AUTH_URL_PROD }}
# ── Compilation check (must pass before Apex tests) ─────────
apex-compilation:
name: Apex Compilation
uses: ./.github/workflows/sf-apex-compilation.yml
secrets:
SFDX_AUTH_URL: ${{ secrets.SFDX_AUTH_URL_PROD }}
# ── Full-org Apex tests (after compilation passes) ──────────
apex-tests:
name: Full-Org Apex Tests
needs: apex-compilation
uses: ./.github/workflows/sf-apex-tests.yml
secrets:
SFDX_AUTH_URL: ${{ secrets.SFDX_AUTH_URL_PROD }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
# ── Failure notification ────────────────────────────────────
notify-failure:
name: Notify on Failure
needs: [drift-detection, apex-tests, apex-compilation]
if: failure()
uses: ./.github/workflows/sf-notify-slack.yml
with:
status: 'Failure'
title: 'Weekly Surveillance Failed'
message: 'One or more surveillance checks failed. Review the workflow run for details.'
run-url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}'
secrets:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
A.1.5 - Scheduled Nightly Test Runner¶
Nightly full-org Apex test run. Catches failures in components that depend on recently changed code but were not included in PR-scoped test execution. Lighter than the weekly surveillance workflow: no drift detection.
# .github/workflows/scheduled-test-runner.yml
# Nightly Apex test runner: compiles first, then runs full-org Apex tests,
# writes results to GITHUB_STEP_SUMMARY, and optionally uploads coverage to Codecov.
name: Nightly Apex Test Runner
on:
schedule:
- cron: '0 22 * * *' # Every night at 10:00 PM UTC
workflow_dispatch: # Allow manual trigger
jobs:
# ── Compilation check (must pass before Apex tests) ─────────
apex-compilation:
name: Apex Compilation
uses: ./.github/workflows/sf-apex-compilation.yml
secrets:
SFDX_AUTH_URL: ${{ secrets.SFDX_AUTH_URL_PROD }}
# ── Full-org Apex tests (after compilation passes) ──────────
apex-tests:
name: Full-Org Apex Tests
needs: apex-compilation
uses: ./.github/workflows/sf-apex-tests.yml
secrets:
SFDX_AUTH_URL: ${{ secrets.SFDX_AUTH_URL_PROD }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
# ── Failure notification ────────────────────────────────────
notify-failure:
name: Notify on Failure
needs: [apex-compilation, apex-tests]
if: failure()
uses: ./.github/workflows/sf-notify-slack.yml
with:
status: 'Failure'
title: 'Nightly Test Runner Failed'
message: 'Apex compilation or test execution failed. Review the workflow run for details.'
run-url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}'
secrets:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}