From 8cf8b2b0ea2c432cfddc10911862d70017b14a9d Mon Sep 17 00:00:00 2001 From: Patrick Tamunjoh <38542007+patricktamunjoh@users.noreply.github.com> Date: Mon, 2 Nov 2026 12:25:48 +0100 Subject: [PATCH 1/2] fix: print only the sdk token to stdout --- docs/user-guide/sdk-commands.md | 8 +--- src/content-cli.ts | 4 +- src/core/command/module-handler.ts | 4 +- src/core/utils/logger.ts | 1 + tests/core/command/module-handler.spec.ts | 45 +++++++++++++++++++++++ tests/core/utils/logger.spec.ts | 22 +++++++++++ 6 files changed, 73 insertions(+), 11 deletions(-) create mode 100644 tests/core/utils/logger.spec.ts diff --git a/docs/user-guide/sdk-commands.md b/docs/user-guide/sdk-commands.md index 6396e50a..5d041deb 100644 --- a/docs/user-guide/sdk-commands.md +++ b/docs/user-guide/sdk-commands.md @@ -49,13 +49,7 @@ Published apps block inline scripts, and so does the Local preview by default. S Print a fresh token that only grants read access to the Celonis SDK, e.g. to authenticate against the npm registry. ``` -content-cli -q sdk token -``` - -The token is printed to the console without any other output when the `-q` option is set, so it can be used in scripts, e.g. to configure npm: - -``` -npm config set //.celonis.cloud/pro-code-app-manager/api/npm/:_authToken "$(content-cli -q sdk token)" +content-cli sdk token ``` The command requires a device code or client credentials profile. API keys can be used directly for authentication instead. diff --git a/src/content-cli.ts b/src/content-cli.ts index 5ca76fc5..65646637 100644 --- a/src/content-cli.ts +++ b/src/content-cli.ts @@ -100,8 +100,8 @@ async function run(): Promise { const globalOpts = bootstrapProgram.opts(); if (!globalOpts.quietmode) { - console.log(`Content CLI - (C) Copyright 2025 - Celonis SE - Version ${VersionUtils.getCurrentCliVersion()}`); - console.log(); + console.error(`Content CLI - (C) Copyright 2025 - Celonis SE - Version ${VersionUtils.getCurrentCliVersion()}`); + console.error(); } if (globalOpts.debug) { diff --git a/src/core/command/module-handler.ts b/src/core/command/module-handler.ts index 5bfbb655..9f5dc51b 100644 --- a/src/core/command/module-handler.ts +++ b/src/core/command/module-handler.ts @@ -257,7 +257,7 @@ export class CommandConfig { private printBetaNoticeIfBetaCommand(): void { if ((this.cmd as any).isBeta) { - logger.info(chalk.yellow("This command is in beta and may change in future releases.")); + logger.warn(chalk.yellow("This command is in beta and may change in future releases.")); } } @@ -269,7 +269,7 @@ export class CommandConfig { for (const option of this.cmd.options) { const optionName = option.attributeName(); if ((option as any).isBeta && Object.hasOwn(providedOptions, optionName)) { - logger.info(chalk.yellow(`The option '${option.long}' is in beta and may change in future releases.`)); + logger.warn(chalk.yellow(`The option '${option.long}' is in beta and may change in future releases.`)); } } } diff --git a/src/core/utils/logger.ts b/src/core/utils/logger.ts index d8a3a853..03830bd6 100644 --- a/src/core/utils/logger.ts +++ b/src/core/utils/logger.ts @@ -50,6 +50,7 @@ export const logger: Logger = winston.createLogger({ transports: [ new winston.transports.Console({ level: "info", + stderrLevels: ["error", "warn"], format: winston.format.combine( winston.format.colorize(), ), diff --git a/tests/core/command/module-handler.spec.ts b/tests/core/command/module-handler.spec.ts index 37508d5a..f7cd7a56 100644 --- a/tests/core/command/module-handler.spec.ts +++ b/tests/core/command/module-handler.spec.ts @@ -78,3 +78,48 @@ describe("CommandConfig action error handling", () => { ).toBe(false); }); }); + +describe("CommandConfig beta notices", () => { + beforeEach(() => { + loggingTestTransport.logMessages = []; + }); + + async function runBetaCommand(): Promise { + const program = new Command(); + const configurator = new Configurator(program, testContext); + + configurator.command("test-command").beta().action(async () => undefined); + + program.exitOverride(); + await program.parseAsync(["node", "content-cli", "test-command"]); + } + + async function runCommandWithBetaOption(): Promise { + const program = new Command(); + const configurator = new Configurator(program, testContext); + + configurator + .command("test-command") + .betaOption("--preview", "Beta option") + .action(async () => undefined); + + program.exitOverride(); + await program.parseAsync(["node", "content-cli", "test-command", "--preview"]); + } + + function findLogEntry(text: string) { + return loggingTestTransport.logMessages.find(entry => String(entry.message).includes(text)); + } + + it("warns that a beta command may change, so the notice goes to stderr", async () => { + await runBetaCommand(); + + expect(findLogEntry("This command is in beta")?.level).toContain("warn"); + }); + + it("warns that a provided beta option may change, so the notice goes to stderr", async () => { + await runCommandWithBetaOption(); + + expect(findLogEntry("The option '--preview' is in beta")?.level).toContain("warn"); + }); +}); diff --git a/tests/core/utils/logger.spec.ts b/tests/core/utils/logger.spec.ts new file mode 100644 index 00000000..88b2c417 --- /dev/null +++ b/tests/core/utils/logger.spec.ts @@ -0,0 +1,22 @@ +import * as winston from "winston"; +import { logger } from "../../../src/core/utils/logger"; + +describe("Logger", () => { + function findConsoleTransport(): winston.transports.ConsoleTransportInstance { + return logger.transports.find( + transport => transport instanceof winston.transports.Console + ) as winston.transports.ConsoleTransportInstance; + } + + it("writes errors and warnings to stderr, so they stay out of captured command output", () => { + const consoleTransport = findConsoleTransport() as any; + + expect(consoleTransport.stderrLevels).toEqual({ error: true, warn: true }); + }); + + it("writes info to stdout", () => { + const consoleTransport = findConsoleTransport() as any; + + expect(consoleTransport.stderrLevels.info).toBeUndefined(); + }); +}); From 5e526c9c54db36691ded1f8b7f19eaca886c36b4 Mon Sep 17 00:00:00 2001 From: Patrick Tamunjoh <38542007+patricktamunjoh@users.noreply.github.com> Date: Mon, 2 Nov 2026 12:46:35 +0100 Subject: [PATCH 2/2] fix: cover beta option notice on node 20 --- src/core/command/module-handler.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/core/command/module-handler.ts b/src/core/command/module-handler.ts index 9f5dc51b..d4ac9d98 100644 --- a/src/core/command/module-handler.ts +++ b/src/core/command/module-handler.ts @@ -266,11 +266,10 @@ export class CommandConfig { return; } const providedOptions = this.cmd.optsWithGlobals(); - for (const option of this.cmd.options) { - const optionName = option.attributeName(); - if ((option as any).isBeta && Object.hasOwn(providedOptions, optionName)) { - logger.warn(chalk.yellow(`The option '${option.long}' is in beta and may change in future releases.`)); - } - } + this.cmd.options + .filter(option => (option as any).isBeta && Object.hasOwn(providedOptions, option.attributeName())) + .forEach(option => + logger.warn(chalk.yellow(`The option '${option.long}' is in beta and may change in future releases.`)) + ); } }