Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
11 changes: 7 additions & 4 deletions docs/user-guide/config-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,17 +204,20 @@ The `--layers` option selects which validation layers to run. Multiple layers ca
| `SCHEMA` | Asset-schema conformance of each node's `configuration` field — required properties, enum values, type checks, conditional schemas. | Asset registry |
| `BUSINESS` | Asset-type-specific business rules — for `SEMANTIC_MODEL`, e.g. PQL parsing, data-model availability, KPI uniqueness. Rules live in the owning asset service. | Owning asset service (e.g. `cloud-semantic-layer` for Knowledge Models) |
| `PACKAGE_SETTINGS` | Package-level configuration rules — package dependencies, package variable definitions, variable assignments such as Studio data models, and flavor-specific package settings for Studio/OCDM packages. | Pacman plus flavor-specific services |
| `PLATFORM_SERVICE` | Platform-service-owned validation — each participating platform service checks the assets it owns against its live service (for example Semantic Layer "list-problems" checks), surfacing platform-level problems that only the running service can detect. Which services take part, and how their findings map to severities, is declared by platform-service descriptors. | Owning platform services (e.g. `cloud-semantic-layer`), coordinated by Pacman |

Currently `SCHEMA`, `BUSINESS`, and `PACKAGE_SETTINGS` are the layers accepted by the Pacman API. Other values are rejected with a `400 layers.unsupported` error.
`SCHEMA`, `BUSINESS`, and `PACKAGE_SETTINGS` are accepted by the Pacman API today. `PLATFORM_SERVICE` is the newest layer and is only accepted once platform-service validation is enabled on the validate endpoint. Any value the endpoint does not (yet) support is rejected with a `400 layers.unsupported` error.
Comment thread
ZgjimHaziri marked this conversation as resolved.
Outdated

To run all layers:

```bash
content-cli config package validate --packageKey <packageKey> --layers SCHEMA BUSINESS PACKAGE_SETTINGS
content-cli config package validate --packageKey <packageKey> --layers SCHEMA BUSINESS PACKAGE_SETTINGS PLATFORM_SERVICE
```

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.

Use `PLATFORM_SERVICE` to additionally validate the package against the live platform services that own its assets — for example Semantic Layer problem checks for Knowledge Models. The set of services that take part, and how their findings map to severities, is declared by platform-service descriptors, so new services can join the layer without CLI changes. Because it runs against the owning services, `PLATFORM_SERVICE` is only accepted once platform-service validation is enabled on the validate endpoint; until then the request is rejected with `400 layers.unsupported`.

### Validate Specific Nodes

