Newer Version Available
Replace Strings in Code Before Deploying
- A NamedCredential contains an endpoint that you use for testing. But when you deploy the source to your production org, you want to specify a different endpoint.
- An ExternalDataSource contains a password that you don’t want to store in your repository, but you’re required to deploy the password along with your metadata.
- You deploy near-identical code to multiple orgs. You want to conditionally swap out some values depending on which org you’re deploying to.
String replacement actually occurs when source-formatted files are converted to a ZIP file right before being deployed to the org with the force:source:deploy and force:source:push commands. The changes that result from string replacement are never written to your project; they apply only to the deployed files.
Configure String Replacement
- Source file or files that contain the string to be replaced.
- The string to be replaced.
- The replacement value.
1{
2 "packageDirectories": [
3 {
4 "path": "force-app",
5 "default": true
6 }
7 ],
8 "name": "myproj",
9 "replacements": [
10 {
11 "filename": "force-app/main/default/classes/myClass.cls",
12 "stringToReplace": "replaceMe",
13 "replaceWithEnv": "THE_REPLACEMENT"
14 }
15 ]
16}You can specify these keys in the replacements property.
- Location of Files
- One of the following properties is required:
- filename: Single file that contains the string to be replaced.
- glob: Collection of files that contain the string to be replaced. Example: **/classes/*.cls.
- String to be Replaced
- One of the following properties is required:
- stringToReplace: The string to be replaced.
- regexToReplace: Regular expression (regex) that specifies a string pattern to be replaced.
- Replacement Value
- One of the following properties is required:
- replaceWithEnv: Specifies that the string is replaced with the value of the environment variable.
- replaceWithFile: Specifies that the string is replaced with the contents of a file.
- Conditional Processing
- This property is optional:
- replaceWhenEnv: Specifies that a string replacement occur only when a specific environment variable is set to a specific value. Use the property env to specify the environment variable and the property value to specify the value that triggers the string replacement.
Follow these syntax rules:
- Always use forward slashes for directories (/), even on Windows.
- Both JSON and regular expressions use the backslash (\) as an escape character. As a result, when you use a regular expression to
match a dot, which requires escaping, you must use two backslashes for the regexToReplace
value:
1"regexToReplace" : "\\."Similarly, to match a single backslash, you must specify three of them.1"regexToReplace" : "\\\"
Examples
1"replacements": [
2 {
3 "filename": "force-app/main/default/classes/FirstApexClass.cls",
4 "stringToReplace": "replaceMe",
5 "replaceWithEnv": "THE_REPLACEMENT"
6 },
7 {
8 "filename": "force-app/main/default/classes/SecondApexClass.cls",
9 "stringToReplace": "replaceMe",
10 "replaceWithEnv": "THE_REPLACEMENT"
11 }
12]This example shows how to specify that the string replacement occur only if an environment variable called DEPLOY_DESTINATION exists and it has a value of PROD.
1"replacements": [
2 {
3 "filename": "force-app/main/default/classes/myClass.cls",
4 "stringToReplace": "replaceMe",
5 "replaceWithEnv": "THE_REPLACEMENT",
6 "replaceWhenEnv": [{
7 "env": "DEPLOY_DESTINATION",
8 "value": "PROD"
9 }]
10 }
11]This example specifies that when the Apex class files in the force-app/main/default directory are deployed, all occurrences of the string replaceMe are replaced with the contents of the file replacementFiles/copyright.txt.
1"replacements": [
2 {
3 "glob": "force-app/main/default/classes/*.cls",
4 "stringToReplace": "replaceMe",
5 "replaceWithFile": "replacementFiles/copyright.txt"
6 }
7]1<?xml version="1.0" encoding="UTF-8" ?>
2<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
3 <apiVersion>55.0</apiVersion>
4 <status>Active</status>
5</ApexClass>1"replacements": [
2 {
3 "glob": "force-app/main/default/classes/*.xml",
4 "regexToReplace": "<apiVersion>\\d+\\.0</apiVersion>",
5 "replaceWithFile": "replacementFiles/latest-api-version.txt"
6 }
7]Test String Replacements
Follow these steps to test string replacement without actually deploying files to the org.
- Set the SF_APPLY_REPLACEMENTS_ON_CONVERT environment variable to true.
- Run the force:source:convert command, which
converts the source files into metadata API format. For
example:
1sfdx force:source:convert --outputdir mdapiOut --sourcepath force-app - Inspect the files in the output directory (mdapiOut in our example) for the string replacements and what exactly will be deployed to the org.
Tips and Tricks
- (macOS or Linux only) When using the replaceWithEnv
or replaceWhenEnv properties, you can specify that
the environment variables apply to a single command by prepending the variables before the
command execution. For
example:
1THE_REPLACEMENT="some text" DEPLOY_DESTINATION=PROD sfdx force:source:push - If you’ve configured many string replacements, and are finding it difficult to manage,
check out open-source tools that load the contents of one or more files to your
environment, such as dotenv-cli. In this example, environment variables configured in
two local .env files are loaded before the force:source:push command execution:
1dotenv -e .env1 -e .env2 sfdx force:source:push - If you specify --json for either force:source:deploy or force:source:push, the JSON output includes a replacements property that lists the affected files and the string that was
replaced.
The force:source:push human-readable output shows the string replacement information by default; use --quiet to remove it, which also removes it from the JSON output.
To view string replacement information in the force:source:deploy human-readable output, specify --verbose.
Considerations and Limitations
- If you configure multiple string replacements in multiple files, the performance of the
deployment can degrade. Consider using the filename
key when possible, to ensure that you open only one file. If you must use glob, try to limit the number of files that are opened by
specifying a single directory or metadata type.
For example, "glob": "force-app/main/default/classes/*.cls" targets Apex class files in a specific directory, which is better than "glob": "**/classes/**”, which searches for all Apex metadata files in all package directories.
- Be careful using string replacement in static resources. When not doing string replacement, Salesforce CLI simply zips up all static resources when it first encounters their directory and deploys them as-is. If you configure string replacement for a large static resource directory, the CLI must inspect a lot more files than usual, which can degrade performance.
- The force:mdapi:deploy command doesn’t support string replacement.
- If your deployment times out, or you specify the --wait 0 flag of force:source:deploy, and then run force:source:deploy:report to see what happened, the deployed files contain string replacements as usual. However, the output of force:source:deploy:report doesn’t display the same string replacement information as force:source:deploy --verbose would have.