| name | sf-deploy |
| description | Orchestrate Salesforce deployments with dependency resolution, package.xml
generation, targeted test execution, error diagnosis, and rollback strategies.
Use when asked to deploy code, troubleshoot deployment errors, generate
package.xml, set up CI/CD pipelines, or validate deployments. Activate on
mentions of "deploy", "deployment", "package.xml", "CI/CD", "GitHub Actions",
"validation error", or "deployment failure".
|
| license | Apache-2.0 |
| compatibility | Requires Salesforce CLI (sf) v2+. Authenticated org needed for deployments. |
| metadata | {"author":"clientell","version":"1.0.0","tags":"salesforce, deployment, ci-cd, devops, package-xml"} |
| allowed-tools | Read,Write,Edit,Bash(sf *),Glob,Grep |
| context | fork |
Deployment Orchestrator
You are a Salesforce deployment specialist. Manage multi-step deployments with error handling and dependency resolution.
Deployment Workflow
1. Pre-Deployment Checks
sf org display --target-org myOrg
sf project deploy preview -d force-app/
sf project deploy start -d force-app/ --dry-run --target-org myOrg
2. Generate package.xml
sf project generate manifest --from-org myOrg --output-dir manifest/
sf project generate manifest -d force-app/ --output-dir manifest/
3. Deployment Order (Dependencies First)
Deploy in this order to avoid dependency failures:
- Custom Objects & Fields — schema must exist before code references it
- Custom Labels & Custom Metadata — referenced by Apex and Flows
- Permission Sets & Custom Permissions — required by bypass logic
- Apex Classes — service classes, selectors, utilities first
- Apex Triggers — depend on handler classes
- Flows — may reference Apex actions
- LWC — may wire to Apex controllers
- Layouts, FlexiPages, Profiles — reference everything above
4. Deploy Commands
sf project deploy start -d force-app/main/default/classes/ --target-org myOrg
sf project deploy start -d force-app/ --test-level RunSpecifiedTests --tests MyClassTest,MyOtherClassTest --target-org myOrg
sf project deploy start -d force-app/ --test-level RunLocalTests --target-org myOrg
sf project deploy start -m ApexClass:MyClass,ApexClass:MyClassTest --target-org myOrg
sf project deploy quick --job-id <validationId> --target-org myOrg
5. Delta Deployments
For CI/CD, deploy only changed files:
sfdx sgd:source:delta --from origin/main --to HEAD --output delta/
sf project deploy start -d delta/force-app/ --target-org myOrg
Scratch Org Workflows
sf org create scratch -f config/project-scratch-def.json -a scratch1 -d 30
sf org create scratch --source-org prodOrg -a scratch1
sf org delete scratch -o scratch1 --no-prompt
Package Development
sf package create --name "My Package" --package-type Unlocked --path force-app
sf package version create --package "My Package" --installation-key test1234 --wait 10
sf package install --package 04t... --target-org myOrg --wait 10
- Unlocked Packages: Org-independent, no namespace lock, editable after install
- 2GP Managed: Namespace-locked, IP protection, AppExchange distribution
Destructive Changes
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>OldClass</members>
<name>ApexClass</name>
</types>
<version>62.0</version>
</Package>
destructiveChangesPre.xml — deletes BEFORE deploy (remove dependencies first)
destructiveChangesPost.xml — deletes AFTER deploy (clean up replaced components)
- Deploy with:
sf project deploy start -d force-app/ --post-destructive-changes destructiveChangesPost.xml
Authentication Methods
| Method | Use Case | Command |
|---|
| Web Login | Interactive / dev | sf org login web |
| JWT Bearer | CI/CD (headless) | sf org login jwt --client-id ... --jwt-key-file ... |
| SFDX Auth URL | CI/CD (simpler) | sf org login sfdx-url --sfdx-url-file authUrl.txt |
| Device Flow | Headless (no cert) | sf org login device |
Salesforce Code Analyzer
sf scanner run --target force-app/ --format csv --outfile results.csv
sf scanner run --target force-app/ --category "Security,Best Practices"
Test Level Guide
| Level | When | Command Flag |
|---|
| NoTestRun | Non-prod, metadata-only | --test-level NoTestRun |
| RunSpecifiedTests | Known affected tests | --test-level RunSpecifiedTests --tests MyTest |
| RunLocalTests | Production deploy | --test-level RunLocalTests |
| RunAllTestsInOrg | Full validation | --test-level RunAllTestsInOrg |
Error Diagnosis
Common Deployment Errors
| Error | Cause | Fix |
|---|
Entity not found: CustomObject__c | Missing dependency | Deploy custom object first |
Dependent class is invalid | Compile error in dependency | Fix dependent class first |
Code coverage is below 75% | Insufficient tests | Run sf-test skill to generate tests |
Component not found: c:myComponent | Missing LWC dependency | Deploy LWC before FlexiPage |
Test failure: System.AssertException | Test expecting wrong data | Fix test assertions |
FIELD_CUSTOM_VALIDATION_EXCEPTION | Validation rule blocking test data | Update test data to pass validation |
INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY | Sharing/permission issue | Check profile/permission set deployment |
Diagnosing Failures
sf project deploy report --job-id <jobId>
sf project deploy resume --job-id <jobId>
CI/CD Pipeline (GitHub Actions)
name: Salesforce CI/CD
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
validate:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm install @salesforce/cli -g
- name: Authenticate
run: sf org login jwt --client-id ${{ secrets.SF_CLIENT_ID }} --jwt-key-file server.key --username ${{ secrets.SF_USERNAME }} --instance-url ${{ secrets.SF_INSTANCE_URL }} --alias ci-org
- name: Validate
run: sf project deploy start -d force-app/ --dry-run --test-level RunLocalTests --target-org ci-org
deploy:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm install @salesforce/cli -g
- name: Authenticate
run: sf org login jwt --client-id ${{ secrets.SF_CLIENT_ID }} --jwt-key-file server.key --username ${{ secrets.SF_USERNAME }} --instance-url ${{ secrets.SF_INSTANCE_URL }} --alias prod-org
- name: Deploy
run: sf project deploy start -d force-app/ --test-level RunLocalTests --target-org prod-org
Gotchas
- Profiles cause merge conflicts — prefer Permission Sets for deployable permissions
- Destructive changes cannot be rolled back — always validate first
- Quick deploy validations expire after 10 days
- Source tracking resets when scratch org expires
- Package dependencies must be installed in dependency order
- API version mismatches between components can cause silent deployment failures
RunLocalTests skips managed package tests — RunAllTestsInOrg includes them
- Sandbox refresh does not preserve manual configuration changes
Rollback Strategy
Salesforce has no native rollback. Mitigation:
- Always validate (
--dry-run) before deploying
- Keep previous version in git — rollback = deploy previous commit
- For destructive changes, prepare
destructiveChangesPost.xml
- Use scratch orgs / sandboxes for testing before production
References
- Deploy Patterns — scratch orgs, packages, destructive changes, sandbox types, Code Analyzer, sfdx-git-delta, auth methods, DevOps Center
Workflow
- Verify org authentication and connection
- Analyze what needs to be deployed
- Resolve dependencies and determine deploy order
- Validate deployment (dry-run)
- Deploy with appropriate test level
- Monitor deployment status
- Diagnose and fix any errors
- Verify deployment success