I encountered this recently with two requirements:
Requirement 1) Store metadata without the Namespace Prefix. Why? So that the code can be deployed unmanaged, so that it works with SFDX out of the box (ie works for Flows under active development), so that test packages can be created with other namespaces, so that both 1GP/2GP can be produced from same source, and so on.
Requirement 2) Deploy only truly necessary NS prefixes in Flow metadata. Why? So that we avoid subscribers hitting the 50 Flow Versions limit. CI deploying extra namespaces in Flow metadata will cause Salesforce to create duplicate flow versions. Deleting flow versions in packaging orgs does not help subscribers. Upgrades are blocked when they hit the 50 Flow Versions limit on their side.
I believe these are the necessary replacements:
Rule: Email Alert elements in <actionCalls>
- When: the actionType is emailAlert
- Then: prefix any
<actionName>
- Then: prefix any
<nameSegment>
Example: <actionName>Object__c.Email_Alert_Name</actionName>
Becomes: <actionName>NS__Object__c.Email_Alert_Name</actionName>
Rule: Decision elements in <rules>
- When the leftValueReference refers to global $Record
- Then: prefix any
Field__c
- Then: prefix any
Related__r
Example: <leftValueReference>$Record.Field__c</leftValueReference>
Becomes: <leftValueReference>$Record.NS__Field__c</leftValueReference>
Rule: Formula resources in <expression>
- When the expression refers to global $Record
- Then: prefix any
{!$Record.Field__c}
- Then: prefix any
{!variable.Field__c}
also
- (Yes, the presence of $Record taints all other variables!)
Example: <expression>{!record.Field__c}</expression>
Remains: <expression>{!record.Field__c}</expression>
Example: <expression>{!$Record.F1__c} + {!record.F2__c}</expression>
Becomes: <expression>{!$Record.NS__F1__c} + {!record.NS__F2__c}</expression>
Rule: Screens in <fields>
- When the extensionName is flowruntime:lookup
- Then: prefix any
Field__c
Example: <stringValue>Field__c</stringValue>
Becomes: <stringValue>NS__Field__c</stringValue>
The above will prevent duplicate versions for Record Triggered, Autolaunched, and Screen flows. I hope Salesforce one day canonicalizes the process, until then, here is how to obtain the canonical NS prefixes:
- Create a 1GP packaging org with a namespace prefix
- In the GUI, create "kitchen sink" flow(s) with 1 of every element
- Specify 1 of every attribute with $Record / Field__c references
- Add 1 of every formula/template resource, also with references
- Retrieve the flow and inspect where the NS appears.
To verify your canonicalization process is correct, you can deploy a flow. If SF creates a duplicate version, the process is not correct. I hope this might help anybody still using Ant or regexp replacements.