diff --git a/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/environment.ts b/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/environment.ts index 7f8129090..40daa9aab 100644 --- a/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/environment.ts +++ b/packages/@aws-cdk/toolkit-lib/lib/api/cloud-assembly/environment.ts @@ -84,12 +84,25 @@ export function synthParametersFromSettings(settings: Settings): { context: Context; env: Env; } { + // These are the environment variables that will switch on debugging in the + // CDK framework. + // + // - CDK_DEBUG: an environment variable instead of a context variable, so it can also + // be accessed in framework code where we don't have access to a construct tree. + // - JSII_HOST_STACK_TRACES: have the jsii client library send call stacks + // across so we can read them in JS-land. Only set if not already set by the + // user, this allows them to switch it off by setting `JSII_HOST_STACK_TRACES=0`. + const debugEnvVars: Record = { + CDK_DEBUG: 'true', + }; + if (process.env.JSII_HOST_STACK_TRACES === undefined) { + debugEnvVars.JSII_HOST_STACK_TRACES = '1'; + } + return { context: contextFromSettings(settings), env: { - // An environment variable instead of a context variable, so it can also - // be accessed in framework code where we don't have access to a construct tree. - ...settings.get(['debugApp']) ? { CDK_DEBUG: 'true' } : {}, + ...settings.get(['debugApp']) ? debugEnvVars : {}, }, }; } diff --git a/packages/@aws-cdk/toolkit-lib/test/api/cloud-assembly/environment.test.ts b/packages/@aws-cdk/toolkit-lib/test/api/cloud-assembly/environment.test.ts index 1a921231d..3e27e50c9 100644 --- a/packages/@aws-cdk/toolkit-lib/test/api/cloud-assembly/environment.test.ts +++ b/packages/@aws-cdk/toolkit-lib/test/api/cloud-assembly/environment.test.ts @@ -30,7 +30,7 @@ test.each([ ])('cmd=%p win=%p (stat=%p) exe=%p node=%p => %p', async (commandLine: string, isWindows: boolean, statFile: string, isExecutable: boolean | undefined, nodePath: string, expected: string) => { // GIVEN process.execPath = nodePath; - Object.defineProperty(process, 'platform', { value: isWindows ? 'win32' : 'linux' }) ; + Object.defineProperty(process, 'platform', { value: isWindows ? 'win32' : 'linux' }); jest.spyOn(fs, 'stat').mockImplementation((p) => { if (p !== statFile) { throw new Error(`Expected a stat() call on '${statFile}' but got '${p}'`); @@ -98,4 +98,17 @@ describe('synthParametersFromSettings sets CDK_DEBUG from debugApp', () => { const { env } = synthParametersFromSettings(new Settings({})); expect(env.CDK_DEBUG).toBeUndefined(); }); + + test('debugApp: true sets JSII_HOST_STACK_TRACES', () => { + delete process.env.JSII_HOST_STACK_TRACES; + const { env } = synthParametersFromSettings(new Settings({ debugApp: true })); + expect(env.JSII_HOST_STACK_TRACES).toBe('1'); + }); + + test('debugApp: true does set JSII_HOST_STACK_TRACES if already set', () => { + process.env.JSII_HOST_STACK_TRACES = '0'; + const { env } = synthParametersFromSettings(new Settings({ debugApp: true })); + expect(Object.keys(env)).not.toContain('JSII_HOST_STACK_TRACES'); + delete process.env.JSII_HOST_STACK_TRACES; + }); });