# RevCloud CML Deployer CLI (`rccml`)

A powerful command-line interface (CLI) to automate the complex deployment of Salesforce Advanced Configurator (CML / ExpressionSet) configurations between orgs.

This tool handles the entire process of exporting a configuration and its deep-nested dependencies, transforming the data for a new org, and deploying it in an idempotent, transactional way.

## Installation

Requires Node.js 18 or later.

Install the CLI globally:

```bash
npm install -g @arohitu/revcloud-cml-cli
```

If npm reports a local cache error during install:

```bash
npm cache verify
npm install -g @arohitu/revcloud-cml-cli --cache .npm-cache
```

## Prerequisites

`rccml` uses the Salesforce CLI (`sf`) for authentication and org access. Before running `retrieve` or `deploy`, make sure:

- Salesforce CLI is installed and available on your `PATH`.
- The source or target org is already authenticated with `sf`.
- You know the org alias or username to pass with `--target-org`.

Example:

```bash
sf org login web --alias my-source-org
sf org display --target-org my-source-org
```

## Usage
The tool provides three main commands: `list`, `retrieve`, and `deploy`.

To disable analytics for a run, append:

```bash
--no-telemetry
```

## List
Lists all available `ExpressionSet` (CML) configurations in an org with numbered output.

```bash
rccml list --target-org <source-org-alias>
```

## Retrieve
Exports a complete snapshot of an `ExpressionSet` and all its dependencies from a source org.

```bash
rccml retrieve --name <ApiName> --target-org <source-org-alias>
```

Or provide a manifest file with one API name per line:

```bash
rccml retrieve --manifest cml/cml-manifest.txt --target-org <source-org-alias>
```

Or choose interactively from a numbered list:

```bash
rccml retrieve --target-org <source-org-alias> --select
```

Or retrieve every CML in the org:

```bash
rccml retrieve --target-org <source-org-alias> --all
```

## Deploy
Deploys the retrieved configuration to a target org, handling all ID mapping and relationship logic.
```bash
rccml deploy --name <ApiName> --target-org <destination-org-alias>
```

Or provide a manifest file with one API name per line:

```bash
rccml deploy --manifest cml/cml-manifest.txt --target-org <destination-org-alias>
```

Example `cml/cml-manifest.txt`:

```text
MyExpressionSetApiName
AnotherExpressionSetApiName
```

Name selection precedence for `deploy` and `retrieve`:
- `--name` (highest)
- `--manifest`
- `cml/settings.json` `deployApiNames`

Before deploy, ensure the local CML package exists under `cml/<ApiName>/` and includes at least:

- `ExpressionSet.json`
- `ExpressionSetConstraintObj.json`

Based on constraint references, `deploy` may also require:

- `Product2.json`
- `ProductClassification.json`
- `ProductRelatedComponent.json`
- `ProductComponentGroup.json`

If required files are missing, `deploy` now fails early with a specific message telling you to run `retrieve` for the same CML from the required source org.

CI/CD behavior:

- `deploy` returns a non-zero exit code when any requested CML fails.
- A success exit code is returned only when all requested CMLs deploy successfully.
- When using `--name` or `--manifest`, `deploy` validates each requested API name exists under `cml/<ApiName>/` and fails fast with a non-zero exit code if any are missing.
- `deploy` retries transient Salesforce connectivity failures with exponential backoff before marking a CML as failed.
- `deploy` prints a concise final summary showing succeeded and failed CMLs, the failed phase, and a short reason/action for each failure.
- When any CML fails, `deploy` writes the failed API names to `.rccml/last-deploy-failures.txt` in manifest format.

Rerun only the failed CMLs:

```bash
rccml deploy --manifest .rccml/last-deploy-failures.txt --target-org <destination-org-alias>
```

## GitHub Actions Deployment Reference

The npm package page renders this README, so GitHub Actions deployment guidance is published here as a reference.

Use the workflow file in this repository:

- [`rccml-github-actions-sample.yml`](https://github.com/arohitu/rlmaccelerators/blob/main/rca-cml-deploy-actions/deploy-cml.yml)

Required GitHub secret:

- `SFDX_AUTH_URL` (used to authenticate the target org alias in CI)

The workflow deploys from `cml/cml-manifest.txt` using:

```bash
npx rccml deploy --manifest cml/cml-manifest.txt --target-org target-org --no-telemetry
```

## Configuration
The tool can be configured using a `cml/settings.json` file in your project to specify which `ExpressionSet`s to deploy in a CI/CD pipeline and to override default external ID fields.

Example `cml/settings.json`:

```json
{
  "deployApiNames": ["MyExpressionSetApiName"],
  "externalIdFields": {
    "product2": "ExternalId",
    "productClassification": "Code",
    "productComponentGroup": "Code"
  }
}
```

- `externalIdFields.productComponentGroup` defaults to `Code` when omitted.
- `ExpressionSetConstraintObj` records with `ConstraintModelTag = Group` are supported. Their `ReferenceObjectId` values (prefix `0y7`) are resolved using `ProductComponentGroup` records retrieved with the configured external ID field.

## Analytics and Tracking

`rccml` asks whether analytics are allowed on first interactive CLI use:

```text
This CLI tool, rccml collects usage analytics to help improve the product.
```

Options:
- `Allow` enables analytics.
- `Do Not Allow` keeps the tool installed and runs future commands with analytics disabled.

Tracked events:
- One `retrieve` event per retrieve run
- One `deploy` event per deploy run

Event properties:
- `cml_succeeded`
- `cml_failed`
- `constraints_processed`

Global option:
- `--no-telemetry` disables analytics for that invocation

## Upgrade Policy

`rccml` checks the latest published npm version at command startup. If your installed version is behind, the CLI shows an upgrade warning and recommends:

```bash
rccml update
```
