cli icon indicating copy to clipboard operation
cli copied to clipboard

CustomLabel String replacement not working correctly with --manifest flag

Open cnwork opened this issue 11 months ago • 5 comments

Summary

When using the sf project deploy start --manifest package.xml, custom labels inside the package.xml will not get replaced. However when using sf project deploy start --source-dir changed-sources, the custom labels inside the folder do get replaced.

Steps To Reproduce

Repo: Forked dreamhouse-lwc Use git-delta tool to generate the delta between the last two commits:

mkdir changed-sources
sf sgd:source:delta --to HEAD  --from HEAD^ --output changed-sources/ --generate-delta --source force-app/

This should generate the following file structure:

changed-sources/
├── destructiveChanges
│   ├── destructiveChanges.xml
│   └── package.xml
├── force-app
│   └── main
│       └── default
│           ├── classes
│           │   ├── MyClass.cls
│           │   ├── MyClass.cls-meta.xml
│           │   ├── MyClassTest.cls
│           │   └── MyClassTest.cls-meta.xml
│           └── labels
│               └── CustomLabels.labels-meta.xml
└── package
    └── package.xml

changed-sources/force-app/main/default/labels/CustomLabels.labels-meta.xml:

<?xml version="1.0" encoding="UTF-8"?>
<CustomLabels xmlns="http://soap.sforce.com/2006/04/metadata">
    <labels>
        <fullName>Test_New_Label1</fullName>
        <categories>General</categories>
        <language>en_US</language>
        <protected>false</protected>
        <shortDescription>Label for testing</shortDescription>
        <value>TestingNEWLabelPROD1</value>
    </labels>
    <labels>
        <fullName>Test_New_Label2</fullName>
        <categories>General</categories>
        <language>en_US</language>
        <protected>false</protected>
        <shortDescription>Label for testing 2</shortDescription>
        <value>TestingNEWLabelPROD2</value>
    </labels>
</CustomLabels>

and changed-sources/package/package.xml

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>MyClass</members>
        <members>MyClassTest</members>
        <name>ApexClass</name>
    </types>
    <types>
        <members>Test_New_Label1</members>
        <members>Test_New_Label2</members>
        <name>CustomLabel</name>
    </types>
    <version>58.0</version>

1. Run deployment with --source-dir

LOG_NAME=LogINT NEW_LABEL1=MyNewLabel1 NEW_LABEL2=MyNewLabel2 \ 
sf project deploy start --dry-run --source-dir changed-sources/ --test-level NoTestRun --verbose -o <target-org>

Deploy result

Deploying (dry-run) v60.0 metadata to <target-org> using the v60.0 SOAP API.
Deploy ID: 0Af05XXXXXXXXXX
Status: Polling SourceMembers | ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ | 0/5 Components | Tracking: 0/4Warning: Polling for 4 SourceMembers timed out after 6 attempts (last 6 were empty).

Validated Sourcembers:
===================================================================================================================
| State     Name            Type         Path                                                                       
| ───────── ─────────────── ──────────── ────────────────────────────────────────────────────────────────────────── 
| Created   MyClass         ApexClass    changed-sources/force-app/main/default/classes/MyClass.cls                 
| Created   MyClass         ApexClass    changed-sources/force-app/main/default/classes/MyClass.cls-meta.xml        
| Created   MyClassTest     ApexClass    changed-sources/force-app/main/default/classes/MyClassTest.cls             
| Created   MyClassTest     ApexClass    changed-sources/force-app/main/default/classes/MyClassTest.cls-meta.xml    
| Created   Test_New_Label1 CustomLabel  changed-sources/force-app/main/default/labels/CustomLabels.labels-meta.xml 
| Created   Test_New_Label2 CustomLabel  changed-sources/force-app/main/default/labels/CustomLabels.labels-meta.xml 
| Unchanged CustomLabels    CustomLabels changed-sources/force-app/main/default/labels/CustomLabels.labels-meta.xml 

