Skip to content
Draft
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
12 changes: 11 additions & 1 deletion docs/user-guide/t2tc-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,22 @@ The name of the file will be printed in the console with the following format:
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**.
By using the `--flavors` option, you can filter which packages to list. The available flavors are: **STUDIO**, **OCDM** and **CCM**.

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 Live Packages

Use the `--live` option to list only the package each project's **LIVE** pointer targets. Projects without a LIVE pointer are skipped. If the live branch pointer feature is not enabled for the team, the deployed main packages are listed instead.

```
content-cli t2tc package list --profile my-profile --live --flavors CCM --json
```

`--live` can be combined with `--json`, `--flavors` and `--withDependencies`. It is not compatible with `--staging`, `--branches`, `--packageKeys`, `--keysByVersion`, `--variableValue` and `--variableType`.

### List Packages with Dependencies

When using the listing command with the `--json` option, two additional options are available:
Expand Down
11 changes: 11 additions & 0 deletions src/commands/t2tc/api/t2tc-package-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@ export class T2tcPackageApi {
});
}

public async findAllLivePackages(flavors: string[], withDependencies: boolean = false): Promise<PackageExportTransport[]> {
const queryParams = new URLSearchParams();

queryParams.set("withDependencies", withDependencies.toString());
flavors.forEach(flavor => queryParams.append("flavors", flavor));

return this.httpClient().get(`/package-manager/api/core/packages/export/list-live?${queryParams.toString()}`).catch(e => {
throw new FatalError(`Problem getting live packages: ${e}`);
});
}

