@codedrifters/configulator 0.0.429 → 0.0.431
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.d.mts +256 -10
- package/lib/index.d.ts +257 -11
- package/lib/index.js +439 -139
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +411 -119
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
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
|
|
41930
|
+
import { Component as Component25 } from "projen";
|
|
41931
41931
|
import { BuildWorkflow } from "projen/lib/build";
|
|
41932
|
-
import { GitHub as GitHub6, WorkflowSteps as
|
|
41933
|
-
import { JobPermission as
|
|
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/
|
|
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
|
|
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,35 @@ 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
|
|
42275
|
-
var
|
|
42276
|
-
var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
|
|
42551
|
+
var BRANCH_NAME_EXPRESSION = "${{ github.head_ref || github.ref_name }}";
|
|
42552
|
+
var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component25 {
|
|
42277
42553
|
constructor(project, options = {}) {
|
|
42278
42554
|
super(project);
|
|
42279
42555
|
this.project = project;
|
|
@@ -42285,30 +42561,8 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
|
|
|
42285
42561
|
* @default 'primary' (this is the only type supported currently)
|
|
42286
42562
|
*/
|
|
42287
42563
|
this.awsEnvironmentType = import_utils11.DEPLOYMENT_TARGET_ROLE.PRIMARY;
|
|
42288
|
-
this.setupNode = () =>
|
|
42289
|
-
|
|
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
|
-
};
|
|
42564
|
+
this.setupNode = () => renderSetupNode();
|
|
42565
|
+
this.setupPnpm = () => renderSetupPnpm(this.rootProject.pnpmVersion);
|
|
42312
42566
|
/**
|
|
42313
42567
|
* Build the deterministic GitHub Actions job name for a deploy target.
|
|
42314
42568
|
*
|
|
@@ -42326,45 +42580,65 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
|
|
|
42326
42580
|
].join("-");
|
|
42327
42581
|
};
|
|
42328
42582
|
/**
|
|
42329
|
-
* Build
|
|
42330
|
-
*
|
|
42331
|
-
*
|
|
42583
|
+
* Build a deploy job's `concurrency` setting from its job name.
|
|
42584
|
+
*
|
|
42585
|
+
* Two shapes, deliberately:
|
|
42586
|
+
*
|
|
42587
|
+
* - Unscoped (the default) stays the bare string the job has always carried,
|
|
42588
|
+
* so an existing consumer's workflow is byte-identical.
|
|
42589
|
+
* - Branch-scoped spells out `cancel-in-progress: false` rather than leaning
|
|
42590
|
+
* on GitHub's default, the same way the apply job does. A group keyed on
|
|
42591
|
+
* the branch reads like a "cancel superseded pushes" group, and that is the
|
|
42592
|
+
* one thing it must not be — cancelling a half-finished `cdk deploy`
|
|
42593
|
+
* strands a CloudFormation stack mid-update.
|
|
42332
42594
|
*/
|
|
42333
|
-
this.
|
|
42595
|
+
this.buildDeployConcurrency = (deployJobName) => {
|
|
42596
|
+
if (!this.branchScopedConcurrency) {
|
|
42597
|
+
return deployJobName;
|
|
42598
|
+
}
|
|
42599
|
+
return {
|
|
42600
|
+
group: `${deployJobName}-${BRANCH_NAME_EXPRESSION}`,
|
|
42601
|
+
"cancel-in-progress": false
|
|
42602
|
+
};
|
|
42603
|
+
};
|
|
42604
|
+
/**
|
|
42605
|
+
* Build the deterministic GitHub Actions job name for a target's apply job.
|
|
42606
|
+
* Mirrors {@link buildJobName} with an `apply` verb.
|
|
42607
|
+
*/
|
|
42608
|
+
this.buildApplyJobName = (target) => {
|
|
42334
42609
|
return [
|
|
42335
42610
|
target.awsStageType,
|
|
42336
42611
|
target.deploymentTargetRole,
|
|
42337
|
-
"
|
|
42612
|
+
"apply",
|
|
42338
42613
|
target.project.name,
|
|
42339
42614
|
target.account,
|
|
42340
42615
|
target.region
|
|
42341
42616
|
].join("-");
|
|
42342
42617
|
};
|
|
42343
42618
|
/**
|
|
42344
|
-
* Build the deterministic GitHub Actions job name for a target's
|
|
42345
|
-
* Mirrors {@link buildJobName} with
|
|
42619
|
+
* Build the deterministic GitHub Actions job name for a target's `cdk diff`
|
|
42620
|
+
* job. Mirrors {@link buildJobName} with a `diff` verb so the diff and deploy
|
|
42621
|
+
* jobs for one target sort next to each other in the run view.
|
|
42346
42622
|
*/
|
|
42347
|
-
this.
|
|
42623
|
+
this.buildDiffJobName = (target) => {
|
|
42348
42624
|
return [
|
|
42349
42625
|
target.awsStageType,
|
|
42350
42626
|
target.deploymentTargetRole,
|
|
42351
|
-
"
|
|
42627
|
+
"diff",
|
|
42352
42628
|
target.project.name,
|
|
42353
42629
|
target.account,
|
|
42354
42630
|
target.region
|
|
42355
42631
|
].join("-");
|
|
42356
42632
|
};
|
|
42357
42633
|
/**
|
|
42358
|
-
* Build the
|
|
42634
|
+
* Build the slug that makes a target unique among every target in the plan
|
|
42635
|
+
* workflow, across every deploy component feeding it.
|
|
42359
42636
|
*
|
|
42360
|
-
*
|
|
42361
|
-
*
|
|
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.
|
|
42637
|
+
* Includes `deploymentTargetRole`, which two otherwise-identical targets can
|
|
42638
|
+
* differ on.
|
|
42364
42639
|
*/
|
|
42365
|
-
this.
|
|
42640
|
+
this.buildDiffSlug = (target) => {
|
|
42366
42641
|
return [
|
|
42367
|
-
"cdk-diff",
|
|
42368
42642
|
target.awsStageType,
|
|
42369
42643
|
target.deploymentTargetRole,
|
|
42370
42644
|
target.project.name,
|
|
@@ -42372,6 +42646,23 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
|
|
|
42372
42646
|
target.region
|
|
42373
42647
|
].join("-");
|
|
42374
42648
|
};
|
|
42649
|
+
/**
|
|
42650
|
+
* Build the file a target's captured diff is written to, both in its own diff
|
|
42651
|
+
* job's workspace and in the merged directory the report job assembles.
|
|
42652
|
+
*/
|
|
42653
|
+
this.buildDiffOutputFile = (target) => {
|
|
42654
|
+
return `${DIFF_OUTPUT_DIRECTORY}/${this.buildDiffSlug(target)}.txt`;
|
|
42655
|
+
};
|
|
42656
|
+
/**
|
|
42657
|
+
* Build the intermediate artifact name carrying one target's captured diff.
|
|
42658
|
+
*
|
|
42659
|
+
* The diff jobs run in parallel and `actions/upload-artifact` v4+ rejects a
|
|
42660
|
+
* duplicate name within a run, so each target needs its own. The report job
|
|
42661
|
+
* merges them into a single artifact, which is the one meant to be read.
|
|
42662
|
+
*/
|
|
42663
|
+
this.buildDiffPartArtifactName = (target) => {
|
|
42664
|
+
return `${DIFF_PART_ARTIFACT_PREFIX}-${this.buildDiffSlug(target)}`;
|
|
42665
|
+
};
|
|
42375
42666
|
/**
|
|
42376
42667
|
* Join an apply workflow another `AwsDeployWorkflow` already created, so this
|
|
42377
42668
|
* component's apply jobs land in that file rather than a second one.
|
|
@@ -42429,9 +42720,9 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
|
|
|
42429
42720
|
],
|
|
42430
42721
|
runsOn: ["ubuntu-latest"],
|
|
42431
42722
|
permissions: {
|
|
42432
|
-
actions:
|
|
42433
|
-
contents:
|
|
42434
|
-
idToken:
|
|
42723
|
+
actions: JobPermission7.READ,
|
|
42724
|
+
contents: JobPermission7.READ,
|
|
42725
|
+
idToken: JobPermission7.WRITE
|
|
42435
42726
|
},
|
|
42436
42727
|
...this.environmentName ? { environment: this.environmentName } : void 0,
|
|
42437
42728
|
/**
|
|
@@ -42439,6 +42730,13 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
|
|
|
42439
42730
|
* same-target deploy. `cancel-in-progress` is spelled out rather than
|
|
42440
42731
|
* left to GitHub's default: cancelling a half-finished `cdk deploy`
|
|
42441
42732
|
* strands a CloudFormation stack mid-update.
|
|
42733
|
+
*
|
|
42734
|
+
* `branchScopedConcurrency` deliberately does not reach here. An apply is
|
|
42735
|
+
* dispatched from whatever ref the operator happens to be on — unrelated
|
|
42736
|
+
* to the branch the nominated plan ran against, which is the only branch
|
|
42737
|
+
* that describes what is about to be deployed. Keying on the dispatch ref
|
|
42738
|
+
* would hand out separate locks to applies of the same target, so the
|
|
42739
|
+
* unsuffixed group stays.
|
|
42442
42740
|
*/
|
|
42443
42741
|
concurrency: {
|
|
42444
42742
|
group: this.buildJobName(target),
|
|
@@ -42621,9 +42919,7 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
|
|
|
42621
42919
|
const { roleArn, stackPattern } = ciDeploymentConfig ?? {};
|
|
42622
42920
|
const { rootCdkOut, cdkCli } = awsDeploymentConfig;
|
|
42623
42921
|
const label = `${awsStageType}/${deploymentTargetRole}/${account}/${region}`;
|
|
42624
|
-
const
|
|
42625
|
-
const capturedFileGuard = `always() && hashFiles('${DIFF_OUTPUT_FILE}') != ''`;
|
|
42626
|
-
const runUrl = "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}";
|
|
42922
|
+
const outputFile = this.buildDiffOutputFile(target);
|
|
42627
42923
|
return [
|
|
42628
42924
|
...this.setupPnpm(),
|
|
42629
42925
|
...this.setupNode(),
|
|
@@ -42643,69 +42939,36 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
|
|
|
42643
42939
|
/**
|
|
42644
42940
|
* Run CDK Diff, capturing the output while leaving it visible in the job
|
|
42645
42941
|
* log. `pipefail` keeps the CLI's exit code from being masked by `tee`.
|
|
42942
|
+
*
|
|
42943
|
+
* The capture lands under the same path the report job will merge it
|
|
42944
|
+
* back to, so a target's file name is identical in both places.
|
|
42646
42945
|
*/
|
|
42647
42946
|
{
|
|
42648
42947
|
name: `Diff ${label}`,
|
|
42649
42948
|
shell: "bash",
|
|
42650
42949
|
run: [
|
|
42651
42950
|
"set -o pipefail",
|
|
42951
|
+
`mkdir -p ${DIFF_OUTPUT_DIRECTORY}`,
|
|
42652
42952
|
`pnpm dlx "aws-cdk@${cdkCli.cliVersion}" ${renderCdkDiff({
|
|
42653
42953
|
...cdkCli.diffOptionsFor(target),
|
|
42654
42954
|
app: rootCdkOut,
|
|
42655
42955
|
ci: true,
|
|
42656
42956
|
noColor: true,
|
|
42657
42957
|
stackPatterns: stackPattern ? [stackPattern] : void 0
|
|
42658
|
-
})} 2>&1 | tee ${
|
|
42958
|
+
})} 2>&1 | tee ${outputFile}`
|
|
42659
42959
|
].join("\n")
|
|
42660
42960
|
},
|
|
42661
42961
|
/**
|
|
42662
|
-
*
|
|
42663
|
-
*
|
|
42664
|
-
*
|
|
42962
|
+
* Hand the capture to the report job. Guarded on `!cancelled()` rather
|
|
42963
|
+
* than success, so a diff that exits non-zero — a synth error, or a
|
|
42964
|
+
* consumer who opted into `--fail` — still contributes what it captured
|
|
42965
|
+
* instead of leaving a hole in the report.
|
|
42665
42966
|
*/
|
|
42666
|
-
|
|
42667
|
-
|
|
42668
|
-
|
|
42669
|
-
|
|
42670
|
-
|
|
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.
|
|
42698
|
-
*/
|
|
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
|
-
] : []
|
|
42967
|
+
renderDiffPartUploadStep({
|
|
42968
|
+
label,
|
|
42969
|
+
artifactName: this.buildDiffPartArtifactName(target),
|
|
42970
|
+
outputFile
|
|
42971
|
+
})
|
|
42709
42972
|
];
|
|
42710
42973
|
};
|
|
42711
42974
|
if (!(project.root instanceof MonorepoProject)) {
|
|
@@ -42739,6 +43002,7 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
|
|
|
42739
43002
|
artifact: options.diff?.artifact ?? true,
|
|
42740
43003
|
summary: options.diff?.summary ?? true
|
|
42741
43004
|
};
|
|
43005
|
+
this.branchScopedConcurrency = options.branchScopedConcurrency ?? false;
|
|
42742
43006
|
this.environmentName = resolveEnvironmentGate(
|
|
42743
43007
|
options.gate,
|
|
42744
43008
|
options.environmentName,
|
|
@@ -42771,14 +43035,20 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
|
|
|
42771
43035
|
buildTask: this.rootProject.buildTask,
|
|
42772
43036
|
/**
|
|
42773
43037
|
* Use push triggers based n the branch config for each environment.
|
|
43038
|
+
*
|
|
43039
|
+
* Deduped: targets in one workflow routinely share a branch — two prod
|
|
43040
|
+
* targets both default to `main` — and a repeated entry is only noise
|
|
43041
|
+
* in the generated file, since GitHub treats this as a filter list.
|
|
42774
43042
|
*/
|
|
42775
43043
|
workflowTriggers: {
|
|
42776
43044
|
push: {
|
|
42777
|
-
branches:
|
|
42778
|
-
|
|
42779
|
-
|
|
43045
|
+
branches: Array.from(
|
|
43046
|
+
new Set(
|
|
43047
|
+
this.awsDeploymentTargets.flatMap(
|
|
43048
|
+
(t) => t.branches.map((b) => b.branch)
|
|
43049
|
+
)
|
|
42780
43050
|
)
|
|
42781
|
-
|
|
43051
|
+
)
|
|
42782
43052
|
},
|
|
42783
43053
|
workflowDispatch: {},
|
|
42784
43054
|
...options.buildWorkflowOptions?.workflowTriggers
|
|
@@ -42796,7 +43066,7 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
|
|
|
42796
43066
|
* Set GIT_BRANCH_NAME so Turborepo remote cache hashes match between local and CI.
|
|
42797
43067
|
*/
|
|
42798
43068
|
env: {
|
|
42799
|
-
GIT_BRANCH_NAME:
|
|
43069
|
+
GIT_BRANCH_NAME: BRANCH_NAME_EXPRESSION,
|
|
42800
43070
|
...options.buildWorkflowOptions?.env,
|
|
42801
43071
|
...buildWorkflowOptions?.env
|
|
42802
43072
|
},
|
|
@@ -42874,19 +43144,19 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
|
|
|
42874
43144
|
name: `Deploy ${this.project.name} ${target.awsStageType}/${target.deploymentTargetRole}/${target.account}/${target.region}`,
|
|
42875
43145
|
needs: [
|
|
42876
43146
|
"build",
|
|
42877
|
-
...gatedOnDiff ? [
|
|
43147
|
+
...gatedOnDiff ? [DIFF_REPORT_JOB_ID] : [],
|
|
42878
43148
|
...this.deployAfterTargets.map((p) => {
|
|
42879
43149
|
return this.buildJobName(p);
|
|
42880
43150
|
})
|
|
42881
43151
|
],
|
|
42882
43152
|
runsOn: ["ubuntu-latest"],
|
|
42883
43153
|
permissions: {
|
|
42884
|
-
contents:
|
|
42885
|
-
idToken:
|
|
42886
|
-
pullRequests:
|
|
43154
|
+
contents: JobPermission7.READ,
|
|
43155
|
+
idToken: JobPermission7.WRITE,
|
|
43156
|
+
pullRequests: JobPermission7.WRITE
|
|
42887
43157
|
},
|
|
42888
43158
|
...this.environmentName ? { environment: this.environmentName } : void 0,
|
|
42889
|
-
concurrency: deployJobName,
|
|
43159
|
+
concurrency: this.buildDeployConcurrency(deployJobName),
|
|
42890
43160
|
if: jobCondition,
|
|
42891
43161
|
steps: [...this.deploySteps(target)]
|
|
42892
43162
|
});
|
|
@@ -42898,14 +43168,28 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
|
|
|
42898
43168
|
needs: ["build"],
|
|
42899
43169
|
runsOn: ["ubuntu-latest"],
|
|
42900
43170
|
permissions: {
|
|
42901
|
-
contents:
|
|
42902
|
-
idToken:
|
|
43171
|
+
contents: JobPermission7.READ,
|
|
43172
|
+
idToken: JobPermission7.WRITE
|
|
42903
43173
|
},
|
|
42904
43174
|
if: jobCondition,
|
|
42905
43175
|
steps: [...this.diffSteps(target)]
|
|
42906
43176
|
});
|
|
42907
43177
|
}
|
|
42908
43178
|
});
|
|
43179
|
+
if (this.diffOptions.enabled && this.awsDeploymentTargets.length > 0) {
|
|
43180
|
+
DiffReportJob.attach(this.rootProject, {
|
|
43181
|
+
buildWorkflow: this.buildWorkflow,
|
|
43182
|
+
homeRepositoryCondition,
|
|
43183
|
+
summary: this.diffOptions.summary,
|
|
43184
|
+
artifact: this.diffOptions.artifact,
|
|
43185
|
+
targets: this.awsDeploymentTargets.map((target) => ({
|
|
43186
|
+
label: `${this.project.name} ${target.awsStageType}/${target.deploymentTargetRole}/${target.account}/${target.region}`,
|
|
43187
|
+
jobName: this.buildDiffJobName(target),
|
|
43188
|
+
outputFile: this.buildDiffOutputFile(target),
|
|
43189
|
+
branchCondition: this.buildBranchFilterCondition(target.branches)
|
|
43190
|
+
}))
|
|
43191
|
+
});
|
|
43192
|
+
}
|
|
42909
43193
|
addBuildCompleteJob(this.buildWorkflow);
|
|
42910
43194
|
}
|
|
42911
43195
|
static of(project, buildWorkflow) {
|
|
@@ -42919,7 +43203,7 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
|
|
|
42919
43203
|
name: "Build Sub Projects",
|
|
42920
43204
|
run: `pnpm exec projen ${ROOT_CI_TASK_NAME}`
|
|
42921
43205
|
},
|
|
42922
|
-
|
|
43206
|
+
WorkflowSteps3.uploadArtifact({
|
|
42923
43207
|
name: "Upload Turbo runs",
|
|
42924
43208
|
if: "always()",
|
|
42925
43209
|
continueOnError: true,
|
|
@@ -42935,9 +43219,9 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends Component24 {
|
|
|
42935
43219
|
};
|
|
42936
43220
|
|
|
42937
43221
|
// src/workflows/aws-teardown-workflow.ts
|
|
42938
|
-
import { Component as
|
|
43222
|
+
import { Component as Component26 } from "projen";
|
|
42939
43223
|
import { GitHub as GitHub7, GithubWorkflow as GithubWorkflow3 } from "projen/lib/github";
|
|
42940
|
-
import { JobPermission as
|
|
43224
|
+
import { JobPermission as JobPermission8 } from "projen/lib/github/workflows-model";
|
|
42941
43225
|
var DEFAULT_TEARDOWN_BRANCH_PATTERNS = [
|
|
42942
43226
|
"feat/*",
|
|
42943
43227
|
"fix/*",
|
|
@@ -42957,7 +43241,7 @@ var resolveBranchPatterns = (explicit, targets) => {
|
|
|
42957
43241
|
}
|
|
42958
43242
|
return [...DEFAULT_TEARDOWN_BRANCH_PATTERNS];
|
|
42959
43243
|
};
|
|
42960
|
-
var AwsTeardownWorkflow = class extends
|
|
43244
|
+
var AwsTeardownWorkflow = class extends Component26 {
|
|
42961
43245
|
constructor(rootProject, options) {
|
|
42962
43246
|
super(rootProject);
|
|
42963
43247
|
this.rootProject = rootProject;
|
|
@@ -43029,8 +43313,8 @@ var AwsTeardownWorkflow = class extends Component25 {
|
|
|
43029
43313
|
runsOn: ["ubuntu-latest"],
|
|
43030
43314
|
...homeRepositoryCondition ? { if: `\${{ ${homeRepositoryCondition} }}` } : {},
|
|
43031
43315
|
permissions: {
|
|
43032
|
-
contents:
|
|
43033
|
-
idToken:
|
|
43316
|
+
contents: JobPermission8.READ,
|
|
43317
|
+
idToken: JobPermission8.WRITE
|
|
43034
43318
|
},
|
|
43035
43319
|
env: {
|
|
43036
43320
|
REPO: "${{ github.repository }}",
|
|
@@ -43890,7 +44174,12 @@ export {
|
|
|
43890
44174
|
DEFAULT_UNBLOCK_DEPENDENTS_ENABLED,
|
|
43891
44175
|
DEFAULT_UPSTREAM_CONFIGULATOR_ENABLED,
|
|
43892
44176
|
DEPLOY_GATE,
|
|
44177
|
+
DIFF_ARTIFACT_NAME,
|
|
44178
|
+
DIFF_OUTPUT_DIRECTORY,
|
|
44179
|
+
DIFF_PART_ARTIFACT_PREFIX,
|
|
44180
|
+
DIFF_REPORT_JOB_ID,
|
|
43893
44181
|
DOCS_SYNC_AUDIT_SCHEMA_VERSION,
|
|
44182
|
+
DiffReportJob,
|
|
43894
44183
|
GITHUB_ISSUE_TYPES,
|
|
43895
44184
|
GITHUB_ISSUE_TYPE_BY_TITLE_PREFIX,
|
|
43896
44185
|
ISSUE_TEMPLATES_GENERATED_SUFFIX,
|
|
@@ -44070,6 +44359,7 @@ export {
|
|
|
44070
44359
|
renderCheckLinksProcedure,
|
|
44071
44360
|
renderCustomDocSectionBlock,
|
|
44072
44361
|
renderCustomDocSections,
|
|
44362
|
+
renderDiffPartUploadStep,
|
|
44073
44363
|
renderExtractApiProcedure,
|
|
44074
44364
|
renderFocusSection,
|
|
44075
44365
|
renderGithubIssueTypeSection,
|
|
@@ -44101,6 +44391,8 @@ export {
|
|
|
44101
44391
|
renderScopeGateSection,
|
|
44102
44392
|
renderScopeGateShellHelpers,
|
|
44103
44393
|
renderSetIssueTypeFallbackLines,
|
|
44394
|
+
renderSetupNode,
|
|
44395
|
+
renderSetupPnpm,
|
|
44104
44396
|
renderSharedEditingBundleHook,
|
|
44105
44397
|
renderSharedEditingHelperScript,
|
|
44106
44398
|
renderSharedEditingRuleContent,
|