Metadata Replacements
====================================================================================================
| PROJECT PATH                                                               TEXT REPLACED           
| ────────────────────────────────────────────────────────────────────────── ─────────────────────── 
| changed-sources/force-app/main/default/labels/CustomLabels.labels-meta.xml /TestingNEWLabelPROD1/g 
| changed-sources/force-app/main/default/labels/CustomLabels.labels-meta.xml /TestingNEWLabelPROD2/g 
| changed-sources/force-app/main/default/classes/MyClass.cls                 /LogPROD/g              
| changed-sources/force-app/main/default/classes/MyClassTest.cls             /LogPROD/g              

2. Run deployment with --manifest

LOG_NAME=LogINT NEW_LABEL1=MyNewLabel1 NEW_LABEL2=MyNewLabel2 \ 
sf project deploy start --dry-run --manifest changed-sources/package/package.xml --test-level NoTestRun --verbose -o <target-org>

Expected result

Same as for above when using the --source-dir flag

Actual result

Deploying (dry-run) v58.0 metadata to <target-org> using the v60.0 SOAP API.
Deploy ID: 0Af05XXXXXXXXX
Status: Polling SourceMembers | ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ | 0/5 Components | Tracking: 0/4Warning: Polling for 4 SourceMembers timed out after 5 attempts (last 5 were empty).

Missing SourceMembers:
  - ApexClass: MyClass, MyClassTest
  - CustomLabel: Test_New_Label1, Test_New_Label2
Status: Succeeded | ████████████████████████████████████████ | 4/4 Components | Tracking: 0/4

Validated Source
================================================================================================
| State   Name            Type        Path                                                       
| ─────── ─────────────── ─────────── ────────────────────────────────────────────────────────── 
| Created MyClass         ApexClass   force-app/main/default/classes/MyClass.cls                 
| Created MyClass         ApexClass   force-app/main/default/classes/MyClass.cls-meta.xml        
| Created MyClassTest     ApexClass   force-app/main/default/classes/MyClassTest.cls             
| Created MyClassTest     ApexClass   force-app/main/default/classes/MyClassTest.cls-meta.xml    
| Created Test_New_Label1 CustomLabel force-app/main/default/labels/CustomLabels.labels-meta.xml 
| Created Test_New_Label2 CustomLabel force-app/main/default/labels/CustomLabels.labels-meta.xml 

Metadata Replacements
==============================================================
| PROJECT PATH                                   TEXT REPLACED 
| ────────────────────────────────────────────── ───────────── 
| force-app/main/default/classes/MyClass.cls     /LogPROD/g    
| force-app/main/default/classes/MyClassTest.cls /LogPROD/g

System Information

{
  "architecture": "wsl-x64",
  "cliVersion": "@salesforce/cli/2.30.8",
  "nodeVersion": "node-v20.7.0",
  "osVersion": "Linux 5.15.133.1-microsoft-standard-WSL2",
  "rootPath": "/home/ubnt2204/.nvm/versions/node/v20.7.0/lib/node_modules/@salesforce/cli",
  "shell": "bash",
  "pluginVersions": [
    "@oclif/plugin-autocomplete 3.0.9 (core)",
    "@oclif/plugin-commands 3.1.4 (core)",
    "@oclif/plugin-help 6.0.13 (core)",
    "@oclif/plugin-not-found 3.0.11 (core)",
    "@oclif/plugin-plugins 4.2.5 (core)",
    "@oclif/plugin-search 1.0.16 (core)",
    "@oclif/plugin-update 4.1.13 (core)",
    "@oclif/plugin-version 2.0.12 (core)",
    "@oclif/plugin-warn-if-update-available 3.0.12 (core)",
    "@oclif/plugin-which 3.1.0 (core)",
    "@salesforce/cli 2.30.8 (core)",
    "apex 3.0.25 (core)",
    "auth 3.3.13 (core)",
    "data 3.1.1 (core)",
    "deploy-retrieve 3.2.16 (core)",
    "env 2.2.1 (user)",
    "info 3.0.27 (core)",
    "limits 3.1.10 (core)",
    "marketplace 1.0.25 (core)",
    "org 3.3.14 (core)",
    "packaging 1.26.3 (user)",
    "schema 3.1.3 (core)",
    "settings 2.0.27 (core)",
    "sobject 1.1.13 (core)",
    "source 3.1.15 (core)",
    "telemetry 3.1.13 (core)",
    "templates 56.0.16 (core)",
    "trust 3.3.10 (core)",
    "user 3.2.11 (core)",
    "@salesforce/sfdx-scanner 3.17.0 (user)",
    "sfdx-git-delta 5.27.0 (user)",
    "sfdx-hardis 4.25.1 (user)"
  ]
}

