Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 115 additions & 2 deletions docs/user-guide/config-commands.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,36 @@
# Configuration Management Commands

The `config` command group allows you to list, batch export, import packages of different flavors such as Studio and OCDM packages.
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 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)).

- **Package commands** — work with a package and its resources:
- [`config package import`](#package-commands-config-package) — import a package
- [`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)

## Two command families

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 `<packageKey>_<version>.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**:

- 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`.

| 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.

## Permissions

Expand All @@ -18,14 +48,16 @@ This applies to every command that reads or modifies a single package or its nod
- `config variables list`
- `config versions get`, `config versions create`
- `config validate`, `config diff`
- `config export`, `config import`, `config metadata export`
- `config export`, `config import`, `config package import`, `config metadata export`

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).

## List Packages

> **Batch command.** Part of the [batch family](#two-command-families) — a bulk listing utility typically used to discover packages before a `config export`.

Packages can be listed using the following command:

```bash
Expand Down Expand Up @@ -73,6 +105,8 @@ content-cli config list -p <sourceProfile> --packageKeys key1 ... keyN

## 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
Expand Down Expand Up @@ -127,6 +161,8 @@ Inside the nodes directory, a file for each node will be present:

## 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
Expand Down Expand Up @@ -177,6 +213,81 @@ content-cli config import -p <sourceProfile> -d <export_dir> --validate --overwr

`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.

## 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)).

### 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 `<packageKey>_<version>.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.

```bash
content-cli config package import -p <sourceProfile> -f <package zip file path>
```

Where `-f` is the shorthand for `--file`. You can also point at an unzipped directory with `-d` / `--directory`, in which case the CLI zips it for you before uploading:

```bash
content-cli config package import -p <sourceProfile> -d <package directory path>
```

`--file` and `--directory` are mutually exclusive — provide exactly one.

This command requires **edit permission** on the target package, or **create** permission when the package does not yet exist (see [Permissions](#permissions)).

#### Package Zip Format

The zip (or directory) must contain a package in the following flat layout:

```bash
package/
├─ package.json # package metadata and configuration (key, name, type, flavor, configuration)
├─ variables.json # optional — variable assignments for the package
├─ nodes/
│ ├─ <nodeKey>.json # one file per node
│ ├─ ...
```

- `package.json` is the **source of truth for variable declarations**. Every assignment in `variables.json` must reference a variable declared in `package.json`, otherwise the import is rejected.
- `variables.json` is optional. If you do not want to import variable assignments, simply omit the file.

This is intentionally different from the batch archive: there is no `manifest.json`, no `studio.json`, and no nested per-package zips — just the one package's files at the top level.

#### Overwriting an Existing Package

By default the import fails if a package with the same key already exists. Use `--overwrite` to replace it:

```bash
content-cli config package import -p <sourceProfile> -f <file path> --overwrite
```

When overwriting, variable assignments whose key is no longer declared in the imported `package.json` are pruned, keeping declarations and assignments consistent.

#### Output

On success, the command prints a summary of the imported package and its nodes to the console:

```bash
info: Successfully imported package: my-package
info: Name: My Package
info: Flavor: STUDIO
info: Imported 2 node(s).
info: - my-view (VIEW)
info: - my-knowledge-model (KNOWLEDGE_MODEL)
```

Use `--json` to write the full import result (imported package and nodes) to a JSON file in the current working directory instead:

```bash
content-cli config package import -p <sourceProfile> -f <file path> --json
```

```bash
info: File downloaded successfully. New filename: 9560f81f-f746-4117-83ee-dd1f614ad624.json
```

## Validate Package Configurations

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.
Expand Down Expand Up @@ -832,6 +943,8 @@ content-cli config nodes dependencies list --packageKey <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 <file>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as FormData from "form-data";
import { HttpClient } from "../../../core/http/http-client";
import { Context } from "../../../core/command/cli-context";
import { SinglePackageImportResult } from "../interfaces/single-package-import.interfaces";

export class SinglePackageImportApi {

private readonly httpClient: () => HttpClient;

constructor(context: Context) {
this.httpClient = () => context.httpClient;
}

public async importPackage(data: FormData, overwrite: boolean): Promise<SinglePackageImportResult> {
return this.httpClient().postFile(
"/pacman/api/core/staging/packages/import-file",
data,
{ overwrite }
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { NodeTransport } from "./node.interfaces";

export interface PackageTransport {
id: string;
key: string;
name: string;
type?: string;
version?: string;
flavor?: string;
schemaVersion?: number;
createdBy?: string;
updatedBy?: string;
creationDate?: string;
changeDate?: string;
[key: string]: any;
}

export interface SinglePackageImportResult {
importedPackage: PackageTransport;
importedNodes: NodeTransport[];
}
29 changes: 23 additions & 6 deletions src/commands/configuration-management/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ import { NodeDiffService } from "./node-diff.service";
import { NodeDependencyService } from "./node-dependency.service";
import { PackageVersionCommandService } from "./package-version-command.service";
import { PackageValidationService } from "./package-validation.service";
import { SinglePackageImportService } from "./single-package-import.service";

class Module extends IModule {

public register(context: Context, configurator: Configurator): void {
const configCommand = configurator.command("config");
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.");
configCommand.command("list")
.description("Command to list packages")
.description("[Batch] List packages in the target team. Part of the batch export/import workflow.")
.option("--json", "Return response as json type", "")
.option("--flavors <flavors...>", "Lists only packages of the given flavors")
.option("--withDependencies", "Include dependencies", "")
Expand All @@ -31,7 +33,7 @@ class Module extends IModule {
.action(this.listPackages);

configCommand.command("export")
.description("Command to export package configs")
.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'.")
.option("--packageKeys <packageKeys...>", "Keys of packages to export. Exports the latest deployed version only")
.option("--keysByVersion <keysByVersion...>", "Keys of packages to export by version")
.option("--withDependencies", "Include variables and dependencies", "")
Expand All @@ -45,13 +47,13 @@ class Module extends IModule {

metadataCommand
.command("export")
.description("Command to show whether packages have unpublished changes")
.description("[Batch] Show whether multiple packages have unpublished changes (bulk metadata export).")
.requiredOption("--packageKeys <packageKeys...>", "Keys of packages to find the metadata of")
.option("--json", "Return response as json type", "")
.action(this.batchExportPackagesMetadata);

configCommand.command("import")
.description("Command to import package configs")
.description("[Batch] Import packages from a batch archive produced by 'config export'. To import one package, use 'config package import' instead.")
.option("--overwrite", "Flag to allow overwriting of packages")
.option("--validate", "Validate node configurations before import", false)
.option("--gitProfile <gitProfile>", "Git profile which you want to use for the Git operations")
Expand All @@ -60,6 +62,17 @@ class Module extends IModule {
.option("-d, --directory <directory>", "Exported packages directory (relative path)")
.action(this.batchImportPackages);

const packageCommand = configCommand.command("package")
.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.")
.option("-f, --file <file>", "Package zip file (relative path)")
.option("-d, --directory <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")
.description("Validate package node configurations")
.requiredOption("--packageKey <packageKey>", "Key of the package to validate")
Expand All @@ -73,7 +86,7 @@ class Module extends IModule {
.action(this.validatePackage);

configCommand.command("diff")
.description("Command to diff configs of packages")
.description("[Batch] Diff a local batch archive (from 'config 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 <version>", "Compare against a given version or STAGING")
.option("--json", "Return the response as a JSON file")
Expand Down Expand Up @@ -256,6 +269,10 @@ class Module extends IModule {
await new ConfigCommandService(context).batchImportPackages(options.file, options.directory, options.overwrite, options.gitBranch, options.validate);
}

private async importSinglePackage(context: Context, command: Command, options: OptionValues): Promise<void> {
await new SinglePackageImportService(context).importPackage(options.file, options.directory, options.overwrite, options.json);
}

private async diffPackages(context: Context, command: Command, options: OptionValues): Promise<void> {
await new ConfigCommandService(context).diffPackages(options.file, options.hasChanges, options.baseVersion, options.json);
}
Expand Down
Loading
Loading