From 7a04a5a280a3946692e3c4120061bd4e57ab1d6c Mon Sep 17 00:00:00 2001 From: Kaizen Conroy <36202692+kaizencc@users.noreply.github.com> Date: Mon, 18 Sep 2023 05:32:46 -0400 Subject: [PATCH] fix(synthetics): synth-time failure for canary assets in nested stages (#27167) Fixes #27089. Canaries inside stages would fail at synth time after #26291 was introduced. This was due to a misunderstanding of `assetOutdir`. It turns out that `this.asset.assetPath` is a relative path of `Stage.of(scope).outdir`, not of `Stage.of(scope).assetOutdir`. These two out directories would be equivalent at the root level, but if there were nested stages, `assetOutdir` would equal `../${outdir}`. This diagram may help: ``` CLOUD ASSEMBLY ROOT +-- asset.12345abcdef/ +-- assembly-Stage +-- MyStack.template.json +-- MyStack.assets.json <- will contain { "path": "../asset.12345abcdef" } ``` ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../@aws-cdk/aws-synthetics-alpha/lib/code.ts | 5 +++-- .../aws-synthetics-alpha/test/code.test.ts | 20 ++++++++++++++++++- packages/aws-cdk-lib/core/lib/stage.ts | 1 - 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/aws-synthetics-alpha/lib/code.ts b/packages/@aws-cdk/aws-synthetics-alpha/lib/code.ts index c8cfb405a4b9c..1c094e90a5b76 100644 --- a/packages/@aws-cdk/aws-synthetics-alpha/lib/code.ts +++ b/packages/@aws-cdk/aws-synthetics-alpha/lib/code.ts @@ -132,8 +132,9 @@ export class AssetCode extends Code { } // Get the staged (or copied) asset path. - const assetOutDir = Stage.of(scope)?.assetOutdir; - const assetPath = assetOutDir ? path.join(assetOutDir, this.asset.assetPath): this.assetPath; + // `this.asset.assetPath` is relative to the `outdir`, not the `assetOutDir`. + const asmManifestDir = Stage.of(scope)?.outdir; + const assetPath = asmManifestDir ? path.join(asmManifestDir, this.asset.assetPath): this.assetPath; if (path.extname(assetPath) !== '.zip') { if (!fs.lstatSync(assetPath).isDirectory()) { diff --git a/packages/@aws-cdk/aws-synthetics-alpha/test/code.test.ts b/packages/@aws-cdk/aws-synthetics-alpha/test/code.test.ts index 396d245d2bd98..e98c53739f264 100644 --- a/packages/@aws-cdk/aws-synthetics-alpha/test/code.test.ts +++ b/packages/@aws-cdk/aws-synthetics-alpha/test/code.test.ts @@ -2,7 +2,7 @@ import * as fs from 'fs'; import * as path from 'path'; import { Template } from 'aws-cdk-lib/assertions'; import * as s3 from 'aws-cdk-lib/aws-s3'; -import { App, Stack, DockerImage } from 'aws-cdk-lib'; +import { App, Stage, Stack, DockerImage } from 'aws-cdk-lib'; import * as cxapi from 'aws-cdk-lib/cx-api'; import * as synthetics from '../lib'; import { RuntimeFamily } from '../lib'; @@ -123,6 +123,24 @@ describe(synthetics.Code.fromAsset, () => { expect(synthesized.assets.length).toEqual(1); }); + test('works when stack is a part of a stage', () => { + // GIVEN + const app = new App(); + const stage1 = new Stage(app, 'Stage1'); + const stage2 = new Stage(stage1, 'Stage2'); + const stack = new Stack(stage2); + + // WHEN + const directoryAsset = synthetics.Code.fromAsset(path.join(__dirname, 'canaries')); + new synthetics.Canary(stack, 'Canary1', { + test: synthetics.Test.custom({ + handler: 'canary.handler', + code: directoryAsset, + }), + runtime: synthetics.Runtime.SYNTHETICS_NODEJS_PUPPETEER_3_8, + }); + }); + test('fails if path does not exist', () => { const assetPath = path.join(__dirname, 'does-not-exist'); expect(() => synthetics.Code.fromAsset(assetPath)) diff --git a/packages/aws-cdk-lib/core/lib/stage.ts b/packages/aws-cdk-lib/core/lib/stage.ts index 80264b754cb71..40a50ec53ca27 100644 --- a/packages/aws-cdk-lib/core/lib/stage.ts +++ b/packages/aws-cdk-lib/core/lib/stage.ts @@ -197,7 +197,6 @@ export class Stage extends Construct { * will return an empty string. * * Derived from the construct path. - * */ public get artifactId() { if (!this.node.path) { return ''; }