Smart Deployment Orchestration
The command sf hardis:project:deploy:smart is the central deployment engine of sfdx-hardis CI/CD. It orchestrates a sophisticated pipeline that handles delta deployments, Quick Deploy, test class selection, package installation, overwrite management, pre/post commands, and notifications, all in a single, unified flow.
End-to-End Flow
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#eaf5fe", "primaryTextColor": "#032d60", "primaryBorderColor": "#0176d3", "lineColor": "#0176d3", "secondaryColor": "#f3f3f3", "tertiaryColor": "#ffffff", "fontFamily": "Salesforce Sans, Arial, sans-serif"}}}%%
flowchart TD
START([Smart Deploy Start]) --> INIT[Initialize: parse flags,<br/>load config, resolve org]
subgraph Preparation
INIT --> TESTS[Resolve Test Level<br/>& Test Classes]
TESTS --> PKG[Install Packages<br/>if configured]
PKG --> SUMMARY[Build Commit Summary<br/>for PR if check-only]
SUMMARY --> MANIFEST[Resolve package.xml<br/>& destructiveChanges.xml]
end
subgraph "Delta Processing"
MANIFEST --> DELTA{Delta<br/>enabled & allowed?}
DELTA -->|Yes| GIT_DELTA[Run sfdx-git-delta<br/>to compute changed metadata]
GIT_DELTA --> INTERSECT[Intersect delta<br/>with full package.xml]
INTERSECT --> SMART{Smart Tests:<br/>only non-impacting<br/>metadata?}
SMART -->|Yes & not prod| NO_TEST[Skip tests]
SMART -->|No| KEEP_TESTS[Keep test level]
DELTA -->|No| KEEP_TESTS
end
subgraph "Overwrite Filtering"
NO_TEST --> OVERWRITE
KEEP_TESTS --> OVERWRITE[Filter package.xml]
OVERWRITE --> OW1[Remove items already<br/>in org via no-overwrite]
end
subgraph "Core Deployment"
OW1 --> PRE[Run Pre-Deploy Commands]
PRE --> QD{Quick Deploy<br/>available?}
QD -->|Yes| QUICK[Quick Deploy<br/>skip full deploy]
QD -->|No| DEPLOY["Full Deploy<br/>sf project deploy start"]
QUICK --> POST
DEPLOY --> COVERAGE[Check Code Coverage]
COVERAGE --> POST[Run Post-Deploy Commands]
POST --> PR[Post PR Comment<br/>with full results]
end
subgraph "Post-Deployment"
PR --> NOTIFY[Send Notifications<br/>Slack / Teams / Email]
NOTIFY --> TICKETS[Update Ticketing<br/>Jira / etc.]
end
TICKETS --> END([Done])
click INIT "#initialization"
click TESTS "#test-level--test-class-resolution"
click PKG "#package-installation"
click MANIFEST "#packagexml--destructive-changes-resolution"
click DELTA "#delta-processing"
click GIT_DELTA "#delta-processing"
click INTERSECT "#delta-processing"
click SMART "#delta-processing"
click NO_TEST "#delta-processing"
click KEEP_TESTS "#delta-processing"
click OVERWRITE "#overwrite-filtering"
click OW1 "#overwrite-filtering"
click PRE "#prepost-deployment-commands"
click QD "#quick-deploy"
click QUICK "#quick-deploy"
click DEPLOY "#deployment-engine-smartdeploy"
click COVERAGE "#deployment-engine-smartdeploy"
click POST "#prepost-deployment-commands"
click PR "#post-deployment"
click NOTIFY "#post-deployment"
click TICKETS "#post-deployment"
classDef sfStart fill:#d8edff,stroke:#032d60,color:#032d60,stroke-width:3px
classDef sfAction fill:#eaf5fe,stroke:#0176d3,color:#032d60,stroke-width:1.5px,cursor:pointer
classDef sfDecision fill:#ffffff,stroke:#0176d3,color:#032d60,stroke-width:2px,cursor:pointer
classDef sfSuccess fill:#cdefc4,stroke:#2e844a,color:#194e31,stroke-width:1.5px,cursor:pointer
classDef sfWarn fill:#fef0cd,stroke:#fe9339,color:#5f3e02,stroke-width:1.5px
class START,END sfStart
class INIT,TESTS,PKG,SUMMARY,MANIFEST,GIT_DELTA,INTERSECT,OVERWRITE,OW1,PRE,DEPLOY,COVERAGE,POST,PR,NOTIFY,TICKETS sfAction
class DELTA,SMART,QD sfDecision
class QUICK,KEEP_TESTS,NO_TEST sfSuccess
Each section below details one part of this flow.
Preparation
Initialization
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#eaf5fe", "primaryTextColor": "#032d60", "primaryBorderColor": "#0176d3", "lineColor": "#0176d3", "fontFamily": "Salesforce Sans, Arial, sans-serif"}}}%%
flowchart LR
A[Parse CLI flags] --> B[Load branch config<br/>.sfdx-hardis.yml]
B --> C{Running in CI?}
C -->|No| D[Prompt user to confirm org]
C -->|Yes| E[Use --target-org]
D --> F[Set connection variables]
E --> F
classDef sfAction fill:#eaf5fe,stroke:#0176d3,color:#032d60,stroke-width:1.5px
classDef sfDecision fill:#ffffff,stroke:#0176d3,color:#032d60,stroke-width:2px
classDef sfSuccess fill:#cdefc4,stroke:#2e844a,color:#194e31,stroke-width:1.5px
class A,B,D,E sfAction
class C sfDecision
class F sfSuccess
The command reads its configuration from config/.sfdx-hardis.yml (or branch-specific files like config/branches/.sfdx-hardis-BRANCHNAME.yml). See CI/CD Configuration for details. Key flags include:
| Flag | Description |
|---|---|
--check |
Simulate deployment (dry-run / validation) |
--testlevel |
Apex test level (RunLocalTests, RunRepositoryTests, NoTestRun, etc.) |
--runtests |
Specific test classes or regex filter |
--delta |
Force delta deployment from CLI |
--packagexml |
Custom path to package.xml |
Test Level & Test Class Resolution
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#eaf5fe", "primaryTextColor": "#032d60", "primaryBorderColor": "#0176d3", "lineColor": "#0176d3", "fontFamily": "Salesforce Sans, Arial, sans-serif"}}}%%
flowchart TD
TL_START[Read testlevel flag or config] --> TL_CHECK{RunRepositoryTests?}
TL_CHECK -->|Yes| SCAN[Scan repo for @isTest classes]
TL_CHECK -->|No| CUSTOM_CHECK
SCAN --> FOUND{Test classes found?}
FOUND -->|Yes| SPECIFIED[Set RunSpecifiedTests + class list]
FOUND -->|No| FALLBACK[Fallback to RunLocalTests]
SPECIFIED --> CUSTOM_CHECK{enableDeploymentApexTestClasses?}
FALLBACK --> CUSTOM_CHECK
CUSTOM_CHECK -->|Yes| PR_CLASSES[Collect test classes from PR descriptions<br/>+ config deploymentApexTestClasses]
CUSTOM_CHECK -->|No| FINAL[Final test level set]
PR_CLASSES --> FINAL
classDef sfAction fill:#eaf5fe,stroke:#0176d3,color:#032d60,stroke-width:1.5px
classDef sfDecision fill:#ffffff,stroke:#0176d3,color:#032d60,stroke-width:2px
classDef sfSuccess fill:#cdefc4,stroke:#2e844a,color:#194e31,stroke-width:1.5px
classDef sfWarn fill:#fef0cd,stroke:#fe9339,color:#5f3e02,stroke-width:1.5px
class TL_START,SCAN,SPECIFIED,PR_CLASSES sfAction
class TL_CHECK,FOUND,CUSTOM_CHECK sfDecision
class FINAL sfSuccess
class FALLBACK sfWarn
Test level modes:
- RunLocalTests (default, highly recommended): Runs all local test classes in the target org. This is the safest option and the Salesforce best practice for production deployments.
- RunRepositoryTests / RunRepositoryTestsExceptSeeAllData: Scans the repo for
@isTestclasses, converts toRunSpecifiedTestswith the discovered list. TheExceptSeeAllDatavariant excludes test classes annotated with@isTest(SeeAllData=true). - RunRelevantTests: Lets Salesforce determine which tests to run based on the deployed metadata.
- NoTestRun: Skips all tests. Only valid for non-production orgs. Should not be used manually, it is set automatically by Smart Deployment Tests when appropriate.
Test options:
- Custom Apex Test Classes: When
enableDeploymentApexTestClasses: true, collects test classes declared in config and across all PR descriptions in scope, and overrides the test level toRunSpecifiedTestswith the collected class list. - Smart Deployment Tests: When enabled, automatically downgrades the test level to
NoTestRunif only non-impacting metadata types are present in the delta and the target is not a production org (see Delta Processing).
Package Installation
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#eaf5fe", "primaryTextColor": "#032d60", "primaryBorderColor": "#0176d3", "lineColor": "#0176d3", "fontFamily": "Salesforce Sans, Arial, sans-serif"}}}%%
flowchart TD
PKG_START[Read installedPackages from config] --> PKG_CHECK{Packages defined?}
PKG_CHECK -->|No| PKG_END[Continue]
PKG_CHECK -->|Yes| MODE{Check-only mode?}
MODE -->|No| INSTALL[Install packages on target org]
MODE -->|Yes| INSTALL_CHECK{INSTALL_PACKAGES_DURING_CHECK_DEPLOY?}
INSTALL_CHECK -->|Yes| INSTALL
INSTALL_CHECK -->|No| WARN[Warn about missing packages]
INSTALL --> PKG_END
WARN --> PKG_END
classDef sfAction fill:#eaf5fe,stroke:#0176d3,color:#032d60,stroke-width:1.5px
classDef sfDecision fill:#ffffff,stroke:#0176d3,color:#032d60,stroke-width:2px
classDef sfSuccess fill:#cdefc4,stroke:#2e844a,color:#194e31,stroke-width:1.5px
classDef sfWarn fill:#fef0cd,stroke:#fe9339,color:#5f3e02,stroke-width:1.5px
class PKG_START,INSTALL sfAction
class PKG_CHECK,MODE,INSTALL_CHECK sfDecision
class PKG_END sfSuccess
class WARN sfWarn
Packages with installDuringDeployments: true in config are installed before the main deployment. In check-only mode, installation is skipped unless explicitly enabled. Use sf hardis:org:retrieve:packageconfig to automatically populate the installedPackages property from an existing org. See Package Installation for more details.
Package.xml & Destructive Changes Resolution
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#eaf5fe", "primaryTextColor": "#032d60", "primaryBorderColor": "#0176d3", "lineColor": "#0176d3", "fontFamily": "Salesforce Sans, Arial, sans-serif"}}}%%
flowchart TD
XML_START[Read manifest/package.xml] --> DC{Destructive changes<br/>files exist?}
DC -->|Post-destructive| POST_DC[manifest/destructiveChanges.xml]
DC -->|Pre-destructive| PRE_DC[manifest/preDestructiveChanges.xml]
DC -->|None| READY[Smart deploy options ready]
POST_DC --> READY
PRE_DC --> READY
classDef sfAction fill:#eaf5fe,stroke:#0176d3,color:#032d60,stroke-width:1.5px
classDef sfDecision fill:#ffffff,stroke:#0176d3,color:#032d60,stroke-width:2px
classDef sfSuccess fill:#cdefc4,stroke:#2e844a,color:#194e31,stroke-width:1.5px
classDef sfDanger fill:#feded8,stroke:#ea001e,color:#8c1717,stroke-width:1.5px
class XML_START sfAction
class DC sfDecision
class READY sfSuccess
class POST_DC,PRE_DC sfDanger
Delta Processing
Delta deployment reduces the deployment scope to only the metadata that changed between the source and target branches, using sfdx-git-delta. See Delta Deployment Configuration for setup instructions.
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#eaf5fe", "primaryTextColor": "#032d60", "primaryBorderColor": "#0176d3", "lineColor": "#0176d3", "fontFamily": "Salesforce Sans, Arial, sans-serif"}}}%%
flowchart TD
D_START{Delta enabled?} -->|No| FULL[Full deployment mode]
D_START -->|Yes| ALLOWED{isDeltaAllowed?}
ALLOWED -->|No| FULL
ALLOWED -->|Yes| SCOPE[Determine delta scope]
SCOPE --> CHECK_MODE{Check-only?}
CHECK_MODE -->|Yes| PR_SCOPE[Get PR source/target branches<br/>compute merge-base commit]
CHECK_MODE -->|No| HEAD_SCOPE["Use HEAD^ → HEAD"]
PR_SCOPE --> GIT_DELTA[Run sfdx-git-delta<br/>sf sgd:source:delta]
HEAD_SCOPE --> GIT_DELTA
GIT_DELTA --> DEPS{Dependencies enabled?}
DEPS -->|Yes| EXTEND[Extend delta with dependencies<br/>+ append modified packages]
DEPS -->|No| INTERSECT
EXTEND --> INTERSECT[Intersect delta with full package.xml<br/>Keep only items in both]
INTERSECT --> SMART{Smart Tests enabled?}
SMART -->|Yes| META_CHECK{All metadata types<br/>non-impacting?}
SMART -->|No| DEPLOY_DELTA[Deploy delta package.xml]
META_CHECK -->|Yes & not prod| NO_TEST[Set NoTestRun]
META_CHECK -->|No or prod| DEPLOY_DELTA
NO_TEST --> DEPLOY_DELTA
INTERSECT --> DC_DELTA[Also intersect destructiveChanges<br/>with git delta destructive output]
DC_DELTA --> DEPLOY_DELTA
classDef sfAction fill:#eaf5fe,stroke:#0176d3,color:#032d60,stroke-width:1.5px
classDef sfDecision fill:#ffffff,stroke:#0176d3,color:#032d60,stroke-width:2px
classDef sfSuccess fill:#cdefc4,stroke:#2e844a,color:#194e31,stroke-width:1.5px
classDef sfWarn fill:#fef0cd,stroke:#fe9339,color:#5f3e02,stroke-width:1.5px
classDef sfDanger fill:#feded8,stroke:#ea001e,color:#8c1717,stroke-width:1.5px
class SCOPE,PR_SCOPE,HEAD_SCOPE,GIT_DELTA,EXTEND,INTERSECT,DC_DELTA sfAction
class D_START,ALLOWED,CHECK_MODE,DEPS,SMART,META_CHECK sfDecision
class DEPLOY_DELTA,NO_TEST sfSuccess
class FULL sfWarn
Delta eligibility rules (isDeltaAllowed)
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#eaf5fe", "primaryTextColor": "#032d60", "primaryBorderColor": "#0176d3", "lineColor": "#0176d3", "fontFamily": "Salesforce Sans, Arial, sans-serif"}}}%%
flowchart TD
DA_START[isDeltaAllowed] --> PR_NO_DELTA{PR has NO_DELTA keyword?}
PR_NO_DELTA -->|Yes| BLOCKED[Delta disabled]
PR_NO_DELTA -->|No| ENV_DISABLE{DISABLE_DELTA_DEPLOYMENT=true?}
ENV_DISABLE -->|Yes| BLOCKED
ENV_DISABLE -->|No| COMMIT_CHECK{Latest commit contains 'nodelta'?}
COMMIT_CHECK -->|Yes| BLOCKED
COMMIT_CHECK -->|No| FORCE_ENABLE{ALWAYS_ENABLE_DELTA or<br/>enableDeltaDeploymentBetweenMajorBranches?}
FORCE_ENABLE -->|Yes| ALLOWED_WARN[Delta enabled with warning]
FORCE_ENABLE -->|No| MERGE_CHECK{Is this a merge job<br/>not check-only?}
MERGE_CHECK -->|Yes & no USE_DELTA_DEPLOYMENT_AFTER_MERGE| BLOCKED
MERGE_CHECK -->|No| BRANCH_CHECK{Source = minor branch?<br/>Target = major branch?}
BRANCH_CHECK -->|Yes| ALLOWED[Delta allowed]
BRANCH_CHECK -->|No, both major| BLOCKED
classDef sfAction fill:#eaf5fe,stroke:#0176d3,color:#032d60,stroke-width:1.5px
classDef sfDecision fill:#ffffff,stroke:#0176d3,color:#032d60,stroke-width:2px
classDef sfSuccess fill:#cdefc4,stroke:#2e844a,color:#194e31,stroke-width:1.5px
classDef sfWarn fill:#fef0cd,stroke:#fe9339,color:#5f3e02,stroke-width:1.5px
classDef sfBlocked fill:#feded8,stroke:#ea001e,color:#8c1717,stroke-width:1.5px
class DA_START sfAction
class PR_NO_DELTA,ENV_DISABLE,COMMIT_CHECK,FORCE_ENABLE,MERGE_CHECK,BRANCH_CHECK sfDecision
class ALLOWED sfSuccess
class ALLOWED_WARN sfWarn
class BLOCKED sfBlocked
Non-impacting metadata types (deployment tests can be skipped if delta contains only these):
ActionLinkGroupTemplate, AppMenu, AuraDefinitionBundle, ContentAsset, CustomApplication, CustomLabel, CustomTab, Dashboard, Document, EmailTemplate, ExperienceBundle, FlexiPage, Layout, LightningComponentBundle, ListView, NavigationMenu, QuickAction, Report, StaticResource, Translations, and more.
Overwrite Filtering
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#eaf5fe", "primaryTextColor": "#032d60", "primaryBorderColor": "#0176d3", "lineColor": "#0176d3", "fontFamily": "Salesforce Sans, Arial, sans-serif"}}}%%
flowchart TD
OW_START[Overwrite Management] --> NO_OW{package-no-overwrite.xml<br/>exists?}
NO_OW -->|Yes| ORG_MANIFEST[Generate full package.xml<br/>from target org]
NO_OW -->|No| DONE_OW[Filtering complete]
ORG_MANIFEST --> INTERSECT_OW[Keep only items from<br/>package-no-overwrite.xml<br/>that already exist in org]
INTERSECT_OW --> REMOVE_OW[Remove those items<br/>from deployment package.xml]
REMOVE_OW --> DONE_OW
classDef sfAction fill:#eaf5fe,stroke:#0176d3,color:#032d60,stroke-width:1.5px
classDef sfDecision fill:#ffffff,stroke:#0176d3,color:#032d60,stroke-width:2px
classDef sfSuccess fill:#cdefc4,stroke:#2e844a,color:#194e31,stroke-width:1.5px
class OW_START,ORG_MANIFEST,INTERSECT_OW,REMOVE_OW sfAction
class NO_OW sfDecision
class DONE_OW sfSuccess
| File | Behavior |
|---|---|
manifest/package-no-overwrite.xml |
Items are deployed only if they don't already exist in the target org. Useful for ListViews that clients customize in production. See Overwrite management. |
Core Deployment
PR-Driven Additional Options
Before deployment starts, the PR description is scanned for special keywords and YAML overrides.
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#eaf5fe", "primaryTextColor": "#032d60", "primaryBorderColor": "#0176d3", "lineColor": "#0176d3", "fontFamily": "Salesforce Sans, Arial, sans-serif"}}}%%
flowchart TD
PR_START[Read PR info] --> PR_PURGE{PR contains<br/>PURGE_FLOW_VERSIONS?}
PR_PURGE -->|Yes| ADD_PURGE[Add pre-deploy command:<br/>sf hardis:org:purge:flow]
PR_PURGE -->|No| PR_DC
ADD_PURGE --> PR_DC{PR contains<br/>DESTRUCTIVE_CHANGES_AFTER_DEPLOYMENT?}
PR_DC -->|Yes| ADD_DC[Add post-deploy command:<br/>deploy destructiveChanges.xml separately]
PR_DC -->|No| DONE[Options ready]
ADD_DC --> DONE
classDef sfAction fill:#eaf5fe,stroke:#0176d3,color:#032d60,stroke-width:1.5px
classDef sfDecision fill:#ffffff,stroke:#0176d3,color:#032d60,stroke-width:2px
classDef sfSuccess fill:#cdefc4,stroke:#2e844a,color:#194e31,stroke-width:1.5px
classDef sfDanger fill:#feded8,stroke:#ea001e,color:#8c1717,stroke-width:1.5px
class PR_START sfAction
class PR_PURGE,PR_DC sfDecision
class ADD_PURGE sfAction
class ADD_DC sfDanger
class DONE sfSuccess
Pull Request descriptions can also override config properties using YAML blocks (see Deployment Actions):
deploymentApexTestClasses: override test classescommandsPreDeploy: add pre-deployment commandscommandsPostDeploy: add post-deployment commands
Pre/Post Deployment Commands
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#eaf5fe", "primaryTextColor": "#032d60", "primaryBorderColor": "#0176d3", "lineColor": "#0176d3", "fontFamily": "Salesforce Sans, Arial, sans-serif"}}}%%
flowchart TD
CMD_START[executePrePostCommands] --> SOURCES[Collect commands from:<br/>1. Branch config<br/>2. Extra commands from PR<br/>3. PR description YAML blocks]
SOURCES --> LOOP{For each command}
LOOP --> VALID{Action valid?}
VALID -->|No| SKIP_INVALID[Skip with reason]
VALID -->|Yes| ERR_CHECK{skipIfError=true<br/>& deploy failed?}
ERR_CHECK -->|Yes| SKIP_ERR[Skip command]
ERR_CHECK -->|No| CTX_CHECK{Context matches?}
CTX_CHECK -->|check-deployment-only<br/>but real deploy| SKIP_CTX[Skip]
CTX_CHECK -->|process-deployment-only<br/>but check mode| SKIP_CTX
CTX_CHECK -->|Matches| ONCE_CHECK{runOnlyOnceByOrg?}
ONCE_CHECK -->|Yes, already run| SKIP_ONCE[Skip]
ONCE_CHECK -->|No or first time| EXEC[Execute command]
EXEC --> LOOP
SKIP_INVALID --> LOOP
SKIP_ERR --> LOOP
SKIP_CTX --> LOOP
SKIP_ONCE --> LOOP
classDef sfAction fill:#eaf5fe,stroke:#0176d3,color:#032d60,stroke-width:1.5px
classDef sfDecision fill:#ffffff,stroke:#0176d3,color:#032d60,stroke-width:2px
classDef sfSuccess fill:#cdefc4,stroke:#2e844a,color:#194e31,stroke-width:1.5px
classDef sfSkip fill:#f3f3f3,stroke:#706e6b,color:#3e3e3c,stroke-width:1px
class CMD_START,SOURCES sfAction
class LOOP,VALID,ERR_CHECK,CTX_CHECK,ONCE_CHECK sfDecision
class EXEC sfSuccess
class SKIP_INVALID,SKIP_ERR,SKIP_CTX,SKIP_ONCE sfSkip
Action types:
| Type | Description | Key parameters |
|---|---|---|
command (default) |
Runs any CLI command (sf, sfdx, shell...) | command: the command line to execute |
data |
Imports data using an SFDMU project workspace | parameters.sfdmuProject: name of the SFDMU data workspace |
apex |
Executes an anonymous Apex script file | parameters.apexScript: path to the .apex script file |
publish-community |
Publishes an Experience Cloud community/site | parameters.communityName: name of the community to publish |
schedule-batch |
Schedules (or re-schedules) a Schedulable Apex batch | parameters.className: Apex class name, parameters.cronExpression: cron schedule, parameters.jobName (optional) |
manual |
Records manual instructions in the deployment report (not executed automatically) | parameters.instructions: text instructions for the operator |
All action types support the following common properties: id, label, context, skipIfError, allowFailure, runOnlyOnceByOrg, and customUsername (to run the action as a different user).
Command context options:
all(default), runs in both check and process modescheck-deployment-only, runs only during--checkprocess-deployment-only, runs only during actual deployment
Quick Deploy
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#eaf5fe", "primaryTextColor": "#032d60", "primaryBorderColor": "#0176d3", "lineColor": "#0176d3", "fontFamily": "Salesforce Sans, Arial, sans-serif"}}}%%
flowchart TD
QD_START{Actual deployment<br/>not check-only?} -->|Yes| QD_CHECK{SFDX_HARDIS_QUICK_DEPLOY<br/>!= false?}
QD_CHECK -->|Yes| QD_ID[Get deployment check ID<br/>from merged PR comment]
QD_ID --> QD_FOUND{ID found?}
QD_FOUND -->|Yes| QD_RUN["sf project deploy quick<br/>--job-id {id}"]
QD_FOUND -->|No| FULL[Full deployment]
QD_RUN --> QD_OK{Succeeded?}
QD_OK -->|Yes| QD_DONE[Deployment complete!<br/>Skip test execution]
QD_OK -->|No| QD_FALLBACK[Fallback to full deploy<br/>with NoTestRun if not prod]
QD_FALLBACK --> FULL
QD_CHECK -->|No| FULL
classDef sfAction fill:#eaf5fe,stroke:#0176d3,color:#032d60,stroke-width:1.5px
classDef sfDecision fill:#ffffff,stroke:#0176d3,color:#032d60,stroke-width:2px
classDef sfSuccess fill:#cdefc4,stroke:#2e844a,color:#194e31,stroke-width:1.5px
classDef sfWarn fill:#fef0cd,stroke:#fe9339,color:#5f3e02,stroke-width:1.5px
class QD_ID,QD_RUN sfAction
class QD_START,QD_CHECK,QD_FOUND,QD_OK sfDecision
class QD_DONE sfSuccess
class QD_FALLBACK,FULL sfWarn
Quick Deploy reuses a previously validated deployment check, skipping the full deployment and test execution. The deployment check ID is stored in the PR comment from the check-only run. See also sf hardis:project:deploy:quick.
Deployment Engine (smartDeploy)
This is the heart of the deployment process, implemented in deployUtils.ts.
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#eaf5fe", "primaryTextColor": "#032d60", "primaryBorderColor": "#0176d3", "lineColor": "#0176d3", "fontFamily": "Salesforce Sans, Arial, sans-serif"}}}%%
flowchart TD
SD_START[smartDeploy called] --> EMPTY_CHECK{package.xml empty?}
EMPTY_CHECK -->|Yes, no destructive| SKIP_ALL[Run pre/post commands<br/>Post PR comment<br/>Return empty]
EMPTY_CHECK -->|No| BUILD[Build calculated package.xml]
BUILD --> FILTER[Apply overwrite filters]
FILTER --> FILTER_ONCE[Remove items from<br/>package-no-overwrite.xml<br/>already in target org]
FILTER_ONCE --> PRE_CMD[Execute commandsPreDeploy]
PRE_CMD --> PKG_EMPTY{Calculated package.xml empty?}
PKG_EMPTY -->|Yes| POST_CMD
PKG_EMPTY -->|No| QUICK_CHECK{Check-only = false<br/>& Quick Deploy available?}
QUICK_CHECK -->|Yes| QUICK[sf project deploy quick<br/>--job-id deploymentCheckId]
QUICK_CHECK -->|No| FULL_DEPLOY
QUICK --> QUICK_OK{Quick Deploy succeeded?}
QUICK_OK -->|Yes| POST_CMD
QUICK_OK -->|No| FULL_DEPLOY[sf project deploy start<br/>--manifest --test-level<br/>--dry-run if check]
FULL_DEPLOY --> DEPLOY_OK{Deploy succeeded?}
DEPLOY_OK -->|Yes| COVERAGE[Check code coverage]
DEPLOY_OK -->|No| ERR_HANDLE[Analyze errors with deploy tips<br/>Post PR comment<br/>Throw error]
COVERAGE --> COV_OK{Coverage sufficient?}
COV_OK -->|Yes| POST_CMD
COV_OK -->|No & testCoverageNotBlocking| POST_CMD
COV_OK -->|No| ERR_HANDLE
POST_CMD[Execute commandsPostDeploy]
POST_CMD --> PR_COMMENT[Post PR comment with results]
PR_COMMENT --> SD_END([Return results])
classDef sfStart fill:#d8edff,stroke:#032d60,color:#032d60,stroke-width:3px
classDef sfAction fill:#eaf5fe,stroke:#0176d3,color:#032d60,stroke-width:1.5px
classDef sfDecision fill:#ffffff,stroke:#0176d3,color:#032d60,stroke-width:2px
classDef sfSuccess fill:#cdefc4,stroke:#2e844a,color:#194e31,stroke-width:1.5px
classDef sfWarn fill:#fef0cd,stroke:#fe9339,color:#5f3e02,stroke-width:1.5px
classDef sfError fill:#feded8,stroke:#ea001e,color:#8c1717,stroke-width:1.5px
classDef sfSkip fill:#f3f3f3,stroke:#706e6b,color:#3e3e3c,stroke-width:1px
class SD_END sfStart
class SD_START,BUILD,FILTER,FILTER_ONCE,PRE_CMD,FULL_DEPLOY,COVERAGE,POST_CMD,PR_COMMENT sfAction
class EMPTY_CHECK,PKG_EMPTY,QUICK_CHECK,QUICK_OK,DEPLOY_OK,COV_OK sfDecision
class QUICK sfSuccess
class SKIP_ALL sfSkip
class ERR_HANDLE sfError
Post-Deployment
%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#eaf5fe", "primaryTextColor": "#032d60", "primaryBorderColor": "#0176d3", "lineColor": "#0176d3", "fontFamily": "Salesforce Sans, Arial, sans-serif"}}}%%
flowchart TD
PD_START[Deployment complete] --> NOTIF[Build notification message]
NOTIF --> TICKET[Post to ticketing system<br/>Jira, etc.]
TICKET --> SLACK[Send notification<br/>Slack, Teams, Email]
SLACK --> PR_COMMENT[Post/update PR comment<br/>with deployment results]
PR_COMMENT --> DONE([Done])
classDef sfStart fill:#d8edff,stroke:#032d60,color:#032d60,stroke-width:3px
classDef sfAction fill:#eaf5fe,stroke:#0176d3,color:#032d60,stroke-width:1.5px
classDef sfSuccess fill:#cdefc4,stroke:#2e844a,color:#194e31,stroke-width:1.5px
class PD_START sfSuccess
class NOTIF,TICKET,SLACK,PR_COMMENT sfAction
class DONE sfStart
The PR comment includes:
- Deployment errors (with fix tips)
- Code coverage report
- Pre/post command results
- Commit summary
- Flow visual git diff (mermaid diagrams)
Configuration Reference
.sfdx-hardis.yml properties
| Property | Type | Description |
|---|---|---|
useDeltaDeployment |
boolean | Enable delta deployments between minor and major branches |
enableDeltaDeploymentBetweenMajorBranches |
boolean | Force delta even between major branches (not recommended) |
useSmartDeploymentTests |
boolean | Skip tests if only non-impacting metadata types in delta |
testLevel |
string | Default test level |
enableDeploymentApexTestClasses |
boolean | Enable custom test class list from config/PRs |
deploymentApexTestClasses |
string[] | Explicit list of Apex test classes to run |
installedPackages |
object[] | Packages to install during deployment |
installPackagesDuringCheckDeploy |
boolean | Install packages even in check-only mode |
commandsPreDeploy |
object[] | Commands to run before deployment |
commandsPostDeploy |
object[] | Commands to run after deployment |
packageNoOverwritePath |
string | Custom path to package-no-overwrite.xml |
testCoverageNotBlocking |
boolean | Allow deployment even with insufficient code coverage |
skipCodeCoverage |
boolean | Skip code coverage reporting |
Environment Variables
See also the full environment variables reference.
| Variable | Description |
|---|---|
USE_DELTA_DEPLOYMENT |
Enable delta deployment |
ALWAYS_ENABLE_DELTA_DEPLOYMENT |
Force delta even between major branches |
DISABLE_DELTA_DEPLOYMENT |
Explicitly disable delta |
USE_DELTA_DEPLOYMENT_AFTER_MERGE |
Allow delta for merge jobs (not just checks) |
USE_SMART_DEPLOYMENT_TESTS |
Enable smart test skipping |
NOT_IMPACTING_METADATA_TYPES |
Override the list of non-impacting types (comma-separated) |
SFDX_HARDIS_QUICK_DEPLOY |
Set to false to disable Quick Deploy |
SFDX_DEPLOY_WAIT_MINUTES |
Deployment wait timeout (default: 120) |
INSTALL_PACKAGES_DURING_CHECK_DEPLOY |
Install packages in check-only mode |
SKIP_PACKAGE_DEPLOY_ONCE |
Skip package-no-overwrite.xml processing |
FORCE_TARGET_BRANCH |
Override target branch for delta scope |
SFDX_HARDIS_DEPLOY_BEFORE_MERGE |
Use current PR instead of merged PR for notifications |
SFDX_DISABLE_FLOW_DIFF |
Disable Flow Visual Git Diff in PR comments |
PR Description Keywords
| Keyword | Effect |
|---|---|
NO_DELTA |
Force full deployment for this PR |
PURGE_FLOW_VERSIONS |
Purge inactive/obsolete Flow versions after deployment (runs sf hardis:org:purge:flow) |
DESTRUCTIVE_CHANGES_AFTER_DEPLOYMENT |
Run destructiveChanges.xml in a separate post-deploy step |
nodelta (in commit message) |
Disable delta for this specific deployment |
nosmart (in commit message) |
Disable Smart Deployment Tests for this deployment |
Check Mode vs. Process Mode
| Aspect | Check Mode (--check) |
Process Mode (no flag) |
|---|---|---|
| Deployment | Dry-run / validation | Actual deployment |
| Quick Deploy | Stores deployment ID in PR | Uses stored deployment ID |
| Delta scope | PR source branch → target branch | HEAD^ → HEAD |
| Packages | Warns about missing packages | Installs packages |
| Post commands | Skips process-deployment-only commands |
Skips check-deployment-only commands |
| Notifications | Posts check results to PR | Sends deployment success notifications |