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 (
varusage, 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
- Start with:
--rule-selector Recommended--severity-threshold 3
- 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.