Advanced Configurator/CML Deployer

A powerful tool to migrate Salesforce Advanced Configurator aka CML code between orgs directly from within Visual Studio Code.
This extension automates the entire complex process of migrating an Advanced Configurator, including its CML script, all related data, and crucially, all its complex lookup relationships to other objects like Products and Components.
Features
End-to-End Migration: Automates the entire migration of an Advanced Configurator setup (ExpressionSet and all its related records).
Intelligent ID Resolution: Automatically resolves Salesforce Record IDs between source and target orgs using external IDs, ensuring data integrity across different environments.
Complex Relationship Handling: Correctly maps complex data relationships, including ProductRelatedComponent records based on their parent product and component group.
Automated Cleanup: Performs a clean deployment by first deleting any old constraint records from a previous version in the target org before deploying the new ones.
Script Migration: Handles the export and import of the CML script.
Resumable Migrations: If a migration fails mid-way (e.g., due to a network error), re-running the command will intelligently resume from the last successful step, saving significant time.
User-Friendly Interface: A fully guided UI within VSCode using the Command Palette, with real-time, detailed progress notifications.
Automatic Workspace Management: Creates all temporary migration files in the system's temp directory, keeping your project folder clean. After a successful migration, all temporary files are automatically deleted.
Data Compliant: This tool enhances security by only retrieving the essential record IDs and unique identifiers needed for the deployment, completely avoiding sensitive data like product names. Furthermore, all temporary files generated during the process are permanently deleted from your local machine upon completion, ensuring your data remains secure.
Prerequisites
Before using this extension, please ensure you have the following configured:
- Visual Studio Code (v1.80.0 or higher).
- Salesforce CLI (
sf ) installed and available in your system's PATH.
- You must be authenticated to both your source and target Salesforce orgs via the CLI. You can check your authenticated orgs by running
sf org list --all in your terminal.
- Salesforce Email Address - You'll need a valid @salesforce.com email address for authentication.
- Make sure the target org has the required PCM data.
How to Use
Install the Extension:
Run the Deployment:
- Open your project folder in VSCode.
- Open the Command Palette (
Cmd+Shift+P on macOS, Ctrl+Shift+P on Windows).
- Type and select
RCCML: Deploy Advanced Configurator .
- Follow the interactive prompts that appear at the top of the screen:
-
- Email Authentication: Enter your @salesforce.com email address
- OTP Verification: Check your email and enter the 6-digit code received
- Select your source org.
- Select your target org.
- Enter the ApiName of the Advanced Configurator to deploy.
- Sit back and Relax.
Configuration (Optional)
Authentication Settings
The extension uses email-based OTP authentication with the following default settings:
Setting |
Default Value |
Description |
cmlDeployer.auth.backendUrl |
https://cml-migrator-auth.herokuapp.com |
Authentication backend service URL |
cmlDeployer.auth.timeout |
30000 |
Request timeout in milliseconds |
Data Mapping Settings
By default, the extension uses a standard set of fields to match records between your source and target orgs.
Object |
Default Field For ExternalId |
Product2 |
ExternalId |
ProductClassification |
Code |
ProductComponentGroup |
Code |
If your org uses different fields as unique identifiers (e.g., ProductCode on the Product object), you can easily override these defaults by adding settings to your VS Code settings.json file. You can find this file in your project at .vscode/settings.json (if the file or folder doesn't exist, you can create them)
The example below shows how you might configure the extension to use custom fields and authentication settings for your specific project.
Example settings.json :
{
// Data mapping settings (optional)
"cmlDeployer.product2.externalIdField": "ProductCode",
"cmlDeployer.productClassification.externalIdField": "Legacy_ID__c",
"cmlDeployer.productComponentGroup.externalIdField": "Group_Code__c"
}
Authentication System
The extension uses a secure email-based OTP (One-Time Password) authentication system with local session management:
Security Features
- Domain Restriction: Only @salesforce.com email addresses are accepted
- OTP Security: 6-digit codes that expire in 5 minutes
- Rate Limiting: Protection against spam and abuse
- Secure Communication: All requests use HTTPS encryption
- Session Management: 72-hour local sessions for extended productivity
Authentication Flow
- Email Input: Enter your @salesforce.com email address
- OTP Generation: A 6-digit code is generated and sent to your email
- Email Delivery: Receive a professional email with your authentication code
- Verification: Enter the OTP code in VSCode to complete authentication
- Session: Authentication remains valid for 72 hours (3 days)
Session Management Commands
You can manage your authentication sessions using these VSCode commands:
Command |
Purpose |
Access |
RCCML: Deploy Advanced Configurator |
Main deployment command |
Command Palette (Ctrl+Shift+P ) |
RCCML: Session Status |
Check current session status and remaining time |
Command Palette (Ctrl+Shift+P ) |
RCCML: Logout |
Manually clear your current session |
Command Palette (Ctrl+Shift+P ) |
Session Status
- Shows current logged-in user email
- Displays session expiration date and time
- Shows time remaining until expiration
Manual Logout
- Immediately clears your 72-hour session
- Useful for security on shared computers
- Includes confirmation prompt for safety
Session Benefits
- Extended Productivity: Work for 3 full days without re-authentication
- Security Control: Manual logout available when needed
- Automatic Cleanup: Sessions clear on VSCode restart
- Transparency: Check session status anytime
Troubleshooting Authentication
- Email not received: Check your spam/junk folder
- Invalid email domain: Ensure you're using a @salesforce.com email address
- Expired OTP: Request a new code if the current one has expired
- Rate limiting: Wait a few minutes if you've exceeded the request limit
- Session issues: Use "RCCML: Logout" to clear corrupted sessions
How It Works
The tool follows a robust 4-step process for each deployment:
Authentication: Securely authenticates the user using email-based OTP verification with @salesforce.com domain restriction.
Export: Connects to the source org and extracts the entire Advanced Configurator configuration, including all its dependent data and relationships.
Transform: Intelligently maps the extracted data to the target org by resolving Salesforce record IDs using the unique external identifiers specified in your settings (or the defaults).
Deploy: Connects to the target org and performs a clean deployment, ensuring all records are created in the correct order and the CML script is uploaded.
Limitations and Known Issues
Limitations
Single CML Deployment: The current version of the extension supports the deployment of only one Advanced Configurator (ExpressionSet ) at a time. Bulk or multi-CML deployments are not supported.
Deployed Inactive: The current version doesn't deploy the CML code in Active status.
Known Issues
- Record Not Found / Timeout Errors: In some cases, a deployment may fail with an error like
Could not find a matching record in target org... . This can happen due to transient Salesforce data replication delays.
Workaround: Simply re-run the RCCML: Deploy Advanced Configurator command.
Verification: If the issue persists, use the following steps to verify your data. The first part of the failing record's ID tells you which object to check.
For Products (Product2 , ID prefix 01t )
- In the Source Org, run this query to find the product's unique identifier (using your configured field, e.g.,
ExternalId or ProductCode ):
SELECT Id, Name, {Your-Product-Ext-ID-Field} FROM Product2 WHERE Id = '{ID FROM ERROR MESSAGE}'
- In the Target Org, use the unique value from the previous query to find the matching record:
SELECT Id, Name, {Your-Product-Ext-ID-Field} FROM Product2 WHERE {Your-Product-Ext-ID-Field} = '{Value FROM PREVIOUS QUERY}'
If a record is found, the data is correct. Try re-running the deployment.
For Product Classifications (ProductClassification , ID prefix 11B )
- In the Source Org, run this query to find the classification's unique identifier:
SELECT Id, Name, {Your-Classification-Ext-ID-Field} FROM ProductClassification WHERE Id = '{ID FROM ERROR MESSAGE}'
- In the Target Org, use the unique value from the previous query to find the matching record:
SELECT Id, Name, {Your-Classification-Ext-ID-Field} FROM ProductClassification WHERE {Your-Classification-Ext-ID-Field} = '{Value FROM PREVIOUS QUERY}'
For Product Related Components (ProductRelatedComponent , ID prefix 0dS )
These records are matched using a composite key derived from their parent records. To verify, check the following:
- In the Source Org, identify the unique ID value (e.g.,
ExternalId or ProductCode ) of the parent Product2 , unique ID value (e.g., ExternalId or ProductCode ) of the parent Product2 and the unique ID value (e.g., Code ) of the parent ProductComponentGroup .
SELECT Id, Name, ParentProduct.{Your-Product-Ext-ID-Field}, ChildProduct.{Your-Product-Ext-ID-Field}, ProductComponentGroup.Code FROM ProductRelatedComponent WHERE Id = 'ID_FROM_ERROR_OUTPUT'
- In the Target Org, confirm that records exist with those exact same unique ID values.
- Finally, confirm that a
ProductRelatedComponent record exists in the target org that links those three records.
SELECT Id, Name, ParentProduct.{Your-Product-Ext-ID-Field}, ChildProduct.{Your-Product-Ext-ID-Field}, ProductComponentGroup.{Your-Classification-Ext-ID-Field} FROM ProductRelatedComponent WHERE ParentProduct.{Your-Product-Ext-ID-Field} = '' AND ProductComponentGroup.{Your-Classification-Ext-ID-Field} = '' AND ChildProduct.{Your-Product-Ext-ID-Field} = ''
Feedback and Contributions
If you encounter any issues or have a feature request, please email at arohitu@gmail.com
| |