Skip to content

6. Metadata Quality and Org Governance

Three Distinct Pipeline Concerns

Metadata governance in a Salesforce pipeline operates across three fundamentally different workflow triggers that should not be conflated architecturally:

Scheduled workflows run on a defined cadence, independently of any developer activity. Their purpose is continual org surveillance: detecting drift, flagging configuration anomalies, and generating governance reports that inform architectural decisions.

PR-time workflows run synchronously against every pull request and enforce hard quality gates. Their purpose is change control: ensuring that every proposed change to the org meets defined standards before it can be merged and promoted.

Push workflows run in response to every branch push and serve as lightweight quality checks, functioning as a redundant check to VS Code auto-formatting and problem presentation with tools such as Code Analyzer or CodeScan. This is part of a shift-left mentality; by preventing commits or sending a message when a commit does not meet standards, the organization saves time and money versus catching these only when the PR is created.

Scheduled: Metadata Drift Detection

Drift is the cumulative divergence between what the repository says the org contains and what the org actually contains. It accumulates through direct org changes - fixes applied in production under pressure, sandbox experiments never committed, declarative changes made by administrators outside the developer workflow - and it compounds silently until a deployment surfaces the inconsistency at the worst possible moment.

Drift detection requires a scheduled GitHub Actions workflow - not a PR gate - that runs on a defined cadence and compares org state to repository state. The sf project retrieve start command retrieves current org metadata into a temporary workspace, and a subsequent git diff against the repository state surfaces divergence. This workflow has no merge-blocking role; its output is informational, feeding into one of three response patterns:

  • Alerting only: The workflow posts a structured drift summary to a Slack channel or creates a GitHub issue; engineers investigate and resolve manually.
  • PR generation: The workflow creates a pull request that brings the repository into alignment with the org, triggering the full PR-time quality gate chain before the drift is accepted into source.
  • Hard failure: For orgs where source-driven deployment is strictly enforced, any detected drift fails the scheduled workflow and blocks further deployments until resolved.

The right pattern depends on the org's deployment maturity. Teams transitioning from change set deployments will typically start with alerting and progress toward hard failure as the source-driven model matures.

PR-Time: Destructive Change Detection and Governance

Destructive changes - field deletions, component removals, object deprecations - are the highest-risk category of Salesforce deployment. Unlike additive changes, destructive changes are frequently irreversible in production and can cascade across dependent metadata, integrations, and data in ways that a deployment validator alone will not surface.

In a source-driven pipeline, destructive changes are expressed in a destructiveChanges.xml manifest. The presence of this file in a pull request is the primary signal that elevated scrutiny is warranted. A GitHub Actions PR workflow can detect and respond to this explicitly:

  • Scanning the PR diff for the presence or modification of destructiveChanges.xml or destructiveChangesPre.xml.
  • Labeling the PR automatically with a destructive-change tag to trigger mandatory reviewer assignment.
  • Blocking auto-merge policies regardless of quality gate status - destructive changes should require explicit human approval even when all automated gates pass.
  • Posting a structured comment to the PR summarizing the components marked for deletion and their metadata type, giving reviewers an immediate impact surface without requiring them to parse the XML manually.

Beyond manifest detection, the workflow can perform dependency analysis before a destructive change is allowed to proceed. The sf CLI's metadata dependency tooling can identify which other components reference the component marked for deletion - surfacing blast radius before the change reaches a validation org.

PR-Time: Metadata Validation and Deployment Integrity

A change that passes static analysis and unit tests can still fail in the target org due to metadata conflicts, missing dependencies, or org-specific configuration state. sf project deploy start --dry-run runs a full server-side validation against the target org without committing any changes - it is the definitive check that metadata is deployable in context, not just syntactically correct in isolation.

Key design decisions for this gate:

  • Target org selection: Validation should run against the closest available approximation of the production org - typically a full-copy sandbox or a dedicated CI sandbox kept in sync with production metadata.
  • Test level: RunLocalTests is the minimum viable threshold, with RunRelevantTests appropriate for large orgs on API 66.0. Refer to Section 5 for the full test level tradeoff discussion; Section 6 covers the corresponding metadata validation pattern.
  • Failure surfacing: Deployment validation errors should be parsed from the CLI output and posted as structured PR annotations rather than left as raw log output for the developer to interpret.
  • Concurrency handling: GitHub Actions concurrency groups prevent simultaneous validations against the same org from producing conflicting results and consuming test execution locks.
  • Empty delta guard: Before executing validation, the workflow should verify that the delta package contains deployable metadata via grep -q '<types>' delta/package/package.xml. If the package is empty - for example on a documentation-only change - validation should be skipped cleanly rather than erroring against an empty manifest.

