Skip to content

Riff-Raff YAML generator doesn't always handle multiple instances of the same GuStack #2298

@akash1810

Description

@akash1810

cc @richpryce

In https://github.com/guardian/datasync-notifier, we're instantiating the same GuStack class twice, to create two CloudFormation stacks. They differ only by the app property.

The Riff-Raff generator fails to correctly produce a file in this scenario:

  it("should create the correct riff-raff.yaml with multiple uses of the same class", () => {
    const app = new App({ outdir: "/tmp/cdk.out" });

    interface StackWithLambdaProps extends GuStackProps {
      app: string;
    }

    class StackWithLambda extends GuStack {
      // eslint-disable-next-line custom-rules/valid-constructors -- this is a test
      constructor(app: App, id: string, props: StackWithLambdaProps) {
        super(app, id, props);
        new GuLambdaFunction(this, "test", {
          app: props.app,
          runtime: Runtime.NODEJS_20_X,
          fileName: `${props.app}.zip`,
          handler: "handler.main",
          timeout: Duration.minutes(1),
        });
      }
    }

    new StackWithLambda(app, "test-stack-SYD", {
      stack: "test",
      stage: "TEST",
      app: "my-lambda-SYD",
      env: { region: "eu-west-1" },
    });

    new StackWithLambda(app, "test-stack-NYC", {
      stack: "test",
      stage: "TEST",
      app: "my-lambda-NYC",
      env: { region: "eu-west-1" },
    });

    const actual = new RiffRaffYamlFile(app).toYAML();
    expect(actual).toMatchSnapshot();
  });

This is because of how GuStacks are grouped; as the class name is the same, the generator thinks there is only one StackWithLambda.

A work-around is to sub-class:

class StackWithLambda extends GuStack {
  // eslint-disable-next-line custom-rules/valid-constructors -- this is a test
  constructor(app: App, id: string, props: StackWithLambdaProps) {
    super(app, id, props);
    new GuLambdaFunction(this, "test", {
      app: props.app,
      runtime: Runtime.NODEJS_20_X,
      fileName: `${props.app}.zip`,
      handler: "handler.main",
      timeout: Duration.minutes(1),
    });
  }
}

class StackOne extends StackWithLambda {}
class StackTwo extends StackWithLambda {}

Should there be better first-class support for this?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions