sf-package-combiner v2.2.0
sf-package-combiner
Combine multiple Salesforce package.xml
files into a single manifest for deployments. This is useful when:
- Using tools like
sfdx-git-delta
to generate incremental package.xml files - Merging different package.xml files from various sources
- Ensuring a streamlined deployment process in CI/CD workflows
Install
sf plugins install sf-package-combiner@x.y.z
Command
sf sfpc combine
Combine Salesforce manifest files together.
USAGE
$ sf sfpc combine [-f <value>] [-d <value>] [-c <value>] [-v <value>] [-n] [--json]
FLAGS
-f, --package-file=<value> The path to an existing package.xml file.
Can be specified multiple times.
-d, --directory=<value> The path to an existing directory with package.xml files.
Only XML files in the immediate directory will be scanned.
Can be specified multiple times.
-v, --api-version=<value> Specify the API version to use in the combined package.xml.
Must be a float value (e.g., '62.0') and be an active API version.
If not declared, it will default to the max API version found in all inputs.
-n, --no-api-version Intentionally omit the API version in the combined package.xml.
If not declared, it will default to the max API version found in all inputs.
-c, --combined-package=<value> The path to save the combined package.xml to.
If this value matches one of the input packages, it will overwrite the file.
Default is "package.xml".
GLOBAL FLAGS
--json Format output as json.
DESCRIPTION
Combine multiple package files into 1 file.
EXAMPLES
Combine pack1.xml and pack2.xml into package.xml
$ sf sfpc combine -f pack1.xml -f pack2.xml -c package.xml
Combine pack1.xml, pack2.xml, and all package XML files in a directory into package.xml
$ sf sfpc combine -f pack1.xml -f pack2.xml -d "test/sample_dir" -c package.xml
Combine pack1.xml and pack2.xml into package.xml set at API version 62.0
$ sf sfpc combine -f pack1.xml -f pack2.xml -v "62.0" -c package.xml
Combine pack1.xml and pack2.xml into package.xml with no API version declared
$ sf sfpc combine -f pack1.xml -f pack2.xml -n -c package.xml
Usage
How it Works
- The
<name>
elements (metadata types) are converted to lowercase to ensure consistency and avoid duplicates. - The
<members>
elements retain their original case, as Salesforce treats them as case-sensitive. - By default, the highest API version found in the input manifests is used.
- If no
<version>
tag is found, it is omitted from the finalpackage.xml
.
To override the API version behavior:
- Use
-v <version>
to set a specific API version. - Use
-n
to omit the API version entirely.
Handling Invalid package.xml
Files
If a file doesn't match the expected structure or has no <types>
in it, it is skipped with a warning:
Warning: Invalid or empty package.xml: .\test\samples\invalid2.xml
If all packages are invalid or empty, the combined package.xml will be an empty package (no <types>
). You can avoid deploying an empty package by searching the manifest for any <types>
in it before running the deploy command.
sf sfpc combine -f "package/package.xml" -f "package.xml" -c "package.xml"
if grep -q '<types>' ./package.xml ; then
echo "---- Deploying added and modified metadata ----"
sf project deploy start -x package.xml
else
echo "---- No changes to deploy ----"
fi
Manifest Structure
Salesforce package.xml
files follow this structure:
- Root:
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
- Metadata Types:
<types>
contains:<members>
: Lists metadata item(s) via their API names.<name>
: Metadata type (e.g.,ApexClass
,CustomObject
).
- API Version (Optional):
<version>
specifies the metadata API version.
Example
The example below demonstrates the following use-case:
- Run
sfdx-git-delta
to generate an incrementalpackage/package.xml
- Declare additional metadata in a commit message and create a temporary
package.xml
- Run
sf-package-combiner
to merge both packages intopackage.xml
Input
package/package.xml
- incremental package
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>MyApexClass</members>
<name>ApexClass</name>
</types>
<version>60.0</version>
</Package>
package.xml
- commit message
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>MyTrigger</members>
<name>ApexTrigger</name>
</types>
<version>62.0</version>
</Package>
Command
sf sfpc combine -f "package/package.xml" -f "package.xml" -c "package.xml"
Output (package.xml
)
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>MyApexClass</members>
<name>apexclass</name>
</types>
<types>
<members>MyTrigger</members>
<name>apextrigger</name>
</types>
<version>62.0</version>
</Package>
#!/bin/bash
set -e
DEPLOY_PACKAGE="package.xml"
# Define a function to build package.xml from commit message
build_package_from_commit() {
local commit_msg="$1"
local output_file="$2"
PACKAGE_FOUND="False"
# Use sed to match and extract the XML package content
package_xml_content=$(echo "$commit_msg" | sed -n '/<Package xmlns=".*">/,/<\/Package>/p')
if [[ -n "$package_xml_content" ]]; then
echo "Found package.xml contents in the commit message."
echo "$package_xml_content" > "$output_file"
PACKAGE_FOUND="True"
else
echo "WARNING: No package.xml contents found in the commit message."
fi
export PACKAGE_FOUND
}
build_package_from_commit "$COMMIT_MSG" "$DEPLOY_PACKAGE"
# create incremental package in default locations
sf sgd source delta --to "HEAD" --from "HEAD~1" --output-dir "."
# combines the sfdx-git-delta package.xml with the package found in the commit message, overwriting the commit message package
if [[ "$PACKAGE_FOUND" == "True" ]]; then
sf sfpc combine -f "package/package.xml" -f "$DEPLOY_PACKAGE" -c "$DEPLOY_PACKAGE"
fi
if grep -q '<types>' ./package.xml ; then
echo "---- Deploying added and modified metadata ----"
sf project deploy start -x package.xml
else
echo "---- No changes to deploy ----"
fi
Issues
If you encounter any issues or would like to suggest features, please create an issue.
License
This project is licensed under the MIT license. Please see the LICENSE file for details.
3 months ago
3 months ago
3 months ago
4 months ago
4 months ago
5 months ago
5 months ago
5 months ago
6 months ago
6 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago