Table of Contents
Break down large Salesforce metadata files into smaller, more manageable files for version control and then recreate deployment-compatible files.
- Install plugin using
sf
sf plugins install [email protected]
- Decompose the metadata type(s) in your Salesforce DX project
sf decomposer decompose -m "flow" -m "labels"
- Add decomposed files to
.forceignore
This is REQUIRED to avoid errors when running
sf
commands. See Ignore Files section.
-
Stage decomposed files in version control
-
Recompose the metadata type(s) before deployment
sf decomposer recompose -m "flow" -m "labels"
- Deploy recomposed metadata
Why should you consider using sf-decomposer
over Salesforce's decomposition?
- Broad Metadata Support: Unlike Salesforce's decomposition,
sf-decomposer
supports most metadata types available in the Metadata API. - Selective Decomposition:
sf-decomposer
allows you to decompose only the metadata you need instead of Salesforce's all-or-nothing approach. - Complete Decomposition: Partially decomposed metadata types (e.g., Salesforce's
decomposePermissionSetBeta2
) can be fully decomposed bysf-decomposer
. - Consistent Sorting:
sf-decomposer
recomposition ensures elements are always sorted consistently for better version control. - Multiple Decompose Formats:
sf-decomposer
allows you to decompose the original XML file into smaller XML, JSON, JSON5, or YAML files depending on your preference.
In general, sf-decomposer
helps Salesforce Admins do a few things with their source deployments:
- Enhance peer reviews of large metadata in CI/CD platforms like GitHub, i.e. easier-to-review diffs in pull requests
- Make deployments safer by ensuring only the intended changes are deployed, improving the overall version control process
The sf-decomposer
supports 2 commands:
sf decomposer decompose
sf decomposer recompose
Decomposes the original metadata files in all local package directories into smaller files for version control.
USAGE
$ sf decomposer decompose -m <value> -f <value> -i <value> [--prepurge --postpurge --debug --json]
FLAGS
-m, --metadata-type=<value> The metadata suffix to process, such as 'flow', 'labels', etc.
Can be declared multiple times.
-f, --format=<value> The file type for the decomposed files.
Must match what format you provide for recompose.
Options: ['xml', 'yaml', 'json', 'json5']
[default: 'xml']
-i, --ignore-package-directory=<value> Package directory to ignore.
Should be as they appear in the "sfdx-project.json".
Can be declared multiple times.
--prepurge Purgd directories of pre-existing decomposed files.
[default: false]
--postpurge Purge the original files after decomposing them.
[default: false]
--debug Log debugging results to a text file (disassemble.log).
[default: false]
GLOBAL FLAGS
--json Format output as json.
DESCRIPTION
Decompose large metadata files into smaller files.
You should run this after you retrieve metadata from an org.
EXAMPLES
Decompose all flows:
$ sf decomposer decompose -m "flow" -f "xml" --prepurge --postpurge --debug
Decompose all flows and custom labels:
$ sf decomposer decompose -m "flow" -m "labels" -f "xml" --prepurge --postpurge --debug
Decompose flows except for those in the "force-app" package directory.
$ sf decomposer decompose -m "flow" -i "force-app"
Recompose decomposed files into deployment-compatible files.
USAGE
$ sf decomposer recompose -m <value> -f <value> -i <value> [--postpurge --debug --json]
FLAGS
-m, --metadata-type=<value> The metadata suffix to process, such as 'flow', 'labels', etc.
Can be declared multiple times.
-f, --format=<value> The file format for the decomposed files.
Must match what format you provide for decompose.
Options: ['xml', 'yaml', 'json', 'json5']
[default: 'xml']
-i, --ignore-package-directory=<value> Package directory to ignore.
Should be as they appear in the "sfdx-project.json".
Can be declared multiple times.
--postpurge Purge the decomposed files after recomposing them.
[default: false]
--debug Log debugging results to a text file (disassemble.log).
[default: false]
GLOBAL FLAGS
--json Format output as json.
DESCRIPTION
Recompose the decomposed files into deployment-compatible metadata files.
You should run this before you deploy decomposed metadata to an org.
EXAMPLES
Recompose all flows:
$ sf decomposer recompose -m "flow" -f "xml" --postpurge --debug
Recompose all flows and custom labels:
$ sf decomposer recompose -m "flow" -m "labels" -f "xml" --postpurge --debug
Recompose flows except for those in the "force-app" package directory.
$ sf decomposer recompose -m "flow" -i "force-app"
When the original metadata files are decomposed, this structure is followed for all metadata types except for custom labels:
- Leaf elements (i.e.
<userLicense>Salesforce</userLicense>
) will be decomposed in the same file in the root of the decomposed directory. The leaf file-name will match the original file-name. - Nested elements will be decomposed into their own files under sub-directories by the element type, i.e. custom permissions in a permission set will have their own decomposed file under a custom permissions sub-folder.
- If unique ID elements are found, the decomposed nested files will be named using them.
- Otherwise, the decomposed nested files will be named with the SHA-256 hash of the element contents.
- See Contributing for more information on unique ID elements.
Decomposed Permission Sets named using unique ID elements
Decomposed Application named using SHA-256 hashes of elements
When custom labels are decomposed, each custom label will have its own file in the original labels directory.
Decomposed Custom Labels
All parent metadata types imported from this plugin's version of @salesforce/source-deploy-retrieve
(SDR) toolkit are supported except for certain types.
The --metadata-type
/-m
flag should be the metadata's suffix
value as listed in the metadataRegistry.json. You can also infer the suffix by looking at the original XML file-name, i.e. *.{suffix}-meta.xml
.
Here are some examples:
- Custom Labels (
--metadata-type "labels"
) - Workflows (
--metadata-type "workflow"
) - Profiles (
--metadata-type "profile"
) - Permission Sets (
--metadata-type "permissionset"
) - AI Scoring Model Definition (
--metadata-type "aiScoringModelDefinition"
) - Decision Matrix Definition (
--metadata-type "decisionMatrixDefinition"
) - Bot (
--metadata-type "bot"
) - Marketing App Extension (
--metadata-type "marketingappextension"
)
botVersion
is blocked from being ran directly. Please use thebot
meta suffix to decompose and recompose bots and bot versions.Error (1): `botVersion` suffix should not be used. Please use `bot` to decompose/recompose bot and bot version files.
- Custom Objects are not supported by this plugin as they already are decomposed by default.
Error (1): Custom Objects are not supported by this plugin.
- Metadata types such as Apex Classes, Apex Components, Triggers, etc. with certain SDR adapter strategies (
matchingContentFile
,digitalExperience
,mixedContent
,bundle
) are not supported by this plugin.Error (1): Metadata types with [matchingContentFile, digitalExperience, mixedContent, bundle] strategies are not supported by this plugin.
- Children metadata types (i.e. custom fields) are not supported and will result in this general error:
Error (1): Metadata type not found for the given suffix: field.
sf-decomposer
searches the current working directory for the sfdx-project.json
, and if it's not found in the current working directory, it will search upwards for it until it hits your root drive. If the sfdx-project.json
file isn't found, the plugin will fail with:
Error (1): sfdx-project.json not found in any parent directory.
The xml-disassembler
package will log errors, and optionally debugging statements, to a log file, disassemble.log
. This log will be created in the working directory and will be created when running this plugin at all times. If there were no errors, this log will be empty. By default, the log will only contain errors. This plugin will print the errors as warnings in the command terminal to allow all other files to be processed. These warnings when decomposing or recomposing will look like:
Warning: C:\Users\matth\Documents\sf-decomposer\test\baselines\flows\Get_Info\actionCalls\Get_Info.actionCalls-meta.xml was unabled to be parsed and will not be processed. Confirm formatting and try again.
To add additional debugging statements to the log file, provide the --debug
flag to the decompose or recompose command. Debugging statements will look like:
[2024-03-30T14:28:37.959] [DEBUG] default - Created disassembled file: mock\no-nested-elements\HR_Admin\HR_Admin.permissionset-meta.xml
Recommend adding the disassemble.log
to your .gitignore
file if you are using this in a git-based repo.
NOTE: In order to avoid errors when running
sf
commands, you must configure your.forceignore
file to have the Salesforce CLI ignore the decomposed files. See Ignore Files section.
To automate decomposing and recomposing before and after sf
commands, create .sfdecomposer.config.json
in the root of your Salesforce DX project. You can copy and update the sample .sfdecomposer.config.json provided.
metadataSuffixes
is required and should be a comma-separated string of metadata suffixes to decompose automatically after retrievals.ignorePackageDirectories
is optional and should be a comma-separated string of package directories to ignore.prePurge
is optional and should be a boolean. If true, this will delete any existing decomposed files before decomposing the files. If you do not provide this, the default will befalse
. This flag is not used by the recompose command/pre-run hook.postPurge
is optional and should be a boolean. If true, this will delete the retrieval file after decomposing it or delete the decomposed files after recomposing them. If you do not provide this, the default will befalse
.decomposedFormat
is optional and should be eitherxml
,json
,json5
, oryaml
, depending on what file format you want the decomposed files created as. If you do not provide this, the default will bexml
.
If .sfdecomposer.config.json
is found, the hooks will fire:
- the decompose command after a
sf project retrieve start
command completes successfully (post-run) - the recompose command before a
sf project deploy [start/validate]
command starts (pre-run)
If .sfdecomposer.config.json
isn't found, the hooks will be skipped.
The Salesforce CLI must ignore the decomposed files and allow the recomposed files.
You can use the sample .forceignore provided. Update the decomposed file extensions based on what format you're using (.xml
, .json
, .json5
, or .yaml
).
If you wish, you can create a .sfdecomposerignore
file in the root of your Salesforce DX project to ignore specific XMLs when running the decompose command. The .sfdecomposerignore
file should follow .gitignore spec 2.22.1.
When the decompose command is ran with the --debug
flag and it processes a file that matches an entry in .sfdecomposerignore
, a warning will be printed to the disassemble.log
:
[2024-05-22T09:32:12.078] [WARN] default - File ignored by .sfdecomposerignore: C:\Users\matth\Documents\sf-decomposer\test\baselines\bots\Assessment_Bot\v1.botVersion-meta.xml
.sfdecomposerignore
is not read by the recompose command.
Optionally, git can ignore the recomposed files so you don't stage those in your repositories. You can also have git ignore the disassemble.log
created by the xml-disassembler
package.
You can use the sample .gitignore provided.
If you encounter any bugs or would like to request features, please create an issue.
- XML Disassembler: Disassembles large XML files into smaller XML files and reassembles the original XML file when needed
- XML2JSON Disassembler: Disassembles large XML files into smaller JSON files and reassembles the original XML file when needed
- XML2YAML Disassembler: Disassembles large XML files into smaller YAML files and reassembles the original XML file when needed
- XML2JSON5 Disassembler: Disassembles large XML files into smaller JSON5 files and reassembles the original XML file when needed
Contributions are welcome! See Contributing.
This project is licensed under the MIT license. Please see the LICENSE file for details.