@guardian/cdk 63.2.1 → 63.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/riff-raff-yaml-file/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAuBvC,OAAO,KAAK,EAMV,mBAAmB,EACnB,YAAY,EAGb,MAAM,SAAS,CAAC;AA+BjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC;;;;;;;OAOG;IACH,SAAgB,aAAa,EAAE,GAAG,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC;gBAG1D,GAAG,EAAE,GAAG;IA6IpB;;;;;OAKG;IACH,MAAM,CAAC,mBAAmB,GAAE,mBAAgD,GAAG,MAAM;IAuBrF;;OAEG;IACH,KAAK,IAAI,IAAI;CAed;AAED,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,MAAM,EAAE,mBAAmB,EAAE,mBAAmB,GAAG,MAAM,CAahH"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/riff-raff-yaml-file/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAuBvC,OAAO,KAAK,EAMV,mBAAmB,EACnB,YAAY,EAGb,MAAM,SAAS,CAAC;AA+BjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC;;;;;;;OAOG;IACH,SAAgB,aAAa,EAAE,GAAG,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC;gBAG1D,GAAG,EAAE,GAAG;IA6IpB;;;;;OAKG;IACH,MAAM,CAAC,mBAAmB,GAAE,mBAAgD,GAAG,MAAM;IAgCrF;;OAEG;IACH,KAAK,IAAI,IAAI;CAed;AAED,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,MAAM,EAAE,mBAAmB,EAAE,mBAAmB,GAAG,MAAM,CAahH"}
@@ -204,7 +204,14 @@ class RiffRaffYamlFile {
204
204
  if (!content) {
205
205
  throw new Error(`No Riff-Raff project found with name: ${riffRaffProjectName}`);
206
206
  }
207
- return (0, js_yaml_1.dump)(content, { replacer });
207
+ const yaml = (0, js_yaml_1.dump)(content, { replacer });
208
+ const comments = [
209
+ "This file was generated by @guardian/cdk, do not edit it directly.",
210
+ "See also https://github.com/guardian/cdk/blob/main/src/riff-raff-yaml-file/README.md.",
211
+ ]
212
+ .map((line) => `# ${line}`)
213
+ .join("\n");
214
+ return [comments, yaml].join("\n");
208
215
  }
