Global Find and Replace Rules

Updated 4 months ago by Iván Minaya

The Global Find and Replace Rules feature allows you to define custom find and replace rules that Copado applies whenever you commit files and deploy files Org-to-Org or Git-to-Org.

The rules must be written in a .YML file and then uploaded to Copado, as an attachment or  created online with Copado's YAML Editor, to an Environment record and/or a Deployment Flow record. If the Copado.yml file is uploaded in a Deployment Flow, the rules will apply to any deployments and commits of the Environments and the branches of the Deployment Flow. If the Copado.yml file is uploaded to an Environment, the rules will apply to Metadata/Git Metadata deployments.

Since Copado Version 10 we have enabled the  Copado Global Find & Replace Online Rule Editor

As of Copado v11,  YAML editor in Copado shows and warns about tabs and whitespaces, among other errors.

In order to open the Rule editor just open the environment or deployment flow and click the Rule Editor Button.

Note that if your Salesforce instance doesn't have Attachments, and instead is using Files, you can still upload the attachment using this URL: https://{instance}.salesforce.com/p/attach/NoteAttach?pid={parentId}

A common use case for this feature is to remove offending XML tags that will make a file not deployable. Like for example:

  • remove all ManageSandbox user permissions from a profile, since this user permission only exists on production environments and will fail when trying to be deployed to sandboxes.
  • remove FLS of deprecated fields, etc.

Click here to open a sample Copado.yml file

To ignore complete files from Git you can leverage the .gitignore functionality. You can find an example here.

You can test the regular expressions here and validate your file before uploading it from here.

The .YML file structure must have two sections: regex_lib and rules. These sections are configured as follows:

regex_lib

The "regex_lib" section contains the 'find' regex expressions. These regex expressions are saved in a variable name so that they can be referenced in the rules section. 

In the following example, the 'find' regex expression for a field is assigned to a variable name called "field":

field: '(?s)(.[^\n]+<fields>(?:(?!<fields>).)*?<fullName>___REPLACEVALUE___</fullName>(?:(?!<fields>).)*?</fields>)'

rules

The "rules" section contains one or more rules to be executed. A rule consists of a rule name and several rule parameters. The rule name cannot have spaces or special characters and the rule parameters are as follows:

  • file_names
    • A list of the exact names of the metadata files where the find and replace will be executed (e.g. "Account.object", "MyCustomLayout.layout", etc.)
    • The rule will execute once for every file name listed
    • If you use file_names you cannot use extensions, but at least one of those is required
  • extensions
    • A list of the metadata file extensions where the find and replace will be executed (e.g. "object", "layout", etc.)
    • The rule will execute once for every file that has one of the extensions listed
    • If you use extensions you cannot use file_names, but at least one of those is required
  • regex_name
    • The variable name of the regex expression defined in the regex_lib section
    • Required value
  • replace_values
    • A list of values to replace in the regex expression (___REPLACEVALUE___)
    • If you do not need to replace values, you can omit replace_values and the ___REPLACEVALUE___ text
  • replace_with
    • The value that will replace the text that is found by the regex expression
    • Leaving this parameter blank means the matching regex will be deleted, instead of replaced with this
    • No backreferences are allowed ( \1 or $1 in the replacement string )
  • branches
    • The list of Git branches where the rule applies. If left blank, the rule applies to all Git branches.
  • exclusion_branches
    • (As of Copado v8.5) The list of Git branches where the rule does not apply. This parameter overrides the branches parameter in case both are included in the .YML file. If left blank, the rule applies to all Git branches

In the following example, the "invalid_fields" rule will be applied to the Account and Contact object. The rule's regex expression is "field" and the values to be replaced in the regex expression are "History__c" and "History_Date__c". The value to replace with is blank since the purpose of the rule is to delete the fields. If using the Git Integration, the branches where the rule applies are dev1, uat and master.

    invalid_fields: #this is the rule name

file_names:
      - 'Account.object'
      - 'Contact.object'
regex_name: 'field'
replace_values:
      - History__c
      - History_Date__c
branches:
      - dev1
      - uat
      - master
replace_with:

 

Important details on how to create regular expressions

To avoid surprises, you should always...

  • Use (?s) at the beginning, to match newlines with the dot operator
  • Non-greedy qualifiers ( *? and +? ) never regular ones ( * and + ), to avoid consuming the longest possible match.
  • With nested tags, use assertions (?!text), this will force the regular expression to skip nested tags.


Virtually all our examples int the documentation have those three features to avoid common pitfalls. Regular expression examples (in javascript, you can test it in your browser's javascript console):

'<a>1</a> <a> 2 </a> <a>3</a>'.replace( new RegExp('(s?)<a>.*?2.*</a>'), "xxx")
          // incorrect, results in "xxx", replacing the first <a> until the last </a>
          
          '<a>1</a> <a> 2 </a> <a>3</a>'.replace( new RegExp('(s?)<a>.*? 2 .*?.*?</a>'), "xxx")
          // incorrect, results in "xxx <a>3</a>", replacing the first <a> until the first </a>
          
          '<a>1</a> <a> 2 </a> <a>3</a>'.replace( new RegExp('(s?)<a>(?:(?!</a><a>).)*? 2 .*?(?:(?!</a>).)*?'), "xxx")
          // correct, results in "<a>1</a> xxx <a>3</a>", replacing the first <a> until the first </a> that contains the text " 2 "
          


How did we do?