@guardian/cdk 52.3.0 → 53.0.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.
@@ -28,7 +28,7 @@ const ssmParamReadiness = async ({ credentialProvider, region }) => {
28
28
  const defaultVpcs = vpcs
29
29
  .filter((vpc) => vpc.IsDefault)
30
30
  .map((vpc) => {
31
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- a VPC always has an ID, the type in CDK is odd!
31
+ // Non-null-assertion, A VPC always has an ID, the type in CDK is odd!
32
32
  return vpc.VpcId;
33
33
  });
34
34
  const ssmParametersMatchingDefaultVpc = ssmParamsFromAccount.filter(({ Value }) => Value && defaultVpcs.includes(Value));
@@ -1 +1 @@
1
- {"version":3,"file":"ssm.js","sourceRoot":"","sources":["../../../../src/bin/commands/account-readiness/ssm.ts"],"names":[],"mappings":"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","sourcesContent":["import AWS from \"aws-sdk\";\nimport chalk from \"chalk\";\nimport type { SsmParameterPath } from \"../../../constants\";\nimport { ALL_SSM_PARAMETER_PATHS } from \"../../../constants\";\nimport type { AwsConfig } from \"../../../types/cli\";\nimport { getSsmParametersForVpc, getVpcsInDetail } from \"../../../utils/cli/vpc\";\nimport type { Report } from \".\";\n\ninterface SSMParameterReadinessOutput {\n missingParameters: SsmParameterPath[];\n foundParameters: SsmParameterPath[];\n defaultVPCReferences: SsmParameterPath[];\n}\n\nconst ssmParamReadiness = async ({ credentialProvider, region }: AwsConfig): Promise<SSMParameterReadinessOutput> => {\n const ssmClient = new AWS.SSM({\n credentialProvider,\n region,\n });\n\n const ec2Client = new AWS.EC2({\n credentialProvider,\n region,\n });\n\n const ssmParams = ALL_SSM_PARAMETER_PATHS.filter((param) => !param.optional);\n const paths: string[] = ssmParams.map((param: SsmParameterPath) => param.path);\n\n const awsResponse = await ssmClient.getParameters({ Names: paths }).promise();\n\n const notFoundParameters = awsResponse.InvalidParameters ?? [];\n const notFoundInDetail = ssmParams.filter((_) => notFoundParameters.includes(_.path));\n const foundInDetail = ssmParams.filter((_) => !notFoundParameters.includes(_.path));\n\n const vpcs = await getVpcsInDetail(ec2Client);\n const ssmParamsFromAccount = await getSsmParametersForVpc(ssmClient);\n const defaultVpcs: string[] = vpcs\n .filter((vpc) => vpc.IsDefault)\n .map((vpc) => {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- a VPC always has an ID, the type in CDK is odd!\n return vpc.VpcId!;\n });\n\n const ssmParametersMatchingDefaultVpc = ssmParamsFromAccount.filter(\n ({ Value }) => Value && defaultVpcs.includes(Value),\n );\n\n const defaultVPCReferencePaths = ssmParametersMatchingDefaultVpc\n .map((param) => {\n return ssmParams.find((p) => p.path === param.Name);\n })\n .filter((p): p is SsmParameterPath => p !== undefined);\n\n return {\n foundParameters: foundInDetail,\n missingParameters: notFoundInDetail,\n defaultVPCReferences: defaultVPCReferencePaths,\n };\n};\n\nexport const report = async (props: AwsConfig): Promise<Report> => {\n const output = await ssmParamReadiness(props);\n const isPass = output.missingParameters.length === 0 && output.defaultVPCReferences.length === 0;\n\n const errs = new Map<string, string>();\n const parametersMsg =\n \"CDK uses predefined SSM parameters within patterns and constructs. For example, the EC2 APP pattern uses a parameter to determine which Kinesis stream to forward logs to. Your CDK app may fail at runtime if these parameters do not exist.\";\n\n const missingParamsMsg = \"Required parameters are missing\";\n const missingParams = output.missingParameters.map((p) => ` ${chalk.yellowBright(p.path)}: ${p.description}`);\n\n if (output.missingParameters.length > 0) {\n errs.set(missingParamsMsg, `\\n${missingParams.join(\"\\n\")}`);\n }\n\n if (output.defaultVPCReferences.length > 0) {\n errs.set(\n \"Default VPC referenced in VPC parameters\",\n `you should use a custom VPC instead. Default VPC is referenced in paths: ${output.defaultVPCReferences.join(\n \", \",\n )}.`,\n );\n }\n\n return {\n name: \"SSM Parameter Readiness\",\n isPass: isPass,\n msg: parametersMsg,\n errors: errs,\n parametersFound: output.foundParameters.length,\n parametersMissing: output.missingParameters.length,\n };\n};\n\nexport const isPass = (output: SSMParameterReadinessOutput): boolean => {\n return output.missingParameters.length === 0;\n};\n"]}
1
+ {"version":3,"file":"ssm.js","sourceRoot":"","sources":["../../../../src/bin/commands/account-readiness/ssm.ts"],"names":[],"mappings":"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","sourcesContent":["import AWS from \"aws-sdk\";\nimport chalk from \"chalk\";\nimport type { SsmParameterPath } from \"../../../constants\";\nimport { ALL_SSM_PARAMETER_PATHS } from \"../../../constants\";\nimport type { AwsConfig } from \"../../../types/cli\";\nimport { getSsmParametersForVpc, getVpcsInDetail } from \"../../../utils/cli/vpc\";\nimport type { Report } from \".\";\n\ninterface SSMParameterReadinessOutput {\n missingParameters: SsmParameterPath[];\n foundParameters: SsmParameterPath[];\n defaultVPCReferences: SsmParameterPath[];\n}\n\nconst ssmParamReadiness = async ({ credentialProvider, region }: AwsConfig): Promise<SSMParameterReadinessOutput> => {\n const ssmClient = new AWS.SSM({\n credentialProvider,\n region,\n });\n\n const ec2Client = new AWS.EC2({\n credentialProvider,\n region,\n });\n\n const ssmParams = ALL_SSM_PARAMETER_PATHS.filter((param) => !param.optional);\n const paths: string[] = ssmParams.map((param: SsmParameterPath) => param.path);\n\n const awsResponse = await ssmClient.getParameters({ Names: paths }).promise();\n\n const notFoundParameters = awsResponse.InvalidParameters ?? [];\n const notFoundInDetail = ssmParams.filter((_) => notFoundParameters.includes(_.path));\n const foundInDetail = ssmParams.filter((_) => !notFoundParameters.includes(_.path));\n\n const vpcs = await getVpcsInDetail(ec2Client);\n const ssmParamsFromAccount = await getSsmParametersForVpc(ssmClient);\n const defaultVpcs: string[] = vpcs\n .filter((vpc) => vpc.IsDefault)\n .map((vpc) => {\n // Non-null-assertion, A VPC always has an ID, the type in CDK is odd!\n return vpc.VpcId!;\n });\n\n const ssmParametersMatchingDefaultVpc = ssmParamsFromAccount.filter(\n ({ Value }) => Value && defaultVpcs.includes(Value),\n );\n\n const defaultVPCReferencePaths = ssmParametersMatchingDefaultVpc\n .map((param) => {\n return ssmParams.find((p) => p.path === param.Name);\n })\n .filter((p): p is SsmParameterPath => p !== undefined);\n\n return {\n foundParameters: foundInDetail,\n missingParameters: notFoundInDetail,\n defaultVPCReferences: defaultVPCReferencePaths,\n };\n};\n\nexport const report = async (props: AwsConfig): Promise<Report> => {\n const output = await ssmParamReadiness(props);\n const isPass = output.missingParameters.length === 0 && output.defaultVPCReferences.length === 0;\n\n const errs = new Map<string, string>();\n const parametersMsg =\n \"CDK uses predefined SSM parameters within patterns and constructs. For example, the EC2 APP pattern uses a parameter to determine which Kinesis stream to forward logs to. Your CDK app may fail at runtime if these parameters do not exist.\";\n\n const missingParamsMsg = \"Required parameters are missing\";\n const missingParams = output.missingParameters.map((p) => ` ${chalk.yellowBright(p.path)}: ${p.description}`);\n\n if (output.missingParameters.length > 0) {\n errs.set(missingParamsMsg, `\\n${missingParams.join(\"\\n\")}`);\n }\n\n if (output.defaultVPCReferences.length > 0) {\n errs.set(\n \"Default VPC referenced in VPC parameters\",\n `you should use a custom VPC instead. Default VPC is referenced in paths: ${output.defaultVPCReferences.join(\n \", \",\n )}.`,\n );\n }\n\n return {\n name: \"SSM Parameter Readiness\",\n isPass: isPass,\n msg: parametersMsg,\n errors: errs,\n parametersFound: output.foundParameters.length,\n parametersMissing: output.missingParameters.length,\n };\n};\n\nexport const isPass = (output: SSMParameterReadinessOutput): boolean => {\n return output.missingParameters.length === 0;\n};\n"]}
@@ -71,7 +71,6 @@ function createPackageJson(outputDirectory) {
71
71
  "ts-jest",
72
72
  "ts-node",
73
73
  "typescript",
74
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- deps come from `package.json`, so shouldn't be `undefined`
75
74
  ].reduce((acc, depName) => ({ ...acc, [depName]: (0, constants_1.getDevDependency)(depName) }), {});
76
75
  const cdkDeps = {
77
76
  /*
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../../../src/bin/commands/new-project/utils/init.ts"],"names":[],"mappings":";;;AAAA,2BAAgG;AAChG,+BAA4B;AAC5B,qDAAsE;AAMtE,8BAA8B;AAC9B,MAAa,cAAc;IAWzB,YAAY,MAAkB;QAV9B,gBAAW,GAAG,GAAG,SAAS,cAAc,CAAC;QAWvC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,cAAc;QACZ,cAAc,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE3C,IAAI,CAAC,IAAA,eAAU,EAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE;YACtC,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;YACjD,IAAA,cAAS,EAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;SAClC;QAED,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACrC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAEzC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QACtC,8DAA8D;QAC9D,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAExD,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC1B,CAAC;IAED,SAAS,CAAC,UAAkB,EAAE,UAAkB;QAC9C,KAAK,MAAM,IAAI,IAAI,IAAA,gBAAW,EAAC,UAAU,CAAC,EAAE;YAC1C,MAAM,IAAI,GAAG,IAAA,WAAI,EAAC,UAAU,EAAE,IAAI,CAAC,CAAC;YAEpC,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE;gBAC5B,SAAS;aACV;iBAAM,IAAI,IAAA,cAAS,EAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE;gBACxC,MAAM,gBAAgB,GAAG,IAAA,WAAI,EAAC,UAAU,EAAE,IAAI,CAAC,CAAC;gBAChD,IAAI,CAAC,IAAA,eAAU,EAAC,gBAAgB,CAAC,EAAE;oBACjC,IAAA,cAAS,EAAC,gBAAgB,CAAC,CAAC;iBAC7B;gBACD,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;aACxC;iBAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE;gBACrC,IAAA,iBAAY,EAAC,IAAI,EAAE,IAAA,WAAI,EAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;aACrE;iBAAM;gBACL,IAAA,iBAAY,EAAC,IAAI,EAAE,IAAA,WAAI,EAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC;aAC5C;SACF;IACH,CAAC;;AAnDH,wCAoDC;AAhDQ,6BAAc,GAAG,CAAC,MAAkB,EAAQ,EAAE;IACnD,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC;IAC9B,IAAI,IAAA,eAAU,EAAC,IAAI,CAAC,IAAI,IAAA,gBAAW,EAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;QACpD,MAAM,IAAI,KAAK,CAAC,aAAa,IAAI,eAAe,CAAC,CAAC;KACnD;AACH,CAAC,AALoB,CAKnB;AA6CG,MAAM,cAAc,GAAG,CAAC,MAAkB,EAAQ,EAAE;IACzD,MAAM,OAAO,GAAG,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;IAC3C,OAAO,CAAC,cAAc,EAAE,CAAC;AAC3B,CAAC,CAAC;AAHW,QAAA,cAAc,kBAGzB;AAEF,SAAS,iBAAiB,CAAC,eAAuB;IAChD,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IACrC,MAAM,MAAM,GAAG,QAAQ,EAAE,WAAW,EAAE,KAAK,MAAM,IAAI,EAAE,EAAE,WAAW,EAAE,KAAK,MAAM,CAAC;IAElF,MAAM,QAAQ,GAA2B;QACvC,oCAAoC;QACpC,oBAAoB;QACpB,aAAa;QACb,aAAa;QACb,QAAQ;QACR,MAAM;QACN,UAAU;QACV,SAAS;QACT,SAAS;QACT,YAAY;QACZ,kIAAkI;KACnI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,IAAA,4BAAgB,EAAC,OAAO,CAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAEpF,MAAM,OAAO,GAA2B;QACtC;;;;;aAKK;QACL,GAAG,CAAC,CAAC,MAAM,IAAI,EAAE,eAAe,EAAE,uBAAW,CAAC,OAAO,EAAE,CAAC;QAExD,SAAS,EAAE,uBAAW,CAAC,eAAe;QACtC,aAAa,EAAE,uBAAW,CAAC,eAAe;QAC1C,UAAU,EAAE,uBAAW,CAAC,kBAAkB;KAC3C,CAAC;IAEF,MAAM,UAAU,GAAG;QACjB,oBAAoB,EAAE,SAAS;QAC/B,oBAAoB,EAAE,OAAO;KAC9B,CAAC;IAEF,MAAM,OAAO,GAA2B,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,EAAE,GAAG,UAAU,EAAE,CAAC;IAEnF,MAAM,eAAe,GAA2B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;SACjE,IAAI,EAAE;SACN,MAAM,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAE3E,MAAM,QAAQ,GAAG;QACf,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,IAAI;QACb,OAAO,EAAE;YACP,KAAK,EAAE,KAAK;YACZ,IAAI,EAAE,MAAM;YACZ,aAAa,EAAE,SAAS;YACxB,MAAM,EAAE,sCAAsC;YAC9C,IAAI,EAAE,gEAAgE;YACtE,KAAK,EAAE,2DAA2D;YAClE,IAAI,EAAE,0DAA0D;SACjE;QACD,eAAe;QAEf,QAAQ,EAAE,oBAAoB;QAE9B,IAAI,EAAE;YACJ,SAAS,EAAE,CAAC,4BAA4B,CAAC;YACzC,SAAS,EAAE;gBACT,aAAa,EAAE,SAAS;aACzB;YACD,kBAAkB,EAAE,CAAC,iBAAiB,CAAC;SACxC;QAED,YAAY,EAAE;YACZ,IAAI,EAAE,IAAI;YACV,GAAG,EAAE;gBACH,IAAI,EAAE,IAAI;gBACV,IAAI,EAAE,IAAI;aACX;YACD,OAAO,EAAE,CAAC,oCAAoC,CAAC;YAC/C,aAAa,EAAE;gBACb,WAAW,EAAE,IAAI;gBACjB,UAAU,EAAE,QAAQ;aACrB;YACD,OAAO,EAAE,CAAC,oBAAoB,CAAC;YAC/B,KAAK,EAAE;gBACL,wCAAwC,EAAE,CAAC;gBAC3C,qBAAqB,EAAE,CAAC;aACzB;YACD,cAAc,EAAE,CAAC,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,cAAc,EAAE,gBAAgB,CAAC;SACzF;KACF,CAAC;IACF,IAAA,kBAAa,EAAC,GAAG,eAAe,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACtF,CAAC","sourcesContent":["import { copyFileSync, existsSync, lstatSync, mkdirSync, readdirSync, writeFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { getDevDependency, LibraryInfo } from \"../../../../constants\";\n\nexport interface InitConfig {\n outputDir: string;\n}\n\n// TODO: Add project name flag\nexport class ProjectBuilder {\n templateDir = `${__dirname}/../template`;\n config: InitConfig;\n\n static validateConfig = (config: InitConfig): void => {\n const path = config.outputDir;\n if (existsSync(path) && readdirSync(path).length > 0) {\n throw new Error(`Directory ${path} is not empty`);\n }\n };\n\n constructor(config: InitConfig) {\n this.config = config;\n }\n\n buildDirectory(): void {\n ProjectBuilder.validateConfig(this.config);\n\n if (!existsSync(this.config.outputDir)) {\n console.log(`Creating ${this.config.outputDir}`);\n mkdirSync(this.config.outputDir);\n }\n\n console.log(\"Creating package.json\");\n createPackageJson(this.config.outputDir);\n\n console.log(\"Copying template files\");\n // TODO: Replace any params in files with .template extensions\n this.copyFiles(this.templateDir, this.config.outputDir);\n\n console.log(\"Success!\");\n }\n\n copyFiles(sourcePath: string, targetPath: string): void {\n for (const file of readdirSync(sourcePath)) {\n const path = join(sourcePath, file);\n\n if (path.endsWith(\".ignore\")) {\n continue;\n } else if (lstatSync(path).isDirectory()) {\n const nestedTargetPath = join(targetPath, file);\n if (!existsSync(nestedTargetPath)) {\n mkdirSync(nestedTargetPath);\n }\n this.copyFiles(path, nestedTargetPath);\n } else if (path.endsWith(\".template\")) {\n copyFileSync(path, join(targetPath, file.replace(\".template\", \"\")));\n } else {\n copyFileSync(path, join(targetPath, file));\n }\n }\n }\n}\n\nexport const buildDirectory = (config: InitConfig): void => {\n const builder = new ProjectBuilder(config);\n builder.buildDirectory();\n};\n\nfunction createPackageJson(outputDirectory: string): void {\n const { NODE_ENV, CI } = process.env;\n const isTest = NODE_ENV?.toUpperCase() === \"TEST\" || CI?.toUpperCase() === \"TRUE\";\n\n const coreDeps: Record<string, string> = [\n \"@guardian/eslint-config-typescript\",\n \"@guardian/tsconfig\",\n \"@types/jest\",\n \"@types/node\",\n \"eslint\",\n \"jest\",\n \"prettier\",\n \"ts-jest\",\n \"ts-node\",\n \"typescript\",\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- deps come from `package.json`, so shouldn't be `undefined`\n ].reduce((acc, depName) => ({ ...acc, [depName]: getDevDependency(depName)! }), {});\n\n const cdkDeps: Record<string, string> = {\n /*\n Do not add `@guardian/cdk` to the generated `package.json` file when in TEST as we'll `npm link` it instead.\n See https://docs.npmjs.com/cli/v8/commands/npm-link#caveat\n\n TODO remove this once the `new` command allows opting out of automatic dependency installation\n */\n ...(!isTest && { \"@guardian/cdk\": LibraryInfo.VERSION }),\n\n \"aws-cdk\": LibraryInfo.AWS_CDK_VERSION,\n \"aws-cdk-lib\": LibraryInfo.AWS_CDK_VERSION,\n constructs: LibraryInfo.CONSTRUCTS_VERSION,\n };\n\n const customDeps = {\n \"source-map-support\": \"^0.5.20\",\n \"@guardian/prettier\": \"5.0.0\",\n };\n\n const allDeps: Record<string, string> = { ...coreDeps, ...cdkDeps, ...customDeps };\n\n const devDependencies: Record<string, string> = Object.keys(allDeps)\n .sort()\n .reduce((acc, depName) => ({ ...acc, [depName]: allDeps[depName] }), {});\n\n const contents = {\n name: \"cdk\",\n version: \"0.0.0\",\n private: true,\n scripts: {\n build: \"tsc\",\n test: \"jest\",\n \"test-update\": \"jest -u\",\n format: 'prettier --write \"{lib,bin}/**/*.ts\"',\n lint: \"eslint lib/** bin/** --ext .ts --no-error-on-unmatched-pattern\",\n synth: \"cdk synth --path-metadata false --version-reporting false\",\n diff: \"cdk diff --path-metadata false --version-reporting false\",\n },\n devDependencies,\n\n prettier: \"@guardian/prettier\",\n\n jest: {\n testMatch: [\"<rootDir>/lib/**/*.test.ts\"],\n transform: {\n \"^.+\\\\.tsx?$\": \"ts-jest\",\n },\n setupFilesAfterEnv: [\"./jest.setup.js\"],\n },\n\n eslintConfig: {\n root: true,\n env: {\n node: true,\n jest: true,\n },\n extends: [\"@guardian/eslint-config-typescript\"],\n parserOptions: {\n ecmaVersion: 2020,\n sourceType: \"module\",\n },\n plugins: [\"@typescript-eslint\"],\n rules: {\n \"@typescript-eslint/no-inferrable-types\": 0,\n \"import/no-namespace\": 2,\n },\n ignorePatterns: [\"**/*.js\", \"node_modules\", \"cdk.out\", \".eslintrc.js\", \"jest.config.js\"],\n },\n };\n writeFileSync(`${outputDirectory}/package.json`, JSON.stringify(contents, null, 2));\n}\n"]}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../../../src/bin/commands/new-project/utils/init.ts"],"names":[],"mappings":"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","sourcesContent":["import { copyFileSync, existsSync, lstatSync, mkdirSync, readdirSync, writeFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { getDevDependency, LibraryInfo } from \"../../../../constants\";\n\nexport interface InitConfig {\n outputDir: string;\n}\n\n// TODO: Add project name flag\nexport class ProjectBuilder {\n templateDir = `${__dirname}/../template`;\n config: InitConfig;\n\n static validateConfig = (config: InitConfig): void => {\n const path = config.outputDir;\n if (existsSync(path) && readdirSync(path).length > 0) {\n throw new Error(`Directory ${path} is not empty`);\n }\n };\n\n constructor(config: InitConfig) {\n this.config = config;\n }\n\n buildDirectory(): void {\n ProjectBuilder.validateConfig(this.config);\n\n if (!existsSync(this.config.outputDir)) {\n console.log(`Creating ${this.config.outputDir}`);\n mkdirSync(this.config.outputDir);\n }\n\n console.log(\"Creating package.json\");\n createPackageJson(this.config.outputDir);\n\n console.log(\"Copying template files\");\n // TODO: Replace any params in files with .template extensions\n this.copyFiles(this.templateDir, this.config.outputDir);\n\n console.log(\"Success!\");\n }\n\n copyFiles(sourcePath: string, targetPath: string): void {\n for (const file of readdirSync(sourcePath)) {\n const path = join(sourcePath, file);\n\n if (path.endsWith(\".ignore\")) {\n continue;\n } else if (lstatSync(path).isDirectory()) {\n const nestedTargetPath = join(targetPath, file);\n if (!existsSync(nestedTargetPath)) {\n mkdirSync(nestedTargetPath);\n }\n this.copyFiles(path, nestedTargetPath);\n } else if (path.endsWith(\".template\")) {\n copyFileSync(path, join(targetPath, file.replace(\".template\", \"\")));\n } else {\n copyFileSync(path, join(targetPath, file));\n }\n }\n }\n}\n\nexport const buildDirectory = (config: InitConfig): void => {\n const builder = new ProjectBuilder(config);\n builder.buildDirectory();\n};\n\nfunction createPackageJson(outputDirectory: string): void {\n const { NODE_ENV, CI } = process.env;\n const isTest = NODE_ENV?.toUpperCase() === \"TEST\" || CI?.toUpperCase() === \"TRUE\";\n\n const coreDeps: Record<string, string> = [\n \"@guardian/eslint-config-typescript\",\n \"@guardian/tsconfig\",\n \"@types/jest\",\n \"@types/node\",\n \"eslint\",\n \"jest\",\n \"prettier\",\n \"ts-jest\",\n \"ts-node\",\n \"typescript\",\n ].reduce((acc, depName) => ({ ...acc, [depName]: getDevDependency(depName)! }), {});\n\n const cdkDeps: Record<string, string> = {\n /*\n Do not add `@guardian/cdk` to the generated `package.json` file when in TEST as we'll `npm link` it instead.\n See https://docs.npmjs.com/cli/v8/commands/npm-link#caveat\n\n TODO remove this once the `new` command allows opting out of automatic dependency installation\n */\n ...(!isTest && { \"@guardian/cdk\": LibraryInfo.VERSION }),\n\n \"aws-cdk\": LibraryInfo.AWS_CDK_VERSION,\n \"aws-cdk-lib\": LibraryInfo.AWS_CDK_VERSION,\n constructs: LibraryInfo.CONSTRUCTS_VERSION,\n };\n\n const customDeps = {\n \"source-map-support\": \"^0.5.20\",\n \"@guardian/prettier\": \"5.0.0\",\n };\n\n const allDeps: Record<string, string> = { ...coreDeps, ...cdkDeps, ...customDeps };\n\n const devDependencies: Record<string, string> = Object.keys(allDeps)\n .sort()\n .reduce((acc, depName) => ({ ...acc, [depName]: allDeps[depName] }), {});\n\n const contents = {\n name: \"cdk\",\n version: \"0.0.0\",\n private: true,\n scripts: {\n build: \"tsc\",\n test: \"jest\",\n \"test-update\": \"jest -u\",\n format: 'prettier --write \"{lib,bin}/**/*.ts\"',\n lint: \"eslint lib/** bin/** --ext .ts --no-error-on-unmatched-pattern\",\n synth: \"cdk synth --path-metadata false --version-reporting false\",\n diff: \"cdk diff --path-metadata false --version-reporting false\",\n },\n devDependencies,\n\n prettier: \"@guardian/prettier\",\n\n jest: {\n testMatch: [\"<rootDir>/lib/**/*.test.ts\"],\n transform: {\n \"^.+\\\\.tsx?$\": \"ts-jest\",\n },\n setupFilesAfterEnv: [\"./jest.setup.js\"],\n },\n\n eslintConfig: {\n root: true,\n env: {\n node: true,\n jest: true,\n },\n extends: [\"@guardian/eslint-config-typescript\"],\n parserOptions: {\n ecmaVersion: 2020,\n sourceType: \"module\",\n },\n plugins: [\"@typescript-eslint\"],\n rules: {\n \"@typescript-eslint/no-inferrable-types\": 0,\n \"import/no-namespace\": 2,\n },\n ignorePatterns: [\"**/*.js\", \"node_modules\", \"cdk.out\", \".eslintrc.js\", \"jest.config.js\"],\n },\n };\n writeFileSync(`${outputDirectory}/package.json`, JSON.stringify(contents, null, 2));\n}\n"]}
@@ -1,5 +1,5 @@
1
- import type { StackProps } from "aws-cdk-lib";
2
- import { App, CfnParameter, Stack } from "aws-cdk-lib";
1
+ import type { App, StackProps } from "aws-cdk-lib";
2
+ import { CfnParameter, Stack } from "aws-cdk-lib";
3
3
  import type { IConstruct } from "constructs";
4
4
  import type { StackStageIdentity } from "./identity";
5
5
  import type { GuStaticLogicalId } from "./migrating";
@@ -162,13 +162,4 @@ export declare class GuStack extends Stack implements StackStageIdentity {
162
162
  */
163
163
  overrideLogicalId(construct: IConstruct, { logicalId, reason }: GuStaticLogicalId): void;
164
164
  }
165
- /**
166
- * A GuStack but designed for Stack Set instances.
167
- *
168
- * In a stack set application, `GuStackForStackSetInstance` is used to represent the infrastructure to provision in target AWS accounts.
169
- */
170
- export declare class GuStackForStackSetInstance extends GuStack {
171
- constructor(id: string, props: GuStackProps);
172
- get cfnJson(): string;
173
- }
174
165
  //# sourceMappingURL=stack.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stack.d.ts","sourceRoot":"","sources":["../../../src/constructs/core/stack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,UAAU,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAe,GAAG,EAAW,YAAY,EAA0B,KAAK,EAAQ,MAAM,aAAa,CAAC;AAE3G,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAQ7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC;IACjE;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,OAAQ,SAAQ,KAAM,YAAW,kBAAkB;IAC9D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAS;IAE1C,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,IAAI,GAAG,IAAI,MAAM,GAAG,SAAS,CAE5B;IAED;;;OAGG;IACH,IAAI,cAAc,IAAI,MAAM,GAAG,SAAS,CAEvC;IAED;;;;;;;;;OASG;IACH,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,wBAAwB,GAAE,OAAc,GAAG,IAAI;IAM5F;;;;OAIG;IACH,IAAI,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAK7C;gBAGW,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY;IAgDvD;;;;;;;OAOG;IACH,OAAO,CAAC,mBAAmB;IAa3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqDG;IACI,iBAAiB,CAAC,SAAS,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,iBAAiB,GAAG,IAAI;CAQhG;AAED;;;;GAIG;AACH,qBAAa,0BAA2B,SAAQ,OAAO;gBAEzC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY;IAI3C,IAAI,OAAO,IAAI,MAAM,CAEpB;CACF"}
1
+ {"version":3,"file":"stack.d.ts","sourceRoot":"","sources":["../../../src/constructs/core/stack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAc,UAAU,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAwB,YAAY,EAA0B,KAAK,EAAQ,MAAM,aAAa,CAAC;AACtG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAQ7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC;IACjE;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,OAAQ,SAAQ,KAAM,YAAW,kBAAkB;IAC9D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAS;IAE1C,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,IAAI,GAAG,IAAI,MAAM,GAAG,SAAS,CAE5B;IAED;;;OAGG;IACH,IAAI,cAAc,IAAI,MAAM,GAAG,SAAS,CAEvC;IAED;;;;;;;;;OASG;IACH,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,wBAAwB,GAAE,OAAc,GAAG,IAAI;IAM5F;;;;OAIG;IACH,IAAI,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAK7C;gBAGW,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY;IAgDvD;;;;;;;OAOG;IACH,OAAO,CAAC,mBAAmB;IAa3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqDG;IACI,iBAAiB,CAAC,SAAS,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,iBAAiB,GAAG,IAAI;CAQhG"}
@@ -3,9 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.GuStackForStackSetInstance = exports.GuStack = void 0;
6
+ exports.GuStack = void 0;
7
7
  const aws_cdk_lib_1 = require("aws-cdk-lib");
8
- const assertions_1 = require("aws-cdk-lib/assertions");
9
8
  const git_url_parse_1 = __importDefault(require("git-url-parse"));
10
9
  const aws_backup_1 = require("../../aspects/aws-backup");
11
10
  const cfn_include_reporter_1 = require("../../aspects/cfn-include-reporter");
@@ -196,19 +195,4 @@ class GuStack extends aws_cdk_lib_1.Stack {
196
195
  }
197
196
  }
198
197
  exports.GuStack = GuStack;
199
- /**
200
- * A GuStack but designed for Stack Set instances.
201
- *
202
- * In a stack set application, `GuStackForStackSetInstance` is used to represent the infrastructure to provision in target AWS accounts.
203
- */
204
- class GuStackForStackSetInstance extends GuStack {
205
- // eslint-disable-next-line custom-rules/valid-constructors -- GuStackForStackSet should have a unique `App`
206
- constructor(id, props) {
207
- super(new aws_cdk_lib_1.App(), id, props);
208
- }
209
- get cfnJson() {
210
- return JSON.stringify(assertions_1.Template.fromStack(this).toJSON(), null, 2);
211
- }
212
- }
213
- exports.GuStackForStackSetInstance = GuStackForStackSetInstance;
214
198
  //# sourceMappingURL=stack.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stack.js","sourceRoot":"","sources":["../../../src/constructs/core/stack.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CfnElement, StackProps } from \"aws-cdk-lib\";\nimport { Annotations, App, Aspects, CfnParameter, LegacyStackSynthesizer, Stack, Tags } from \"aws-cdk-lib\";\nimport { Template } from \"aws-cdk-lib/assertions\";\nimport type { IConstruct } from \"constructs\";\nimport gitUrlParse from \"git-url-parse\";\nimport { AwsBackupTag } from \"../../aspects/aws-backup\";\nimport { CfnIncludeReporter } from \"../../aspects/cfn-include-reporter\";\nimport { CfnParameterReporter } from \"../../aspects/cfn-parameter-reporter\";\nimport { Metadata } from \"../../aspects/metadata\";\nimport { ContextKeys, MetadataKeys, TrackingTag } from \"../../constants\";\nimport { gitRemoteOriginUrl } from \"../../utils/git\";\nimport type { StackStageIdentity } from \"./identity\";\nimport type { GuStaticLogicalId } from \"./migrating\";\n\nexport interface GuStackProps extends Omit<StackProps, \"stackName\"> {\n /**\n * The Guardian stack being used (as defined in your riff-raff.yaml).\n * This will be applied as a tag to all of your resources.\n */\n stack: string;\n\n stage: string;\n\n /**\n * Optional name of the app. If defined, all resources will have an App tag.\n */\n app?: string;\n\n /**\n * The AWS CloudFormation stack name (as shown in the AWS CloudFormation UI).\n * @defaultValue the `GU_CFN_STACK_NAME` environment variable\n */\n cloudFormationStackName?: string;\n /**\n * Set this to true to stop the GuStack from tagging all of your AWS resources.\n * This should only be turned on as part of an initial migration from CloudFormation.\n */\n withoutTags?: boolean;\n\n /**\n * Set to disable CDK metadata. Only for internal use (for disabling for some\n * snapshot tests). We rely on tracking data to prioritise future work so\n * please do not override this.\n */\n withoutMetadata?: boolean;\n\n /**\n * Set to enable all resources in the stack for backup provided by https://github.com/guardian/aws-backup.\n *\n * @default false - backups are not enabled\n *\n * @see https://github.com/guardian/aws-backup\n */\n withBackup?: boolean;\n}\n\n/**\n * GuStack provides the `stack` and `stage` parameters to a template.\n * It also takes the `app` in the constructor.\n *\n * GuStack will add the Stack, Stage and App tags to all resources.\n *\n * GuStack also adds the tag `X-Gu-CDK-Version`.\n * This tag allows us to measure adoption of this library.\n * It's value is the version of guardian/cdk being used, as defined in `package.json`.\n * As a result, the change sets between version numbers will be fairly noisy,\n * as all resources receive a tag update.\n * It is recommended to upgrade the version of @guardian/cdk being used in two steps:\n * 1. Bump the library, apply the tag updates\n * 2. Make any other stack changes\n *\n * Typical usage is to extend GuStack:\n *\n * ```typescript\n * class MyStack extends GuStack {\n * constructor(scope: App, id: string, props: GuStackProps) {\n * super(scope, id, props)\n * }\n *\n * // add resources here\n * }\n * ```\n */\nexport class GuStack extends Stack implements StackStageIdentity {\n private readonly _stack: string;\n private readonly _stage: string;\n private readonly _app?: string;\n private readonly _repositoryName?: string;\n\n get stage(): string {\n return this._stage;\n }\n\n get stack(): string {\n return this._stack;\n }\n\n get app(): string | undefined {\n return this._app;\n }\n\n /**\n * The repository name, if it can be determined from the context or the git remote origin url.\n * If it cannot be determined from either of these sources, it will be `undefined`.\n */\n get repositoryName(): string | undefined {\n return this._repositoryName;\n }\n\n /**\n * A helper function to add a tag to all resources in a stack.\n *\n * Note: tags will be listed in alphabetical order during synthesis.\n *\n * @param key the tag name\n * @param value the value of the tag\n * @param applyToLaunchedInstances whether or not to apply the tag to instances launched in an ASG.\n * @protected\n */\n protected addTag(key: string, value: string, applyToLaunchedInstances: boolean = true): void {\n // TODO add validation for `key` and `value`\n // see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resource-tags.html\n Tags.of(this).add(key, value, { applyToLaunchedInstances });\n }\n\n /**\n * Returns all the parameters on this stack.\n *\n * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html\n */\n get parameters(): Record<string, CfnParameter> {\n return this.node\n .findAll()\n .filter((construct) => construct instanceof CfnParameter)\n .reduce((acc, param) => ({ ...acc, [param.node.id]: param as CfnParameter }), {});\n }\n\n // eslint-disable-next-line custom-rules/valid-constructors -- GuStack is the exception as it must take an App\n constructor(scope: App, id: string, props: GuStackProps) {\n const {\n cloudFormationStackName = process.env.GU_CFN_STACK_NAME,\n stack,\n stage,\n withoutTags,\n withBackup = false,\n } = props;\n\n super(scope, id, {\n ...props,\n stackName: cloudFormationStackName,\n\n // TODO Use `DefaultStackSynthesizer` or create own synthesizer?\n // see https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html#bootstrapping-custom-synth\n synthesizer: new LegacyStackSynthesizer(),\n });\n\n this._stack = stack;\n this._stage = stage.toUpperCase();\n this._repositoryName = this.tryGetRepositoryTag();\n\n if (!withoutTags) {\n this.addTag(TrackingTag.Key, TrackingTag.Value);\n\n this.addTag(\"Stack\", this.stack);\n this.addTag(\"Stage\", this.stage);\n if (this.app) {\n this.addTag(\"App\", this.app);\n }\n\n if (this.repositoryName) {\n this.addTag(MetadataKeys.REPOSITORY_NAME, this.repositoryName);\n }\n }\n\n if (!props.withoutMetadata) {\n Aspects.of(this).add(new Metadata(this));\n }\n\n Aspects.of(this).add(new CfnIncludeReporter());\n Aspects.of(this).add(new CfnParameterReporter());\n\n if (withBackup) {\n Aspects.of(this).add(new AwsBackupTag());\n }\n }\n\n /**\n * Returns the repository name.\n * The value is retrieved in the following order:\n * 1. From the context\n * 2. From git config\n *\n * @private\n */\n private tryGetRepositoryTag(): string | undefined {\n try {\n const urlFromContext = this.node.tryGetContext(ContextKeys.REPOSITORY_URL) as string | undefined;\n const repositoryUrl: string = urlFromContext ?? gitRemoteOriginUrl();\n return gitUrlParse(repositoryUrl).full_name;\n } catch {\n console.info(\n `Unable to find git repository name. Set the ${ContextKeys.REPOSITORY_URL} context value or configure a git remote`,\n );\n return undefined;\n }\n }\n\n /**\n * Override the auto-generated logical ID for a resource, in the generated CloudFormation template, with a static one.\n *\n * Of particular use when migrating a JSON/YAML CloudFormation template into GuCDK.\n * It's generally advised to retain the logical ID for stateful resources, such as databases or buckets.\n *\n * Let's say we have a YAML template:\n *\n * ```yaml\n * AWSTemplateFormatVersion: '2010-09-09'\n * Resources:\n * UsesTable:\n * Type: AWS::DynamoDB::Table\n * Properties:\n * TableName: !Sub 'users-${stage}'\n * ```\n *\n * When moving to GuCDK we'll have this:\n *\n * class MyStack extends GuStack {\n * constructor(app: App, id: string, props: GuStackProps) {\n * super(app, id, props);\n *\n * const { stage } = this;\n *\n * new Table(this, \"UsersTable\", {\n * name: `users-${stage}`\n * });\n * }\n * }\n *\n * During synthesis, CDK auto-generates logical IDs, so we'll have a stack with a DynamoDB table named 'UsersTable<SOME GUID>', NOT `UsersTable`.\n * That is, the `UsersTable` table will be deleted.\n *\n * In order to retain the original ID from the YAML template, we will do:\n *\n * class MyStack extends GuStack {\n * constructor(app: App, id: string, props: GuStackProps) {\n * super(app, id, props);\n *\n * const { stage } = this;\n *\n * const table = new Table(this, \"UsersTable\", {\n * name: `users-${stage}`\n * });\n *\n * this.overrideLogicalId(table, { logicalId: \"UsersTable\", reason: \"Retaining a stateful resource from the YAML template\" });\n * }\n * }\n *\n * @param construct The (stateful) resource to retain the logical ID of.\n * @param logicalId The logical ID of the resource (as defined in the JSON/YAML template.\n * @param reason A small explanation to keep the logical ID. Mainly used to help future developers.\n */\n public overrideLogicalId(construct: IConstruct, { logicalId, reason }: GuStaticLogicalId): void {\n const {\n node: { id, defaultChild },\n } = construct;\n\n (defaultChild as CfnElement).overrideLogicalId(logicalId);\n Annotations.of(construct).addInfo(`Setting logical ID for ${id} to ${logicalId}. Reason: ${reason}`);\n }\n}\n\n/**\n * A GuStack but designed for Stack Set instances.\n *\n * In a stack set application, `GuStackForStackSetInstance` is used to represent the infrastructure to provision in target AWS accounts.\n */\nexport class GuStackForStackSetInstance extends GuStack {\n // eslint-disable-next-line custom-rules/valid-constructors -- GuStackForStackSet should have a unique `App`\n constructor(id: string, props: GuStackProps) {\n super(new App(), id, props);\n }\n\n get cfnJson(): string {\n return JSON.stringify(Template.fromStack(this).toJSON(), null, 2);\n }\n}\n"]}
1
+ {"version":3,"file":"stack.js","sourceRoot":"","sources":["../../../src/constructs/core/stack.ts"],"names":[],"mappings":"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","sourcesContent":["import type { App, CfnElement, StackProps } from \"aws-cdk-lib\";\nimport { Annotations, Aspects, CfnParameter, LegacyStackSynthesizer, Stack, Tags } from \"aws-cdk-lib\";\nimport type { IConstruct } from \"constructs\";\nimport gitUrlParse from \"git-url-parse\";\nimport { AwsBackupTag } from \"../../aspects/aws-backup\";\nimport { CfnIncludeReporter } from \"../../aspects/cfn-include-reporter\";\nimport { CfnParameterReporter } from \"../../aspects/cfn-parameter-reporter\";\nimport { Metadata } from \"../../aspects/metadata\";\nimport { ContextKeys, MetadataKeys, TrackingTag } from \"../../constants\";\nimport { gitRemoteOriginUrl } from \"../../utils/git\";\nimport type { StackStageIdentity } from \"./identity\";\nimport type { GuStaticLogicalId } from \"./migrating\";\n\nexport interface GuStackProps extends Omit<StackProps, \"stackName\"> {\n /**\n * The Guardian stack being used (as defined in your riff-raff.yaml).\n * This will be applied as a tag to all of your resources.\n */\n stack: string;\n\n stage: string;\n\n /**\n * Optional name of the app. If defined, all resources will have an App tag.\n */\n app?: string;\n\n /**\n * The AWS CloudFormation stack name (as shown in the AWS CloudFormation UI).\n * @defaultValue the `GU_CFN_STACK_NAME` environment variable\n */\n cloudFormationStackName?: string;\n /**\n * Set this to true to stop the GuStack from tagging all of your AWS resources.\n * This should only be turned on as part of an initial migration from CloudFormation.\n */\n withoutTags?: boolean;\n\n /**\n * Set to disable CDK metadata. Only for internal use (for disabling for some\n * snapshot tests). We rely on tracking data to prioritise future work so\n * please do not override this.\n */\n withoutMetadata?: boolean;\n\n /**\n * Set to enable all resources in the stack for backup provided by https://github.com/guardian/aws-backup.\n *\n * @default false - backups are not enabled\n *\n * @see https://github.com/guardian/aws-backup\n */\n withBackup?: boolean;\n}\n\n/**\n * GuStack provides the `stack` and `stage` parameters to a template.\n * It also takes the `app` in the constructor.\n *\n * GuStack will add the Stack, Stage and App tags to all resources.\n *\n * GuStack also adds the tag `X-Gu-CDK-Version`.\n * This tag allows us to measure adoption of this library.\n * It's value is the version of guardian/cdk being used, as defined in `package.json`.\n * As a result, the change sets between version numbers will be fairly noisy,\n * as all resources receive a tag update.\n * It is recommended to upgrade the version of @guardian/cdk being used in two steps:\n * 1. Bump the library, apply the tag updates\n * 2. Make any other stack changes\n *\n * Typical usage is to extend GuStack:\n *\n * ```typescript\n * class MyStack extends GuStack {\n * constructor(scope: App, id: string, props: GuStackProps) {\n * super(scope, id, props)\n * }\n *\n * // add resources here\n * }\n * ```\n */\nexport class GuStack extends Stack implements StackStageIdentity {\n private readonly _stack: string;\n private readonly _stage: string;\n private readonly _app?: string;\n private readonly _repositoryName?: string;\n\n get stage(): string {\n return this._stage;\n }\n\n get stack(): string {\n return this._stack;\n }\n\n get app(): string | undefined {\n return this._app;\n }\n\n /**\n * The repository name, if it can be determined from the context or the git remote origin url.\n * If it cannot be determined from either of these sources, it will be `undefined`.\n */\n get repositoryName(): string | undefined {\n return this._repositoryName;\n }\n\n /**\n * A helper function to add a tag to all resources in a stack.\n *\n * Note: tags will be listed in alphabetical order during synthesis.\n *\n * @param key the tag name\n * @param value the value of the tag\n * @param applyToLaunchedInstances whether or not to apply the tag to instances launched in an ASG.\n * @protected\n */\n protected addTag(key: string, value: string, applyToLaunchedInstances: boolean = true): void {\n // TODO add validation for `key` and `value`\n // see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resource-tags.html\n Tags.of(this).add(key, value, { applyToLaunchedInstances });\n }\n\n /**\n * Returns all the parameters on this stack.\n *\n * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html\n */\n get parameters(): Record<string, CfnParameter> {\n return this.node\n .findAll()\n .filter((construct) => construct instanceof CfnParameter)\n .reduce((acc, param) => ({ ...acc, [param.node.id]: param as CfnParameter }), {});\n }\n\n // eslint-disable-next-line custom-rules/valid-constructors -- GuStack is the exception as it must take an App\n constructor(scope: App, id: string, props: GuStackProps) {\n const {\n cloudFormationStackName = process.env.GU_CFN_STACK_NAME,\n stack,\n stage,\n withoutTags,\n withBackup = false,\n } = props;\n\n super(scope, id, {\n ...props,\n stackName: cloudFormationStackName,\n\n // TODO Use `DefaultStackSynthesizer` or create own synthesizer?\n // see https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html#bootstrapping-custom-synth\n synthesizer: new LegacyStackSynthesizer(),\n });\n\n this._stack = stack;\n this._stage = stage.toUpperCase();\n this._repositoryName = this.tryGetRepositoryTag();\n\n if (!withoutTags) {\n this.addTag(TrackingTag.Key, TrackingTag.Value);\n\n this.addTag(\"Stack\", this.stack);\n this.addTag(\"Stage\", this.stage);\n if (this.app) {\n this.addTag(\"App\", this.app);\n }\n\n if (this.repositoryName) {\n this.addTag(MetadataKeys.REPOSITORY_NAME, this.repositoryName);\n }\n }\n\n if (!props.withoutMetadata) {\n Aspects.of(this).add(new Metadata(this));\n }\n\n Aspects.of(this).add(new CfnIncludeReporter());\n Aspects.of(this).add(new CfnParameterReporter());\n\n if (withBackup) {\n Aspects.of(this).add(new AwsBackupTag());\n }\n }\n\n /**\n * Returns the repository name.\n * The value is retrieved in the following order:\n * 1. From the context\n * 2. From git config\n *\n * @private\n */\n private tryGetRepositoryTag(): string | undefined {\n try {\n const urlFromContext = this.node.tryGetContext(ContextKeys.REPOSITORY_URL) as string | undefined;\n const repositoryUrl: string = urlFromContext ?? gitRemoteOriginUrl();\n return gitUrlParse(repositoryUrl).full_name;\n } catch {\n console.info(\n `Unable to find git repository name. Set the ${ContextKeys.REPOSITORY_URL} context value or configure a git remote`,\n );\n return undefined;\n }\n }\n\n /**\n * Override the auto-generated logical ID for a resource, in the generated CloudFormation template, with a static one.\n *\n * Of particular use when migrating a JSON/YAML CloudFormation template into GuCDK.\n * It's generally advised to retain the logical ID for stateful resources, such as databases or buckets.\n *\n * Let's say we have a YAML template:\n *\n * ```yaml\n * AWSTemplateFormatVersion: '2010-09-09'\n * Resources:\n * UsesTable:\n * Type: AWS::DynamoDB::Table\n * Properties:\n * TableName: !Sub 'users-${stage}'\n * ```\n *\n * When moving to GuCDK we'll have this:\n *\n * class MyStack extends GuStack {\n * constructor(app: App, id: string, props: GuStackProps) {\n * super(app, id, props);\n *\n * const { stage } = this;\n *\n * new Table(this, \"UsersTable\", {\n * name: `users-${stage}`\n * });\n * }\n * }\n *\n * During synthesis, CDK auto-generates logical IDs, so we'll have a stack with a DynamoDB table named 'UsersTable<SOME GUID>', NOT `UsersTable`.\n * That is, the `UsersTable` table will be deleted.\n *\n * In order to retain the original ID from the YAML template, we will do:\n *\n * class MyStack extends GuStack {\n * constructor(app: App, id: string, props: GuStackProps) {\n * super(app, id, props);\n *\n * const { stage } = this;\n *\n * const table = new Table(this, \"UsersTable\", {\n * name: `users-${stage}`\n * });\n *\n * this.overrideLogicalId(table, { logicalId: \"UsersTable\", reason: \"Retaining a stateful resource from the YAML template\" });\n * }\n * }\n *\n * @param construct The (stateful) resource to retain the logical ID of.\n * @param logicalId The logical ID of the resource (as defined in the JSON/YAML template.\n * @param reason A small explanation to keep the logical ID. Mainly used to help future developers.\n */\n public overrideLogicalId(construct: IConstruct, { logicalId, reason }: GuStaticLogicalId): void {\n const {\n node: { id, defaultChild },\n } = construct;\n\n (defaultChild as CfnElement).overrideLogicalId(logicalId);\n Annotations.of(construct).addInfo(`Setting logical ID for ${id} to ${logicalId}. Reason: ${reason}`);\n }\n}\n"]}
@@ -2,12 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.addAmiParametersToCloudFormationDeployment = exports.cloudFormationDeployment = void 0;
4
4
  function cloudFormationDeployment(cdkStacks, dependencies, contentDirectory) {
5
- if (cdkStacks.length === 0) {
5
+ // The stacks in `cdkStacks` only differ by stage, so we can just use the first item in the list for key information.
6
+ const [cdkStack] = cdkStacks;
7
+ if (!cdkStack) {
6
8
  throw new Error("Unable to produce a working riff-raff.yaml file; there are no stacks!");
7
9
  }
8
- // The stacks in `cdkStacks` only differ by stage, so we can just use the first item in the list for key information.
9
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length of `cdkStacks` is checked above
10
- const cdkStack = cdkStacks[0];
11
10
  const { region, stack, constructor: { name }, } = cdkStack;
12
11
  // TODO remove `lodash.kebabcase` dep as it's not that much code to kebab-ise a string...
13
12
  const kebabClassName = name.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
@@ -1 +1 @@
1
- {"version":3,"file":"cloudformation.js","sourceRoot":"","sources":["../../../src/riff-raff-yaml-file/deployments/cloudformation.ts"],"names":[],"mappings":"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","sourcesContent":["import type { GuAutoScalingGroup } from \"../../constructs/autoscaling\";\nimport type { CdkStacksDifferingOnlyByStage, RiffRaffDeployment, RiffRaffDeploymentProps } from \"../types\";\n\nexport function cloudFormationDeployment(\n cdkStacks: CdkStacksDifferingOnlyByStage,\n dependencies: RiffRaffDeployment[],\n contentDirectory: string,\n): RiffRaffDeployment {\n if (cdkStacks.length === 0) {\n throw new Error(\"Unable to produce a working riff-raff.yaml file; there are no stacks!\");\n }\n\n // The stacks in `cdkStacks` only differ by stage, so we can just use the first item in the list for key information.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length of `cdkStacks` is checked above\n const cdkStack = cdkStacks[0]!;\n const {\n region,\n stack,\n constructor: { name },\n } = cdkStack;\n\n // TODO remove `lodash.kebabcase` dep as it's not that much code to kebab-ise a string...\n const kebabClassName = name.replace(/([a-z])([A-Z])/g, \"$1-$2\").toLowerCase();\n\n const templateStagePaths = cdkStacks.reduce(\n (acc, { stage, templateFile }) => ({\n ...acc,\n [stage]: templateFile,\n }),\n {},\n );\n\n return {\n name: [\"cfn\", region, stack, kebabClassName].join(\"-\"),\n props: {\n type: \"cloud-formation\",\n regions: new Set([region]),\n stacks: new Set([stack]),\n app: kebabClassName,\n contentDirectory,\n parameters: {\n templateStagePaths,\n },\n // only add the `dependencies` property if there are some\n ...(dependencies.length > 0 && { dependencies: dependencies.map(({ name }) => name) }),\n },\n };\n}\n\nexport function addAmiParametersToCloudFormationDeployment(\n cfnDeployment: RiffRaffDeployment,\n autoScalingGroups: GuAutoScalingGroup[],\n): RiffRaffDeploymentProps {\n const amiParametersToTags = autoScalingGroups.reduce((acc, asg) => {\n const { imageRecipe, app, amiParameter } = asg;\n\n if (!imageRecipe) {\n throw new Error(`Unable to produce a working riff-raff.yaml file; imageRecipe missing from ASG ${app}`);\n }\n\n const Recipe = typeof imageRecipe === \"string\" ? imageRecipe : imageRecipe.Recipe;\n const AmigoStage = typeof imageRecipe === \"string\" ? \"PROD\" : imageRecipe.AmigoStage ?? \"PROD\";\n\n // In YAML `true` is a Boolean. Riff-Raff expects a String here, so call `toString` to make it `'true'`.\n const Encrypted = (typeof imageRecipe === \"string\" ? true : imageRecipe.Encrypted ?? true).toString();\n\n return {\n ...acc,\n [amiParameter.node.id]: {\n BuiltBy: \"amigo\",\n AmigoStage,\n Recipe,\n Encrypted,\n },\n };\n }, {});\n\n return {\n ...cfnDeployment.props,\n parameters: {\n ...cfnDeployment.props.parameters,\n\n // only add the `amiParametersToTags` property if there are some\n ...(autoScalingGroups.length > 0 && { amiParametersToTags }),\n },\n };\n}\n"]}
1
+ {"version":3,"file":"cloudformation.js","sourceRoot":"","sources":["../../../src/riff-raff-yaml-file/deployments/cloudformation.ts"],"names":[],"mappings":"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","sourcesContent":["import type { GuAutoScalingGroup } from \"../../constructs/autoscaling\";\nimport type { CdkStacksDifferingOnlyByStage, RiffRaffDeployment, RiffRaffDeploymentProps } from \"../types\";\n\nexport function cloudFormationDeployment(\n cdkStacks: CdkStacksDifferingOnlyByStage,\n dependencies: RiffRaffDeployment[],\n contentDirectory: string,\n): RiffRaffDeployment {\n // The stacks in `cdkStacks` only differ by stage, so we can just use the first item in the list for key information.\n const [cdkStack] = cdkStacks;\n\n if (!cdkStack) {\n throw new Error(\"Unable to produce a working riff-raff.yaml file; there are no stacks!\");\n }\n\n const {\n region,\n stack,\n constructor: { name },\n } = cdkStack;\n\n // TODO remove `lodash.kebabcase` dep as it's not that much code to kebab-ise a string...\n const kebabClassName = name.replace(/([a-z])([A-Z])/g, \"$1-$2\").toLowerCase();\n\n const templateStagePaths = cdkStacks.reduce(\n (acc, { stage, templateFile }) => ({\n ...acc,\n [stage]: templateFile,\n }),\n {},\n );\n\n return {\n name: [\"cfn\", region, stack, kebabClassName].join(\"-\"),\n props: {\n type: \"cloud-formation\",\n regions: new Set([region]),\n stacks: new Set([stack]),\n app: kebabClassName,\n contentDirectory,\n parameters: {\n templateStagePaths,\n },\n // only add the `dependencies` property if there are some\n ...(dependencies.length > 0 && { dependencies: dependencies.map(({ name }) => name) }),\n },\n };\n}\n\nexport function addAmiParametersToCloudFormationDeployment(\n cfnDeployment: RiffRaffDeployment,\n autoScalingGroups: GuAutoScalingGroup[],\n): RiffRaffDeploymentProps {\n const amiParametersToTags = autoScalingGroups.reduce((acc, asg) => {\n const { imageRecipe, app, amiParameter } = asg;\n\n if (!imageRecipe) {\n throw new Error(`Unable to produce a working riff-raff.yaml file; imageRecipe missing from ASG ${app}`);\n }\n\n const Recipe = typeof imageRecipe === \"string\" ? imageRecipe : imageRecipe.Recipe;\n const AmigoStage = typeof imageRecipe === \"string\" ? \"PROD\" : imageRecipe.AmigoStage ?? \"PROD\";\n\n // In YAML `true` is a Boolean. Riff-Raff expects a String here, so call `toString` to make it `'true'`.\n const Encrypted = (typeof imageRecipe === \"string\" ? true : imageRecipe.Encrypted ?? true).toString();\n\n return {\n ...acc,\n [amiParameter.node.id]: {\n BuiltBy: \"amigo\",\n AmigoStage,\n Recipe,\n Encrypted,\n },\n };\n }, {});\n\n return {\n ...cfnDeployment.props,\n parameters: {\n ...cfnDeployment.props.parameters,\n\n // only add the `amiParametersToTags` property if there are some\n ...(autoScalingGroups.length > 0 && { amiParametersToTags }),\n },\n };\n}\n"]}
@@ -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;AAUvC,OAAO,KAAK,EAMV,YAAY,EAGb,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAY;IACzC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAW;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC;;;;;;;;;;OAUG;IACH,SAAgB,YAAY,EAAE,YAAY,CAAC;IAE3C,OAAO,CAAC,iBAAiB;IASzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqDG;IACH,OAAO,CAAC,mBAAmB;IAiC3B,OAAO,CAAC,6BAA6B;IAQrC,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,sBAAsB;gBAKlB,GAAG,EAAE,GAAG;IAwEpB;;;OAGG;IACH,MAAM,IAAI,MAAM;IAiBhB;;;OAGG;IACH,KAAK,IAAI,IAAI;CAId"}
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;AAUvC,OAAO,KAAK,EAMV,YAAY,EAGb,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAY;IACzC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAW;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC;;;;;;;;;;OAUG;IACH,SAAgB,YAAY,EAAE,YAAY,CAAC;IAE3C,OAAO,CAAC,iBAAiB;IASzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqDG;IACH,OAAO,CAAC,mBAAmB;IAiC3B,OAAO,CAAC,6BAA6B;IAQrC,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,sBAAsB;gBAKlB,GAAG,EAAE,GAAG;IAuEpB;;;OAGG;IACH,MAAM,IAAI,MAAM;IAiBhB;;;OAGG;IACH,KAAK,IAAI,IAAI;CAId"}
@@ -174,12 +174,11 @@ class RiffRaffYamlFile {
174
174
  Object.values(stackTagGroup).forEach((regionGroup) => {
175
175
  Object.values(regionGroup).forEach((stageGroup) => {
176
176
  const stacks = Object.values(stageGroup).flat();
177
- if (stacks.length === 0) {
177
+ // The items in `stacks` only differ by stage, so we can just use the first item in the list.
178
+ const [stack] = stacks;
179
+ if (!stack) {
178
180
  throw new Error("Unable to produce a working riff-raff.yaml file; there are no stacks!");
179
181
  }
180
- // The items in `stacks` only differ by stage, so we can just use the first item in the list.
181
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length of `stacks` is checked above
182
- const stack = stacks[0];
183
182
  const lambdas = this.getLambdas(stack);
184
183
  const autoscalingGroups = this.getAutoScalingGroups(stack);
185
184
  const artifactUploads = [
@@ -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 { writeFileSync } from \"fs\";\nimport path from \"path\";\nimport type { App } from \"aws-cdk-lib\";\nimport { Token } from \"aws-cdk-lib\";\nimport { dump } from \"js-yaml\";\nimport { GuAutoScalingGroup } from \"../constructs/autoscaling\";\nimport { GuStack } from \"../constructs/core\";\nimport { GuLambdaFunction } from \"../constructs/lambda\";\nimport { autoscalingDeployment, uploadAutoscalingArtifact } from \"./deployments/autoscaling\";\nimport { addAmiParametersToCloudFormationDeployment, cloudFormationDeployment } from \"./deployments/cloudformation\";\nimport { updateLambdaDeployment, uploadLambdaArtifact } from \"./deployments/lambda\";\nimport { groupByClassNameStackRegionStage } from \"./group-by\";\nimport type {\n GroupedCdkStacks,\n Region,\n RiffRaffDeployment,\n RiffRaffDeploymentName,\n RiffRaffDeploymentProps,\n RiffRaffYaml,\n StackTag,\n StageTag,\n} from \"./types\";\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 allCdkStacks: GuStack[];\n private readonly allStackTags: StackTag[];\n private readonly allStageTags: StageTag[];\n private readonly allRegions: Region[];\n private readonly outdir: string;\n\n /**\n * The `riff-raff.yaml` file 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 * In most cases, you shouldn't need to access this.\n * No validation is performed on the parameters you provide, so you might get deployment errors.\n *\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types\n */\n public readonly riffRaffYaml: RiffRaffYaml;\n\n private isCdkStackPresent(expectedStack: StackTag, expectedStage: StageTag): boolean {\n const matches = this.allCdkStacks.find((cdkStack) => {\n const { stack, stage } = cdkStack;\n return stack === expectedStack && stage === expectedStage;\n });\n\n return !!matches;\n }\n\n /**\n * Check there are the appropriate number of `GuStack`s.\n * Expect to find an instance for each combination of `stack`, and `stage`.\n *\n * If not valid, a message is logged describing what is missing to aid debugging.\n *\n * Given the following:\n *\n * ```ts\n * const app = new App();\n *\n * class MyApplicationStack extends GuStack { }\n *\n * new MyApplicationStack(app, \"App-CODE-deploy\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"deploy\",\n * stage: \"CODE\"\n * });\n *\n * new MyApplicationStack(app, \"App-PROD-media-service\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"media-service\",\n * stage: \"PROD\",\n * });\n *\n * new MyApplicationStack(app, \"App-PROD-deploy\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"deploy\",\n * stage: \"PROD\"\n * });\n * ```\n *\n * This will log a message like this, where ❌ denotes something missing,\n * specifically there is no `CODE` template for `media-service`.\n *\n * ```log\n * Unable to produce a working riff-raff.yaml file; missing 1 definitions (details below)\n *\n * ┌───────────────┬──────┬──────┐\n * │ (index) │ CODE │ PROD │\n * ├───────────────┼──────┼──────┤\n * │ deploy │ '✅' │ '✅' │\n * │ media-service │ '❌' │ '✅' │\n * └───────────────┴──────┴──────┘\n * ```\n *\n * @private\n */\n private validateStacksInApp(): void {\n type Found = \"✅\";\n type NotFound = \"❌\";\n type AppValidation = Record<StackTag, Record<StageTag, Found | NotFound>>;\n\n const { allStackTags, allStageTags } = this;\n\n const checks: AppValidation = allStackTags.reduce((accStackTag, stackTag) => {\n return {\n ...accStackTag,\n [stackTag]: allStageTags.reduce((accStageTag, stageTag) => {\n return {\n ...accStageTag,\n [stageTag]: this.isCdkStackPresent(stackTag, stageTag) ? \"✅\" : \"❌\",\n };\n }, {}),\n };\n }, {});\n\n const missingDefinitions: Array<Found | NotFound> = Object.values(checks).flatMap((groupedByStackTag) => {\n return Object.values(groupedByStackTag).filter((_) => _ === \"❌\");\n });\n\n if (missingDefinitions.length > 0) {\n const message = `Unable to produce a working riff-raff.yaml file; missing ${missingDefinitions.length} definitions`;\n\n console.log(`${message} (details below)`);\n console.table(checks);\n\n throw new Error(message);\n }\n }\n\n private validateAllRegionsAreResolved(): void {\n const unresolved = this.allRegions.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\n private getLambdas(cdkStack: GuStack): GuLambdaFunction[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuLambdaFunction) as GuLambdaFunction[];\n }\n\n private getAutoScalingGroups(cdkStack: GuStack): GuAutoScalingGroup[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuAutoScalingGroup) as GuAutoScalingGroup[];\n }\n\n private getGuStackDependencies(cdkStack: GuStack): GuStack[] {\n return cdkStack.dependencies.filter((_) => _ instanceof GuStack) as GuStack[];\n }\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 this.allCdkStacks = app.node.findAll().filter((_) => _ instanceof GuStack) as GuStack[];\n const allowedStages = new Set(this.allCdkStacks.map(({ stage }) => stage));\n this.allStageTags = Array.from(allowedStages);\n this.allStackTags = Array.from(new Set(this.allCdkStacks.map(({ stack }) => stack)));\n this.allRegions = Array.from(new Set(this.allCdkStacks.map(({ region }) => region)));\n\n this.validateStacksInApp();\n this.validateAllRegionsAreResolved();\n\n this.outdir = app.outdir;\n\n const deployments = new Map<RiffRaffDeploymentName, RiffRaffDeploymentProps>();\n\n const groupedStacks: GroupedCdkStacks = groupByClassNameStackRegionStage(this.allCdkStacks);\n\n Object.values(groupedStacks).forEach((stackTagGroup) => {\n Object.values(stackTagGroup).forEach((regionGroup) => {\n Object.values(regionGroup).forEach((stageGroup) => {\n const stacks: GuStack[] = Object.values(stageGroup).flat();\n\n if (stacks.length === 0) {\n throw new Error(\"Unable to produce a working riff-raff.yaml file; there are no stacks!\");\n }\n\n // The items in `stacks` only differ by stage, so we can just use the first item in the list.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length of `stacks` is checked above\n const stack = stacks[0]!;\n\n const lambdas = this.getLambdas(stack);\n const autoscalingGroups = this.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[] = this.getGuStackDependencies(stack).map((x) =>\n cloudFormationDeployment([x], [], this.outdir),\n );\n\n const cfnDeployment = cloudFormationDeployment(stacks, [...artifactUploads, ...parentStacks], this.outdir);\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 autoscalingGroups.forEach((asg) => {\n const asgDeployment = autoscalingDeployment(asg, cfnDeployment);\n deployments.set(asgDeployment.name, asgDeployment.props);\n });\n\n deployments.set(\n cfnDeployment.name,\n addAmiParametersToCloudFormationDeployment(cfnDeployment, autoscalingGroups),\n );\n });\n });\n });\n\n this.riffRaffYaml = {\n allowedStages,\n deployments,\n };\n }\n\n /**\n * The `riff-raff.yaml` file as a string.\n * Useful for testing.\n */\n toYAML(): 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 return dump(this.riffRaffYaml, { replacer });\n }\n\n /**\n * Write the `riff-raff.yaml` file to disk.\n * It'll be located with the CFN JSON templates generated by `cdk synth`.\n */\n synth(): void {\n const outPath = path.join(this.outdir, \"riff-raff.yaml\");\n writeFileSync(outPath, this.toYAML());\n }\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 { writeFileSync } from \"fs\";\nimport path from \"path\";\nimport type { App } from \"aws-cdk-lib\";\nimport { Token } from \"aws-cdk-lib\";\nimport { dump } from \"js-yaml\";\nimport { GuAutoScalingGroup } from \"../constructs/autoscaling\";\nimport { GuStack } from \"../constructs/core\";\nimport { GuLambdaFunction } from \"../constructs/lambda\";\nimport { autoscalingDeployment, uploadAutoscalingArtifact } from \"./deployments/autoscaling\";\nimport { addAmiParametersToCloudFormationDeployment, cloudFormationDeployment } from \"./deployments/cloudformation\";\nimport { updateLambdaDeployment, uploadLambdaArtifact } from \"./deployments/lambda\";\nimport { groupByClassNameStackRegionStage } from \"./group-by\";\nimport type {\n GroupedCdkStacks,\n Region,\n RiffRaffDeployment,\n RiffRaffDeploymentName,\n RiffRaffDeploymentProps,\n RiffRaffYaml,\n StackTag,\n StageTag,\n} from \"./types\";\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 allCdkStacks: GuStack[];\n private readonly allStackTags: StackTag[];\n private readonly allStageTags: StageTag[];\n private readonly allRegions: Region[];\n private readonly outdir: string;\n\n /**\n * The `riff-raff.yaml` file 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 * In most cases, you shouldn't need to access this.\n * No validation is performed on the parameters you provide, so you might get deployment errors.\n *\n * @see https://riffraff.gutools.co.uk/docs/magenta-lib/types\n */\n public readonly riffRaffYaml: RiffRaffYaml;\n\n private isCdkStackPresent(expectedStack: StackTag, expectedStage: StageTag): boolean {\n const matches = this.allCdkStacks.find((cdkStack) => {\n const { stack, stage } = cdkStack;\n return stack === expectedStack && stage === expectedStage;\n });\n\n return !!matches;\n }\n\n /**\n * Check there are the appropriate number of `GuStack`s.\n * Expect to find an instance for each combination of `stack`, and `stage`.\n *\n * If not valid, a message is logged describing what is missing to aid debugging.\n *\n * Given the following:\n *\n * ```ts\n * const app = new App();\n *\n * class MyApplicationStack extends GuStack { }\n *\n * new MyApplicationStack(app, \"App-CODE-deploy\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"deploy\",\n * stage: \"CODE\"\n * });\n *\n * new MyApplicationStack(app, \"App-PROD-media-service\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"media-service\",\n * stage: \"PROD\",\n * });\n *\n * new MyApplicationStack(app, \"App-PROD-deploy\", {\n * env: {\n * region: \"eu-west-1\",\n * },\n * stack: \"deploy\",\n * stage: \"PROD\"\n * });\n * ```\n *\n * This will log a message like this, where ❌ denotes something missing,\n * specifically there is no `CODE` template for `media-service`.\n *\n * ```log\n * Unable to produce a working riff-raff.yaml file; missing 1 definitions (details below)\n *\n * ┌───────────────┬──────┬──────┐\n * │ (index) │ CODE │ PROD │\n * ├───────────────┼──────┼──────┤\n * │ deploy │ '✅' │ '✅' │\n * │ media-service │ '❌' │ '✅' │\n * └───────────────┴──────┴──────┘\n * ```\n *\n * @private\n */\n private validateStacksInApp(): void {\n type Found = \"✅\";\n type NotFound = \"❌\";\n type AppValidation = Record<StackTag, Record<StageTag, Found | NotFound>>;\n\n const { allStackTags, allStageTags } = this;\n\n const checks: AppValidation = allStackTags.reduce((accStackTag, stackTag) => {\n return {\n ...accStackTag,\n [stackTag]: allStageTags.reduce((accStageTag, stageTag) => {\n return {\n ...accStageTag,\n [stageTag]: this.isCdkStackPresent(stackTag, stageTag) ? \"✅\" : \"❌\",\n };\n }, {}),\n };\n }, {});\n\n const missingDefinitions: Array<Found | NotFound> = Object.values(checks).flatMap((groupedByStackTag) => {\n return Object.values(groupedByStackTag).filter((_) => _ === \"❌\");\n });\n\n if (missingDefinitions.length > 0) {\n const message = `Unable to produce a working riff-raff.yaml file; missing ${missingDefinitions.length} definitions`;\n\n console.log(`${message} (details below)`);\n console.table(checks);\n\n throw new Error(message);\n }\n }\n\n private validateAllRegionsAreResolved(): void {\n const unresolved = this.allRegions.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\n private getLambdas(cdkStack: GuStack): GuLambdaFunction[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuLambdaFunction) as GuLambdaFunction[];\n }\n\n private getAutoScalingGroups(cdkStack: GuStack): GuAutoScalingGroup[] {\n return cdkStack.node.findAll().filter((_) => _ instanceof GuAutoScalingGroup) as GuAutoScalingGroup[];\n }\n\n private getGuStackDependencies(cdkStack: GuStack): GuStack[] {\n return cdkStack.dependencies.filter((_) => _ instanceof GuStack) as GuStack[];\n }\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 this.allCdkStacks = app.node.findAll().filter((_) => _ instanceof GuStack) as GuStack[];\n const allowedStages = new Set(this.allCdkStacks.map(({ stage }) => stage));\n this.allStageTags = Array.from(allowedStages);\n this.allStackTags = Array.from(new Set(this.allCdkStacks.map(({ stack }) => stack)));\n this.allRegions = Array.from(new Set(this.allCdkStacks.map(({ region }) => region)));\n\n this.validateStacksInApp();\n this.validateAllRegionsAreResolved();\n\n this.outdir = app.outdir;\n\n const deployments = new Map<RiffRaffDeploymentName, RiffRaffDeploymentProps>();\n\n const groupedStacks: GroupedCdkStacks = groupByClassNameStackRegionStage(this.allCdkStacks);\n\n Object.values(groupedStacks).forEach((stackTagGroup) => {\n Object.values(stackTagGroup).forEach((regionGroup) => {\n Object.values(regionGroup).forEach((stageGroup) => {\n const stacks: GuStack[] = Object.values(stageGroup).flat();\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 = this.getLambdas(stack);\n const autoscalingGroups = this.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[] = this.getGuStackDependencies(stack).map((x) =>\n cloudFormationDeployment([x], [], this.outdir),\n );\n\n const cfnDeployment = cloudFormationDeployment(stacks, [...artifactUploads, ...parentStacks], this.outdir);\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 autoscalingGroups.forEach((asg) => {\n const asgDeployment = autoscalingDeployment(asg, cfnDeployment);\n deployments.set(asgDeployment.name, asgDeployment.props);\n });\n\n deployments.set(\n cfnDeployment.name,\n addAmiParametersToCloudFormationDeployment(cfnDeployment, autoscalingGroups),\n );\n });\n });\n });\n\n this.riffRaffYaml = {\n allowedStages,\n deployments,\n };\n }\n\n /**\n * The `riff-raff.yaml` file as a string.\n * Useful for testing.\n */\n toYAML(): 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 return dump(this.riffRaffYaml, { replacer });\n }\n\n /**\n * Write the `riff-raff.yaml` file to disk.\n * It'll be located with the CFN JSON templates generated by `cdk synth`.\n */\n synth(): void {\n const outPath = path.join(this.outdir, \"riff-raff.yaml\");\n writeFileSync(outPath, this.toYAML());\n }\n}\n"]}