@codedrifters/configulator 0.0.429 → 0.0.430

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
@@ -41927,10 +41927,10 @@ import { merge as merge4 } from "ts-deepmerge";
41927
41927
 
41928
41928
  // src/workflows/aws-deploy-workflow.ts
41929
41929
  var import_utils11 = __toESM(require_lib());
41930
- import { Component as Component24 } from "projen";
41930
+ import { Component as Component25 } from "projen";
41931
41931
  import { BuildWorkflow } from "projen/lib/build";
41932
- import { GitHub as GitHub6, WorkflowSteps as WorkflowSteps2 } from "projen/lib/github";
41933
- import { JobPermission as JobPermission6 } from "projen/lib/github/workflows-model";
41932
+ import { GitHub as GitHub6, WorkflowSteps as WorkflowSteps3 } from "projen/lib/github";
41933
+ import { JobPermission as JobPermission7 } from "projen/lib/github/workflows-model";
41934
41934
 
41935
41935
  // src/workflows/apply-workflow.ts
41936
41936
  import { Component as Component22 } from "projen";
@@ -42222,8 +42222,260 @@ var resolveEnvironmentGate = (gate, environmentName, componentName) => {
42222
42222
  return trimmed;
42223
42223
  };
42224
42224
 
42225
- // src/workflows/home-repository.ts
42225
+ // src/workflows/diff-report-job.ts
42226
42226
  import { Component as Component23 } from "projen";
