Smart Deployment Orchestration
The command sf hardis:project:deploy:smart is the central deployment engine of sfdx-hardis CI/CD. It orchestrates a pipeline that handles delta deployments, Quick Deploy, test class selection, package installation, overwrite management, pre/post commands, and notifications in a single 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] --> SCOPE{Merge from a<br/>feature branch?}
SCOPE -->|Yes| ONE_PR[Scope: the merged PR only]
SCOPE -->|No: major or retrofit branch| BATCH[Scope: all PRs since<br/>the previous merge]
ONE_PR --> SOURCES[Collect commands from:<br/>1. Branch config<br/>2. Extra commands from PR<br/>3. PR description YAML blocks]
BATCH --> SOURCES
SOURCES --> DEPLOY_KO{Metadata deployment<br/>failed?}
DEPLOY_KO -->|Yes| SKIP_ERR[Report every action as<br/>not run and stop]
DEPLOY_KO -->|No| LOOP{For each command}
LOOP --> VALID{Action valid?}
VALID -->|No| SKIP_INVALID[Skip with reason]
VALID -->|Yes| 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_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,ONE_PR,BATCH sfAction
class LOOP,VALID,SCOPE,DEPLOY_KO,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, allowFailure, runOnlyOnceByOrg, and customUsername (to run the action as a different user).
Post-deployment actions are never run when the metadata deployment failed. They are reported as not run in the Pull Request comment, no execution state is stored, and they are proposed again during the next successful deployment.
A merge from a feature branch only processes the actions and the Apex test classes of the Pull Request that has just been merged. A merge between major branches, or from a retrofit branch (retrofit/*), processes those of every Pull Request merged into the source major branch since its last promotion. A merge into the production branch processes those of every Pull Request carried by the go-live merge. Pull Requests merged upstream (ex: a hotfix in main) are included as soon as their commits arrive in the window, for example through a retrofit branch.
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_HARDIS_DEPLOY_CHECK_ID |
Force the Quick Deploy job id instead of reading it from Pull Request comments |
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 |