Additional information

Comparing the two results I can see that there's that one extra line in the Validated metadata that is showing the Unchanged CustomLabels file.

| Unchanged CustomLabels    CustomLabels changed-sources/force-app/main/default/labels/CustomLabels.labels-meta.xml 

Other than this and of course, the Metadata Replacement results which clearly show that those 2 labels have been changed

Metadata Replacements
====================================================================================================
| PROJECT PATH                                                               TEXT REPLACED           
| ────────────────────────────────────────────────────────────────────────── ─────────────────────── 
| changed-sources/force-app/main/default/labels/CustomLabels.labels-meta.xml /TestingNEWLabelPROD1/g 
| changed-sources/force-app/main/default/labels/CustomLabels.labels-meta.xml /TestingNEWLabelPROD2/g 

there's nothing else that's different.

I did deploy in both cases and the actual results in the org match the validate commands' output.

I also added manually to the package.xml another type like this:

    <types>
        <members>*</members>
        <name>CustomLabels</name>
    </types>

And this did work but it caused a full deployment of all CustomLabels, which is really not desirable.

Expected final result

Deployment using the sf project deploy start --manifest package.xml should have the exact same behavior as sf project deploy start --source-dir changed-sources.

I'm happy to provide any other details.

cnwork avatar Mar 05 '24 17:03 cnwork

Thank you for filing this issue. We appreciate your feedback and will review the issue as soon as possible. Remember, however, that GitHub isn't a mechanism for receiving support under any agreement or SLA. If you require immediate assistance, contact Salesforce Customer Support.

github-actions[bot] avatar Mar 05 '24 17:03 github-actions[bot]

Excellent repro steps! Makes it so much easier to understand the problem. Thank you!

If you compare the manifests that are actually generated by those 2 commands (use the SF_MDAPI_TEMP_DIR env var) the manifest that results in the correct behavior has this entry:

<types>
    <members>CustomLabels</members>
    <name>CustomLabels</name>
</types>

I modified changed-sources/package/package.xml to include it and it results in the same behavior as running the command: sf project deploy start --dry-run --manifest changed-sources/package/package.xml --test-level NoTestRun --verbose -o <target-org>

So there is at least a good workaround. However, this seems like it could be improved. I tried this command: sf project deploy start --dry-run -m "ApexClass:MyClass*" -m CustomLabel --test-level NoTestRun --verbose and that causes the same behavior. You have to include -m CustomLabels:CustomLabels to get the desired behavior.

shetzel avatar Mar 14 '24 21:03 shetzel

This issue has been linked to a new work item: W-15262083

git2gus[bot] avatar Mar 15 '24 16:03 git2gus[bot]

Thanks a lot @shetzel ! Yes, that workaround does indeed get the desired behavior. However, I'm glad that a fix is being worked on. We are using this in a CI pipeline and currently I would have to do some script gymnastics to add the CustomLabel type inside the package.xml. Not a biggie but if a fix is in the works, we can deal with it until it's released. We don't deploy CustomLabels every day. I appreciate the help! Thanks!

cnwork avatar Mar 19 '24 08:03 cnwork

@cnwork - should make it into the CLI release candidate tomorrow.

shetzel avatar Mar 19 '24 19:03 shetzel

This issue is fixed in version 2.34.6 of Salesforce CLI.

jshackell-sfdc avatar Mar 27 '24 18:03 jshackell-sfdc