42227
+ import { WorkflowSteps as WorkflowSteps2 } from "projen/lib/github";
42228
+ import { JobPermission as JobPermission6 } from "projen/lib/github/workflows-model";
42229
+ var DIFF_REPORT_JOB_ID = "diff-report";
42230
+ var DIFF_OUTPUT_DIRECTORY = "cdk-diff";
42231
+ var DIFF_PART_ARTIFACT_PREFIX = "cdk-diff-part";
42232
+ var DIFF_ARTIFACT_NAME = "cdk-diff";
42233
+ var DIFF_PART_RETENTION_DAYS = 1;
42234
+ var DIFF_SUMMARY_BYTE_LIMIT = 9e5;
42235
+ var RUN_URL = "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}";
42236
+ var DiffReportJob = class _DiffReportJob extends Component23 {
42237
+ constructor(project, options) {
42238
+ super(project);
42239
+ /**
42240
+ * Every contributed target, in attach order.
42241
+ */
42242
+ this.targets = [];
42243
+ /**
42244
+ * Publish settings are OR-ed rather than first-wins: one report means one
42245
+ * answer, and a component that asked for a summary should get one even when
42246
+ * a sibling did not.
42247
+ */
42248
+ this.summary = false;
42249
+ this.artifact = false;
42250
+ /**
42251
+ * Fold one component's contribution in.
42252
+ */
42253
+ this.record = (options) => {
42254
+ this.targets.push(...options.targets);
42255
+ this.summary = this.summary || options.summary;
42256
+ this.artifact = this.artifact || options.artifact;
42257
+ };
42258
+ /**
42259
+ * Compose the report's own condition.
42260
+ *
42261
+ * `!cancelled()` leads, and it is load-bearing: a job whose `needs` failed or
42262
+ * were skipped is skipped by default, so without a status function the report
42263
+ * would vanish in exactly the cases it is most wanted — one target's diff
42264
+ * failing, or some targets not applying to this branch.
42265
+ */
42266
+ this.renderJobCondition = () => {
42267
+ const branchConditions = this.targets.map(
42268
+ (target) => target.branchCondition
42269
+ );
42270
+ const anyBranch = branchConditions.some((condition) => !condition);
42271
+ const branchClause = anyBranch ? void 0 : Array.from(new Set(branchConditions)).join(" || ");
42272
+ return "${{ " + [
42273
+ "!cancelled()",
42274
+ "!needs.build.outputs.self_mutation_happened",
42275
+ ...this.homeRepositoryCondition ? [this.homeRepositoryCondition] : [],
42276
+ ...branchClause ? [`(${branchClause})`] : []
42277
+ ].join(" && ") + " }}";
42278
+ };
42279
+ /**
42280
+ * Pull every target's part into one directory.
42281
+ *
42282
+ * `continueOnError` because a run where every target's diff job was skipped
42283
+ * by its branch filter matches no parts at all, and a report with nothing to
42284
+ * report is not a failure.
42285
+ */
42286
+ this.renderDownloadStep = () => {
42287
+ return [
42288
+ WorkflowSteps2.downloadArtifact({
42289
+ name: "Download target diffs",
42290
+ continueOnError: true,
42291
+ with: {
42292
+ pattern: `${DIFF_PART_ARTIFACT_PREFIX}-*`,
42293
+ mergeMultiple: true,
42294
+ path: DIFF_OUTPUT_DIRECTORY
42295
+ }
42296
+ })
42297
+ ];
42298
+ };
42299
+ /**
42300
+ * Render every target's diff into the job summary, one collapsed `<details>`
42301
+ * block per target.
42302
+ *
42303
+ * A target whose part is absent renders as "did not run", which is what
42304
+ * distinguishes a target that was skipped or whose diff failed before it
42305
+ * captured anything from one that simply had no changes — the latter has a
42306
+ * file, carrying the CDK CLI's own no-differences wording, rather than being
42307
+ * detected by matching on it.
42308
+ */
42309
+ this.renderSummaryStep = () => {
42310
+ if (!this.summary || this.targets.length === 0) {
42311
+ return [];
42312
+ }
42313
+ const budget = Math.floor(DIFF_SUMMARY_BYTE_LIMIT / this.targets.length);
42314
+ const rows = this.targets.map(
42315
+ (target) => `'${target.label}|${target.outputFile}'`
42316
+ );
42317
+ return [
42318
+ {
42319
+ name: "Render diff report",
42320
+ if: "!cancelled()",
42321
+ shell: "bash",
42322
+ run: [
42323
+ "{",
42324
+ " while IFS='|' read -r label file; do",
42325
+ ' echo "## cdk diff \u2014 $label"',
42326
+ ' echo ""',
42327
+ ' if [ ! -f "$file" ]; then',
42328
+ " echo '_Did not run._'",
42329
+ ' echo ""',
42330
+ " continue",
42331
+ " fi",
42332
+ " echo '<details><summary>cdk diff output</summary>'",
42333
+ ' echo ""',
42334
+ " echo '```'",
42335
+ ` if [ "$(wc -c < "$file")" -gt ${budget} ]; then`,
42336
+ ` head -c ${budget} "$file"`,
42337
+ ` printf '\\n... truncated at ${budget} bytes ...\\n'`,
42338
+ " else",
42339
+ ' cat "$file"',
42340
+ " fi",
42341
+ " echo '```'",
42342
+ ' echo ""',
42343
+ " echo '</details>'",
42344
+ ' echo ""',
42345
+ ` done < <(printf '%s\\n' ${rows.join(" ")})`,
42346
+ ...this.artifact ? [
42347
+ ` echo 'Full diff: the \`${DIFF_ARTIFACT_NAME}\` artifact on [this run](${RUN_URL}).'`
42348
+ ] : [],
42349
+ '} >> "$GITHUB_STEP_SUMMARY"'
42350
+ ].join("\n")
42351
+ }
42352
+ ];
42353
+ };
42354
+ /**
42355
+ * Fail the report when any target's diff failed.
42356
+ *
42357
+ * Runs last, so the summary and the artifact are published first — a reviewer
42358
+ * still gets the whole picture, including whatever the failing target managed
42359
+ * to capture. But the report must not end up green: everything gated behind
42360
+ * it `needs` it, and a job whose `needs` failed is skipped, which is what
42361
+ * keeps a failed diff from letting a gated deploy through to *Waiting for
42362
+ * approval*. Without this the report would always succeed and a diff failure
42363
+ * would only soft-block behind a human.
42364
+ *
42365
+ * Only `failure` counts. A target skipped by its branch filter reports
42366
+ * `skipped`, which is normal and must not fail the report.
42367
+ */
42368
+ this.renderFailureStep = () => {
42369
+ const jobNames = Array.from(
42370
+ new Set(this.targets.map((target) => target.jobName))
42371
+ );
42372
+ if (jobNames.length === 0) {
42373
+ return [];
42374
+ }
42375
+ return [
42376
+ {
42377
+ name: "Fail if any target's diff failed",
42378
+ if: "!cancelled()",
42379
+ shell: "bash",
42380
+ run: [
42381
+ ...jobNames.map(
42382
+ (jobName) => `if [ "\${{ needs.${jobName}.result }}" = "failure" ]; then echo "::error::Diff job ${jobName} failed"; failed=1; fi`
42383
+ ),
42384
+ 'if [ "${failed:-0}" = "1" ]; then exit 1; fi'
42385
+ ].join("\n")
42386
+ }
42387
+ ];
42388
+ };
42389
+ /**
42390
+ * Upload the merged directory as the one artifact meant to be read.
42391
+ */
42392
+ this.renderUploadStep = () => {
42393
+ if (!this.artifact || this.targets.length === 0) {
42394
+ return [];
42395
+ }
42396
+ return [
42397
+ WorkflowSteps2.uploadArtifact({
42398
+ name: "Upload combined diff",
42399
+ if: "!cancelled()",
42400
+ with: {
42401
+ name: DIFF_ARTIFACT_NAME,
42402
+ path: DIFF_OUTPUT_DIRECTORY,
42403
+ ifNoFilesFound: "ignore"
42404
+ }
42405
+ })
42406
+ ];
42407
+ };
42408
+ this.buildWorkflow = options.buildWorkflow;
42409
+ this.homeRepositoryCondition = options.homeRepositoryCondition;
42410
+ this.record(options);
42411
+ this.buildWorkflow.workflow.addJob(DIFF_REPORT_JOB_ID, {
42412
+ name: "Diff report",
42413
+ needs: ["build"],
42414
+ runsOn: ["ubuntu-latest"],
42415
+ permissions: {
42416
+ contents: JobPermission6.READ
42417
+ },
42418
+ steps: []
42419
+ });
42420
+ }
42421
+ static of(project, buildWorkflow) {
42422
+ const isDefined = (c) => c instanceof _DiffReportJob && c.buildWorkflow === buildWorkflow;
42423
+ return project.components.find(isDefined);
42424
+ }
42425
+ /**
42426
+ * Add a component's targets to the plan workflow's diff report, creating the
42427
+ * report job the first time it is called for that workflow.
42428
+ */
42429
+ static attach(project, options) {
42430
+ const existing = _DiffReportJob.of(project, options.buildWorkflow);
42431
+ if (existing) {
42432
+ existing.record(options);
42433
+ return existing;
42434
+ }
42435
+ return new _DiffReportJob(project, options);
42436
+ }
42437
+ preSynthesize() {
42438
+ this.buildWorkflow.workflow.updateJob(DIFF_REPORT_JOB_ID, {
42439
+ name: "Diff report",
42440
+ /**
42441
+ * `build` is a direct dependency so the job can read its
42442
+ * self-mutation output, which is otherwise unreachable — the `needs`
42443
+ * context only carries direct dependencies, not transitive ones.
42444
+ */
42445
+ needs: [
42446
+ "build",
42447
+ ...Array.from(new Set(this.targets.map((target) => target.jobName)))
42448
+ ],
42449
+ runsOn: ["ubuntu-latest"],
42450
+ permissions: {
42451
+ contents: JobPermission6.READ
42452
+ },
42453
+ if: this.renderJobCondition(),
42454
+ steps: [
42455
+ ...this.renderDownloadStep(),
42456
+ ...this.renderSummaryStep(),
42457
+ ...this.renderUploadStep(),
42458
+ ...this.renderFailureStep()
42459
+ ]
42460
+ });
42461
+ super.preSynthesize();
42462
+ }
42463
+ };
42464
+ var renderDiffPartUploadStep = (options) => {
42465
+ return WorkflowSteps2.uploadArtifact({
42466
+ name: `Upload diff ${options.label}`,
42467
+ if: "!cancelled()",
42468
+ with: {
42469
+ name: options.artifactName,
42470
+ path: options.outputFile,
42471
+ ifNoFilesFound: "ignore",
42472
+ retentionDays: DIFF_PART_RETENTION_DAYS
42473
+ }
42474
+ });
42475
+ };
42476
+
42477
+ // src/workflows/home-repository.ts
42478
+ import { Component as Component24 } from "projen";
42227
42479
  var HOME_REPOSITORY_PATTERN = /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/;