public async findActivePackagesByVariableValue(flavors: string[], variableValue: string, variableType: string, includeBranches: boolean = false): Promise<PackageExportTransport[]> {
const queryParams = new URLSearchParams();

Expand Down
7 changes: 6 additions & 1 deletion src/commands/t2tc/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Module extends IModule {
.option("--variableType <variableType>", "Variable type for filtering packages by.")
.option("--branches", "Include branches", false)
.option("--staging", "List staging packages instead", false)
.option("--live", "List only the package each LIVE pointer targets", false)
.action(this.listPackages);

t2tcPackageCommand.command("export")
Expand Down Expand Up @@ -61,6 +62,9 @@ class Module extends IModule {
if (options.packageKeys && options.keysByVersion) {
throw new Error("Please provide either --packageKeys or --keysByVersion, but not both.");
}
if (options.live && (options.staging || options.branches || options.packageKeys || options.keysByVersion || options.variableValue || options.variableType)) {
throw new Error("Live parameter is not compatible with --staging, --branches, --packageKeys, --keysByVersion, --variableValue, --variableType");
}

await new T2tcCommandService(context).listPackages(
options.json,
Expand All @@ -71,7 +75,8 @@ class Module extends IModule {
options.variableValue,
options.variableType,
options.branches,
options.staging);
options.staging,
options.live);
}

private async batchExportPackages(context: Context, command: Command, options: OptionValues): Promise<void> {
Expand Down
7 changes: 5 additions & 2 deletions src/commands/t2tc/t2tc-command.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@
variableValue: string,
variableType: string,
includeBranches: boolean,
staging: boolean): Promise<void> {
if (staging) {
staging: boolean,
live: boolean = false): Promise<void> {
if (live) {

Check warning on line 30 in src/commands/t2tc/t2tc-command.service.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Provide multiple methods instead of using "live" to determine which action to take.

See more on https://sonarcloud.io/project/issues?id=celonis_content-cli&issues=AaE0EI9ZSU7UZ9wpah85&open=AaE0EI9ZSU7UZ9wpah85&pullRequest=430
await this.t2tcPackageService.listLivePackages(flavors ?? [], withDependencies, jsonResponse);
} else if (staging) {
await this.stagingPackageService.listStagingPackages(flavors ?? [], includeBranches, jsonResponse);
} else if (variableValue) {
await this.listPackagesByVariableValue(jsonResponse, flavors, variableValue, variableType, includeBranches);
Expand Down
13 changes: 13 additions & 0 deletions src/commands/t2tc/t2tc-package.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,19 @@ export class T2tcPackageService {
});
}

public async listLivePackages(flavors: string[], withDependencies: boolean, jsonResponse: boolean): Promise<void> {
const livePackages = await this.t2tcPackageApi.findAllLivePackages(flavors, withDependencies);

if (jsonResponse) {
await this.exportListOfPackages(await this.studioService.getExportPackagesWithStudioData(livePackages, withDependencies));
return;
}

livePackages.forEach(pkg => {
logger.info(`${pkg.name} - Key: "${pkg.key}"`);
});
}

public async findAndExportListOfPackages(flavors: string[], packageKeys: string[], keysByVersion: string[], withDependencies: boolean, includeBranches: boolean): Promise<void> {
let packagesToExport: PackageExportTransport[];

Expand Down
41 changes: 41 additions & 0 deletions tests/commands/t2tc/module.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,50 @@ describe("T2TC Module", () => {
undefined,
undefined,
undefined,
undefined,
undefined
);
});

it.each([
["--staging", { staging: true }],
["--branches", { branches: true }],
["--packageKeys", { packageKeys: ["package1"] }],
["--keysByVersion", { keysByVersion: ["package1.1.0.0"] }],
["--variableValue", { variableValue: "value" }],
["--variableType", { variableType: "DATA_MODEL" }],
])("throws when --live is combined with %s", async (_name: string, extraOptions: OptionValues) => {
const options: OptionValues = { live: true, ...extraOptions };

await expect(
(module as any).listPackages(testContext, mockCommand, options)
).rejects.toThrow("Live parameter is not compatible with");

expect(mockT2tcCommandService.listPackages).not.toHaveBeenCalled();
});

it("delegates --live to T2tcCommandService", async () => {
const options: OptionValues = {
json: true,
flavors: ["CCM"],
live: true,
};

await (module as any).listPackages(testContext, mockCommand, options);

expect(mockT2tcCommandService.listPackages).toHaveBeenCalledWith(
true,
["CCM"],
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
true
);
});
});

describe("batchExportPackages", () => {
Expand Down
40 changes: 39 additions & 1 deletion tests/commands/t2tc/t2tc-package-list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@

it.each([
"",
"STUDIO,TEST"
"STUDIO,TEST",
"CCM"
])(
"Should list all packages by key for non-json response with flavors: %p",
async (flavors: string) => {
Expand Down Expand Up @@ -61,6 +62,18 @@
expect(exportedFirstPackage).toEqual({...firstPackage, spaceId: "spaceId-1"});
})

it("Should export CCM packages unchanged for json response with CCM flavor", async () => {
const ccmPackage = {...PacmanApiUtils.buildPackageExportTransport("ccm-key", "ccm-name"), flavor: "CCM"};

mockAxiosGet("https://myTeam.celonis.cloud/package-manager/api/core/packages/export/list?withDependencies=false&includeBranches=false&flavors=CCM", [{...ccmPackage}]);
mockAxiosGet("https://myTeam.celonis.cloud/package-manager/api/packages/with-variable-assignments?type=DATA_MODEL", []);

await new T2tcCommandService(testContext).listPackages(true, ["CCM"], false, [], undefined, null, null, false, false);

const exportedTransports = getJsonFromDownloadedFile() as PackageExportTransport[];
expect(exportedTransports).toEqual([ccmPackage]);
})

it("Should export all packages with dependencies and data models set for json response and withDependencies option", async () => {
const firstPackage = PacmanApiUtils.buildPackageExportTransport("key-1", "name-1");
const secondPackage = PacmanApiUtils.buildPackageExportTransport("key-2", "name-2");
Expand Down Expand Up @@ -251,6 +264,31 @@
expect(exportedFirstPackage).toEqual({...firstPackage, spaceId: "spaceId-1"});
})

it("Should list live packages by key for non-json response", async () => {
const livePackage = PacmanApiUtils.buildPackageExportTransport("project@release", "live-name");

mockAxiosGet("https://myTeam.celonis.cloud/package-manager/api/core/packages/export/list-live?withDependencies=false&flavors=CCM", [livePackage]);

await new T2tcCommandService(testContext).listPackages(false, ["CCM"], false, [], undefined, null, null, false, false, true);

expect(loggingTestTransport.logMessages.length).toBe(1);

Check warning on line 274 in tests/commands/t2tc/t2tc-package-list.spec.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer "expect(loggingTestTransport.logMessages).toHaveLength(1)" over this generic assertion for better reporting; it works on any object with a numeric length property.

See more on https://sonarcloud.io/project/issues?id=celonis_content-cli&issues=AaE0EJBTSU7UZ9wpah86&open=AaE0EJBTSU7UZ9wpah86&pullRequest=430
expect(loggingTestTransport.logMessages[0].message).toContain(`${livePackage.name} - Key: "${livePackage.key}"`);
})

it("Should export live packages for json response with spaceId set for studio packages", async () => {
const studioLivePackage = {...PacmanApiUtils.buildPackageExportTransport("studio@release", "studio-name"), flavor: "STUDIO"};
const ccmLivePackage = {...PacmanApiUtils.buildPackageExportTransport("ccm@live", "ccm-name"), flavor: "CCM"};
const studioNode: ContentNodeTransport = PacmanApiUtils.buildContentNodeTransport("studio@release", "spaceId-1");

mockAxiosGet("https://myTeam.celonis.cloud/package-manager/api/core/packages/export/list-live?withDependencies=false", [{...studioLivePackage}, {...ccmLivePackage}]);
mockAxiosGet("https://myTeam.celonis.cloud/package-manager/api/packages/with-variable-assignments?type=DATA_MODEL", [studioNode]);

await new T2tcCommandService(testContext).listPackages(true, [], false, [], undefined, null, null, false, false, true);

const exportedTransports = getJsonFromDownloadedFile() as PackageExportTransport[];
expect(exportedTransports).toEqual([{...studioLivePackage, spaceId: "spaceId-1"}, ccmLivePackage]);
})

it("Should list all staging packages by key for non-json response with flavors", async () => {
const firstPackage = PacmanApiUtils.buildPackageExportTransport("studio", "name-1");
const secondPackage = PacmanApiUtils.buildPackageExportTransport("ocdm", "name-2");
Expand Down
Loading