From f641fd49776c2e4fd1aee41bf23e7bfa9c762b16 Mon Sep 17 00:00:00 2001 From: "b.mucolli" Date: Mon, 26 Oct 2026 17:20:05 +0100 Subject: [PATCH 1/2] SP-3478: Add config versions list command List all created versions of a package or branch through pacman's public versions endpoint. Co-Authored-By: Claude Includes-AI-Code: true --- docs/command-graph.html | 5 +- docs/user-guide/config-commands.md | 26 ++++++++- .../api/package-version-api.ts | 8 +++ .../configuration-management/module.ts | 10 ++++ .../package-version-command.service.ts | 4 ++ .../package-version.service.ts | 13 +++++ .../config-version-list.spec.ts | 56 +++++++++++++++++++ .../commands/configuration-management.spec.ts | 24 ++++++++ 8 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 tests/commands/configuration-management/config-version-list.spec.ts diff --git a/docs/command-graph.html b/docs/command-graph.html index e20f2ffe..752514fb 100644 --- a/docs/command-graph.html +++ b/docs/command-graph.html @@ -361,6 +361,9 @@ { id: "config_versions_get", label: "get", group: "command", path: "config versions get", description: "Get version metadata for a specific package version", options: ["-p, --profile ", "--packageKey ", "--packageVersion (specific version or \"LATEST\")", "--json", "-h, --help"] }, + { id: "config_versions_list", label: "list", group: "command", path: "config versions list", + description: "List all created versions of a package or branch", + options: ["-p, --profile ", "--packageKey (use @ for a branch)", "--json", "-h, --help"] }, { id: "config_versions_create", label: "create", group: "command", path: "config versions create", description: "Create a new version for a package", options: ["-p, --profile ", "--packageKey ", "--packageVersion (required if versionBumpOption is NONE)", "--versionBumpOption (NONE or PATCH, default: \"NONE\")", "--summaryOfChanges ", "--nodeFilterKeys (default: all nodes)", "--json", "-h, --help"] }, @@ -521,7 +524,7 @@ ["config_branch_merge_area","config_branch_merge_preview"],["config_branch_merge_area","config_branch_merge_apply"], ["area_config","config_metadata_area"],["config_metadata_area","config_metadata_export"], ["area_config","config_versions_area"],["config_versions_area","config_versions_get"], - ["config_versions_area","config_versions_create"], + ["config_versions_area","config_versions_list"],["config_versions_area","config_versions_create"], ["area_config","config_variables_area"],["config_variables_area","config_variables_list"], ["area_config","config_nodes_area"], ["config_nodes_area","config_nodes_get"],["config_nodes_area","config_nodes_create"], diff --git a/docs/user-guide/config-commands.md b/docs/user-guide/config-commands.md index a9893d72..086ff699 100644 --- a/docs/user-guide/config-commands.md +++ b/docs/user-guide/config-commands.md @@ -10,7 +10,7 @@ The `config` command group manages a package and its resources — importing a s - [`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 versions …`](#package-version) — read, list and create package versions - [`config variables list`](#listing--mapping-variables) — read package variables - `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): @@ -39,7 +39,7 @@ This applies to every command that reads or modifies a single package or its nod - `config nodes get`, `config nodes list`, `config nodes diff`, `config nodes dependencies list` - `config nodes create`, `config nodes update`, `config nodes archive` - `config variables list` -- `config versions get`, `config versions create` +- `config versions get`, `config versions list`, `config versions create` - `config package validate`, `config package import`, `config package export`, `config metadata export` - `t2tc package export`, `t2tc package import`, `t2tc package diff` @@ -440,6 +440,28 @@ To export the version metadata as a JSON file instead of displaying it in the co content-cli config versions get --packageKey --packageVersion --json ``` +### List Package Versions + +To list all created versions of a package, use the following command: + +```bash +content-cli config versions list --packageKey +``` + +Branches are packages too, so the same command lists the versions of a branch: + +```bash +content-cli config versions list --packageKey @ +``` + +The command prints one line of version metadata per version. A package without versions prints `Package has no versions.` + +To export the list as a JSON file instead, use the `--json` option: + +```bash +content-cli config versions list --packageKey --json +``` + ### Create Package Version To create a new version for a package, use the following command: diff --git a/src/commands/configuration-management/api/package-version-api.ts b/src/commands/configuration-management/api/package-version-api.ts index b088f43f..4d97560c 100644 --- a/src/commands/configuration-management/api/package-version-api.ts +++ b/src/commands/configuration-management/api/package-version-api.ts @@ -14,6 +14,14 @@ export class PackageVersionApi { this.httpClient = () => context.httpClient; } + public async findAll(packageKey: string): Promise { + return this.httpClient() + .get(`/pacman/api/core/packages/${packageKey}/versions`) + .catch(e => { + throw new FatalError(`Problem listing versions of Package with key '${packageKey}': ${e}`); + }); + } + public async findOne(packageKey: string, version: string): Promise { return this.httpClient() .get(`/pacman/api/core/packages/${packageKey}/versions/${version}`) diff --git a/src/commands/configuration-management/module.ts b/src/commands/configuration-management/module.ts index 90691247..fe994e1f 100644 --- a/src/commands/configuration-management/module.ts +++ b/src/commands/configuration-management/module.ts @@ -220,6 +220,12 @@ class Module extends IModule { .option("--json", "Return the response as a JSON file") .action(this.getPackageVersion) + configVersionCommand.command("list") + .description("List all created versions of a package or branch") + .requiredOption("--packageKey ", "Identifier of the package. Use @ for a branch.") + .option("--json", "Return the response as a JSON file") + .action(this.listPackageVersions); + configVersionCommand.command("create") .description("Create a new version for a package") .requiredOption("--packageKey ", "Identifier of the package") @@ -451,6 +457,10 @@ class Module extends IModule { await new PackageVersionCommandService(context).getPackageVersion(options.packageKey, options.packageVersion, options.json); } + private async listPackageVersions(context: Context, command: Command, options: OptionValues): Promise { + await new PackageVersionCommandService(context).listPackageVersions(options.packageKey, options.json); + } + private async createPackageVersion(context: Context, command: Command, options: OptionValues): Promise { const hasExplicitVersion = !!options.packageVersion; const hasVersionBump = options.versionBumpOption && options.versionBumpOption !== "NONE"; diff --git a/src/commands/configuration-management/package-version-command.service.ts b/src/commands/configuration-management/package-version-command.service.ts index 262d87a3..33a67ab6 100644 --- a/src/commands/configuration-management/package-version-command.service.ts +++ b/src/commands/configuration-management/package-version-command.service.ts @@ -13,6 +13,10 @@ export class PackageVersionCommandService { await this.packageVersionService.findPackageVersion(packageKey, version, jsonResponse); } + public async listPackageVersions(packageKey: string, jsonResponse: boolean): Promise { + await this.packageVersionService.listPackageVersions(packageKey, jsonResponse); + } + public async createPackageVersion( packageKey: string, version: string | undefined, diff --git a/src/commands/configuration-management/package-version.service.ts b/src/commands/configuration-management/package-version.service.ts index f4aa60f2..c2ee5893 100644 --- a/src/commands/configuration-management/package-version.service.ts +++ b/src/commands/configuration-management/package-version.service.ts @@ -31,6 +31,19 @@ export class PackageVersionService { } } + public async listPackageVersions(packageKey: string, jsonResponse: boolean): Promise { + const packageVersions: PackageVersionTransport[] = await this.packageVersionApi.findAll(packageKey); + if (jsonResponse) { + const filename = uuidv4() + ".json"; + const writtenFilename = await this.cuiFileService.writeToFileWithGivenName(JSON.stringify(packageVersions, null, 2), filename); + logger.info(FileService.fileDownloadedMessage + writtenFilename); + } else if (packageVersions.length === 0) { + logger.info(`Package ${packageKey} has no versions.`); + } else { + packageVersions.forEach(packageVersion => logger.info(JSON.stringify(packageVersion))); + } + } + public async createPackageVersion( packageKey: string, version: string | undefined, diff --git a/tests/commands/configuration-management/config-version-list.spec.ts b/tests/commands/configuration-management/config-version-list.spec.ts new file mode 100644 index 00000000..c819025f --- /dev/null +++ b/tests/commands/configuration-management/config-version-list.spec.ts @@ -0,0 +1,56 @@ +import { PackageVersionTransport } from "../../../src/commands/configuration-management/interfaces/package-version.interfaces"; +import { mockAxiosGet } from "../../utls/http-requests-mock"; +import { testContext } from "../../utls/test-context"; +import { loggingTestTransport } from "../../jest.setup"; +import { + PackageVersionCommandService +} from "../../../src/commands/configuration-management/package-version-command.service"; +import { getJsonFromDownloadedFile } from "../../utls/fs-utils"; + +describe("Package Version list", () => { + const buildPackageVersion = (packageKey: string, version: string, deployed: boolean): PackageVersionTransport => ({ + packageKey, + historyId: `history-${version}`, + version, + changeDate: new Date("2024-01-15T10:30:00Z").toISOString(), + publishDate: new Date("2024-01-15T11:00:00Z").toISOString(), + publishMessage: `Release ${version}`, + deployed, + publishedBy: "user@example.com", + }); + + it("Should list package versions", async () => { + const packageKey = "test-package-key"; + const packageVersions = [ + buildPackageVersion(packageKey, "1.0.1", true), + buildPackageVersion(packageKey, "1.0.0", false), + ]; + mockAxiosGet(`https://myTeam.celonis.cloud/pacman/api/core/packages/${packageKey}/versions`, packageVersions); + + await new PackageVersionCommandService(testContext).listPackageVersions(packageKey, false); + + expect(loggingTestTransport.logMessages.length).toBe(2); + expect(JSON.parse(loggingTestTransport.logMessages[0].message)).toEqual(packageVersions[0]); + expect(JSON.parse(loggingTestTransport.logMessages[1].message)).toEqual(packageVersions[1]); + }); + + it("Should list branch versions and return them as JSON", async () => { + const branchPackageKey = "project-key@my-branch"; + const packageVersions = [buildPackageVersion(branchPackageKey, "0.0.2", false)]; + mockAxiosGet(`https://myTeam.celonis.cloud/pacman/api/core/packages/${branchPackageKey}/versions`, packageVersions); + + await new PackageVersionCommandService(testContext).listPackageVersions(branchPackageKey, true); + + expect(getJsonFromDownloadedFile()).toEqual(packageVersions); + }); + + it("Should report a package without versions", async () => { + const packageKey = "unpublished-package"; + mockAxiosGet(`https://myTeam.celonis.cloud/pacman/api/core/packages/${packageKey}/versions`, []); + + await new PackageVersionCommandService(testContext).listPackageVersions(packageKey, false); + + expect(loggingTestTransport.logMessages.length).toBe(1); + expect(loggingTestTransport.logMessages[0].message).toContain(`Package ${packageKey} has no versions.`); + }); +}); diff --git a/tests/integration/commands/configuration-management.spec.ts b/tests/integration/commands/configuration-management.spec.ts index c5a48ec7..d19e74e0 100644 --- a/tests/integration/commands/configuration-management.spec.ts +++ b/tests/integration/commands/configuration-management.spec.ts @@ -69,6 +69,7 @@ describe("configuration-management command integration", () => { mockPackageVersionCommandService = { createPackageVersion: jest.fn().mockResolvedValue(undefined), getPackageVersion: jest.fn().mockResolvedValue(undefined), + listPackageVersions: jest.fn().mockResolvedValue(undefined), } as any; mockSinglePackageImportService = { @@ -981,6 +982,29 @@ describe("configuration-management command integration", () => { }); }); + describe("config versions list (listPackageVersions)", () => { + it("forwards the branch package key and --json", async () => { + await runCli([ + "config", "versions", "list", + "--packageKey", "project-key@my-branch", + "--json", + ]); + + expect(lastResult.exitCode).toBe(0); + expect(mockPackageVersionCommandService.listPackageVersions).toHaveBeenCalledWith( + "project-key@my-branch", + true + ); + }); + + it("rejects when --packageKey is missing", async () => { + await runCli(["config", "versions", "list"]); + + expectError("--packageKey "); + expect(mockPackageVersionCommandService.listPackageVersions).not.toHaveBeenCalled(); + }); + }); + describe("config versions create (createPackageVersion)", () => { it("rejects when both --packageVersion and --versionBumpOption PATCH are provided", async () => { await runCli([ From 92e2eee829e4d29768bd34aa8a88649f563b3c64 Mon Sep 17 00:00:00 2001 From: "b.mucolli" Date: Mon, 26 Oct 2026 17:50:37 +0100 Subject: [PATCH 2/2] SP-3478: Use toHaveLength in the versions list tests Co-Authored-By: Claude Includes-AI-Code: true --- .../configuration-management/config-version-list.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/commands/configuration-management/config-version-list.spec.ts b/tests/commands/configuration-management/config-version-list.spec.ts index c819025f..a0945faf 100644 --- a/tests/commands/configuration-management/config-version-list.spec.ts +++ b/tests/commands/configuration-management/config-version-list.spec.ts @@ -29,7 +29,7 @@ describe("Package Version list", () => { await new PackageVersionCommandService(testContext).listPackageVersions(packageKey, false); - expect(loggingTestTransport.logMessages.length).toBe(2); + expect(loggingTestTransport.logMessages).toHaveLength(2); expect(JSON.parse(loggingTestTransport.logMessages[0].message)).toEqual(packageVersions[0]); expect(JSON.parse(loggingTestTransport.logMessages[1].message)).toEqual(packageVersions[1]); }); @@ -50,7 +50,7 @@ describe("Package Version list", () => { await new PackageVersionCommandService(testContext).listPackageVersions(packageKey, false); - expect(loggingTestTransport.logMessages.length).toBe(1); + expect(loggingTestTransport.logMessages).toHaveLength(1); expect(loggingTestTransport.logMessages[0].message).toContain(`Package ${packageKey} has no versions.`); }); });