Here are some basic bash scripts to make this task simpler. I have created a folder called bash
in my scripts
folder, and added the following new files in my SFDX project:
scripts
└───bash
| deployCustomMetadata.sh
| retrieveCustomMetadata.sh
Step 1: Retrieve the Custom Metadata Type records as a CSV
Here is an example bash script for retrieving Custom Metadata Type records in CSV format. This will create a new folder called data
at the top of your SFDX project directory structure, unless you change the DIR
variable. Replace the QUERY
with your own SOQL logic.
retrieveCustomMetadata.sh
#!/bin/bash
# Script to retrieve custom metadata records
# Prerequisites: Must be run within an SFDX project with Salesforce CLI
# installed and authenticated to an org
# Call example: . scripts/bash/retrieveCustomMetadata.sh
COUNTRY="USA"
QUERY="SELECT \
DeveloperName, \
Country__r.DeveloperName, \
State_Code__c, \
Population__c \
FROM State__mdt \
WHERE Country__r.DeveloperName = '${COUNTRY}'"
# Update DIR if you want to put the CSV file somewhere else
DIR=data
# FILENAME is the name the CSV file will have when it's saved
FILENAME=State__mdt.csv
FILEPATH=${DIR}/${FILENAME}
# Create the directory to store the CSV data, if it doesn't exist
mkdir -p ${DIR}
# Query State__mdt data
echo "Executing query: ${QUERY}"
sfdx force:data:soql:query -q "${QUERY}" -r csv > ${FILEPATH}
Step 2: Update the CSV
You can now update field values and/or add new rows, using the CSV editing tool of your choice.
Step 3: Deploy the updated CSV data
This script transforms and deploys the CSV data to your org. It deals with the quirks of Custom Metadata relationship fields, in case you have any. Be sure to update the FILEPATH
and METADATA_TYPE
variables according to your own scenario.
deployCustomMetadata.sh
#!/bin/bash
# Script to deploy custom metadata records
# Prerequisites: Must be run within an SFDX project with Salesforce CLI
# installed and authenticated to an org
# Inputs: file path for the CSV you want to import
# Call example: . scripts/bash/deployCustomMetadata.sh
FILEPATH=data/State__mdt.csv
METADATA_TYPE=State
# Create the XMLs for the custom metadata records in the SFDX project
echo "Retrieving custom metadata definition from Salesforce"
sfdx force:source:retrieve -m "CustomObject:${METADATA_TYPE}__mdt"
echo "Updating CSV headers to work with force:cmdt:record:insert"
# Replace "__r.DeveloperName" with "__c" in the header row. We use the parent
# CMDT's DeveloperName as the foreign key on deployment -- not its ID.
sed -i -e "1 s/__r.DeveloperName/__c/" ${FILEPATH}
echo "Converting CSV data to XML for deployment"
sfdx force:cmdt:record:insert \
--filepath ${FILEPATH} \
--typename ${METADATA_TYPE} \
--namecolumn "DeveloperName"
echo "Transforming custom metadata records for deployment"
for FILE in force-app/main/default/customMetadata/${METADATA_TYPE}*; do
# force:cmdt:record:insert creates lookup fields with xsi:type="xsd:undefined"
# Need to make it xsi:type="xsd:string" so it won't fail on deployment
sed -i -e "s/xsd:undefined/xsd:string/g" $FILE
done
echo "Deploying new custom metadata records"
sfdx force:source:deploy -p force-app/main/default/customMetadata
Notes on this last script:
- The final line deploys all Custom Metadata you have defined in your SFDX project. If there is a lot more there than you want to deploy, you'll want to customize the filepath to make it more selective.