By default, every node in the package's staging version is validated. To restrict the scope to a subset of nodes, use `--nodeKeys`:
Expand All @@ -228,7 +231,7 @@ content-cli config package validate --packageKey <packageKey> --nodeKeys node-ke
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 package validate --packageKey <packageKey> --layers SCHEMA BUSINESS PACKAGE_SETTINGS --json
content-cli config package validate --packageKey <packageKey> --layers SCHEMA BUSINESS PACKAGE_SETTINGS PLATFORM_SERVICE --json
```

The filename is printed on success:
Expand All @@ -248,7 +251,7 @@ interface ValidationReport {
}

interface ValidationResult {
layer: "SCHEMA" | "BUSINESS" | "PACKAGE_SETTINGS";
layer: "SCHEMA" | "BUSINESS" | "PACKAGE_SETTINGS" | "PLATFORM_SERVICE";
severity: "ERROR" | "WARNING" | "INFO";
nodeKey: string;
assetType: string;
Expand Down
4 changes: 2 additions & 2 deletions src/commands/configuration-management/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class Module extends IModule {
.requiredOption("--packageKey <packageKey>", "Key of the package to validate")
.option(
"--layers <layers...>",
"Validation layers to run. Allowed values: SCHEMA, BUSINESS, PACKAGE_SETTINGS (can be combined, e.g. --layers SCHEMA BUSINESS PACKAGE_SETTINGS). Defaults to SCHEMA.",
"Validation layers to run. Allowed values: SCHEMA, BUSINESS, PACKAGE_SETTINGS, PLATFORM_SERVICE (can be combined, e.g. --layers SCHEMA BUSINESS PACKAGE_SETTINGS PLATFORM_SERVICE). Defaults to SCHEMA.",
["SCHEMA"]
)
.option("--nodeKeys <nodeKeys...>", "Specific node keys to validate (default: all nodes)")
Expand All @@ -103,7 +103,7 @@ class Module extends IModule {
.requiredOption("--packageKey <packageKey>", "Key of the package to validate")
.option(
"--layers <layers...>",
"Validation layers to run. Allowed values: SCHEMA, BUSINESS, PACKAGE_SETTINGS (can be combined, e.g. --layers SCHEMA BUSINESS PACKAGE_SETTINGS). Defaults to SCHEMA.",
"Validation layers to run. Allowed values: SCHEMA, BUSINESS, PACKAGE_SETTINGS, PLATFORM_SERVICE (can be combined, e.g. --layers SCHEMA BUSINESS PACKAGE_SETTINGS PLATFORM_SERVICE). Defaults to SCHEMA.",
["SCHEMA"]
)
.option("--nodeKeys <nodeKeys...>", "Specific node keys to validate (default: all nodes)")
Expand Down
76 changes: 76 additions & 0 deletions tests/commands/configuration-management/config-validate.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,80 @@ describe("Config validate", () => {
expect(allMessages).toContain("Validation result: VALID");
expect(allMessages).toContain("Errors: 0");
})

it("Should send PLATFORM_SERVICE layer in request body when combined with other layers", async () => {
const response: SchemaValidationResponse = {
packageKey: "my-package",
valid: true,
summary: { errors: 0, warnings: 0, info: 0 },
results: []
};

mockAxiosPost(VALIDATE_URL, response);

await new PackageValidationService(testContext).validatePackage(
"my-package",
["SCHEMA", "BUSINESS", "PACKAGE_SETTINGS", "PLATFORM_SERVICE"],
null,
false
);

expect(mockedPostRequestBodyByUrl.get(VALIDATE_URL)).toEqual(
JSON.stringify({ layers: ["SCHEMA", "BUSINESS", "PACKAGE_SETTINGS", "PLATFORM_SERVICE"] })
);
})

it("Should render PLATFORM_SERVICE findings in human-readable output", async () => {
const response: SchemaValidationResponse = {
packageKey: "my-package",
valid: false,
summary: { errors: 0, warnings: 1, info: 0 },
results: [{
layer: "PLATFORM_SERVICE",
severity: "WARNING",
nodeKey: "my-knowledge-model",
assetType: "SEMANTIC_MODEL",
path: "$.dataModel",
code: "DATA_MODEL_NOT_FOUND",
message: "Referenced data model is not available in the target team"
}]
};

mockAxiosPost(VALIDATE_URL, response);

await new PackageValidationService(testContext).validatePackage("my-package", ["PLATFORM_SERVICE"], null, false);

const allMessages = loggingTestTransport.logMessages.map(m => m.message).join("\n");
expect(allMessages).toContain("Validation result: INVALID");
expect(allMessages).toContain("Warnings: 1");
expect(allMessages).toContain("my-knowledge-model (SEMANTIC_MODEL)");
expect(allMessages).toContain("DATA_MODEL_NOT_FOUND");
})

it("Should write PLATFORM_SERVICE findings to the JSON report when json flag is set", async () => {
const response: SchemaValidationResponse = {
packageKey: "my-package",
valid: false,
summary: { errors: 1, warnings: 0, info: 0 },
results: [{
layer: "PLATFORM_SERVICE",
severity: "ERROR",
nodeKey: "my-knowledge-model",
assetType: "SEMANTIC_MODEL",
path: "$.dataModel",
code: "DATA_MODEL_NOT_FOUND",
message: "Referenced data model is not available in the target team"
}]
};

mockAxiosPost(VALIDATE_URL, response);

await new PackageValidationService(testContext).validatePackage("my-package", ["PLATFORM_SERVICE"], null, true);

expect(mockWriteFileSync).toHaveBeenCalledWith(
expect.stringMatching(/config_validate_report_.+\.json$/),
JSON.stringify(response),
{ encoding: "utf-8", mode: 0o600 }
);
})
})
Loading