209
216
  /**
210
217
  * Write the `riff-raff.yaml` file(s) to disk, located in the same directory as the CFN JSON templates generated by `cdk synth`.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/riff-raff-yaml-file/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from \"fs\";\nimport path from \"path\";\nimport type { App } from \"aws-cdk-lib\";\nimport { Token } from \"aws-cdk-lib\";\nimport type { CfnAutoScalingGroup } from \"aws-cdk-lib/aws-autoscaling\";\nimport { dump } from \"js-yaml\";\nimport { GuAutoScalingGroup } from \"../constructs/autoscaling\";\nimport { GuStack } from \"../constructs/core\";\nimport { GuLambdaFunction } from \"../constructs/lambda\";\nimport { GuAsgMinInstancesInServiceParameterExperimental } from \"../experimental/patterns/ec2-app\";\nimport { autoscalingDeployment, uploadAutoscalingArtifact } from \"./deployments/autoscaling\";\nimport {\n cloudFormationDeployment,\n getAmiParameters,\n getMinInstancesInServiceParameters,\n} from \"./deployments/cloudformation\";\nimport { updateLambdaDeployment, uploadLambdaArtifact } from \"./deployments/lambda\";\nimport { updateDeploymentParameters } from \"./deployments/update-parameters\";\nimport {\n groupByClassName,\n groupByRegion,\n groupByRiffRaffProjectName,\n groupByStackTag,\n groupByStageTag,\n} from \"./group-by\";\nimport type {\n ClassName,\n Region,\n RiffRaffDeployment,\n RiffRaffDeploymentName,\n RiffRaffDeploymentProps,\n RiffRaffProjectName,\n RiffRaffYaml,\n StackTag,\n StageTag,\n} from \"./types\";\nimport { UnknownRiffRaffProjectName } from \"./types\";\n\nfunction validateAllRegionsAreResolved(regions: Region[]): void {\n const unresolved = regions.filter((region) => Token.isUnresolved(region));\n\n if (unresolved.length !== 0) {\n throw new Error(`Unable to produce a working riff-raff.yaml file; all stacks must have an explicit region set`);\n }\n}\n\nfunction getLambdas(cdkStack: GuStack): GuLambdaFunction[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuLambdaFunction) as GuLambdaFunction[];\n}\n\nfunction getAutoScalingGroups(cdkStack: GuStack): GuAutoScalingGroup[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuAutoScalingGroup) as GuAutoScalingGroup[];\n}\n\nfunction getGuStackDependencies(cdkStack: GuStack): GuStack[] {\n return cdkStack.dependencies.filter((_) => _ instanceof GuStack) as GuStack[];\n}\n\ninterface MissingStack {\n riffRaffProjectName: RiffRaffProjectName;\n className: ClassName;\n stack: StackTag;\n stage: StageTag;\n region: Region;\n}\n\n/**\n * A class that creates a `riff-raff.yaml` file.\n *\n * Rather than using this directly, prefer to use [[`GuRoot`]] instead.\n *\n * Supports:\n * - Multiple CloudFormation stacks\n * - Multiple regions\n * - Lambda applications\n * - EC2 (autoscaling) applications\n *\n * For lambda applications, 3 deployments will be defined:\n * 1. Lambda upload (`aws-lambda`, `action: [uploadLambda]`)\n * 2. CloudFormation deploy (`cloud-formation`)\n * 3. Lambda update (`aws-lambda`, `action: [updateLambda]`)\n *\n * For EC2 applications, 3 deployments will be defined:\n * 1. Artifact upload (`autoscaling`, `action: [uploadArtifacts]`)\n * 2. CloudFormation deploy (`cloud-formation`)\n * 3. Autoscaling deploy (`autoscaling`, `action: [deploy]`)\n *\n * It assumes a Riff-Raff bundle structure as follows:\n *\n * ```\n * .\n * ├── cdk.out\n * │ └── MyApplication.template.json\n * ├── my-application\n * │ └── my-application.deb\n * └── my-lambda\n * └── my-lambda.zip\n * ```\n *\n * That is, all CloudFormation templates are in a `cdk.out` directory, and there is a directory per app.\n * Application artifact(s) are in the app directory.\n *\n * NOTE: The file extension is decided by you, the above file tree is used for illustration purposes.\n *\n * NOTE: Resources will be looked up by tags (Stack, Stage, App). Ensure your CFN stack is tagged appropriately!\n *\n * @see https://riffraff.gutools.co.uk/docs/reference/riff-raff.yaml.md\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types\n */\nexport class RiffRaffYamlFile {\n private readonly outdir: string;\n\n /**\n * A mapping between a Riff-Raff project and `riff-raff.yaml` content as an object.\n *\n * It is useful for specifying additional deployment types that GuCDK does not support.\n * Consider raising an issue or pull request if you think it should be supported.\n *\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types\n */\n public readonly configuration: Map<RiffRaffProjectName, RiffRaffYaml>;\n\n // eslint-disable-next-line custom-rules/valid-constructors -- this needs to sit above GuStack on the cdk tree\n constructor(app: App) {\n const allCdkStacks = app.node.findAll().filter((_) => _ instanceof GuStack) as GuStack[];\n const allRegions = Array.from(new Set(allCdkStacks.map((_) => _.region)));\n\n validateAllRegionsAreResolved(allRegions);\n\n this.outdir = app.outdir;\n const configuration = new Map<RiffRaffProjectName, RiffRaffYaml>();\n const missingStacks: MissingStack[] = [];\n\n Object.entries(groupByRiffRaffProjectName(allCdkStacks)).forEach(\n ([riffRaffProjectName, stacksGroupedByRiffRaffProject]) => {\n const allowedStages = new Set(stacksGroupedByRiffRaffProject.map((_) => _.stage));\n const requiredStages = Array.from(allowedStages);\n const deployments = new Map<RiffRaffDeploymentName, RiffRaffDeploymentProps>();\n\n Object.entries(groupByClassName(stacksGroupedByRiffRaffProject)).forEach(\n ([className, stacksGroupedByClassName]) => {\n Object.entries(groupByStackTag(stacksGroupedByClassName)).forEach(([stackTag, stacksGroupedByStackTag]) => {\n Object.entries(groupByRegion(stacksGroupedByStackTag)).forEach(([region, stacksGroupedByRegion]) => {\n const stacks: GuStack[] = Object.values(groupByStageTag(stacksGroupedByRegion)).flat();\n\n requiredStages.forEach((requiredStage) => {\n if (!stacks.find(({ stage }) => stage === requiredStage)) {\n missingStacks.push({\n riffRaffProjectName,\n className,\n region,\n stack: stackTag,\n stage: requiredStage,\n });\n }\n });\n\n // The items in `stacks` only differ by stage, so we can just use the first item in the list.\n const [stack] = stacks;\n\n if (!stack) {\n throw new Error(\"Unable to produce a working riff-raff.yaml file; there are no stacks!\");\n }\n\n const lambdas = getLambdas(stack);\n const autoscalingGroups = getAutoScalingGroups(stack);\n\n const artifactUploads: RiffRaffDeployment[] = [\n lambdas.filter((_) => !_.withoutArtifactUpload).map(uploadLambdaArtifact),\n autoscalingGroups.map(uploadAutoscalingArtifact),\n ].flat();\n artifactUploads.forEach(({ name, props }) => deployments.set(name, props));\n\n const parentStacks: RiffRaffDeployment[] = getGuStackDependencies(stack).map((x) =>\n cloudFormationDeployment([x], [], this.outdir),\n );\n\n const cfnDeployment = cloudFormationDeployment(\n stacks,\n [...artifactUploads, ...parentStacks],\n this.outdir,\n );\n deployments.set(cfnDeployment.name, cfnDeployment.props);\n\n const lambdasWithoutAnAlias = lambdas.filter((lambda) => lambda.alias === undefined);\n // If the Lambda has an alias it is using versioning. When using versioning, there is no need for Riff-Raff\n // to modify the unpublished version of the function\n lambdasWithoutAnAlias.forEach((lambda) => {\n const lambdaDeployment = updateLambdaDeployment(lambda, cfnDeployment);\n deployments.set(lambdaDeployment.name, lambdaDeployment.props);\n });\n\n /*\n Instances in an ASG with an `AutoScalingRollingUpdate` update policy are rotated via CloudFormation.\n Therefore, they do not need to also perform an `autoscaling` deployment via Riff-Raff.\n */\n const legacyAutoscalingGroups = autoscalingGroups.filter((asg) => {\n const { cfnOptions } = asg.node.defaultChild as CfnAutoScalingGroup;\n const { updatePolicy } = cfnOptions;\n return updatePolicy?.autoScalingRollingUpdate === undefined;\n });\n\n legacyAutoscalingGroups.forEach((asg) => {\n const asgDeployment = autoscalingDeployment(asg, cfnDeployment);\n deployments.set(asgDeployment.name, asgDeployment.props);\n });\n\n // only add the `amiParametersToTags` property if there are some ASGs in the stack\n if (autoscalingGroups.length > 0) {\n updateDeploymentParameters(deployments, cfnDeployment, {\n amiParametersToTags: getAmiParameters(autoscalingGroups),\n });\n }\n\n /*\n At this point, `stacks` is a collection of similar `GuStack`s that differ only by their `stage`.\n We're about to add `minInstancesInServiceParameters` to assist Riff-Raff when deploying ASGs with scaling policies.\n This is driven by the presence of conditionally added CFN Parameters.\n To support the possibility of there being a scaling policy in PROD but not CODE, look at all the CFN Parameters in `stacks`.\n */\n const minInstancesInServiceParameters: Map<string, GuAsgMinInstancesInServiceParameterExperimental> =\n stacks\n .flatMap((stack) => Object.values(stack.parameters))\n .filter(\n (_): _ is GuAsgMinInstancesInServiceParameterExperimental =>\n _ instanceof GuAsgMinInstancesInServiceParameterExperimental,\n )\n .reduce((acc, item) => {\n if (!acc.has(item.node.id)) {\n acc.set(item.node.id, item);\n }\n return acc;\n }, new Map<string, GuAsgMinInstancesInServiceParameterExperimental>());\n\n /**\n * Only add the `minInstancesInServiceParameters` property if there are some ASGs affected by {@link GuHorizontallyScalingDeploymentPropertiesExperimental}.\n */\n if (minInstancesInServiceParameters.size > 0) {\n updateDeploymentParameters(deployments, cfnDeployment, {\n minInstancesInServiceParameters: getMinInstancesInServiceParameters(\n minInstancesInServiceParameters,\n ),\n });\n }\n });\n });\n },\n );\n\n configuration.set(riffRaffProjectName, { allowedStages, deployments });\n },\n );\n\n if (missingStacks.length > 0) {\n const message = `Unable to produce a working riff-raff.yaml file; missing ${missingStacks.length} definitions`;\n console.log(`${message} (details below)`);\n console.table(missingStacks);\n\n throw new Error(message);\n }\n\n this.configuration = configuration;\n }\n\n /**\n * A `riff-raff.yaml` file as a string.\n * Useful for testing.\n *\n * @param riffRaffProjectName which project to convert to YAML. Defaults to {@link UnknownRiffRaffProjectName} - any {@link GuStack} without an explicit `riffRaffProjectName` property.\n */\n toYAML(riffRaffProjectName: RiffRaffProjectName = UnknownRiffRaffProjectName): string {\n // Add support for ES6 Set and Map. See https://github.com/nodeca/js-yaml/issues/436.\n const replacer = (_key: string, value: unknown) => {\n if (value instanceof Set) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Array.from(value);\n }\n if (value instanceof Map) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Object.fromEntries(value);\n }\n return value;\n };\n\n const content = this.configuration.get(riffRaffProjectName);\n\n if (!content) {\n throw new Error(`No Riff-Raff project found with name: ${riffRaffProjectName}`);\n }\n\n return dump(content, { replacer });\n }\n\n /**\n * Write the `riff-raff.yaml` file(s) to disk, located in the same directory as the CFN JSON templates generated by `cdk synth`.\n */\n synth(): void {\n this.configuration.forEach((_, riffRaffProjectName) => {\n const targetDirectory =\n riffRaffProjectName === UnknownRiffRaffProjectName\n ? this.outdir\n : validateRiffRaffYamlDirectory(this.outdir, riffRaffProjectName);\n\n if (!existsSync(targetDirectory)) {\n mkdirSync(targetDirectory, { recursive: true });\n }\n\n const outPath = path.join(targetDirectory, \"riff-raff.yaml\");\n writeFileSync(outPath, this.toYAML(riffRaffProjectName));\n });\n }\n}\n\nexport function validateRiffRaffYamlDirectory(basePath: string, riffRaffProjectName: RiffRaffProjectName): string {\n const resolvedBase = path.resolve(basePath);\n const resolvedPath = path.resolve(basePath, riffRaffProjectName);\n const relativePath = path.relative(resolvedBase, resolvedPath);\n const isOutside = relativePath === \"..\" || relativePath.startsWith(`..${path.sep}`) || path.isAbsolute(relativePath);\n\n if (isOutside) {\n throw new Error(\n `Directory traversal detected: '${riffRaffProjectName}' would create a directory outside of ${basePath} (riffRaffProjectName=${riffRaffProjectName}, resolvedPath='${resolvedPath}', resolvedBase='${resolvedBase}')`,\n );\n }\n\n return resolvedPath;\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/riff-raff-yaml-file/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from \"fs\";\nimport path from \"path\";\nimport type { App } from \"aws-cdk-lib\";\nimport { Token } from \"aws-cdk-lib\";\nimport type { CfnAutoScalingGroup } from \"aws-cdk-lib/aws-autoscaling\";\nimport { dump } from \"js-yaml\";\nimport { GuAutoScalingGroup } from \"../constructs/autoscaling\";\nimport { GuStack } from \"../constructs/core\";\nimport { GuLambdaFunction } from \"../constructs/lambda\";\nimport { GuAsgMinInstancesInServiceParameterExperimental } from \"../experimental/patterns/ec2-app\";\nimport { autoscalingDeployment, uploadAutoscalingArtifact } from \"./deployments/autoscaling\";\nimport {\n cloudFormationDeployment,\n getAmiParameters,\n getMinInstancesInServiceParameters,\n} from \"./deployments/cloudformation\";\nimport { updateLambdaDeployment, uploadLambdaArtifact } from \"./deployments/lambda\";\nimport { updateDeploymentParameters } from \"./deployments/update-parameters\";\nimport {\n groupByClassName,\n groupByRegion,\n groupByRiffRaffProjectName,\n groupByStackTag,\n groupByStageTag,\n} from \"./group-by\";\nimport type {\n ClassName,\n Region,\n RiffRaffDeployment,\n RiffRaffDeploymentName,\n RiffRaffDeploymentProps,\n RiffRaffProjectName,\n RiffRaffYaml,\n StackTag,\n StageTag,\n} from \"./types\";\nimport { UnknownRiffRaffProjectName } from \"./types\";\n\nfunction validateAllRegionsAreResolved(regions: Region[]): void {\n const unresolved = regions.filter((region) => Token.isUnresolved(region));\n\n if (unresolved.length !== 0) {\n throw new Error(`Unable to produce a working riff-raff.yaml file; all stacks must have an explicit region set`);\n }\n}\n\nfunction getLambdas(cdkStack: GuStack): GuLambdaFunction[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuLambdaFunction) as GuLambdaFunction[];\n}\n\nfunction getAutoScalingGroups(cdkStack: GuStack): GuAutoScalingGroup[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuAutoScalingGroup) as GuAutoScalingGroup[];\n}\n\nfunction getGuStackDependencies(cdkStack: GuStack): GuStack[] {\n return cdkStack.dependencies.filter((_) => _ instanceof GuStack) as GuStack[];\n}\n\ninterface MissingStack {\n riffRaffProjectName: RiffRaffProjectName;\n className: ClassName;\n stack: StackTag;\n stage: StageTag;\n region: Region;\n}\n\n/**\n * A class that creates a `riff-raff.yaml` file.\n *\n * Rather than using this directly, prefer to use [[`GuRoot`]] instead.\n *\n * Supports:\n * - Multiple CloudFormation stacks\n * - Multiple regions\n * - Lambda applications\n * - EC2 (autoscaling) applications\n *\n * For lambda applications, 3 deployments will be defined:\n * 1. Lambda upload (`aws-lambda`, `action: [uploadLambda]`)\n * 2. CloudFormation deploy (`cloud-formation`)\n * 3. Lambda update (`aws-lambda`, `action: [updateLambda]`)\n *\n * For EC2 applications, 3 deployments will be defined:\n * 1. Artifact upload (`autoscaling`, `action: [uploadArtifacts]`)\n * 2. CloudFormation deploy (`cloud-formation`)\n * 3. Autoscaling deploy (`autoscaling`, `action: [deploy]`)\n *\n * It assumes a Riff-Raff bundle structure as follows:\n *\n * ```\n * .\n * ├── cdk.out\n * │ └── MyApplication.template.json\n * ├── my-application\n * │ └── my-application.deb\n * └── my-lambda\n * └── my-lambda.zip\n * ```\n *\n * That is, all CloudFormation templates are in a `cdk.out` directory, and there is a directory per app.\n * Application artifact(s) are in the app directory.\n *\n * NOTE: The file extension is decided by you, the above file tree is used for illustration purposes.\n *\n * NOTE: Resources will be looked up by tags (Stack, Stage, App). Ensure your CFN stack is tagged appropriately!\n *\n * @see https://riffraff.gutools.co.uk/docs/reference/riff-raff.yaml.md\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types\n */\nexport class RiffRaffYamlFile {\n private readonly outdir: string;\n\n /**\n * A mapping between a Riff-Raff project and `riff-raff.yaml` content as an object.\n *\n * It is useful for specifying additional deployment types that GuCDK does not support.\n * Consider raising an issue or pull request if you think it should be supported.\n *\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types\n */\n public readonly configuration: Map<RiffRaffProjectName, RiffRaffYaml>;\n\n // eslint-disable-next-line custom-rules/valid-constructors -- this needs to sit above GuStack on the cdk tree\n constructor(app: App) {\n const allCdkStacks = app.node.findAll().filter((_) => _ instanceof GuStack) as GuStack[];\n const allRegions = Array.from(new Set(allCdkStacks.map((_) => _.region)));\n\n validateAllRegionsAreResolved(allRegions);\n\n this.outdir = app.outdir;\n const configuration = new Map<RiffRaffProjectName, RiffRaffYaml>();\n const missingStacks: MissingStack[] = [];\n\n Object.entries(groupByRiffRaffProjectName(allCdkStacks)).forEach(\n ([riffRaffProjectName, stacksGroupedByRiffRaffProject]) => {\n const allowedStages = new Set(stacksGroupedByRiffRaffProject.map((_) => _.stage));\n const requiredStages = Array.from(allowedStages);\n const deployments = new Map<RiffRaffDeploymentName, RiffRaffDeploymentProps>();\n\n Object.entries(groupByClassName(stacksGroupedByRiffRaffProject)).forEach(\n ([className, stacksGroupedByClassName]) => {\n Object.entries(groupByStackTag(stacksGroupedByClassName)).forEach(([stackTag, stacksGroupedByStackTag]) => {\n Object.entries(groupByRegion(stacksGroupedByStackTag)).forEach(([region, stacksGroupedByRegion]) => {\n const stacks: GuStack[] = Object.values(groupByStageTag(stacksGroupedByRegion)).flat();\n\n requiredStages.forEach((requiredStage) => {\n if (!stacks.find(({ stage }) => stage === requiredStage)) {\n missingStacks.push({\n riffRaffProjectName,\n className,\n region,\n stack: stackTag,\n stage: requiredStage,\n });\n }\n });\n\n // The items in `stacks` only differ by stage, so we can just use the first item in the list.\n const [stack] = stacks;\n\n if (!stack) {\n throw new Error(\"Unable to produce a working riff-raff.yaml file; there are no stacks!\");\n }\n\n const lambdas = getLambdas(stack);\n const autoscalingGroups = getAutoScalingGroups(stack);\n\n const artifactUploads: RiffRaffDeployment[] = [\n lambdas.filter((_) => !_.withoutArtifactUpload).map(uploadLambdaArtifact),\n autoscalingGroups.map(uploadAutoscalingArtifact),\n ].flat();\n artifactUploads.forEach(({ name, props }) => deployments.set(name, props));\n\n const parentStacks: RiffRaffDeployment[] = getGuStackDependencies(stack).map((x) =>\n cloudFormationDeployment([x], [], this.outdir),\n );\n\n const cfnDeployment = cloudFormationDeployment(\n stacks,\n [...artifactUploads, ...parentStacks],\n this.outdir,\n );\n deployments.set(cfnDeployment.name, cfnDeployment.props);\n\n const lambdasWithoutAnAlias = lambdas.filter((lambda) => lambda.alias === undefined);\n // If the Lambda has an alias it is using versioning. When using versioning, there is no need for Riff-Raff\n // to modify the unpublished version of the function\n lambdasWithoutAnAlias.forEach((lambda) => {\n const lambdaDeployment = updateLambdaDeployment(lambda, cfnDeployment);\n deployments.set(lambdaDeployment.name, lambdaDeployment.props);\n });\n\n /*\n Instances in an ASG with an `AutoScalingRollingUpdate` update policy are rotated via CloudFormation.\n Therefore, they do not need to also perform an `autoscaling` deployment via Riff-Raff.\n */\n const legacyAutoscalingGroups = autoscalingGroups.filter((asg) => {\n const { cfnOptions } = asg.node.defaultChild as CfnAutoScalingGroup;\n const { updatePolicy } = cfnOptions;\n return updatePolicy?.autoScalingRollingUpdate === undefined;\n });\n\n legacyAutoscalingGroups.forEach((asg) => {\n const asgDeployment = autoscalingDeployment(asg, cfnDeployment);\n deployments.set(asgDeployment.name, asgDeployment.props);\n });\n\n // only add the `amiParametersToTags` property if there are some ASGs in the stack\n if (autoscalingGroups.length > 0) {\n updateDeploymentParameters(deployments, cfnDeployment, {\n amiParametersToTags: getAmiParameters(autoscalingGroups),\n });\n }\n\n /*\n At this point, `stacks` is a collection of similar `GuStack`s that differ only by their `stage`.\n We're about to add `minInstancesInServiceParameters` to assist Riff-Raff when deploying ASGs with scaling policies.\n This is driven by the presence of conditionally added CFN Parameters.\n To support the possibility of there being a scaling policy in PROD but not CODE, look at all the CFN Parameters in `stacks`.\n */\n const minInstancesInServiceParameters: Map<string, GuAsgMinInstancesInServiceParameterExperimental> =\n stacks\n .flatMap((stack) => Object.values(stack.parameters))\n .filter(\n (_): _ is GuAsgMinInstancesInServiceParameterExperimental =>\n _ instanceof GuAsgMinInstancesInServiceParameterExperimental,\n )\n .reduce((acc, item) => {\n if (!acc.has(item.node.id)) {\n acc.set(item.node.id, item);\n }\n return acc;\n }, new Map<string, GuAsgMinInstancesInServiceParameterExperimental>());\n\n /**\n * Only add the `minInstancesInServiceParameters` property if there are some ASGs affected by {@link GuHorizontallyScalingDeploymentPropertiesExperimental}.\n */\n if (minInstancesInServiceParameters.size > 0) {\n updateDeploymentParameters(deployments, cfnDeployment, {\n minInstancesInServiceParameters: getMinInstancesInServiceParameters(\n minInstancesInServiceParameters,\n ),\n });\n }\n });\n });\n },\n );\n\n configuration.set(riffRaffProjectName, { allowedStages, deployments });\n },\n );\n\n if (missingStacks.length > 0) {\n const message = `Unable to produce a working riff-raff.yaml file; missing ${missingStacks.length} definitions`;\n console.log(`${message} (details below)`);\n console.table(missingStacks);\n\n throw new Error(message);\n }\n\n this.configuration = configuration;\n }\n\n /**\n * A `riff-raff.yaml` file as a string.\n * Useful for testing.\n *\n * @param riffRaffProjectName which project to convert to YAML. Defaults to {@link UnknownRiffRaffProjectName} - any {@link GuStack} without an explicit `riffRaffProjectName` property.\n */\n toYAML(riffRaffProjectName: RiffRaffProjectName = UnknownRiffRaffProjectName): string {\n // Add support for ES6 Set and Map. See https://github.com/nodeca/js-yaml/issues/436.\n const replacer = (_key: string, value: unknown) => {\n if (value instanceof Set) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Array.from(value);\n }\n if (value instanceof Map) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- this is how `js-yaml` is typed\n return Object.fromEntries(value);\n }\n return value;\n };\n\n const content = this.configuration.get(riffRaffProjectName);\n\n if (!content) {\n throw new Error(`No Riff-Raff project found with name: ${riffRaffProjectName}`);\n }\n\n const yaml = dump(content, { replacer });\n\n const comments = [\n \"This file was generated by @guardian/cdk, do not edit it directly.\",\n \"See also https://github.com/guardian/cdk/blob/main/src/riff-raff-yaml-file/README.md.\",\n ]\n .map((line) => `# ${line}`)\n .join(\"\\n\");\n\n return [comments, yaml].join(\"\\n\");\n }\n\n /**\n * Write the `riff-raff.yaml` file(s) to disk, located in the same directory as the CFN JSON templates generated by `cdk synth`.\n */\n synth(): void {\n this.configuration.forEach((_, riffRaffProjectName) => {\n const targetDirectory =\n riffRaffProjectName === UnknownRiffRaffProjectName\n ? this.outdir\n : validateRiffRaffYamlDirectory(this.outdir, riffRaffProjectName);\n\n if (!existsSync(targetDirectory)) {\n mkdirSync(targetDirectory, { recursive: true });\n }\n\n const outPath = path.join(targetDirectory, \"riff-raff.yaml\");\n writeFileSync(outPath, this.toYAML(riffRaffProjectName));\n });\n }\n}\n\nexport function validateRiffRaffYamlDirectory(basePath: string, riffRaffProjectName: RiffRaffProjectName): string {\n const resolvedBase = path.resolve(basePath);\n const resolvedPath = path.resolve(basePath, riffRaffProjectName);\n const relativePath = path.relative(resolvedBase, resolvedPath);\n const isOutside = relativePath === \"..\" || relativePath.startsWith(`..${path.sep}`) || path.isAbsolute(relativePath);\n\n if (isOutside) {\n throw new Error(\n `Directory traversal detected: '${riffRaffProjectName}' would create a directory outside of ${basePath} (riffRaffProjectName=${riffRaffProjectName}, resolvedPath='${resolvedPath}', resolvedBase='${resolvedBase}')`,\n );\n }\n\n return resolvedPath;\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@guardian/cdk",
3
3
  "description": "Generic Guardian flavoured AWS CDK components",
4
- "version": "63.2.1",
4
+ "version": "63.3.0",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
7
7
  "files": [