42228
42480
  var renderHomeRepositoryCondition = (homeRepository, componentName) => {
42229
42481
  if (homeRepository === void 0) {
@@ -42237,7 +42489,7 @@ var renderHomeRepositoryCondition = (homeRepository, componentName) => {
42237
42489
  return `github.repository == '${homeRepository}'`;
42238
42490
  };
42239
42491
  var describePin = (homeRepository) => homeRepository === void 0 ? "unset" : `"${homeRepository}"`;
42240
- var WorkflowHomeRepository = class _WorkflowHomeRepository extends Component23 {
42492
+ var WorkflowHomeRepository = class _WorkflowHomeRepository extends Component24 {
42241
42493
  static of(project, workflow) {
42242
42494
  const isDefined = (c) => c instanceof _WorkflowHomeRepository && c.workflow === workflow;
42243
42495
  return project.components.find(isDefined);
@@ -42269,11 +42521,34 @@ var WorkflowHomeRepository = class _WorkflowHomeRepository extends Component23 {
42269
42521
  }
42270
42522
  };
42271
42523
 
42524
+ // src/workflows/node-setup.ts
42525
+ var renderSetupNode = () => {
42526
+ return [
42527
+ {
42528
+ name: "Setup Node",
42529
+ uses: `actions/setup-node@${VERSION.SETUP_NODE_ACTION_VERSION}`,
42530
+ with: {
42531
+ ["node-version"]: VERSION.NODE_WORKFLOWS
42532
+ },
42533
+ timeoutMinutes: 1
42534
+ }
42535
+ ];
42536
+ };
42537
+ var renderSetupPnpm = (pnpmVersion) => {
42538
+ return [
42539
+ {
42540
+ name: "Setup PNPM",
42541
+ uses: `pnpm/action-setup@${VERSION.PNPM_ACTION_SETUP_VERSION}`,
42542
+ with: {
42543
+ version: pnpmVersion
42544
+ }
42545
+ }
42546
+ ];
42547
+ };
42548
+
42272
42549
  // src/workflows/aws-deploy-workflow.ts
42273
42550
  var PROD_DEPLOY_NAME = "prod-deploy";
42274
- var DIFF_OUTPUT_FILE = "cdk-diff.txt";
42275
- var DIFF_SUMMARY_BYTE_LIMIT = 9e5;
42276
- var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
42551
+ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component25 {
42277
42552
  constructor(project, options = {}) {
42278
42553
  super(project);
42279
42554
  this.project = project;
@@ -42285,30 +42560,8 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
42285
42560
  * @default 'primary' (this is the only type supported currently)
42286
42561
  */
42287
42562
  this.awsEnvironmentType = import_utils11.DEPLOYMENT_TARGET_ROLE.PRIMARY;
42288
- this.setupNode = () => {
42289
- return [
42290
- {
42291
- name: "Setup Node",
42292
- uses: `actions/setup-node@${VERSION.SETUP_NODE_ACTION_VERSION}`,
42293
- with: {
42294
- ["node-version"]: VERSION.NODE_WORKFLOWS
42295
- },
42296
- // occasionally this step fails due to internal issues at github
42297
- timeoutMinutes: 1
42298
- }
42299
- ];
42300
- };
42301
- this.setupPnpm = () => {
42302
- return [
42303
- {
42304
- name: "Setup PNPM",
42305
- uses: `pnpm/action-setup@${VERSION.PNPM_ACTION_SETUP_VERSION}`,
42306
- with: {
42307
- version: this.rootProject.pnpmVersion
42308
- }
42309
- }
42310
- ];
42311
- };
42563
+ this.setupNode = () => renderSetupNode();
42564
+ this.setupPnpm = () => renderSetupPnpm(this.rootProject.pnpmVersion);
42312
42565
  /**
42313
42566
  * Build the deterministic GitHub Actions job name for a deploy target.
42314
42567
  *
@@ -42326,45 +42579,43 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
42326
42579
  ].join("-");
42327
42580
  };
42328
42581
  /**
42329
- * Build the deterministic GitHub Actions job name for a target's `cdk diff`
42330
- * job. Mirrors {@link buildJobName} with a `diff` verb so the diff and deploy
42331
- * jobs for one target sort next to each other in the run view.
42582
+ * Build the deterministic GitHub Actions job name for a target's apply job.
42583
+ * Mirrors {@link buildJobName} with an `apply` verb.
42332
42584
  */
42333
- this.buildDiffJobName = (target) => {
42585
+ this.buildApplyJobName = (target) => {
42334
42586
  return [
42335
42587
  target.awsStageType,
42336
42588
  target.deploymentTargetRole,
42337
- "diff",
42589
+ "apply",
42338
42590
  target.project.name,
42339
42591
  target.account,
42340
42592
  target.region
42341
42593
  ].join("-");
42342
42594
  };
42343
42595
  /**
42344
- * Build the deterministic GitHub Actions job name for a target's apply job.
42345
- * Mirrors {@link buildJobName} with an `apply` verb.
42596
+ * Build the deterministic GitHub Actions job name for a target's `cdk diff`
42597
+ * job. Mirrors {@link buildJobName} with a `diff` verb so the diff and deploy
42598
+ * jobs for one target sort next to each other in the run view.
42346
42599
  */
42347
- this.buildApplyJobName = (target) => {
42600
+ this.buildDiffJobName = (target) => {
42348
42601
  return [
42349
42602
  target.awsStageType,
42350
42603
  target.deploymentTargetRole,
42351
- "apply",
42604
+ "diff",
42352
42605
  target.project.name,
42353
42606
  target.account,
42354
42607
  target.region
42355
42608
  ].join("-");
42356
42609
  };
42357
42610
  /**
42358
- * Build the CI artifact name for a target's captured diff.
42611
+ * Build the slug that makes a target unique among every target in the plan
42612
+ * workflow, across every deploy component feeding it.
42359
42613
  *
42360
- * Carries every component that makes a target unique — including
42361
- * `deploymentTargetRole`, which two otherwise-identical targets can differ
42362
- * on. `actions/upload-artifact` v4+ treats artifacts as immutable and rejects
42363
- * a duplicate name within a run, so parallel diff jobs cannot share one.
42614
+ * Includes `deploymentTargetRole`, which two otherwise-identical targets can
42615
+ * differ on.
42364
42616
  */
42365
- this.buildDiffArtifactName = (target) => {
42617
+ this.buildDiffSlug = (target) => {
42366
42618
  return [
42367
- "cdk-diff",
42368
42619
  target.awsStageType,
42369
42620
  target.deploymentTargetRole,
42370
42621
  target.project.name,
@@ -42372,6 +42623,23 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
42372
42623
  target.region
42373
42624
  ].join("-");
42374
42625
  };
42626
+ /**
42627
+ * Build the file a target's captured diff is written to, both in its own diff
42628
+ * job's workspace and in the merged directory the report job assembles.
42629
+ */
42630
+ this.buildDiffOutputFile = (target) => {
42631
+ return `${DIFF_OUTPUT_DIRECTORY}/${this.buildDiffSlug(target)}.txt`;
42632
+ };
42633
+ /**
42634
+ * Build the intermediate artifact name carrying one target's captured diff.
42635
+ *
42636
+ * The diff jobs run in parallel and `actions/upload-artifact` v4+ rejects a
42637
+ * duplicate name within a run, so each target needs its own. The report job
42638
+ * merges them into a single artifact, which is the one meant to be read.
42639
+ */
42640
+ this.buildDiffPartArtifactName = (target) => {
42641
+ return `${DIFF_PART_ARTIFACT_PREFIX}-${this.buildDiffSlug(target)}`;
42642
+ };
42375
42643
  /**
42376
42644
  * Join an apply workflow another `AwsDeployWorkflow` already created, so this
42377
42645
  * component's apply jobs land in that file rather than a second one.
@@ -42429,9 +42697,9 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
42429
42697
  ],
42430
42698
  runsOn: ["ubuntu-latest"],
42431
42699
  permissions: {
42432
- actions: JobPermission6.READ,
42433
- contents: JobPermission6.READ,
42434
- idToken: JobPermission6.WRITE
42700
+ actions: JobPermission7.READ,
42701
+ contents: JobPermission7.READ,
42702
+ idToken: JobPermission7.WRITE
42435
42703
  },
42436
42704
  ...this.environmentName ? { environment: this.environmentName } : void 0,
42437
42705
  /**
@@ -42621,9 +42889,7 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
42621
42889
  const { roleArn, stackPattern } = ciDeploymentConfig ?? {};
42622
42890
  const { rootCdkOut, cdkCli } = awsDeploymentConfig;
42623
42891
  const label = `${awsStageType}/${deploymentTargetRole}/${account}/${region}`;
42624
- const artifactName = this.buildDiffArtifactName(target);
42625
- const capturedFileGuard = `always() && hashFiles('${DIFF_OUTPUT_FILE}') != ''`;
42626
- const runUrl = "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}";
42892
+ const outputFile = this.buildDiffOutputFile(target);
42627
42893
  return [
42628
42894
  ...this.setupPnpm(),
42629
42895
  ...this.setupNode(),
@@ -42643,69 +42909,36 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
42643
42909
  /**
42644
42910
  * Run CDK Diff, capturing the output while leaving it visible in the job
42645
42911
  * log. `pipefail` keeps the CLI's exit code from being masked by `tee`.
42912
+ *
42913
+ * The capture lands under the same path the report job will merge it
42914
+ * back to, so a target's file name is identical in both places.
42646
42915
  */
42647
42916
  {
42648
42917
  name: `Diff ${label}`,
42649
42918
  shell: "bash",
42650
42919
  run: [
42651
42920
  "set -o pipefail",
42921
+ `mkdir -p ${DIFF_OUTPUT_DIRECTORY}`,
42652
42922
  `pnpm dlx "aws-cdk@${cdkCli.cliVersion}" ${renderCdkDiff({
42653
42923
  ...cdkCli.diffOptionsFor(target),
42654
42924
  app: rootCdkOut,
42655
42925
  ci: true,
42656
42926
  noColor: true,
42657
42927
  stackPatterns: stackPattern ? [stackPattern] : void 0
42658
- })} 2>&1 | tee ${DIFF_OUTPUT_FILE}`
42928
+ })} 2>&1 | tee ${outputFile}`
42659
42929
  ].join("\n")
42660
42930
  },
42661
42931
  /**
42662
- * Render the captured diff into the job summary inside a collapsed
42663
- * `<details>` block, truncated below GitHub's 1 MiB per-step cap — a
42664
- * summary that exceeds the cap is dropped in full rather than clipped.
42665
- */
42666
- ...this.diffOptions.summary ? [
42667
- {
42668
- name: `Render diff summary ${label}`,
42669
- if: capturedFileGuard,
42670
- shell: "bash",
42671
- run: [
42672
- `size=$(wc -c < ${DIFF_OUTPUT_FILE})`,
42673
- "{",
42674
- ` echo '## cdk diff \u2014 ${label}'`,
42675
- ' echo ""',
42676
- " echo '<details><summary>cdk diff output</summary>'",
42677
- ' echo ""',
42678
- " echo '```'",
42679
- ` if [ "$size" -gt ${DIFF_SUMMARY_BYTE_LIMIT} ]; then`,
42680
- ` head -c ${DIFF_SUMMARY_BYTE_LIMIT} ${DIFF_OUTPUT_FILE}`,
42681
- ` printf '\\n... truncated at ${DIFF_SUMMARY_BYTE_LIMIT} bytes ...\\n'`,
42682
- " else",
42683
- ` cat ${DIFF_OUTPUT_FILE}`,
42684
- " fi",
42685
- " echo '```'",
42686
- ' echo ""',
42687
- " echo '</details>'",
42688
- ...this.diffOptions.artifact ? [
42689
- ' echo ""',
42690
- ` echo 'Full diff: the \`${artifactName}\` artifact on [this run](${runUrl}).'`
42691
- ] : [],
42692
- '} >> "$GITHUB_STEP_SUMMARY"'
42693
- ].join("\n")
42694
- }
42695
- ] : [],
42696
- /**
42697
- * Upload the untruncated diff as a per-run artifact.
42932
+ * Hand the capture to the report job. Guarded on `!cancelled()` rather
42933
+ * than success, so a diff that exits non-zero — a synth error, or a
42934
+ * consumer who opted into `--fail` still contributes what it captured
42935
+ * instead of leaving a hole in the report.
42698
42936
  */
42699
- ...this.diffOptions.artifact ? [
42700
- WorkflowSteps2.uploadArtifact({
42701
- name: `Upload diff ${label}`,
42702
- if: capturedFileGuard,
42703
- with: {
42704
- name: artifactName,
42705
- path: DIFF_OUTPUT_FILE
42706
- }
42707
- })
42708
- ] : []
42937
+ renderDiffPartUploadStep({
42938
+ label,
42939
+ artifactName: this.buildDiffPartArtifactName(target),
42940
+ outputFile
42941
+ })
42709
42942
  ];
42710
42943
  };
42711
42944
  if (!(project.root instanceof MonorepoProject)) {
@@ -42771,14 +43004,20 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
42771
43004
  buildTask: this.rootProject.buildTask,
42772
43005
  /**
42773
43006
  * Use push triggers based n the branch config for each environment.
43007
+ *
43008
+ * Deduped: targets in one workflow routinely share a branch — two prod
43009
+ * targets both default to `main` — and a repeated entry is only noise
43010
+ * in the generated file, since GitHub treats this as a filter list.
42774
43011
  */
42775
43012
  workflowTriggers: {
42776
43013
  push: {
42777
- branches: [
42778
- ...this.awsDeploymentTargets.flatMap(
42779
- (t) => t.branches.map((b) => b.branch)
43014
+ branches: Array.from(
43015
+ new Set(
43016
+ this.awsDeploymentTargets.flatMap(
43017
+ (t) => t.branches.map((b) => b.branch)
43018
+ )
42780
43019
  )
42781
- ]
43020
+ )
42782
43021
  },
42783
43022
  workflowDispatch: {},
42784
43023
  ...options.buildWorkflowOptions?.workflowTriggers
@@ -42874,16 +43113,16 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
42874
43113
  name: `Deploy ${this.project.name} ${target.awsStageType}/${target.deploymentTargetRole}/${target.account}/${target.region}`,
42875
43114
  needs: [
42876
43115
  "build",
42877
- ...gatedOnDiff ? [this.buildDiffJobName(target)] : [],
43116
+ ...gatedOnDiff ? [DIFF_REPORT_JOB_ID] : [],
42878
43117
  ...this.deployAfterTargets.map((p) => {
42879
43118
  return this.buildJobName(p);
42880
43119
  })
42881
43120
  ],
42882
43121
  runsOn: ["ubuntu-latest"],
42883
43122
  permissions: {
42884
- contents: JobPermission6.READ,
42885
- idToken: JobPermission6.WRITE,
42886
- pullRequests: JobPermission6.WRITE
43123
+ contents: JobPermission7.READ,
43124
+ idToken: JobPermission7.WRITE,
43125
+ pullRequests: JobPermission7.WRITE
42887
43126
  },
42888
43127
  ...this.environmentName ? { environment: this.environmentName } : void 0,
42889
43128
  concurrency: deployJobName,
@@ -42898,14 +43137,28 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
42898
43137
  needs: ["build"],
42899
43138
  runsOn: ["ubuntu-latest"],
42900
43139
  permissions: {
42901
- contents: JobPermission6.READ,
42902
- idToken: JobPermission6.WRITE
43140
+ contents: JobPermission7.READ,
43141
+ idToken: JobPermission7.WRITE
42903
43142
  },
42904
43143
  if: jobCondition,
42905
43144
  steps: [...this.diffSteps(target)]
42906
43145
  });
42907
43146
  }
42908
43147
  });
43148
+ if (this.diffOptions.enabled && this.awsDeploymentTargets.length > 0) {
43149
+ DiffReportJob.attach(this.rootProject, {
43150
+ buildWorkflow: this.buildWorkflow,
43151
+ homeRepositoryCondition,
43152
+ summary: this.diffOptions.summary,
43153
+ artifact: this.diffOptions.artifact,
43154
+ targets: this.awsDeploymentTargets.map((target) => ({
43155
+ label: `${this.project.name} ${target.awsStageType}/${target.deploymentTargetRole}/${target.account}/${target.region}`,
43156
+ jobName: this.buildDiffJobName(target),
43157
+ outputFile: this.buildDiffOutputFile(target),
43158
+ branchCondition: this.buildBranchFilterCondition(target.branches)
43159
+ }))
43160
+ });
43161
+ }
42909
43162
  addBuildCompleteJob(this.buildWorkflow);
42910
43163
  }
