There's two basic ways you can install packages, depending on if you have dependencies (which are unusual, but can happen).
MDAPI Deployment
If you do not have any dependencies, the most simple format is to use a package.xml
mdapi style deployment.
sfdx force:mdapi:deploy -d packages/ -u alias -w 99
Where packages/ contains a package.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>*</members>
<name>InstalledPackage</name>
</types>
</Package>
And, for each package to install, a NAMESPACE.installedPackage:
<?xml version="1.0" encoding="UTF-8"?>
<InstalledPackage xmlns="http://soap.sforce.com/2006/04/metadata" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<activateRSS>false</activateRSS>
<versionNumber>216.10.1</versionNumber>
<password>ClearTextPassword</password>
</InstalledPackage>
<password>
is required if the package install has a password, and must not be supplied if there is no package install password.
SFDX Install Script
The installing multiple packages can be written as a shell script.
For example:
sfdx force:package:install -w -99 -p package-1 -r -k password-1
sfdx force:package:install -w -99 -p package-2 -r -k password-2
sfdx force:package:install -w -99 -p package-3 -r
In this example, there's two packages that need a password, and a third that does not. Here, you have precise order over the order of execution, and you could also perform other tasks at the same time, such as importing custom settings or normal records (accounts, contacts, etc).
If all the packages don't require a password, you can also use this script from Salesforce:
#!/bin/bash
# The execution of this script stops if a command or pipeline has an error.
# For example, failure to install a dependent package will cause the script
# to stop execution.
set -e
# Specify a package version id (starts with 04t)
# If you know the package alias but not the id, use force:package:version:list to find it.
PACKAGE=04tB0000000NmnHIAS
# Specify the user name of the subscriber org.
[email protected]
# Specify the timeout in minutes for package installation.
WAIT_TIME=15
echo "Retrieving dependencies for package Id: "$PACKAGE
# Execute soql query to retrieve package dependencies in json format.
RESULT_JSON=`sfdx force:data:soql:query -u $USER_NAME -t -q "SELECT Dependencies FROM SubscriberPackageVersion WHERE Id='$PACKAGE'" --json`
# Parse the json string using python to test whether the result json contains a list of ids or not.
DEPENDENCIES=`echo $RESULT_JSON | python -c 'import sys, json; print json.load(sys.stdin)["result"]["records"][0]["Dependencies"]'`
# If the parsed dependencies is None, the package has no dependencies. Otherwise, parse the result into a list of ids.
# Then loop through the ids to install each of the dependent packages.
if [[ "$DEPENDENCIES" != 'None' ]]; then
DEPENDENCIES=`echo $RESULT_JSON | python -c '
import sys, json
ids = json.load(sys.stdin)["result"]["records"][0]["Dependencies"]["ids"]
dependencies = []
for id in ids:
dependencies.append(id["subscriberPackageVersionId"])
print " ".join(dependencies)
'`
echo "The package you are installing depends on these packages (in correct dependency order): "$DEPENDENCIES
for id in $DEPENDENCIES
do
echo "Installing dependent package: "$id
sfdx force:package:install --package $id -u $USER_NAME -w $WAIT_TIME --publishwait 10
done
else
echo "The package has no dependencies"
fi
# After processing the dependencies, proceed to install the specified package.
echo "Installing package: "$PACKAGE
sfdx force:package:install --package $PACKAGE -u $USER_NAME -w $WAIT_TIME --publishwait 10
exit 0;
This script queries a package from an org, figures out their dependencies in order, and then installs everything for you. Note that if there are passwords involve, this script will fail. You can also manually create a file with passwords in it, and write a shell script to read those.
set -e
while IFS=, read -r package password; do
if [ -z "$password" ]
then
sfdx force:package:install -p "$package" -w 99
else
sfdx force:package:install -p "$package" -w 99 -k "$password"
fi
done < packages-to-install.csv
Where the format is a list of package names or aliases, followed by an optional password:
package1,password1
package2,password2
package3
You could spruce this up with more elaborate features, but this should be fine for most simple install paths.