hardis:mdapi:upsert
Description
Command Behavior
Deploys local source files to an org using the CRUD-based Metadata API (upsertMetadata), pushing each component whole.
This is a standalone, manually invoked command. It is the mirror of sf hardis:mdapi:read and exists for the same reason: types like Profile and PermissionSet deploy completely this way. File-based deploy of a Profile only writes permissions for components present in the same deployment; upsertMetadata writes the whole Profile.
Warning - whole-component overwrite.
upsertMetadatareplaces each component entirely. Any object/field permission, Apex-class access, or tab visibility that is not in your local file is removed in the org. A stale or partial local file will strip permissions. There is no check-only / validation mode for the CRUD Metadata API.
This command is not part of the CI/CD pipeline and runs no Apex tests, no check-only validation, no quick deploy, and no coverage gate. Use sf hardis:project:deploy:smart for gated deployments.
Key functionalities:
- Component selection:
--source-dir(default: the project package directories),--manifest(apackage.xml), or--metadatato filter. - Confirmation: In interactive mode it lists the components that will be overwritten whole and asks for confirmation before pushing.
- Chunking: Upserts are batched to respect the CRUD Metadata API limit (10 components per call, 200 for
CustomMetadataandCustomApplication). - Supported types are adapter-gated: Compatibility is decided by the metadata type's @salesforce/source-deploy-retrieve registry adapter (
strategies.adapter). Only pure-XML types are upserted through the CRUD Metadata API; types whose source carries non-XML content (code, binaries, multi-file bundles) are reported as skipped with a warning. The incompatible adapters arebundle(LWC, Aura),matchingContentFile(Apex classes/triggers/pages/components, Visualforce),mixedContent(StaticResource,Document), anddigitalExperience(DigitalExperienceBundle). Deploy those with file-based deploy (sf project deploy start).
Technical explanations
- Input resolution:
ComponentSetBuilderresolves--source-dir/--manifest/--metadatafrom local source. - Recomposition: Source is converted to metadata format with
@salesforce/source-deploy-retrieve(recomposing decomposed types such as CustomObject into a single file), then each top-level component is upserted with jsforceconnection.metadata.upsert. - Granularity: Components are upserted at the top-level-type granularity; child types (e.g. RecordType) are deployed inside their parent component.
- Adapter rule:
partitionCrudCompatibilityresolves each type to its SDR adapter viaRegistryAccess.getTypeByName(name).strategies.adapter. Types with adapterbundle,matchingContentFile,mixedContent, ordigitalExperienceare set aside as skipped (and re-checked before sending); types withdecomposed,default, or no adapter (e.g.CustomObject,Profile,PermissionSet,Layout,CustomMetadata,CustomApplication) are processed. Unknown type names are treated as compatible so the API call (not the guard) surfaces the real error.
Agent Mode
Supports non-interactive execution with --agent:
sf hardis:mdapi:upsert --source-dir force-app/main/default/profiles --agent
In agent mode (and in CI), the overwrite confirmation prompt is skipped and the deployment proceeds. The caller owns the risk of the whole-component overwrite.
Parameters
| Name | Type | Description | Default | Required | Options |
|---|---|---|---|---|---|
| agent | boolean | Run in non-interactive mode for agents and automation | |||
| chunk-size | option | Components upserted per API call (max 10, or 200 for CustomMetadata/CustomApplication) | |||
| debug -d |
boolean | Activate debug mode (more logs) | |||
| flags-dir | option | undefined | |||
| ignore-errors | boolean | Report component failures but exit with code 0 | |||
| json | boolean | Format output as json. | |||
| manifest -x |
option | Path to a package.xml listing the metadata to deploy | |||
| metadata -m |
option | Metadata to deploy, as Type or Type:Name (e.g. Profile, "Profile:Admin"). Repeatable. | |||
| skipauth | boolean | Skip authentication check when a default username is required | |||
| source-dir | option | Local source path to deploy (default: the project package directories) | |||
| target-org -o |
option | undefined | |||
| websocket | option | Websocket host:port for VsCode SFDX Hardis UI integration |
Examples
$ sf hardis:mdapi:upsert --metadata Profile
$ sf hardis:mdapi:upsert --source-dir force-app/main/default/profiles
$ sf hardis:mdapi:upsert --manifest manifest/package.xml
$ sf hardis:mdapi:upsert --source-dir force-app/main/default/profiles --agent