From a0b2d816bd63a65364c6ffd708f70fa7f3220d60 Mon Sep 17 00:00:00 2001 From: harshitha-cstk Date: Mon, 27 Jul 2026 19:21:31 +0530 Subject: [PATCH] DX-9992 | Always show errors and warnings on console in progress-manager mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Progress-supported modules (e.g. bulk-operations) omitted the console transport entirely when console logs were disabled, so errors and warnings — like an invalid stack API key or a taxonomy error — were written to file but silently swallowed on screen. Attach the console transport for error and warn levels regardless of showConsoleLogs, while keeping info/success/debug hidden so the progress bars stay clean. Co-Authored-By: Claude Opus 4.8 --- .../src/logger/logger.ts | 7 +- .../test/unit/logger.test.ts | 64 +++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/packages/contentstack-utilities/src/logger/logger.ts b/packages/contentstack-utilities/src/logger/logger.ts index 6c5575b0d0..02d14640c7 100644 --- a/packages/contentstack-utilities/src/logger/logger.ts +++ b/packages/contentstack-utilities/src/logger/logger.ts @@ -85,7 +85,12 @@ export default class Logger { } } - if (showConsoleLogs) { + // Errors and warnings must always reach the console, even when progress bars + // suppress info/success/debug output — otherwise failures (e.g. an invalid + // stack API key or a taxonomy error) are silently swallowed in progress mode. + const isErrorOrWarn = level === 'error' || level === 'warn'; + + if (showConsoleLogs || isErrorOrWarn) { transports.push( new winston.transports.Console({ format: winston.format.combine( diff --git a/packages/contentstack-utilities/test/unit/logger.test.ts b/packages/contentstack-utilities/test/unit/logger.test.ts index a840e46a3e..0bd8f3992b 100644 --- a/packages/contentstack-utilities/test/unit/logger.test.ts +++ b/packages/contentstack-utilities/test/unit/logger.test.ts @@ -233,6 +233,70 @@ describe('Logger', () => { }); }); +describe('Console output in progress-manager mode', () => { + const tempDir = path.join(os.tmpdir(), `csdx-progress-log-${Date.now()}`); + + function hasConsoleTransport(winLogger: any): boolean { + return winLogger.transports.some((t: any) => t.constructor && t.constructor.name === 'Console'); + } + + fancy + .stub(configHandler, 'get', (...args: any[]) => { + const key = args[0]; + if (key === 'log') return { progressSupportedModule: 'bulk-operations', showConsoleLogs: false }; + if (key === 'log.path') return tempDir; + if (key === 'currentCommandId') return 'bulk-operations'; + if (key === 'sessionId') return 'test-session'; + return undefined; + }) + .it('keeps console output for errors when progress bars suppress info logs', () => { + const progressLogger = new Logger({ basePath: tempDir, consoleLogLevel: 'info', logLevel: 'info' }); + expect(hasConsoleTransport(progressLogger['loggers'].error)).to.equal(true); + }); + + fancy + .stub(configHandler, 'get', (...args: any[]) => { + const key = args[0]; + if (key === 'log') return { progressSupportedModule: 'bulk-operations', showConsoleLogs: false }; + if (key === 'log.path') return tempDir; + if (key === 'currentCommandId') return 'bulk-operations'; + if (key === 'sessionId') return 'test-session'; + return undefined; + }) + .it('keeps console output for warnings when progress bars suppress info logs', () => { + const progressLogger = new Logger({ basePath: tempDir, consoleLogLevel: 'info', logLevel: 'info' }); + expect(hasConsoleTransport(progressLogger['loggers'].warn)).to.equal(true); + }); + + fancy + .stub(configHandler, 'get', (...args: any[]) => { + const key = args[0]; + if (key === 'log') return { progressSupportedModule: 'bulk-operations', showConsoleLogs: false }; + if (key === 'log.path') return tempDir; + if (key === 'currentCommandId') return 'bulk-operations'; + if (key === 'sessionId') return 'test-session'; + return undefined; + }) + .it('suppresses console output for info logs so progress bars stay clean', () => { + const progressLogger = new Logger({ basePath: tempDir, consoleLogLevel: 'info', logLevel: 'info' }); + expect(hasConsoleTransport(progressLogger['loggers'].info)).to.equal(false); + }); + + fancy + .stub(configHandler, 'get', (...args: any[]) => { + const key = args[0]; + if (key === 'log') return { progressSupportedModule: 'bulk-operations', showConsoleLogs: true }; + if (key === 'log.path') return tempDir; + if (key === 'currentCommandId') return 'bulk-operations'; + if (key === 'sessionId') return 'test-session'; + return undefined; + }) + .it('shows console output for info logs when console logging is enabled', () => { + const progressLogger = new Logger({ basePath: tempDir, consoleLogLevel: 'info', logLevel: 'info' }); + expect(hasConsoleTransport(progressLogger['loggers'].info)).to.equal(true); + }); +}); + describe('Session Log Path', () => { let sandbox: sinon.SinonSandbox; let tempDir: string;