diff --git a/packages/aws-cdk-lib/core/lib/aspect.ts b/packages/aws-cdk-lib/core/lib/aspect.ts index 3ee6e97958a93..e8353264085ef 100644 --- a/packages/aws-cdk-lib/core/lib/aspect.ts +++ b/packages/aws-cdk-lib/core/lib/aspect.ts @@ -82,7 +82,11 @@ export class Aspects { * @param options Options to apply on this aspect. */ public add(aspect: IAspect, options?: AspectOptions) { - this._appliedAspects.push(new AspectApplication(this._scope, aspect, options?.priority ?? AspectPriority.DEFAULT)); + const newApplication = new AspectApplication(this._scope, aspect, options?.priority ?? AspectPriority.DEFAULT); + if (this._appliedAspects.some(a => a.aspect === newApplication.aspect && a.priority === newApplication.priority)) { + return; + } + this._appliedAspects.push(newApplication); } /** diff --git a/packages/aws-cdk-lib/core/test/aspect.test.ts b/packages/aws-cdk-lib/core/test/aspect.test.ts index 865f17b031dc0..9718fd5aa5163 100644 --- a/packages/aws-cdk-lib/core/test/aspect.test.ts +++ b/packages/aws-cdk-lib/core/test/aspect.test.ts @@ -74,6 +74,20 @@ describe('aspect', () => { expect(root.visitCounter).toEqual(1); }); + test('Adding the same aspect twice to the same construct only adds 1', () => { + // GIVEN + const app = new App(); + const root = new MyConstruct(app, 'MyConstruct'); + + // WHEN + const asp = new VisitOnce(); + Aspects.of(root).add(asp); + Aspects.of(root).add(asp); + + // THEN + expect(Aspects.of(root).all.length).toEqual(1); + }); + test('if stabilization is disabled, warn if an Aspect is added via another Aspect', () => { const app = new App({ context: { '@aws-cdk/core:aspectStabilization': false } }); const root = new MyConstruct(app, 'MyConstruct'); @@ -91,7 +105,7 @@ describe('aspect', () => { expect(root.node.metadata[0].type).toEqual(cxschema.ArtifactMetadataEntryType.WARN); expect(root.node.metadata[0].data).toEqual('We detected an Aspect was added via another Aspect, and will not be applied [ack: @aws-cdk/core:ignoredAspect]'); // warning is not added to child construct - expect(child.node.metadata.length).toEqual(0); + expect(child.node.metadata).toEqual([]); }); test('Do not warn if an Aspect is added directly (not by another aspect)', () => {