From 1daed1f13e8463f5b5c5b31b51f9257101f1561c Mon Sep 17 00:00:00 2001 From: akash1810 Date: Fri, 6 Feb 2026 21:21:44 +0000 Subject: [PATCH] feat(riff-raff.yaml): Better support repositories deploying multiple Riff-Raff projects Support customised output directory for `riff-raff.yaml` file to support repositories that deploy multiple Riff-Raff projects. --- .changeset/clean-planes-scream.md | 35 +++++++++++++++++++++++++++++++ src/riff-raff-yaml-file/README.md | 32 ++++++++++++++++++++++++++++ src/riff-raff-yaml-file/index.ts | 23 ++++++++++++++++---- 3 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 .changeset/clean-planes-scream.md diff --git a/.changeset/clean-planes-scream.md b/.changeset/clean-planes-scream.md new file mode 100644 index 0000000000..8827b5648a --- /dev/null +++ b/.changeset/clean-planes-scream.md @@ -0,0 +1,35 @@ +--- +"@guardian/cdk": minor +--- + +Support customised output directory for `riff-raff.yaml` file to support repositories that deploy multiple Riff-Raff projects. + +Example usage: + +```ts +import { RiffRaffYamlFile } from "./index"; + +const appForInfra = new App(); + +const myInfraStack = new MyInfraStack(appForInfra, "my-infra-stack", { + stack: "playground", + stage: "INFRA", + env: { region: "eu-west-1" }, +}); + +const appForMyApp = new App(); + +const myAppStackCODE = new MyAppStack(appForMyApp, "my-stack-CODE", { + stack: "playground", + stage: "CODE", + env: { region: "eu-west-1" }, +}); +const myAppStackPROD = new MyAppStack(appForMyApp, "my-stack-PROD", { + stack: "playground", + stage: "CODE", + env: { region: "eu-west-1" }, +}); + +new RiffRaffYamlFile(appForInfra, "playground::core-infra"); // Generates a file to `cdk.out/playground::core-infra/riff-raff.yaml` +new RiffRaffYamlFile(appForMyApp, "playground::my-app"); // Generates a file to `cdk.out/playground::my-app/riff-raff.yaml` +``` diff --git a/src/riff-raff-yaml-file/README.md b/src/riff-raff-yaml-file/README.md index 4c8ab9da2e..143dfc3d40 100644 --- a/src/riff-raff-yaml-file/README.md +++ b/src/riff-raff-yaml-file/README.md @@ -38,6 +38,7 @@ new MyStack(app, "my-stack-PROD", {}); ``` ### Advanced usage +#### Additional deployment types As noted above, only specific deployment types are currently supported. If you want to add additional deployment types, you can do so by instantiating `RiffRaffYamlFile` directly: @@ -79,6 +80,37 @@ riffRaff.synth(); When the CDK stack is synthesized, a `riff-raff.yaml` file will be created in the output directory, typically `//cdk/cdk.out`. +#### Multiple Riff-Raff projects in a single repository +If your repository deploys multiple Riff-Raff projects, multiple `riff-raff.yaml` files can be created thus: + +```ts +import { RiffRaffYamlFile } from "./index"; + +const appForInfra = new App(); + +const myInfraStack = new MyInfraStack(appForInfra, "my-infra-stack", { + stack: "playground", + stage: "INFRA", + env: { region: "eu-west-1" }, +}); + +const appForMyApp = new App(); + +const myAppStackCODE = new MyAppStack(appForMyApp, "my-stack-CODE", { + stack: "playground", + stage: "CODE", + env: { region: "eu-west-1" }, +}); +const myAppStackPROD = new MyAppStack(appForMyApp, "my-stack-PROD", { + stack: "playground", + stage: "CODE", + env: { region: "eu-west-1" }, +}); + +new RiffRaffYamlFile(appForInfra, "playground::core-infra"); // Generates a file to `cdk.out/playground::core-infra/riff-raff.yaml` +new RiffRaffYamlFile(appForMyApp, "playground::my-app"); // Generates a file to `cdk.out/playground::my-app/riff-raff.yaml` +``` + ## Package layout `RiffRaffYamlFile` assumes CI has uploaded files in the following structure: diff --git a/src/riff-raff-yaml-file/index.ts b/src/riff-raff-yaml-file/index.ts index 80ec355158..c9110c3f24 100644 --- a/src/riff-raff-yaml-file/index.ts +++ b/src/riff-raff-yaml-file/index.ts @@ -1,4 +1,4 @@ -import { writeFileSync } from "fs"; +import { existsSync, mkdirSync, writeFileSync } from "fs"; import path from "path"; import type { App } from "aws-cdk-lib"; import { Token } from "aws-cdk-lib"; @@ -76,6 +76,7 @@ export class RiffRaffYamlFile { private readonly allStageTags: StageTag[]; private readonly allRegions: Region[]; private readonly outdir: string; + private readonly riffRaffProjectName?: string; /** * The `riff-raff.yaml` file as an object. @@ -206,8 +207,13 @@ export class RiffRaffYamlFile { return cdkStack.dependencies.filter((_) => _ instanceof GuStack) as GuStack[]; } + /** + * Creates a `riff-raff.yaml` file. + * @param app - the root node of the CDK construct tree. Every GuStack within will be added to `riff-raff.yaml`. + * @param riffRaffProjectName - the name of the Riff-Raff project the stacks belong to. The `riff-raff.yaml` file will be generated to this directory _within_ `cdk.out`. + */ // eslint-disable-next-line custom-rules/valid-constructors -- this needs to sit above GuStack on the cdk tree - constructor(app: App) { + constructor(app: App, riffRaffProjectName?: string) { this.allCdkStacks = app.node.findAll().filter((_) => _ instanceof GuStack) as GuStack[]; const allowedStages = new Set(this.allCdkStacks.map(({ stage }) => stage)); this.allStageTags = Array.from(allowedStages); @@ -218,6 +224,7 @@ export class RiffRaffYamlFile { this.validateAllRegionsAreResolved(); this.outdir = app.outdir; + this.riffRaffProjectName = riffRaffProjectName; const deployments = new Map(); @@ -329,7 +336,15 @@ export class RiffRaffYamlFile { * It'll be located with the CFN JSON templates generated by `cdk synth`. */ synth(): void { - const outPath = path.join(this.outdir, "riff-raff.yaml"); - writeFileSync(outPath, this.toYAML()); + const outputDirectory = path.join(this.outdir, this.riffRaffProjectName ?? ""); + const outputFile = path.join(outputDirectory, "riff-raff.yaml"); + + if (!existsSync(outputDirectory)) { + console.log(`Output directory ${outputDirectory} does not exist; creating it...`); + mkdirSync(outputDirectory); + } + + writeFileSync(outputFile, this.toYAML()); + console.log(`Successfully created ${outputFile}`); } }