42911
43164
  static of(project, buildWorkflow) {
@@ -42919,7 +43172,7 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
42919
43172
  name: "Build Sub Projects",
42920
43173
  run: `pnpm exec projen ${ROOT_CI_TASK_NAME}`
42921
43174
  },
42922
- WorkflowSteps2.uploadArtifact({
43175
+ WorkflowSteps3.uploadArtifact({
42923
43176
  name: "Upload Turbo runs",
42924
43177
  if: "always()",
42925
43178
  continueOnError: true,
@@ -42935,9 +43188,9 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
42935
43188
  };
42936
43189
 
42937
43190
  // src/workflows/aws-teardown-workflow.ts
42938
- import { Component as Component25 } from "projen";
43191
+ import { Component as Component26 } from "projen";
42939
43192
  import { GitHub as GitHub7, GithubWorkflow as GithubWorkflow3 } from "projen/lib/github";
42940
- import { JobPermission as JobPermission7 } from "projen/lib/github/workflows-model";
43193
+ import { JobPermission as JobPermission8 } from "projen/lib/github/workflows-model";
42941
43194
  var DEFAULT_TEARDOWN_BRANCH_PATTERNS = [
42942
43195
  "feat/*",
42943
43196
  "fix/*",
@@ -42957,7 +43210,7 @@ var resolveBranchPatterns = (explicit, targets) => {
42957
43210
  }
42958
43211
  return [...DEFAULT_TEARDOWN_BRANCH_PATTERNS];
42959
43212
  };
42960
- var AwsTeardownWorkflow = class extends Component25 {
43213
+ var AwsTeardownWorkflow = class extends Component26 {
42961
43214
  constructor(rootProject, options) {
42962
43215
  super(rootProject);
42963
43216
  this.rootProject = rootProject;
@@ -43029,8 +43282,8 @@ var AwsTeardownWorkflow = class extends Component25 {
43029
43282
  runsOn: ["ubuntu-latest"],
43030
43283
  ...homeRepositoryCondition ? { if: `\${{ ${homeRepositoryCondition} }}` } : {},
43031
43284
  permissions: {
43032
- contents: JobPermission7.READ,
43033
- idToken: JobPermission7.WRITE
43285
+ contents: JobPermission8.READ,
43286
+ idToken: JobPermission8.WRITE
43034
43287
  },
43035
43288
  env: {
43036
43289
  REPO: "${{ github.repository }}",
@@ -43890,7 +44143,12 @@ export {
43890
44143
  DEFAULT_UNBLOCK_DEPENDENTS_ENABLED,
43891
44144
  DEFAULT_UPSTREAM_CONFIGULATOR_ENABLED,
43892
44145
  DEPLOY_GATE,
44146
+ DIFF_ARTIFACT_NAME,
44147
+ DIFF_OUTPUT_DIRECTORY,
44148
+ DIFF_PART_ARTIFACT_PREFIX,
44149
+ DIFF_REPORT_JOB_ID,
43893
44150
  DOCS_SYNC_AUDIT_SCHEMA_VERSION,
44151
+ DiffReportJob,
43894
44152
  GITHUB_ISSUE_TYPES,
43895
44153
  GITHUB_ISSUE_TYPE_BY_TITLE_PREFIX,
43896
44154
  ISSUE_TEMPLATES_GENERATED_SUFFIX,
@@ -44070,6 +44328,7 @@ export {
44070
44328
  renderCheckLinksProcedure,
44071
44329
  renderCustomDocSectionBlock,
44072
44330
  renderCustomDocSections,
44331
+ renderDiffPartUploadStep,
44073
44332
  renderExtractApiProcedure,
44074
44333
  renderFocusSection,
44075
44334
  renderGithubIssueTypeSection,
@@ -44101,6 +44360,8 @@ export {
44101
44360
  renderScopeGateSection,
44102
44361
  renderScopeGateShellHelpers,
44103
44362
  renderSetIssueTypeFallbackLines,
44363
+ renderSetupNode,
44364
+ renderSetupPnpm,
44104
44365
  renderSharedEditingBundleHook,
44105
44366
  renderSharedEditingHelperScript,
44106
44367
  renderSharedEditingRuleContent,