Adding Static Code Analysis to a Salesforce Bitbucket Pipeline (Without Breaking Delivery)

We recently introduced static code analysis into our Salesforce CI/CD pipeline—and did it in a way that improves code quality progressively without slowing the team down.

Here’s how

The Context

We’re running an org development model with a Bitbucket pipeline that:

  • Generates deltas using sfdx-git-delta
  • Runs unit tests
  • Validates and deploys metadata to target orgs

The requirement was adding static code analysis without forcing a full legacy cleanup.

The Strategy

Instead of scanning the entire codebase, we chose a delta-based enforcement model:

Only code that is changed must meet static analysis standards.

This means:

  • Every enhancement improves the codebase
  • No massive refactor required upfront
  • Developers own the quality of what they touch

Tooling: Salesforce Code Analyzer

We used Salesforce Code Analyzer, the official static analysis tool for Salesforce.

It runs multiple engines under the hood:

  • PMD ? Apex issues
  • ESLint ? LWC / JavaScript
  • RetireJS ? vulnerable libraries
  • CPD ? duplicate code

Docs: https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/guide/code-analyzer.html

Pipeline Implementation

1. Delta-Based Scan (Blocking)

We added static analysis right after delta generation and before deployment validation:

sf code-analyzer run \
  --workspace delta/force-app \
  --rule-selector Recommended \
  --severity-threshold 3 \
  --view table \
  --output-file reports/code-analyzer.html

What this does:

  • Scans only modified metadata
  • Fails the pipeline on Moderate+ issues
  • Shows results directly in pipeline logs
  • There is no external report retrieval — the pipeline logs are the source of truth for failures.

3. Full Scan (Optional, Non-Blocking)

We added a custom pipeline for full repo scanning:

sf code-analyzer run \
  --workspace force-app \
  --rule-selector Recommended \
  --view summary \
  --output-file reports/full-scan.html || true

This:

  • Does NOT block deployment
  • Provides visibility into legacy issues
  • Can be run on demand (e.g. before releases)

Example Outcome

In one run, the analyzer reported:

  • 63 total violations
  • 6 High severity
  • 55 Moderate severity

Most issues came from:

  • Aura JS (var usage, unused variables)
  • Legacy patterns flagged by ESLint rules

This is expected when introducing static analysis into an existing codebase — especially with Aura components.

Why This Approach Works

Instead of enforcing perfection across the entire repo, we enforce:

“Leave the code better than you found it.”

Benefits:

  • No disruption to delivery
  • Gradual improvement of legacy code
  • Developers fix issues in context
  • Faster pipeline execution (delta vs full scan)

Trade-offs

Delta scanning won’t catch:

  • Issues in untouched files
  • Cross-file design problems
  • Some architectural concerns

That’s why the full scan still exists as a health check.

Recommended Maturity Path

  1. Start with:
    • --rule-selector Recommended
    • --severity-threshold 3
  2. Gradually:
    • Tighten severity threshold
    • Introduce custom rules
    • Expand to full-scan enforcement (optional)

Final Pipeline Model

  • PR Validation ? Delta scan (blocking)
  • Deploy ? continues if clean
  • Custom Pipeline ? Full scan (non-blocking)

? Key Takeaway

You don’t need to fix your entire Salesforce codebase to introduce static analysis.

Start with:

“If you touch it, you own its quality.”

Everything else improves over time.

Leave a Reply

Your email address will not be published. Required fields are marked *