SFTasker
is a powerful Salesforce CLI plugin designed for Salesforce developers and administrators. It includes a set of commands that simplify Salesforce DX project management, addressing specific tasks like metadata merging for Profiles, Translations, and Custom Labels. These automation tools help reduce manual effort, prevent data loss, and improve workflow efficiency, making it easier to manage complex Salesforce projects.
âš Note: This is an unofficial Salesforce plugin and is not endorsed or supported by Salesforce. Be sure to thoroughly test it before using it in production environments.
The merge-meta
command addresses a common issue in Salesforce metadata management for Profiles, Custom Labels, and Translations. In Salesforce DX projects, these metadata files often contain multiple sections representing different settings, such as permissions, labels, and translations for various components. For example, a single Profile file might include sections for object permissions, field-level security, user permissions, and more.
When retrieving metadata using tools like Salesforce CLI, only certain sections may be pulled, potentially causing other sections to be lost.
Here's an example of a package.xml
manifest file that retrieves only the MyAdmin
custom Profile and the Account
custom object:
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>MyAdmin</members>
<name>Profile</name>
</types>
<types>
<members>Account</members>
<name>CustomObject</name>
</types>
<version>61.0</version>
</Package>
This package.xml
will only retrieve the objectPermissions for the Account
object within the MyAdmin
Profile.
Below is an example of a Profile metadata file (MyAdmin.profile-meta.xml
) that contains both objectPermissions
and fieldPermissions
sections:
<?xml version="1.0" encoding="UTF-8"?>
<Profile xmlns="http://soap.sforce.com/2006/04/metadata">
<userPermissions>
<enabled>true</enabled>
<name>ViewAllData</name>
</userPermissions>
<fieldPermissions>
<field>Account.Name</field>
<readable>true</readable>
<editable>true</editable>
</fieldPermissions>
<objectPermissions>
<object>Account</object>
<allowCreate>true</allowCreate>
<allowDelete>true</allowDelete>
<allowEdit>true</allowEdit>
<allowRead>true</allowRead>
<viewAllRecords>true</viewAllRecords>
</objectPermissions>
</Profile>
Now, suppose permissions for the Account
object in the MyAdmin
profile have been updated to restrict the ability to delete and edit Account
records. You want to retrieve these changes and store them in your local Salesforce DX project.
Using the standard Salesforce CLI to retrieve the updated permissions from the Org:
$ sf project retrieve start -x manifest/package.xml
The new content of the MyAdmin.profile-meta.xml
file after retrieval will look like this:
<?xml version="1.0" encoding="UTF-8"?>
<Profile xmlns="http://soap.sforce.com/2006/04/metadata">
<userPermissions>
<enabled>true</enabled>
<name>ViewAllData</name>
</userPermissions>
<objectPermissions>
<object>Account</object>
<allowCreate>true</allowCreate>
<allowDelete>false</allowDelete>
<allowEdit>false</allowEdit>
<allowRead>true</allowRead>
<viewAllRecords>true</viewAllRecords>
</objectPermissions>
</Profile>
As you can see, only the objectPermissions
section for Account
remains, and the fieldPermissions
section is missing, even though it wasn't part of the retrieval operation. If your profile contains many other sections, overwriting or reordering them can become more problematic and undesirable.
The merge-meta
command prevents data loss by intelligently merging newly retrieved metadata sections with existing ones. Instead of overwriting the entire file, the command retains sections that were not part of the current retrieval.
Running the same retrieval with sftasker merge-meta
:
$ sf sftasker merge-meta -t Profile -x manifest/package.xml
The resulting MyAdmin.profile-meta.xml
file will contain all sections, with only the allowDelete
and allowEdit
permissions updated for the Account
object:
<?xml version="1.0" encoding="UTF-8"?>
<Profile xmlns="http://soap.sforce.com/2006/04/metadata">
<userPermissions>
<enabled>true</enabled>
<name>ViewAllData</name>
</userPermissions>
<fieldPermissions>
<field>Account.Name</field>
<readable>true</readable>
<editable>true</editable>
</fieldPermissions>
<objectPermissions>
<object>Account</object>
<allowCreate>true</allowCreate>
<allowDelete>false</allowDelete>
<allowEdit>false</allowEdit>
<allowRead>true</allowRead>
<viewAllRecords>true</viewAllRecords>
</objectPermissions>
</Profile>
All sections remain intact, and only the necessary changes were made:
<allowDelete>false</allowDelete>
<allowEdit>false</allowEdit>
Additionally, you can use the merge-meta
command to manage other metadata types, such as Translations and Custom Labels, ensuring that unretrieved sections are preserved and not overwritten during the process.
Example to Retrieve Partial Custom Labels:
Below is an example of a package.xml
to modify the CustomLabels.labels-meta.xml
file to retrieve only LabelOne
and LabelTwo
, leaving other labels inside this file intact:
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>LabelOne</members>
<members>LabelTwo</members>
<name>CustomLabel</name>
</types>
<types>
<members>iw</members>
<name>Translations</name>
</types>
<version>61.0</version>
</Package>
To retrieve the CustomLabels
metadata using merge-meta
, use the following command within your Salesforce DX root folder:
$ sf sftasker merge-meta -t CustomLabels -x manifest/package.xml
Example to Retrieve Partial Translations:
To retrieve translations for LabelOne
and LabelTwo
only, you can use the same package.xml
as above:
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>LabelOne</members>
<members>LabelTwo</members>
<name>CustomLabel</name>
</types>
<types>
<members>iw</members>
<name>Translations</name>
</types>
<version>61.0</version>
</Package>
To retrieve the Translations
metadata using merge-meta
, use the following command within your Salesforce DX root folder:
$ sf sftasker merge-meta -t Translations -x manifest/package.xml
Below is the full format to run the merge-meta
command using the console:
$ sf sftasker merge-meta -o <value> -t Profile|CustomLabels|Translations [--json] [--flags-dir <value>] [-a <value>] [-x <value>] [-p <value>] [-k]
-
-o, --target-org=<value>
: The alias or username of the target Salesforce org. Note: The-o
flag can be omitted if you run the command from within a Salesforce DX project where the default org is already set. -
-x, --manifest=<value>
: Path to thepackage.xml
file for metadata retrieval. Note: This flag is mandatory when the plugin is run from outside the Salesforce DX project directory. However, it is optional when running from inside the project, as it defaults to the standardmanifest/package.xml
location. -
-t, --type=<Profile|CustomLabels|Translations>
(required): The type of metadata to merge. Note: Thepackage.xml
can include other metadata types, but the plugin will only focus on the metadata type specified by the--type
flag. -
-p, --source-dir=<value>
: Relative or absolute path to the local folder where project metadata is stored. Typically it's theforce-app
folder within the Salesforce DX project root. Note: When running the command outside the SFDX project root, you need to provide an absolute path to theforce-app
directory to locate and access the project's metadata. However, when running inside the SFDX project root, the plugin automatically uses the default metadata path specified in thesfdx-project.json
file. This means the-p
flag can be omitted if the plugin runs within the SFDX project root and the correct path is defined insfdx-project.json
. -
--apiversion=<value>
: Override the API version used for Salesforce requests. -
--json
: Formats the output as JSON. When the command succeeds, it returns an empty result with a'status': 0
response, as shown below:{ "status": 0, "result": {}, "warnings": [] }
Note: When the
--json
flag is provided, it suppresses all other standard output (stdout) log messages.
It is recommended to run the plugin from the root of the SFDX project. By doing so, the plugin can use the default project settings, such as the default org and the standard manifest/package.xml
location, reducing the need to explicitly specify certain flags:
$ sf sftasker merge-meta -t Profile
When running the plugin outside the SFDX project root, you will need to explicitly specify the -p
flag to point to the root folder of the metadata, the -x
flag to provide the path to the package.xml
file, and -o
to define the Salesforce org connection to retrieve the metadata from, as the plugin cannot automatically detect these settings:
$ sf sftasker merge-meta -o MY-ORG -t Profile -x "path/to/sfdx/root/manifest/package.xml" -p "path/to/sfdx/root/force-app"
- Use Version Control: It is recommended to use version control (e.g., Git) to store your Salesforce DX project. This allows you to easily track changes made by the plugin and provides a safety net if unintended changes occur.
- Overrides Target Directory: The
merge-meta
command overrides the metadata in the target directory specified by the-p
flag. Ensure that the correct path is provided to avoid unintentional modifications. - Metadata Retrieval Timeout: The command has a maximum metadata retrieval timeout of 5 minutes. Avoid using overly large
package.xml
files; instead, prefer smaller packages with only necessary components to ensure successful retrieval. - Temporary Data Storage: The command stores downloaded resources in a temporary directory located at
./tmp/sftasker/[orgId]/[random dir name]
. A new random directory is created with each command execution. - Avoid Including StaticResources: Do not include
StaticResource
in thepackage.xml
formerge-meta
, as it may cause retrieval issues and incomplete merges. Handle StaticResources separately to avoid conflicts. - Working with Multiple Profiles: When using the
-t Profile
flag, the plugin can handle multiple profile files in a single call, including using a wildcard (*
) to select all profiles.
-
Fresh installation of the Plugin.
Run the following command in the Terminal:
$ sf plugins install sftasker
Because this plugin is not signed, you may see a warning during installation. Proceed by confirming with y
(yes) to continue.
-
Update the Plugin.
To update the Plugin, you should uninstall and install it again.
Run the following commands in the Terminal:
$ sf plugins uninstall sftasker
$ sf plugins install sftasker
If you prefer to run sftasker
directly from the source without installing it as a plugin via sf plugins install
, follow these steps:
-
Clone the repository:
$ git clone https://github.com/hknokh/sftasker.git $ cd sftasker
-
Install dependencies:
Run the following command to install all the required dependencies:
$ npm install
-
Run the plugin commands locally:
After installing the source code, for example, to run the
merge-meta
command, you can use:$ ./bin/dev sftasker merge-meta -o MY-ORG -t Profile -x "path/to/sfdx/root/manifest/package.xml" -p "path/to/sfdx/root/force-app"
-
Linking the plugin locally using
sf plugins link
:To use the plugin source code as a normal SF CLI Plugin, you can link the plugin to your local Salesforce CLI with the following command:
$ sf plugins link
Once linked, you can run the plugin commands as a normal SF CLI Plugin. For example, to run from the Salesforce DX project root:
$ sf sftasker merge-meta -t Profile
To debug the sftasker
plugin using Visual Studio Code, follow these steps:
-
Clone the repository:
First, clone the
sftasker
repository from GitHub:$ git clone https://github.com/hknokh/sftasker $ cd sftasker
-
Install dependencies:
Run the following command to install all required dependencies:
$ npm install
If you encounter any dependency issues, you can run the following command to automatically fix them:
$ npm audit fix
-
Set breakpoints in Visual Studio Code:
- Open the
sftasker
project in Visual Studio Code. - Navigate to the relevant
.ts
(TypeScript) files where you want to inspect the code. - Set breakpoints in the desired locations by clicking on the left margin next to the line numbers.
- Open the
-
Run the CLI command in the VS Code terminal:
Open the terminal in VS Code and run the following command (
merge-meta
or whichever command you are debugging):$ ./bin/debug sftasker merge-meta -o MY-ORG -t Profile -x "path/to/sfdx/root/manifest/package.xml" -p "path/to/sfdx/root/force-app"
-
Attach the Debugger:
- After running the command, go to the Run and Debug tab on the left sidebar of VS Code.
- Select the Attach configuration from the dropdown menu.
- Click the green Start Debugging button (or press
F5
). - The debugger will attach to the running process, and you can now step through the code.
-
Investigate the code:
Once attached, you can step through the code, inspect variables, and analyze how the plugin processes your metadata.
If the issue persists, please create an issue in the GitHub Issue Tracker with detailed steps, logs, and configuration files.
This project utilizes several dependencies and libraries to provide functionality, ranging from CLI frameworks to XML parsing and Salesforce integration. Below is a brief explanation of each:
- @oclif/core: Provides the core framework for building CLI applications. It is used to structure and manage commands, handle arguments and flags, and generate help output.
- @salesforce/core: A library that provides the core components required to interact with Salesforce. It includes authentication, connection management, and Salesforce API interactions.
- @salesforce/sf-plugins-core: A library of common functionality used by Salesforce CLI plugins, offering a set of utilities to streamline plugin development and enhance compatibility within Salesforce environments.
- @types/object-path: Provides TypeScript type definitions for the
object-path
library, which is used to manipulate and navigate deeply nested objects. - fast-xml-parser: A high-performance XML parser and validator that converts XML data to JSON and vice versa. This is used to efficiently process Salesforce metadata files.
- object-path: A utility library that allows manipulation of deeply nested objects, making it easier to access, modify, and work with large metadata structures in the Salesforce environment.
- unzipper: A library used for extracting files from ZIP archives, which is often needed when handling compressed Salesforce metadata files.
- husky: A tool for managing Git hooks, enabling you to enforce pre-commit and pre-push checks such as linting, testing, or formatting automatically before committing code.
- @oclif/plugin-command-snapshot: A plugin used to create and verify command snapshots during testing, ensuring CLI commands function as expected across updates.
- @salesforce/cli-plugins-testkit: Provides a set of tools and helpers to test Salesforce CLI plugins, ensuring they work correctly in different environments.
- @salesforce/dev-scripts: A set of scripts and configuration files used to automate common development tasks, such as building, testing, and linting the project.
- @types/unzipper: TypeScript type definitions for the
unzipper
library, ensuring that ZIP file extraction operations are properly typed and safe. - eslint-plugin-sf-plugin: An ESLint plugin providing rules and configurations specifically for Salesforce CLI plugins, helping to maintain consistent code quality and style.
- oclif: The Oclif framework is used for building the CLI tool, providing the foundation for command parsing, help generation, and other core features.
- ts-node: A utility that enables TypeScript to be directly executed in a Node.js environment, without needing to compile the TypeScript code into JavaScript first.
- typescript: The TypeScript compiler, which is used to compile TypeScript code to JavaScript. It provides type safety and modern JavaScript features during development.
This project follows Semantic Versioning. For each release:
- Major: Breaking changes or significant feature updates.
- Minor: New features that are backward compatible.
- Patch: Bug fixes or minor improvements.
You can view the full list of versions and release notes in the Changelog.
Contributions are welcome! Please follow these steps to contribute:
- Fork the repository.
- Create a new branch with a descriptive name (
feature/your-feature
). - Make your changes.
- Run tests and ensure the code passes linting.
- Submit a pull request.
For more detailed instructions, check out the CONTRIBUTING.md.
- hknokh - Author and maintainer of the
sftasker
plugin.
This project is licensed under the MIT License. See the LICENSE file for more details.
This plugin is provided "as-is" with no warranties or guarantees. It is not an official Salesforce product. Always test in a development or sandbox environment before deploying to production.