From c3212a567a6874231d51575e88e65d576de6f103 Mon Sep 17 00:00:00 2001 From: zgjimhaziri Date: Fri, 5 Jun 2026 16:29:15 +0200 Subject: [PATCH] SP-957: move Team-to-Team Copy package commands to 't2tc package' group Bulk T2TC operations (list/export/import/diff) move from the top-level 'config' group to a dedicated 't2tc package' group, and 'config validate' moves to 'config package validate'. The old commands remain as deprecated aliases with runtime deprecation notices pointing to the new ones, so the change is non-breaking. Also adds a staging-focused 'config package list' and updates the docs. Includes-AI-Code: true Co-authored-by: Cursor --- docs/user-guide/agentic-development-guide.md | 12 +- docs/user-guide/config-commands.md | 240 ++++-------------- docs/user-guide/t2tc-commands.md | 211 +++++++++++++++ mkdocs.yaml | 1 + .../config-command.service.ts | 4 + .../configuration-management/module.ts | 90 ++++++- .../configuration-management/module.spec.ts | 51 +++- 7 files changed, 405 insertions(+), 204 deletions(-) create mode 100644 docs/user-guide/t2tc-commands.md diff --git a/docs/user-guide/agentic-development-guide.md b/docs/user-guide/agentic-development-guide.md index 59d8070..b7b8a94 100644 --- a/docs/user-guide/agentic-development-guide.md +++ b/docs/user-guide/agentic-development-guide.md @@ -45,7 +45,7 @@ content-cli asset-registry examples --assetType BOARD_V2 --json ### 3. Export the target package ```bash -content-cli config export --packageKeys --unzip +content-cli t2tc package export --packageKeys --unzip ``` This gives you the directory structure with `package.json`, `manifest.json`, and existing node JSONs to use as reference. @@ -84,13 +84,13 @@ content-cli asset-registry validate --assetType \ Or validate during import with the `--validate` flag — note that this runs the `SCHEMA` layer only: ```bash -content-cli config import -d --validate --overwrite +content-cli t2tc package import -d --validate --overwrite ``` -To also run business-layer rules (PQL parsing, data-model availability, KPI uniqueness, …) and package-settings checks (dependencies, variables, and flavor-specific package settings), run `config validate` against the just-imported staging version: +To also run business-layer rules (PQL parsing, data-model availability, KPI uniqueness, …) and package-settings checks (dependencies, variables, and flavor-specific package settings), run `config package validate` against the just-imported staging version: ```bash -content-cli config validate --packageKey --layers SCHEMA BUSINESS PACKAGE_SETTINGS +content-cli config package validate --packageKey --layers SCHEMA BUSINESS PACKAGE_SETTINGS ``` If validation returns errors, fix the issues before importing. @@ -98,7 +98,7 @@ If validation returns errors, fix the issues before importing. ### 6. Import ```bash -content-cli config import -d --overwrite +content-cli t2tc package import -d --overwrite ``` This creates a new version in staging (not deployed). To create a brand-new package instead of updating, omit `--overwrite`. @@ -106,7 +106,7 @@ This creates a new version in staging (not deployed). To create a brand-new pack To later export a staging version, use `--keysByVersion`: ```bash -content-cli config export --keysByVersion _ --unzip +content-cli t2tc package export --keysByVersion _ --unzip ``` ## Troubleshooting diff --git a/docs/user-guide/config-commands.md b/docs/user-guide/config-commands.md index d823e27..fce1e75 100644 --- a/docs/user-guide/config-commands.md +++ b/docs/user-guide/config-commands.md @@ -1,40 +1,32 @@ # Configuration Management Commands -The `config` command group manages package configurations. Most of its commands work with a package and its resources — importing a package, working with nodes, versions, or variables, and validating configurations. Separately, it includes a set of **batch commands** built for specific bulk use-cases, such as moving many packages at once between teams and realms. +The `config` command group manages a package and its resources — importing a single package, working with nodes, versions, or variables, reading metadata, and validating configurations. -The batch commands are **batch-specific**: they use their own archive format that only the batch commands understand, so their artifacts are **not interchangeable** with the package commands (see [Two command families](#two-command-families)). +> **Bulk Team-to-Team Copy commands have moved.** `config list`, `config export`, `config import`, and `config diff` are **deprecated** and now live under the [`t2tc package`](./t2tc-commands.md) command group. `config validate` is deprecated too and has moved to [`config package validate`](#validate-package-configurations-config-package-validate). The deprecated commands still work for now but print a deprecation notice — switch to the new commands at your earliest convenience. -- **Package commands** — work with a package and its resources: - - [`config package import`](#package-commands-config-package) — import a package +- **Package & resource commands** — work with a package and its contents: + - [`config package import`](#package-commands-config-package) — import a single package + - [`config package validate`](#validate-package-configurations-config-package-validate) — validate a package's staging version + - [`config package list`](#list-packages-config-package-list) — list packages (staging by default) - [`config nodes …`](#finding-nodes) — work with individual nodes - [`config versions …`](#package-version) — read and create package versions - [`config variables list`](#listing--mapping-variables) — read package variables - - [`config validate`](#validate-package-configurations) — validate a package's staging version -- **Batch commands** — bulk multi-package transport for specific use-cases: - - [`config list`](#list-packages), [`config export`](#batch-export-packages), [`config import`](#batch-import-packages), [`config diff`](#diff-local-zip-with-deployed-versionspecific-versionstaging), [`config metadata export`](#batch-export-packages) + - `config metadata export` — check whether packages have unpublished changes +- **Team-to-Team Copy (batch) commands** — bulk multi-package transport, now under [`t2tc package`](./t2tc-commands.md): + - [`t2tc package list`](./t2tc-commands.md#list-packages), [`t2tc package export`](./t2tc-commands.md#export-packages), [`t2tc package import`](./t2tc-commands.md#import-packages), [`t2tc package diff`](./t2tc-commands.md#diff-local-zip-with-deployed-versionspecific-versionstaging) -## Two command families +## Package vs. batch archive format -The batch commands are a **self-contained, batch-specific set**. `config export` produces a multi-package **batch archive** — a top-level `manifest.json`, `variables.json`, `studio.json`, and one nested `_.zip` per package — that is produced and consumed **only** by other batch commands. `config package import`, by contrast, works with a plain **package zip** (a `package.json`, an optional `variables.json`, and a `nodes/` folder). The two formats are **not interchangeable**: +`config package import` works with a plain **package zip** (a `package.json`, an optional `variables.json`, and a `nodes/` folder). The Team-to-Team Copy commands instead use a multi-package **batch archive** (a top-level `manifest.json`, `variables.json`, `studio.json`, and a nested `_.zip` per package). The two formats are **not interchangeable**: -- An archive from `config export` can be imported with `config import` or inspected with `config diff` — but **not** with `config package import`. -- A package zip used by `config package import` **cannot** be imported with `config import` or diffed with `config diff`. +- An archive from `t2tc package export` can be imported with `t2tc package import` or inspected with `t2tc package diff` — but **not** with `config package import`. +- A package zip used by `config package import` **cannot** be imported with `t2tc package import` or diffed with `t2tc package diff`. -| Command | Group | Artifact it reads / writes | -|---|---|---| -| `config package import` | Package commands | Package zip/dir (`package.json`, optional `variables.json`, `nodes/`) | -| `config nodes …` | Package commands | Node JSON payload | -| `config validate`, `config versions …`, `config variables list` | Package commands | — (operate directly on the platform) | -| `config export` | Batch commands | Batch archive (multi-package) | -| `config import` | Batch commands | Batch archive (multi-package) | -| `config diff` | Batch commands | Batch archive (multi-package) | -| `config list`, `config metadata export` | Batch commands | — (JSON list output) | - -**Which should I use?** Reach for the batch commands only for their specific bulk use-cases — moving a set of packages together (for example, a migration between teams). For everything else, use the package commands. +For the full Team-to-Team Copy reference, see [T2TC Commands](./t2tc-commands.md). ## Permissions -All `config` commands run against the Pacman API and are subject to the same permission checks the platform applies in the UI. The required permission depends on the **flavor** of the target package: +All `config` commands run against the Pacman API and are subject to the same permission checks the platform applies in the UI. The same permissions apply to the [`t2tc package`](./t2tc-commands.md) commands. The required permission depends on the **flavor** of the target package: | Package flavor | Required permission | |---|---| @@ -47,181 +39,68 @@ This applies to every command that reads or modifies a single package or its nod - `config nodes create`, `config nodes update`, `config nodes archive` - `config variables list` - `config versions get`, `config versions create` -- `config validate`, `config diff` -- `config export`, `config import`, `config package import`, `config metadata export` +- `config package validate`, `config package import`, `config metadata export` +- `t2tc package export`, `t2tc package import`, `t2tc package diff` If the authenticated profile does not have the required permission, the command fails with `Access is Denied`. -`config list` is the one exception: instead of failing, it **filters out packages the profile does not have permission to access**. If a package you expect to see is missing from the list, the most likely cause is missing edit permission on the package (Studio) or on its connected data pool (OCDM). +The listing commands (`config package list` and `t2tc package list`) are the one exception: instead of failing, they **filter out packages the profile does not have permission to access**. If a package you expect to see is missing from the list, the most likely cause is missing edit permission on the package (Studio) or on its connected data pool (OCDM). -## List Packages +## List Packages (`config package list`) -> **Batch command.** Part of the [batch family](#two-command-families) — a bulk listing utility typically used to discover packages before a `config export`. +> The deprecated `config list` command has moved to [`t2tc package list`](./t2tc-commands.md#list-packages) (bulk listing for the Team-to-Team Copy workflow, with `--withDependencies` / `--packageKeys` / `--keysByVersion` filtering). For day-to-day listing, use `config package list` below. `config list` still works but prints a deprecation notice. -Packages can be listed using the following command: +`config package list` lists packages in the target team. **By default it lists staging packages.** ```bash -content-cli config list -p +content-cli config package list -p ``` -The result will be printed in the console containing only the package name and key: +The result is printed in the console containing the package name and key: ```bash info: Package1 - Key: "package-1" ``` -By using the `--json` option, packages can be exported (saved) in an extended form as a json file in the current working directory. +Use `--json` to export the list as a JSON file in the current working directory: ```bash -content-cli config list -p --json +content-cli config package list -p --json ``` -The name of the file will be printed in the console with the following format: - ```bash info: File downloaded successfully. New filename: 9560f81f-f746-4117-83ee-dd1f614ad624.json ``` -By using the `--flavors` option, you can filter which packages to list. The available flavors are: **STUDIO** and **OCDM**. - -To list staging packages instead of deployed packages use the `--staging` option. Please note that this flag is not compatible with the below options. - -### List Packages with Dependencies - -When using the listing command with the `--json` option, two additional options are available: - -- **--withDependencies**: This option will include the dependencies of the packages in the output. - -```bash -content-cli config list -p --withDependencies -``` - -- **--packageKeys**: This option allows you to filter the packages by their keys. You can specify multiple package keys separated by spaces. - -```bash -content-cli config list -p --packageKeys key1 ... keyN -[optional] –-withDependencies -``` - -## Batch Export Packages - -> **Batch command.** Part of the [batch family](#two-command-families). It produces a multi-package **batch archive** that can only be re-imported with [`config import`](#batch-import-packages) or inspected with [`config diff`](#diff-local-zip-with-deployed-versionspecific-versionstaging) — **not** with `config package import`. To work with one package, use [`config package import`](#package-commands-config-package). - -Packages can be exported using the following command: - -```bash -content-cli config export -p --packageKeys key1 ... keyN -``` - -The `--keysByVersion` option can be used to export packages by specific version. You can specify multiple packages with version separated by spaces, in the format of 'packageKey.version'. -The `--withDependencies` option can be used to also export dependencies of the given packages. -The `--unzip` option can be used to unzip the exported packages into the current working directory. - -Depending on the `--unzip` option used, a zip file, or a directory containing the exported packages, will be created in the current working directory containing: - -```bash -exported_package_random_uuid/ -├─ manifest.json -├─ variable.json -├─ studio.json -├─ package_key1-version.zip -├─ ... -├─ package_keyN-version.zip -``` - -### Git Integration for Export - -The following **Git options** are available: - -- `--gitProfile ` – specifies the Git profile to use for exporting directly to a repository. - If not specified, the default profile will be used. -- `--gitBranch ` – specifies the branch in the Github repository where the export will be pushed. - -Example exporting to Git: - -```bash -content-cli config export -p --packageKeys key1 key2 --gitProfile myGitProfile --gitBranch feature-branch -``` - -### Export Directory Structure - -- manifest.json - File which contains the metadata of the exported packages. -- studio.json - File which contains the metadata of the exported packages in a format compatible with Studio. -- variables.json - File which contains the variables of the exported packages. -- exported packages directories - Directories containing the exported package files, each directory is named after the package key and the version. - -Inside each exported package directory, the following files will be present: - -- package.json - File which contains the configuration of the exported package. -- nodes/ - Directory containing the nodes of the exported package. - -Inside the nodes directory, a file for each node will be present: - -- node_key.json - File which contains the configuration of the exported node. - -## Batch Import Packages - -> **Batch command.** Part of the [batch family](#two-command-families). It expects a multi-package **batch archive** produced by [`config export`](#batch-export-packages). To import one package from a package zip, use [`config package import`](#package-commands-config-package) instead. - -Packages can be imported using the following commands, if importing from a zip file: - -```bash -content-cli config import -p -f -``` - -Where `-f` is the short hand operation for `--file`. -If importing from a directory containing the exported packages, the following command can be used: +Use `--flavors` to filter which packages to list. The available flavors are **STUDIO** and **OCDM**: ```bash -content-cli config import -p -d +content-cli config package list -p --flavors STUDIO ``` -Where `-d` is the shorthand operation for `--directory`. -When packages with the same keys exist in the target team, the --overwrite option can be used for allowing overwriting of those packages. If the package in target environment contains unpublished changes, they are automatically saved under a new version. This allows you to audit, compare, or roll back to your previous state via the version history if needed. +> Need active (deployed) versions, dependency expansion, or `--packageKeys` / `--keysByVersion` filtering? Those belong to the bulk copy workflow — use [`t2tc package list`](./t2tc-commands.md#list-packages). -```bash -content-cli config import -p -f --overwrite -``` +## Bulk Export / Import / Diff (moved to `t2tc package`) -### Git Integration for Import - -The following **Git options** are available: - -- `--gitProfile ` – specifies the Git profile to use for importing directly from a repository. - If not specified, the default profile will be used. -- `--gitBranch ` – specifies the branch in the Github repository from which to import. - -Example importing from Git: - -```bash -content-cli config import -p --gitProfile myGitProfile --gitBranch feature-branch -``` - -Finally, the result of this command will be a list of PostPackageImportData exported as a json file. The file name will be printed with the following message format: - -```bash -info: Config import report file: 9560f81f-f746-4117-83ee-dd1f614ad624.json -``` - -### Validate During Import - -Add `--validate` to `config import` to run validation against each node **before** the import is committed: - -```bash -content-cli config import -p -d --validate --overwrite -``` - -`config import --validate` runs the **SCHEMA** layer only. It does **not** run BUSINESS-layer checks (PQL parsing, data-model availability, KPI uniqueness, etc.) or PACKAGE_SETTINGS checks (package dependencies, variables, and flavor-specific package settings). To run those validations, use [`config validate`](#validate-package-configurations) after the import. +> **Deprecated and moved.** The bulk multi-package commands have moved to the [`t2tc package`](./t2tc-commands.md) group: +> +> | Old (deprecated) | New | +> |---|---| +> | `config export` | [`t2tc package export`](./t2tc-commands.md#export-packages) | +> | `config import` | [`t2tc package import`](./t2tc-commands.md#import-packages) | +> | `config diff` | [`t2tc package diff`](./t2tc-commands.md#diff-local-zip-with-deployed-versionspecific-versionstaging) | +> +> The flags and behaviour are unchanged — only the command path moved. The old commands still work but print a deprecation notice. See [T2TC Commands](./t2tc-commands.md) for the full reference (batch archive format, Git integration, validation during import, and more). To import a **single** package from a package zip, use [`config package import`](#package-commands-config-package). ## Package Commands (`config package`) -The `config package` command group works with a package and its contents. It is **not** part of the batch-specific set — it uses the plain package format described below, which is not interchangeable with the batch archive (see [Two command families](#two-command-families)). +The `config package` command group works with a package and its contents. It uses the plain package format described below, which is not interchangeable with the batch archive used by the Team-to-Team Copy commands (see [Package vs. batch archive format](#package-vs-batch-archive-format)). ### Import a Package -`config package import` imports a package from a package zip (or directory). Unlike [`config import`](#batch-import-packages) — which performs a **batch** import and expects the multi-package batch archive (`manifest.json`, a top-level `variables.json`, `studio.json`, and a nested `_.zip` per package) — `config package import` takes a plain, flat package layout and imports it on its own. +`config package import` imports a package from a package zip (or directory). Unlike [`t2tc package import`](./t2tc-commands.md#import-packages) — which performs a **batch** import and expects the multi-package batch archive (`manifest.json`, a top-level `variables.json`, `studio.json`, and a nested `_.zip` per package) — `config package import` takes a plain, flat package layout and imports it on its own. -> A zip produced by `config export` is a **batch archive** and cannot be imported with `config package import`. Likewise, a package zip cannot be imported with `config import`. Use the command that matches how the artifact was produced. +> A zip produced by `t2tc package export` is a **batch archive** and cannot be imported with `config package import`. Likewise, a package zip cannot be imported with `t2tc package import`. Use the command that matches how the artifact was produced. ```bash content-cli config package import -p -f @@ -288,14 +167,16 @@ content-cli config package import -p -f --json info: File downloaded successfully. New filename: 9560f81f-f746-4117-83ee-dd1f614ad624.json ``` -## Validate Package Configurations +## Validate Package Configurations (`config package validate`) -The `config validate` command validates the **staging (draft) version** of a package by sending its nodes through one or more validation layers. The command runs against the Pacman validate API and returns a structured report of errors, warnings, and info findings. +> **Renamed.** This command moved from `config validate` to `config package validate`. The old `config validate` still works but prints a deprecation notice; switch to `config package validate`. + +The `config package validate` command validates the **staging (draft) version** of a package by sending its nodes through one or more validation layers. The command runs against the Pacman validate API and returns a structured report of errors, warnings, and info findings. This command requires **edit permission** on the target package (see [Permissions](#permissions)). ```bash -content-cli config validate --packageKey +content-cli config package validate --packageKey ``` By default, only the `SCHEMA` layer is run. The console output looks like: @@ -329,7 +210,7 @@ Currently `SCHEMA`, `BUSINESS`, and `PACKAGE_SETTINGS` are the layers accepted b To run all layers: ```bash -content-cli config validate --packageKey --layers SCHEMA BUSINESS PACKAGE_SETTINGS +content-cli config package validate --packageKey --layers SCHEMA BUSINESS PACKAGE_SETTINGS ``` Use `PACKAGE_SETTINGS` when you need to verify that the package's own settings are usable in the destination team before continuing authoring or import work. It reports issues such as missing dependency versions, duplicate dependency or variable keys, blank variable keys/types, missing Studio data model assignments, and OCDM package-settings problems when the corresponding backend validation is enabled. @@ -339,7 +220,7 @@ Use `PACKAGE_SETTINGS` when you need to verify that the package's own settings a By default, every node in the package's staging version is validated. To restrict the scope to a subset of nodes, use `--nodeKeys`: ```bash -content-cli config validate --packageKey --nodeKeys node-key-1 node-key-2 +content-cli config package validate --packageKey --nodeKeys node-key-1 node-key-2 ``` ### Export Validation Report as JSON @@ -347,7 +228,7 @@ content-cli config validate --packageKey --nodeKeys node-key-1 node Use `--json` to write the full validation report to a JSON file in the current working directory instead of printing it to the console: ```bash -content-cli config validate --packageKey --layers SCHEMA BUSINESS PACKAGE_SETTINGS --json +content-cli config package validate --packageKey --layers SCHEMA BUSINESS PACKAGE_SETTINGS --json ``` The filename is printed on success: @@ -885,7 +766,7 @@ To diff a local node JSON file (the compare side) against a version of the node content-cli config nodes diff --packageKey --nodeKey --baseVersion --file ``` -The file must follow the `NodeExportTransport` shape — the format produced by `config export --unzip` under `_/nodes/.json`. `--baseVersion` accepts either `STAGING` or a specific package version. `--file` and `--compareVersion` are mutually exclusive; exactly one must be provided. +The file must follow the `NodeExportTransport` shape — the format produced by `t2tc package export --unzip` under `_/nodes/.json`. `--baseVersion` accepts either `STAGING` or a specific package version. `--file` and `--compareVersion` are mutually exclusive; exactly one must be provided. If no node with the given key exists for the resolved base version, the file is diffed against an empty configuration `{}`. @@ -943,23 +824,4 @@ content-cli config nodes dependencies list --packageKey --nodeKey < ## Diff local zip with deployed version/specific version/staging -> **Batch command.** Part of the [batch family](#two-command-families). It expects a multi-package **batch archive** produced by [`config export`](#batch-export-packages); a package zip is not supported here. - -To compare local zipped packages with online packages use: -```bash -content-cli config diff --file -``` - -As with other commands, use `--json` to export the diff to a file. -To diff against a specific version use the `--baseVersion` parameter. When omitted it will diff against the current deployed version. -To diff against staging use `--baseVersion STAGING`. - -```bash -content-cli config diff --file --baseVersion -``` - -To diff against the current deployed version and only return whether there are any changes, use the `--hasChanges` flag. - -```bash -content-cli config diff --file --hasChanges -``` \ No newline at end of file +> **Deprecated and moved.** `config diff` has moved to [`t2tc package diff`](./t2tc-commands.md#diff-local-zip-with-deployed-versionspecific-versionstaging). The flags and behaviour are unchanged — only the command path moved. The old command still works but prints a deprecation notice. See [T2TC Commands](./t2tc-commands.md#diff-local-zip-with-deployed-versionspecific-versionstaging) for the full reference. \ No newline at end of file diff --git a/docs/user-guide/t2tc-commands.md b/docs/user-guide/t2tc-commands.md new file mode 100644 index 0000000..115e4fe --- /dev/null +++ b/docs/user-guide/t2tc-commands.md @@ -0,0 +1,211 @@ +# Team-to-Team Copy (T2TC) Commands + +The `t2tc package` command group moves whole packages — and, optionally, their dependencies and variables — between teams and realms. These commands power the **Team-to-Team Copy** feature: the T2TC backend drives the copy by exporting from a source team and importing into a target team through this CLI. + +These commands are a **self-contained, batch-specific set**. `t2tc package export` produces a multi-package **batch archive**, and only the other `t2tc package` commands (`import`, `diff`) understand that archive. It is **not** interchangeable with the package format used by [`config package import`](./config-commands.md#package-commands-config-package) (see [Batch archive vs. package format](#batch-archive-vs-package-format)). + +> **Migrating from `config`?** `t2tc package list/export/import/diff` replace the deprecated `config list/export/import/diff` commands. The flags and behaviour are identical — only the command path changed. + +| Old (deprecated) | New | +|---|---| +| `config list` | `t2tc package list` | +| `config export` | `t2tc package export` | +| `config import` | `t2tc package import` | +| `config diff` | `t2tc package diff` | + +## Permissions + +`t2tc package` commands run against the Pacman API and are subject to the same permission checks the platform applies in the UI. The required permission depends on the **flavor** of the target package: + +| Package flavor | Required permission | +|---|---| +| **Studio** (Studio packages and their assets) | **Edit package** permission on the package | +| **OCDM** (OCDM packages and their assets) | **Edit** (admin) permission on the **data pool** the OCDM package is connected to | + +`t2tc package list` is the one exception: instead of failing, it **filters out packages the profile does not have permission to access**. If a package you expect to see is missing from the list, the most likely cause is missing edit permission on the package (Studio) or on its connected data pool (OCDM). + +## Batch archive vs. package format + +`t2tc package export` produces a multi-package **batch archive** — a top-level `manifest.json`, `variables.json`, `studio.json`, and one nested `_.zip` per package — that is produced and consumed **only** by the `t2tc package` commands. [`config package import`](./config-commands.md#package-commands-config-package), by contrast, works with a plain **package zip** (a `package.json`, an optional `variables.json`, and a `nodes/` folder). The two formats are **not interchangeable**: + +- An archive from `t2tc package export` can be imported with `t2tc package import` or inspected with `t2tc package diff` — but **not** with `config package import`. +- A package zip used by `config package import` **cannot** be imported with `t2tc package import` or diffed with `t2tc package diff`. + +Reach for `t2tc package` only for its specific bulk use-case — moving a set of packages together (for example, a migration between teams). To work with a single package, use [`config package import`](./config-commands.md#package-commands-config-package). + +## List Packages + +Packages can be listed using the following command: + +```bash +content-cli t2tc package list -p +``` + +The result will be printed in the console containing only the package name and key: + +```bash +info: Package1 - Key: "package-1" +``` + +By using the `--json` option, packages can be exported (saved) in an extended form as a json file in the current working directory. + +```bash +content-cli t2tc package list -p --json +``` + +The name of the file will be printed in the console with the following format: + +```bash +info: File downloaded successfully. New filename: 9560f81f-f746-4117-83ee-dd1f614ad624.json +``` + +By using the `--flavors` option, you can filter which packages to list. The available flavors are: **STUDIO** and **OCDM**. + +To list staging packages instead of deployed packages use the `--staging` option. Please note that this flag is not compatible with the below options. + +> For day-to-day staging listing outside the copy workflow, prefer [`config package list`](./config-commands.md#list-packages-config-package-list), which lists staging packages by default. + +### List Packages with Dependencies + +When using the listing command with the `--json` option, two additional options are available: + +- **--withDependencies**: This option will include the dependencies of the packages in the output. + +```bash +content-cli t2tc package list -p --withDependencies +``` + +- **--packageKeys**: This option allows you to filter the packages by their keys. You can specify multiple package keys separated by spaces. + +```bash +content-cli t2tc package list -p --packageKeys key1 ... keyN +[optional] --withDependencies +``` + +## Export Packages + +Packages can be exported using the following command: + +```bash +content-cli t2tc package export -p --packageKeys key1 ... keyN +``` + +The `--keysByVersion` option can be used to export packages by specific version. You can specify multiple packages with version separated by spaces, in the format of 'packageKey.version'. +The `--withDependencies` option can be used to also export dependencies of the given packages. +The `--unzip` option can be used to unzip the exported packages into the current working directory. + +Depending on the `--unzip` option used, a zip file, or a directory containing the exported packages, will be created in the current working directory containing: + +```bash +exported_package_random_uuid/ +├─ manifest.json +├─ variable.json +├─ studio.json +├─ package_key1-version.zip +├─ ... +├─ package_keyN-version.zip +``` + +### Git Integration for Export + +The following **Git options** are available: + +- `--gitProfile ` – specifies the Git profile to use for exporting directly to a repository. + If not specified, the default profile will be used. +- `--gitBranch ` – specifies the branch in the Github repository where the export will be pushed. + +Example exporting to Git: + +```bash +content-cli t2tc package export -p --packageKeys key1 key2 --gitProfile myGitProfile --gitBranch feature-branch +``` + +### Export Directory Structure + +- manifest.json - File which contains the metadata of the exported packages. +- studio.json - File which contains the metadata of the exported packages in a format compatible with Studio. +- variables.json - File which contains the variables of the exported packages. +- exported packages directories - Directories containing the exported package files, each directory is named after the package key and the version. + +Inside each exported package directory, the following files will be present: + +- package.json - File which contains the configuration of the exported package. +- nodes/ - Directory containing the nodes of the exported package. + +Inside the nodes directory, a file for each node will be present: + +- node_key.json - File which contains the configuration of the exported node. + +## Import Packages + +Packages can be imported using the following commands, if importing from a zip file: + +```bash +content-cli t2tc package import -p -f +``` + +Where `-f` is the short hand operation for `--file`. +If importing from a directory containing the exported packages, the following command can be used: + +```bash +content-cli t2tc package import -p -d +``` + +Where `-d` is the shorthand operation for `--directory`. +When packages with the same keys exist in the target team, the `--overwrite` option can be used for allowing overwriting of those packages. If the package in target environment contains unpublished changes, they are automatically saved under a new version. This allows you to audit, compare, or roll back to your previous state via the version history if needed. + +```bash +content-cli t2tc package import -p -f --overwrite +``` + +### Git Integration for Import + +The following **Git options** are available: + +- `--gitProfile ` – specifies the Git profile to use for importing directly from a repository. + If not specified, the default profile will be used. +- `--gitBranch ` – specifies the branch in the Github repository from which to import. + +Example importing from Git: + +```bash +content-cli t2tc package import -p --gitProfile myGitProfile --gitBranch feature-branch +``` + +Finally, the result of this command will be a list of PostPackageImportData exported as a json file. The file name will be printed with the following message format: + +```bash +info: Config import report file: 9560f81f-f746-4117-83ee-dd1f614ad624.json +``` + +### Validate During Import + +Add `--validate` to `t2tc package import` to run validation against each node **before** the import is committed: + +```bash +content-cli t2tc package import -p -d --validate --overwrite +``` + +`t2tc package import --validate` runs the **SCHEMA** layer only. It does **not** run BUSINESS-layer checks (PQL parsing, data-model availability, KPI uniqueness, etc.) or PACKAGE_SETTINGS checks (package dependencies, variables, and flavor-specific package settings). To run those validations, use [`config package validate`](./config-commands.md#validate-package-configurations-config-package-validate) after the import. + +## Diff local zip with deployed version/specific version/staging + +To compare local zipped packages with online packages use: + +```bash +content-cli t2tc package diff --file +``` + +As with other commands, use `--json` to export the diff to a file. +To diff against a specific version use the `--baseVersion` parameter. When omitted it will diff against the current deployed version. +To diff against staging use `--baseVersion STAGING`. + +```bash +content-cli t2tc package diff --file --baseVersion +``` + +To diff against the current deployed version and only return whether there are any changes, use the `--hasChanges` flag. + +```bash +content-cli t2tc package diff --file --hasChanges +``` diff --git a/mkdocs.yaml b/mkdocs.yaml index 15cf176..f0b07a7 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -13,6 +13,7 @@ nav: - Overview: './user-guide/index.md' - Studio Commands: './user-guide/studio-commands.md' - Config Commands: './user-guide/config-commands.md' + - T2TC Commands: './user-guide/t2tc-commands.md' - Deployment Commands: './user-guide/deployment-commands.md' - Asset Registry Commands: './user-guide/asset-registry-commands.md' - Data Pool Commands: './user-guide/data-pool-commands.md' diff --git a/src/commands/configuration-management/config-command.service.ts b/src/commands/configuration-management/config-command.service.ts index 510d44c..9f9ec48 100644 --- a/src/commands/configuration-management/config-command.service.ts +++ b/src/commands/configuration-management/config-command.service.ts @@ -39,6 +39,10 @@ export class ConfigCommandService { } } + public listStagingPackages(jsonResponse: boolean, flavors: string[]): Promise { + return this.batchImportExportService.listStagingPackages(flavors ?? [], false, jsonResponse); + } + public async listVariables( jsonResponse: boolean, keysByVersion: string[], diff --git a/src/commands/configuration-management/module.ts b/src/commands/configuration-management/module.ts index ebbecb9..ca4ebbe 100644 --- a/src/commands/configuration-management/module.ts +++ b/src/commands/configuration-management/module.ts @@ -18,9 +18,10 @@ class Module extends IModule { public register(context: Context, configurator: Configurator): void { const configCommand = configurator.command("config") - .description("Manage package configurations. Most commands work with a package and its resources. The batch commands (list, export, import, diff, metadata) are a separate, batch-specific set for bulk multi-package transport: their archive format is only understood by other batch commands and is not interchangeable with the package commands."); + .description("Manage package configurations and their resources (package, nodes, versions, variables, metadata). Note: 'config list/export/import/diff' are deprecated — bulk Team-to-Team Copy operations have moved to the 't2tc package' group, and single-package operations live under 'config package'."); configCommand.command("list") - .description("[Batch] List packages in the target team. Part of the batch export/import workflow.") + .description("[Deprecated] Use 't2tc package list' instead. List packages in the target team.") + .deprecationNotice("'config list' is deprecated and will be removed in a future release. Use 't2tc package list' instead.") .option("--json", "Return response as json type", "") .option("--flavors ", "Lists only packages of the given flavors") .option("--withDependencies", "Include dependencies", "") @@ -33,7 +34,8 @@ class Module extends IModule { .action(this.listPackages); configCommand.command("export") - .description("[Batch] Export one or more packages into a batch archive. The archive only works with the batch commands ('config import' / 'config diff') and cannot be imported with 'config package import'.") + .description("[Deprecated] Use 't2tc package export' instead. Export one or more packages into a Team-to-Team Copy archive.") + .deprecationNotice("'config export' is deprecated and will be removed in a future release. Use 't2tc package export' instead.") .option("--packageKeys ", "Keys of packages to export. Exports the latest deployed version only") .option("--keysByVersion ", "Keys of packages to export by version") .option("--withDependencies", "Include variables and dependencies", "") @@ -47,13 +49,14 @@ class Module extends IModule { metadataCommand .command("export") - .description("[Batch] Show whether multiple packages have unpublished changes (bulk metadata export).") + .description("Show whether multiple packages have unpublished changes (bulk metadata export).") .requiredOption("--packageKeys ", "Keys of packages to find the metadata of") .option("--json", "Return response as json type", "") .action(this.batchExportPackagesMetadata); configCommand.command("import") - .description("[Batch] Import packages from a batch archive produced by 'config export'. To import one package, use 'config package import' instead.") + .description("[Deprecated] Use 't2tc package import' (batch) or 'config package import' (single package) instead. Import packages from a Team-to-Team Copy archive.") + .deprecationNotice("'config import' is deprecated and will be removed in a future release. Use 't2tc package import' (batch archive) or 'config package import' (single package) instead.") .option("--overwrite", "Flag to allow overwriting of packages") .option("--validate", "Validate node configurations before import", false) .option("--gitProfile ", "Git profile which you want to use for the Git operations") @@ -66,14 +69,14 @@ class Module extends IModule { .description("Commands for working with a package."); packageCommand.command("import") - .description("Import a package from a zip file or directory. Uses the package format, which is not interchangeable with the batch 'config export' / 'config import' archive.") + .description("Import a package from a zip file or directory. Uses the package format, which is not interchangeable with the 't2tc package export' / 't2tc package import' batch archive.") .option("-f, --file ", "Package zip file (relative path)") .option("-d, --directory ", "Package directory (relative path)") .option("--overwrite", "Flag to allow overwriting an existing package with the same key") .option("--json", "Return the response as a JSON file") .action(this.importSinglePackage); - configCommand.command("validate") + packageCommand.command("validate") .description("Validate package node configurations") .requiredOption("--packageKey ", "Key of the package to validate") .option( @@ -85,8 +88,28 @@ class Module extends IModule { .option("--json", "Return the response as a JSON file") .action(this.validatePackage); + packageCommand.command("list") + .description("List packages in the target team. Lists staging packages by default.") + .option("--json", "Return response as json type", "") + .option("--flavors ", "Lists only packages of the given flavors") + .action(this.listStagingPackages); + + configCommand.command("validate") + .description("[Deprecated] Use 'config package validate' instead. Validate package node configurations.") + .deprecationNotice("'config validate' is deprecated and will be removed in a future release. Use 'config package validate' instead.") + .requiredOption("--packageKey ", "Key of the package to validate") + .option( + "--layers ", + "Validation layers to run. Allowed values: SCHEMA, BUSINESS, PACKAGE_SETTINGS (can be combined, e.g. --layers SCHEMA BUSINESS PACKAGE_SETTINGS). Defaults to SCHEMA.", + ["SCHEMA"] + ) + .option("--nodeKeys ", "Specific node keys to validate (default: all nodes)") + .option("--json", "Return the response as a JSON file") + .action(this.validatePackage); + configCommand.command("diff") - .description("[Batch] Diff a local batch archive (from 'config export') against deployed or staging packages.") + .description("[Deprecated] Use 't2tc package diff' instead. Diff a local Team-to-Team Copy archive against deployed or staging packages.") + .deprecationNotice("'config diff' is deprecated and will be removed in a future release. Use 't2tc package diff' instead.") .option("--hasChanges", "Flag to return only the information if the package has changes without the actual changes") .option("--baseVersion ", "Compare against a given version or STAGING") .option("--json", "Return the response as a JSON file") @@ -193,6 +216,53 @@ class Module extends IModule { .option("--json", "Return the response as a JSON file") .action(this.listNodeDependencies); + const t2tcCommand = configurator.command("t2tc") + .description("Team-to-Team Copy (T2TC) commands for moving whole packages and their dependencies between teams using the batch transport archive format."); + + const t2tcPackageCommand = t2tcCommand.command("package") + .description("Team-to-Team Copy package commands: list, export, import and diff packages using the batch transport archive."); + + t2tcPackageCommand.command("list") + .description("List packages in the target team. Part of the Team-to-Team Copy export/import workflow.") + .option("--json", "Return response as json type", "") + .option("--flavors ", "Lists only packages of the given flavors") + .option("--withDependencies", "Include dependencies", "") + .option("--packageKeys ", "Lists only active versions of given package keys") + .option("--keysByVersion ", "Lists packages by given key and version [packageKey.version]") + .option("--variableValue ", "Variable value for filtering packages by.") + .option("--variableType ", "Variable type for filtering packages by.") + .option("--branches", "Include branches", false) + .option("--staging", "List staging packages instead", false) + .action(this.listPackages); + + t2tcPackageCommand.command("export") + .description("Export one or more packages into a Team-to-Team Copy archive. The archive is consumed by 't2tc package import' / 't2tc package diff'.") + .option("--packageKeys ", "Keys of packages to export. Exports the latest deployed version only") + .option("--keysByVersion ", "Keys of packages to export by version") + .option("--withDependencies", "Include variables and dependencies", "") + .option("--unzip", "Unzip the exported file", "") + .option("--gitProfile ", "Git profile which you want to use for the Git operations") + .option("--gitBranch ", "Git branch in which you want to push the exported file") + .action(this.batchExportPackages); + + t2tcPackageCommand.command("import") + .description("Import packages from a Team-to-Team Copy archive produced by 't2tc package export'. To import a single standalone package, use 'config package import'.") + .option("--overwrite", "Flag to allow overwriting of packages") + .option("--validate", "Validate node configurations before import", false) + .option("--gitProfile ", "Git profile which you want to use for the Git operations") + .option("--gitBranch ", "Git branch from which you want to pull the exported file and import") + .option("-f, --file ", "Exported packages file (relative path)") + .option("-d, --directory ", "Exported packages directory (relative path)") + .action(this.batchImportPackages); + + t2tcPackageCommand.command("diff") + .description("Diff a local Team-to-Team Copy archive (from 't2tc package export') against deployed or staging packages.") + .option("--hasChanges", "Flag to return only the information if the package has changes without the actual changes") + .option("--baseVersion ", "Compare against a given version or STAGING") + .option("--json", "Return the response as a JSON file") + .requiredOption("-f, --file ", "Exported packages file (relative or absolute path)") + .action(this.diffPackages); + const listCommand = configurator.command("list"); listCommand.command("assignments") .description("Command to list possible variable assignments for a type") @@ -222,6 +292,10 @@ class Module extends IModule { options.staging); } + private async listStagingPackages(context: Context, command: Command, options: OptionValues): Promise { + await new ConfigCommandService(context).listStagingPackages(options.json, options.flavors); + } + private async batchExportPackages(context: Context, command: Command, options: OptionValues): Promise { if ((options.packageKeys && options.keysByVersion) || (!options.packageKeys && !options.keysByVersion)) { throw new Error("Please provide either --packageKeys or --keysByVersion, but not both."); diff --git a/tests/commands/configuration-management/module.spec.ts b/tests/commands/configuration-management/module.spec.ts index 80ef7ea..03672b7 100644 --- a/tests/commands/configuration-management/module.spec.ts +++ b/tests/commands/configuration-management/module.spec.ts @@ -36,6 +36,7 @@ describe("Configuration Management Module - Action Validations", () => { mockConfigCommandService = { listPackages: jest.fn().mockResolvedValue(undefined), + listStagingPackages: jest.fn().mockResolvedValue(undefined), listVariables: jest.fn().mockResolvedValue(undefined), batchExportPackages: jest.fn().mockResolvedValue(undefined), batchImportPackages: jest.fn().mockResolvedValue(undefined), @@ -221,6 +222,38 @@ describe("Configuration Management Module - Action Validations", () => { }); }); + describe("config package list handler", () => { + it("should list staging packages with json and flavors", async () => { + const options: OptionValues = { + json: true, + flavors: ["APP"], + }; + + await (module as any).listStagingPackages(testContext, mockCommand, options); + + expect(mockConfigCommandService.listStagingPackages).toHaveBeenCalledWith(true, ["APP"]); + }); + + it("should default json and flavors to undefined when not provided", async () => { + const options: OptionValues = {}; + + await (module as any).listStagingPackages(testContext, mockCommand, options); + + expect(mockConfigCommandService.listStagingPackages).toHaveBeenCalledWith(undefined, undefined); + }); + + it("should not pass legacy listPackages options", async () => { + const options: OptionValues = { + flavors: ["APP", "ANALYSIS"], + }; + + await (module as any).listStagingPackages(testContext, mockCommand, options); + + expect(mockConfigCommandService.listStagingPackages).toHaveBeenCalledWith(undefined, ["APP", "ANALYSIS"]); + expect(mockConfigCommandService.listPackages).not.toHaveBeenCalled(); + }); + }); + describe("batchExportPackages validation", () => { describe("packageKeys and keysByVersion validation", () => { it("should throw error when both packageKeys and keysByVersion are provided", async () => { @@ -773,6 +806,8 @@ describe("Configuration Management Module - Action Validations", () => { // Top-level groups attached to the root configurator expect(mockConfigurator.command).toHaveBeenCalledWith("config"); expect(mockConfigurator.command).toHaveBeenCalledWith("list"); + expect(mockConfigurator.command).toHaveBeenCalledWith("t2tc"); + expect(mockConfigurator.command).toHaveBeenCalledWith("package"); }); it("wires an action handler for every leaf subcommand", () => { @@ -782,12 +817,26 @@ describe("Configuration Management Module - Action Validations", () => { // Each leaf command terminates the fluent chain with .action(handler). // Keep this count in sync when adding or removing commands in module.ts. - const expectedLeafCommands = 18; + const expectedLeafCommands = 24; expect(mockConfigurator.action).toHaveBeenCalledTimes(expectedLeafCommands); for (const call of mockConfigurator.action.mock.calls) { expect(typeof call[0]).toBe("function"); } }); + + it("marks the moved config commands as deprecated", () => { + const mockConfigurator = createMockConfigurator(); + + new Module().register(testContext, mockConfigurator); + + // config list/export/import/diff/validate are duplicated under t2tc package / + // config package and the originals carry a deprecation notice. + const expectedDeprecatedCommands = 5; + expect(mockConfigurator.deprecationNotice).toHaveBeenCalledTimes(expectedDeprecatedCommands); + for (const call of mockConfigurator.deprecationNotice.mock.calls) { + expect(typeof call[0]).toBe("string"); + } + }); }); describe("listNodeDependencies", () => {