@codedrifters/configulator 0.0.196 → 0.0.197

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.
package/lib/index.mjs CHANGED
@@ -6140,6 +6140,210 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component16 {
6140
6140
  }
6141
6141
  };
6142
6142
 
6143
+ // src/workflows/aws-teardown-workflow.ts
6144
+ import { Component as Component17 } from "projen";
6145
+ import { GitHub as GitHub3, GithubWorkflow } from "projen/lib/github";
6146
+ import { JobPermission as JobPermission6 } from "projen/lib/github/workflows-model";
6147
+ var DEFAULT_TEARDOWN_BRANCH_PATTERNS = [
6148
+ "feat/*",
6149
+ "fix/*",
6150
+ "feature/*"
6151
+ ];
6152
+ var resolveBranchPatterns = (explicit, targets) => {
6153
+ if (explicit && explicit.length > 0) {
6154
+ return [...explicit];
6155
+ }
6156
+ const derived = Array.from(
6157
+ new Set(
6158
+ targets.flatMap((target) => target.branches.map((b) => b.branch)).filter((branch) => typeof branch === "string").filter((branch) => branch.includes("*"))
6159
+ )
6160
+ );
6161
+ if (derived.length > 0) {
6162
+ return derived;
6163
+ }
6164
+ return [...DEFAULT_TEARDOWN_BRANCH_PATTERNS];
6165
+ };
6166
+ var AwsTeardownWorkflow = class extends Component17 {
6167
+ constructor(rootProject, options) {
6168
+ super(rootProject);
6169
+ this.rootProject = rootProject;
6170
+ const {
6171
+ awsDestructionTargets,
6172
+ repoTagName,
6173
+ stageTypeTagName,
6174
+ environmentTypeTagName,
6175
+ branchNameTagName,
6176
+ deleteBranchPatterns
6177
+ } = options;
6178
+ if (!repoTagName) {
6179
+ throw new Error("AwsTeardownWorkflow requires `repoTagName`");
6180
+ }
6181
+ if (!stageTypeTagName) {
6182
+ throw new Error("AwsTeardownWorkflow requires `stageTypeTagName`");
6183
+ }
6184
+ if (!environmentTypeTagName) {
6185
+ throw new Error("AwsTeardownWorkflow requires `environmentTypeTagName`");
6186
+ }
6187
+ if (!branchNameTagName) {
6188
+ throw new Error("AwsTeardownWorkflow requires `branchNameTagName`");
6189
+ }
6190
+ if (!(rootProject instanceof MonorepoProject)) {
6191
+ throw new Error(
6192
+ "AwsTeardownWorkflow requires the root project to be a MonorepoProject"
6193
+ );
6194
+ }
6195
+ const github = GitHub3.of(this.rootProject);
6196
+ if (!github) {
6197
+ throw new Error(
6198
+ "AwsTeardownWorkflow requires a GitHub component in the root project"
6199
+ );
6200
+ }
6201
+ const branchPatterns = resolveBranchPatterns(
6202
+ deleteBranchPatterns,
6203
+ awsDestructionTargets
6204
+ );
6205
+ const workflow = new GithubWorkflow(github, "teardown-dev");
6206
+ workflow.on({
6207
+ workflowDispatch: {},
6208
+ schedule: [
6209
+ {
6210
+ cron: "32 6 * * *"
6211
+ }
6212
+ ],
6213
+ delete: {
6214
+ branches: branchPatterns
6215
+ }
6216
+ });
6217
+ awsDestructionTargets.forEach((target) => {
6218
+ const {
6219
+ awsStageType,
6220
+ deploymentTargetRole,
6221
+ account,
6222
+ region,
6223
+ ciDeploymentConfig
6224
+ } = target;
6225
+ const { roleArn } = ciDeploymentConfig ?? {};
6226
+ workflow.addJob(
6227
+ `teardown-${awsStageType}-${deploymentTargetRole}-${account}-${region}`.toLowerCase(),
6228
+ {
6229
+ name: `Teardown Stacks in ${awsStageType}/${deploymentTargetRole}/${account}/${region}`,
6230
+ runsOn: ["ubuntu-latest"],
6231
+ permissions: {
6232
+ contents: JobPermission6.READ,
6233
+ idToken: JobPermission6.WRITE
6234
+ },
6235
+ env: {
6236
+ REPO: "${{ github.repository }}",
6237
+ REGIONS: [region].join(" ")
6238
+ },
6239
+ steps: [
6240
+ {
6241
+ name: `AWS Creds ${account}/${region}`,
6242
+ uses: "aws-actions/configure-aws-credentials@v6",
6243
+ with: {
6244
+ "role-to-assume": roleArn,
6245
+ "aws-region": region,
6246
+ "role-duration-seconds": 900
6247
+ }
6248
+ },
6249
+ {
6250
+ name: "Fetch All Branches",
6251
+ id: "fetch_branches",
6252
+ uses: "actions/github-script@v9",
6253
+ with: {
6254
+ script: [
6255
+ "const all = await github.paginate(github.rest.repos.listBranches, {",
6256
+ " owner: context.repo.owner,",
6257
+ " repo: context.repo.repo,",
6258
+ " per_page: 100",
6259
+ "});",
6260
+ "const names = all.map(b => b.name);",
6261
+ "console.log(`Found branches: ${names}`);",
6262
+ 'core.setOutput("json", JSON.stringify(names));'
6263
+ ].join("\n")
6264
+ }
6265
+ },
6266
+ {
6267
+ name: "Save Branches to File",
6268
+ run: [
6269
+ 'echo "Saving branches to file"',
6270
+ "echo '${{ steps.fetch_branches.outputs.json }}' | jq -r '.[]' | sort -u > branches.txt",
6271
+ 'echo "Branches:"',
6272
+ "cat branches.txt"
6273
+ ].join("\n")
6274
+ },
6275
+ {
6276
+ name: "Find Stacks by Tag",
6277
+ id: "find_stacks",
6278
+ run: [
6279
+ "set -euo pipefail",
6280
+ ": > candidates.txt # columns: arn region branchTag",
6281
+ "# Build tag filters",
6282
+ `TAG_FILTERS=( "Key=${repoTagName},Values=$REPO" )`,
6283
+ `TAG_FILTERS+=( "Key=${stageTypeTagName},Values=${awsStageType}" )`,
6284
+ `TAG_FILTERS+=( "Key=${environmentTypeTagName},Values=${deploymentTargetRole}" )`,
6285
+ "for r in $REGIONS; do",
6286
+ ` echo "Scanning region: $r"`,
6287
+ " aws resourcegroupstaggingapi get-resources \\",
6288
+ ' --region "$r" \\',
6289
+ ' --resource-type-filters "cloudformation:stack" \\',
6290
+ ' --tag-filters "${TAG_FILTERS[@]}" \\',
6291
+ ` | jq -r --arg r "$r" '`,
6292
+ " .ResourceTagMappingList[]",
6293
+ " | . as $res",
6294
+ ` | ($res.Tags[] | select(.Key=="${branchNameTagName}") | .Value) as $branch`,
6295
+ ' | [$res.ResourceARN, $r, ($branch // "")]',
6296
+ " | @tsv",
6297
+ " ' >> candidates.txt",
6298
+ "done",
6299
+ "echo 'Tagged stacks:'",
6300
+ `(echo -e "ARN\\tREGION\\tBRANCH"; cat candidates.txt) | column -t -s $'\\t'`
6301
+ ].join("\n")
6302
+ },
6303
+ {
6304
+ name: "Determine Orphan Stacks (No Matching Branch)",
6305
+ run: [
6306
+ "set -euo pipefail",
6307
+ ": > orphans.txt # arn region branch",
6308
+ "while IFS=$'\\t' read -r arn region branch; do",
6309
+ ' [ -z "$arn" ] && continue',
6310
+ ' if [ -z "$branch" ]; then',
6311
+ " # If no Branch tag, treat as not-a-preview; skip",
6312
+ " continue",
6313
+ " fi",
6314
+ ' if ! grep -Fxq "$branch" branches.txt; then',
6315
+ ' echo -e "$arn\\t$region\\t$branch" >> orphans.txt',
6316
+ " fi",
6317
+ "done < candidates.txt",
6318
+ "",
6319
+ "if [ -s orphans.txt ]; then",
6320
+ ' echo "Orphan stacks (no matching branch):"',
6321
+ ` (echo -e "ARN\\tREGION\\tBRANCH"; cat orphans.txt) | column -t -s $'\\t'`,
6322
+ "else",
6323
+ ' echo "No orphan stacks found."',
6324
+ "fi"
6325
+ ].join("\n")
6326
+ },
6327
+ {
6328
+ name: "Delete Orphan Stacks",
6329
+ if: "hashFiles('orphans.txt') != ''",
6330
+ run: [
6331
+ "set -euo pipefail",
6332
+ "while IFS=$'\\t' read -r arn region branch; do",
6333
+ ' [ -z "$arn" ] && continue',
6334
+ ` stack_name=$(cut -d'/' -f2 <<<"$arn")`,
6335
+ ' echo "Deleting $stack_name (branch=$branch) in $region"',
6336
+ ' aws cloudformation delete-stack --region "$region" --stack-name "$stack_name" || true',
6337
+ "done < orphans.txt"
6338
+ ].join("\n")
6339
+ }
6340
+ ]
6341
+ }
6342
+ );
6343
+ });
6344
+ }
6345
+ };
6346
+
6143
6347
  // src/projects/aws-cdk-project.ts