PR-Time: Metadata Type Risk Classification

Not all metadata types carry equal risk. A metadata type risk classification framework assigns each metadata type a risk tier that drives PR workflow behavior automatically.

Tier 1 - High Risk: Metadata types where errors have broad, potentially irreversible consequences - Sharing Rules, Territory configurations, Named Credentials, Connected Apps, Auth Providers, and Custom Permissions. Changes to Tier 1 metadata trigger mandatory senior reviewer assignment, block auto-merge unconditionally, and may require a linked change management record depending on the organization's ITSM posture.

Tier 2 - Standard Risk: The majority of programmatic and declarative metadata - Apex classes, LWC components, Flows, Validation Rules, Custom Objects and Fields, and all Agentforce and AI metadata types. The standard PR quality gate chain applies with no elevated reviewer requirements.

Tier 3 - Low Risk: Metadata unlikely to cause functional regressions - Custom Labels, Static Resources, Email Templates, Reports and Dashboards. Candidates for expedited review in mature teams.

Risk classification is implemented in the PR workflow via path-based trigger conditions and automated PR labeling logic. The classification matrix itself should be a versioned artifact in the configuration repository (Section 8). A reference classification matrix is provided in Appendix B.

PR-Time: Dependency Analysis and Impact Assessment

For most organizations, a combination of well-chosen PR-time test levels and scheduled full-org quality runs provides sufficient coverage without requiring explicit dependency graph tooling:

  • PR-time test execution using RunLocalTests or RunRelevantTests (API 66.0) provides fast, targeted feedback on the components being changed.
  • Scheduled full-org Apex test runs - wired into a nightly or cadence-based GitHub Actions workflow - catch regressions that PR-scoped test execution may not surface, including failures in components that depend on recently changed code but were not included in the PR-time test scope.
  • Scheduled Apex compilation checks - running a full org compilation on a schedule confirms that no accumulated changes have introduced compilation failures across the codebase, independent of test coverage.

For organizations that need deeper impact assessment, the sf CLI exposes dependency information via sf data query against the MetadataComponentDependency tooling object, which returns the full dependency graph for any component in the org. This is an advanced capability that introduces meaningful pipeline complexity and is most appropriate for large, highly interconnected orgs where the cost of a missed dependency failure in production justifies the investment. For large orgs where querying the full dependency graph on every PR is prohibitively slow, a pragmatic alternative is to maintain a cached dependency manifest - generated by the scheduled drift detection workflow and committed to the repository - that the PR workflow queries locally rather than hitting the org API on each run.

Push-Time: Lightweight Local Feedback and Prevention

Push workflows operate at commit time, before a PR is created, and serve as a shift-left mechanism to catch issues early in the development cycle. Unlike PR-time workflows which enforce hard blocking gates, push workflows provide fast feedback and lightweight prevention, functioning as a redundant check to local development tooling.

Push workflow design principles:

  • Fast execution: Push workflows must complete in seconds, not minutes. Heavy static analysis, full test execution, and metadata validation belong in PR-time gates; push-time checks should focus on formatting, linting, and basic syntax validation with static analysis.
  • Problem presentation: Rather than blocking commits unconditionally, push workflows typically post findings as structured annotations on a failed workflow, allowing developers to review and commit with awareness.
  • Redundancy to local tooling: Push workflows reinforce checks already available locally via VS Code extensions (Code Analyzer, CodeScan) and pre-commit hooks. They catch developers who skip local checks and provide organizational consistency across the team.
  • Formatting and style consistency: Push workflows commonly enforce code formatting and linting (Prettier, ESLint) and flagrant style violations (unused variables, incorrect naming conventions).
  • Reusable workflow integration: Push workflows should be implemented as reusable workflow_call targets (Appendix A.1.1) invoked from the baseline push gate, allowing centralized maintenance across all team repositories.
  • Scope limitation: Push workflows should run on all branches, as they do lightweight checks and are the first line of defense.

Push workflows are not a substitute for PR-time gates; they are a complement, catching low-hanging fruit at the earliest point in the development cycle and reinforcing organizational standards without the cognitive load of mandatory blocking gates on every feature branch commit.