6144
6348
  var AwsCdkProject = class extends awscdk.AwsCdkTypeScriptApp {
6145
6349
  constructor(userOptions) {
@@ -6272,6 +6476,9 @@ var AwsCdkProject = class extends awscdk.AwsCdkTypeScriptApp {
6272
6476
  deployWorkflows.forEach(
6273
6477
  (workflowOptions) => new AwsDeployWorkflow(this, workflowOptions)
6274
6478
  );
6479
+ if (options.teardownWorkflow) {
6480
+ new AwsTeardownWorkflow(parent, options.teardownWorkflow);
6481
+ }
6275
6482
  const turboActive = TurboRepo.of(parent) !== void 0;
6276
6483
  if (turboActive) {
6277
6484
  const turbo = new TurboRepo(this);
@@ -6332,9 +6539,9 @@ var AwsCdkProject = class extends awscdk.AwsCdkTypeScriptApp {
6332
6539
 
6333
6540
  // src/typescript/typescript-config.ts
6334
6541
  import { relative as relative4 } from "path";
6335
- import { Component as Component17 } from "projen";
6542
+ import { Component as Component18 } from "projen";
6336
6543
  import { ensureRelativePathStartsWithDot } from "projen/lib/util/path";
6337
- var TypeScriptConfig = class extends Component17 {
6544
+ var TypeScriptConfig = class extends Component18 {
6338
6545
  constructor(project) {
6339
6546
  super(project);
6340
6547
  let tsPaths = {};
@@ -6371,11 +6578,13 @@ export {
6371
6578
  AwsDeployWorkflow,
6372
6579
  AwsDeploymentConfig,
6373
6580
  AwsDeploymentTarget,
6581
+ AwsTeardownWorkflow,
6374
6582
  BUILT_IN_BUNDLES,
6375
6583
  CLAUDE_RULE_TARGET,
6376
6584
  COMPLETE_JOB_ID,
6377
6585
  DEFAULT_PRIORITY_LABELS,
6378
6586
  DEFAULT_STATUS_LABELS,
6587
+ DEFAULT_TEARDOWN_BRANCH_PATTERNS,
6379
6588
  DEFAULT_TYPE_LABELS,
6380
6589
  JsiiFaker,
6381
6590
  MCP_TRANSPORT,