@codedrifters/configulator 0.0.425 → 0.0.427
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 +194 -15
- package/lib/index.d.ts +195 -16
- package/lib/index.js +357 -51
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +355 -54
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -195,6 +195,7 @@ __export(index_exports, {
|
|
|
195
195
|
AwsDeploymentConfig: () => AwsDeploymentConfig,
|
|
196
196
|
AwsDeploymentTarget: () => AwsDeploymentTarget,
|
|
197
197
|
AwsTeardownWorkflow: () => AwsTeardownWorkflow,
|
|
198
|
+
BUILD_ARTIFACT_NAME: () => BUILD_ARTIFACT_NAME,
|
|
198
199
|
BUILT_IN_BUNDLES: () => BUILT_IN_BUNDLES,
|
|
199
200
|
BUNDLE_OWNERSHIP: () => BUNDLE_OWNERSHIP,
|
|
200
201
|
CDK_BOOTSTRAP_DEFAULTS_BY_STAGE: () => CDK_BOOTSTRAP_DEFAULTS_BY_STAGE,
|
|
@@ -293,7 +294,9 @@ __export(index_exports, {
|
|
|
293
294
|
MONOREPO_LAYOUT: () => MONOREPO_LAYOUT,
|
|
294
295
|
MonorepoProject: () => MonorepoProject,
|
|
295
296
|
Nvmrc: () => Nvmrc,
|
|
297
|
+
PERMISSION_BACKUP_FILE: () => PERMISSION_BACKUP_FILE,
|
|
296
298
|
PHASE_LABEL_TYPE_MAP: () => PHASE_LABEL_TYPE_MAP,
|
|
299
|
+
PLAN_RUN_ID_INPUT: () => PLAN_RUN_ID_INPUT,
|
|
297
300
|
PROD_DEPLOY_NAME: () => PROD_DEPLOY_NAME,
|
|
298
301
|
PROGRESS_FILES_FORMAT_VALUES: () => PROGRESS_FILES_FORMAT_VALUES,
|
|
299
302
|
PnpmWorkspace: () => PnpmWorkspace,
|
|
@@ -327,6 +330,7 @@ __export(index_exports, {
|
|
|
327
330
|
TypeScriptConfig: () => TypeScriptConfig,
|
|
328
331
|
TypeScriptProject: () => TypeScriptProject,
|
|
329
332
|
UNKNOWN_TYPE_FALLBACK_TIER: () => UNKNOWN_TYPE_FALLBACK_TIER,
|
|
333
|
+
VALIDATE_PLAN_JOB_ID: () => VALIDATE_PLAN_JOB_ID,
|
|
330
334
|
VALID_PRIORITY_VALUES: () => VALID_PRIORITY_VALUES,
|
|
331
335
|
VALID_STATUS_VALUES: () => VALID_STATUS_VALUES,
|
|
332
336
|
VERSION: () => VERSION,
|
|
@@ -471,6 +475,7 @@ __export(index_exports, {
|
|
|
471
475
|
renderNextRequirementIdProcedure: () => renderNextRequirementIdProcedure,
|
|
472
476
|
renderPhaseTypeInvariantSection: () => renderPhaseTypeInvariantSection,
|
|
473
477
|
renderPhaseTypeInvariantShellHelpers: () => renderPhaseTypeInvariantShellHelpers,
|
|
478
|
+
renderPlanValidationScript: () => renderPlanValidationScript,
|
|
474
479
|
renderPriorityRulesSection: () => renderPriorityRulesSection,
|
|
475
480
|
renderProgressFileName: () => renderProgressFileName,
|
|
476
481
|
renderProgressFilePath: () => renderProgressFilePath,
|
|
@@ -42304,7 +42309,17 @@ var DEPLOY_GATE = {
|
|
|
42304
42309
|
* required reviewers, wait timers, deployment branch policies — apply before
|
|
42305
42310
|
* the job is sent to a runner.
|
|
42306
42311
|
*/
|
|
42307
|
-
ENVIRONMENT: "environment"
|
|
42312
|
+
ENVIRONMENT: "environment",
|
|
42313
|
+
/**
|
|
42314
|
+
* Split the workflow in two. A **plan** workflow builds and diffs but never
|
|
42315
|
+
* deploys; a dispatch-only **apply** workflow deploys the exact cloud
|
|
42316
|
+
* assembly a nominated plan run produced.
|
|
42317
|
+
*
|
|
42318
|
+
* Needs no protection rule, so unlike {@link DEPLOY_GATE.ENVIRONMENT} it
|
|
42319
|
+
* works on every GitHub plan. `environmentName` is optional here and layers
|
|
42320
|
+
* an environment onto the apply jobs.
|
|
42321
|
+
*/
|
|
42322
|
+
PLAN_APPLY: "plan-apply"
|
|
42308
42323
|
};
|
|
42309
42324
|
var resolveEnvironmentGate = (gate, environmentName, componentName) => {
|
|
42310
42325
|
const trimmed = environmentName?.trim();
|
|
@@ -42316,7 +42331,7 @@ var resolveEnvironmentGate = (gate, environmentName, componentName) => {
|
|
|
42316
42331
|
}
|
|
42317
42332
|
return void 0;
|
|
42318
42333
|
}
|
|
42319
|
-
if (!trimmed) {
|
|
42334
|
+
if (gate === DEPLOY_GATE.ENVIRONMENT && !trimmed) {
|
|
42320
42335
|
throw new Error(
|
|
42321
42336
|
`${componentName} requires a non-empty \`environmentName\` when \`gate\` is "${gate}"`
|
|
42322
42337
|
);
|
|
@@ -42338,6 +42353,105 @@ var renderHomeRepositoryCondition = (homeRepository, componentName) => {
|
|
|
42338
42353
|
return `github.repository == '${homeRepository}'`;
|
|
42339
42354
|
};
|
|
42340
42355
|
|
|
42356
|
+
// src/workflows/plan-apply.ts
|
|
42357
|
+
var VALIDATE_PLAN_JOB_ID = "validate-plan";
|
|
42358
|
+
var PLAN_RUN_ID_INPUT = "plan_run_id";
|
|
42359
|
+
var BUILD_ARTIFACT_NAME = "build-artifact";
|
|
42360
|
+
var PERMISSION_BACKUP_FILE = "permissions-backup.acl";
|
|
42361
|
+
var renderPlanValidationScript = (options) => {
|
|
42362
|
+
const {
|
|
42363
|
+
planWorkflowPath,
|
|
42364
|
+
allowedBranches,
|
|
42365
|
+
requireCurrentHead,
|
|
42366
|
+
verifyArtifactDigest
|
|
42367
|
+
} = options;
|
|
42368
|
+
return [
|
|
42369
|
+
"const raw = (process.env.PLAN_RUN_ID ?? '').trim();",
|
|
42370
|
+
"const runId = Number(raw);",
|
|
42371
|
+
"if (!/^[0-9]+$/.test(raw) || !Number.isSafeInteger(runId) || runId <= 0) {",
|
|
42372
|
+
' core.setFailed(`plan_run_id must be a positive run id, got "${raw}"`);',
|
|
42373
|
+
" return;",
|
|
42374
|
+
"}",
|
|
42375
|
+
"",
|
|
42376
|
+
"const { owner, repo } = context.repo;",
|
|
42377
|
+
"const { data: run } = await github.rest.actions.getWorkflowRun({",
|
|
42378
|
+
" owner,",
|
|
42379
|
+
" repo,",
|
|
42380
|
+
" run_id: runId,",
|
|
42381
|
+
"});",
|
|
42382
|
+
"",
|
|
42383
|
+
`const expectedPath = ${JSON.stringify(planWorkflowPath)};`,
|
|
42384
|
+
"if (run.path !== expectedPath) {",
|
|
42385
|
+
' core.setFailed(`Run ${runId} belongs to workflow "${run.path}", expected "${expectedPath}".`);',
|
|
42386
|
+
" return;",
|
|
42387
|
+
"}",
|
|
42388
|
+
"",
|
|
42389
|
+
'if (run.status !== "completed" || run.conclusion !== "success") {',
|
|
42390
|
+
' core.setFailed(`Run ${runId} is status "${run.status}" / conclusion "${run.conclusion}", expected a completed successful plan run.`);',
|
|
42391
|
+
" return;",
|
|
42392
|
+
"}",
|
|
42393
|
+
"",
|
|
42394
|
+
`const allowedBranches = ${JSON.stringify(allowedBranches)};`,
|
|
42395
|
+
'const branch = run.head_branch ?? "";',
|
|
42396
|
+
"const branchAllowed = allowedBranches.some((pattern) =>",
|
|
42397
|
+
' pattern.includes("*")',
|
|
42398
|
+
' ? branch.startsWith(pattern.slice(0, pattern.indexOf("*")))',
|
|
42399
|
+
" : branch === pattern,",
|
|
42400
|
+
");",
|
|
42401
|
+
"if (!branchAllowed) {",
|
|
42402
|
+
' core.setFailed(`Run ${runId} ran on branch "${branch}", which no deployment target in this workflow accepts (allowed: ${allowedBranches.join(", ")}).`);',
|
|
42403
|
+
" return;",
|
|
42404
|
+
"}",
|
|
42405
|
+
...requireCurrentHead ? [
|
|
42406
|
+
"",
|
|
42407
|
+
"const { data: liveBranch } = await github.rest.repos.getBranch({",
|
|
42408
|
+
" owner,",
|
|
42409
|
+
" repo,",
|
|
42410
|
+
" branch,",
|
|
42411
|
+
"});",
|
|
42412
|
+
"if (liveBranch.commit.sha !== run.head_sha) {",
|
|
42413
|
+
' core.setFailed(`Run ${runId} planned ${run.head_sha} but "${branch}" now points at ${liveBranch.commit.sha}. Re-run the plan workflow against the current head.`);',
|
|
42414
|
+
" return;",
|
|
42415
|
+
"}"
|
|
42416
|
+
] : [],
|
|
42417
|
+
"",
|
|
42418
|
+
"const artifacts = await github.paginate(",
|
|
42419
|
+
" github.rest.actions.listWorkflowRunArtifacts,",
|
|
42420
|
+
" { owner, repo, run_id: runId, per_page: 100 },",
|
|
42421
|
+
");",
|
|
42422
|
+
`const artifactName = ${JSON.stringify(BUILD_ARTIFACT_NAME)};`,
|
|
42423
|
+
"const artifact = artifacts.find((a) => a.name === artifactName);",
|
|
42424
|
+
"if (!artifact) {",
|
|
42425
|
+
' core.setFailed(`Run ${runId} published no "${artifactName}" artifact. Only a plan run whose build job completed can be applied.`);',
|
|
42426
|
+
" return;",
|
|
42427
|
+
"}",
|
|
42428
|
+
"if (artifact.expired) {",
|
|
42429
|
+
' core.setFailed(`The "${artifactName}" artifact on run ${runId} expired at ${artifact.expires_at}. Artifact retention is this gate\'s approval window \u2014 re-run the plan workflow.`);',
|
|
42430
|
+
" return;",
|
|
42431
|
+
"}",
|
|
42432
|
+
...verifyArtifactDigest ? [
|
|
42433
|
+
"if (!artifact.digest) {",
|
|
42434
|
+
' core.setFailed(`The "${artifactName}" artifact on run ${runId} reports no digest, so it cannot be verified. Disable planApply.verifyArtifactDigest or re-run the plan workflow.`);',
|
|
42435
|
+
" return;",
|
|
42436
|
+
"}",
|
|
42437
|
+
'core.setOutput("artifact_digest", artifact.digest);'
|
|
42438
|
+
] : [],
|
|
42439
|
+
"",
|
|
42440
|
+
'core.setOutput("head_sha", run.head_sha);',
|
|
42441
|
+
'core.setOutput("head_branch", branch);',
|
|
42442
|
+
"await core.summary",
|
|
42443
|
+
" .addHeading(`Applying plan run ${runId}`, 2)",
|
|
42444
|
+
" .addTable([",
|
|
42445
|
+
' [{ data: "Field", header: true }, { data: "Value", header: true }],',
|
|
42446
|
+
' ["Plan run", `<a href="${run.html_url}">${runId}</a>`],',
|
|
42447
|
+
' ["Branch", branch],',
|
|
42448
|
+
' ["Commit", run.head_sha],',
|
|
42449
|
+
' ["Artifact expires", artifact.expires_at ?? "unknown"],',
|
|
42450
|
+
" ])",
|
|
42451
|
+
" .write();"
|
|
42452
|
+
].join("\n");
|
|
42453
|
+
};
|
|
42454
|
+
|
|
42341
42455
|
// src/workflows/aws-deploy-workflow.ts
|
|
42342
42456
|
var PROD_DEPLOY_NAME = "prod-deploy";
|
|
42343
42457
|
var DIFF_OUTPUT_FILE = "cdk-diff.txt";
|
|
@@ -42409,6 +42523,20 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends import_projen26.Compone
|
|
|
42409
42523
|
target.region
|
|
42410
42524
|
].join("-");
|
|
42411
42525
|
};
|
|
42526
|
+
/**
|
|
42527
|
+
* Build the deterministic GitHub Actions job name for a target's apply job.
|
|
42528
|
+
* Mirrors {@link buildJobName} with an `apply` verb.
|
|
42529
|
+
*/
|
|
42530
|
+
this.buildApplyJobName = (target) => {
|
|
42531
|
+
return [
|
|
42532
|
+
target.awsStageType,
|
|
42533
|
+
target.deploymentTargetRole,
|
|
42534
|
+
"apply",
|
|
42535
|
+
target.project.name,
|
|
42536
|
+
target.account,
|
|
42537
|
+
target.region
|
|
42538
|
+
].join("-");
|
|
42539
|
+
};
|
|
42412
42540
|
/**
|
|
42413
42541
|
* Build the CI artifact name for a target's captured diff.
|
|
42414
42542
|
*
|
|
@@ -42427,6 +42555,163 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends import_projen26.Compone
|
|
|
42427
42555
|
target.region
|
|
42428
42556
|
].join("-");
|
|
42429
42557
|
};
|
|
42558
|
+
/**
|
|
42559
|
+
* Create the dispatch-only apply workflow and its validation job.
|
|
42560
|
+
*
|
|
42561
|
+
* The workflow file name defaults to the plan workflow's name suffixed with
|
|
42562
|
+
* `-apply`. A name already in use throws rather than silently colliding on
|
|
42563
|
+
* the underlying `.github/workflows/<name>.yml` file — the usual cause is two
|
|
42564
|
+
* `AwsDeployWorkflow`s sharing one build workflow, and the fix is an explicit
|
|
42565
|
+
* `planApply.applyWorkflowName`.
|
|
42566
|
+
*/
|
|
42567
|
+
this.createApplyWorkflow = (github, homeRepositoryCondition) => {
|
|
42568
|
+
const { applyWorkflowName, requireCurrentHead, verifyArtifactDigest } = this.planApplyOptions;
|
|
42569
|
+
if (github.tryFindWorkflow(applyWorkflowName)) {
|
|
42570
|
+
throw new Error(
|
|
42571
|
+
`AwsDeployWorkflow cannot create the apply workflow "${applyWorkflowName}" because a workflow with that name already exists. Set \`planApply.applyWorkflowName\` to something unique.`
|
|
42572
|
+
);
|
|
42573
|
+
}
|
|
42574
|
+
const workflow = new import_github6.GithubWorkflow(github, applyWorkflowName);
|
|
42575
|
+
workflow.on({
|
|
42576
|
+
workflowDispatch: {
|
|
42577
|
+
inputs: {
|
|
42578
|
+
[PLAN_RUN_ID_INPUT]: {
|
|
42579
|
+
description: "Run id of the plan workflow run to apply. Its build artifact is deployed verbatim.",
|
|
42580
|
+
required: true,
|
|
42581
|
+
type: "string"
|
|
42582
|
+
}
|
|
42583
|
+
}
|
|
42584
|
+
}
|
|
42585
|
+
});
|
|
42586
|
+
const allowedBranches = Array.from(
|
|
42587
|
+
new Set(
|
|
42588
|
+
this.awsDeploymentTargets.flatMap(
|
|
42589
|
+
(target) => target.branches.map((b) => b.branch)
|
|
42590
|
+
)
|
|
42591
|
+
)
|
|
42592
|
+
);
|
|
42593
|
+
workflow.addJob(VALIDATE_PLAN_JOB_ID, {
|
|
42594
|
+
name: "Validate plan run",
|
|
42595
|
+
runsOn: ["ubuntu-latest"],
|
|
42596
|
+
permissions: {
|
|
42597
|
+
actions: import_workflows_model5.JobPermission.READ,
|
|
42598
|
+
contents: import_workflows_model5.JobPermission.READ
|
|
42599
|
+
},
|
|
42600
|
+
...homeRepositoryCondition ? { if: `\${{ ${homeRepositoryCondition} }}` } : {},
|
|
42601
|
+
outputs: {
|
|
42602
|
+
head_sha: { stepId: "validate_plan_run", outputName: "head_sha" },
|
|
42603
|
+
head_branch: { stepId: "validate_plan_run", outputName: "head_branch" },
|
|
42604
|
+
...verifyArtifactDigest ? {
|
|
42605
|
+
artifact_digest: {
|
|
42606
|
+
stepId: "validate_plan_run",
|
|
42607
|
+
outputName: "artifact_digest"
|
|
42608
|
+
}
|
|
42609
|
+
} : {}
|
|
42610
|
+
},
|
|
42611
|
+
steps: [
|
|
42612
|
+
{
|
|
42613
|
+
name: "Validate plan run",
|
|
42614
|
+
id: "validate_plan_run",
|
|
42615
|
+
uses: "actions/github-script@v9",
|
|
42616
|
+
/**
|
|
42617
|
+
* The dispatch input reaches the script through the environment
|
|
42618
|
+
* rather than a `${{ }}` interpolation, so a crafted run id cannot
|
|
42619
|
+
* inject JavaScript into the validation itself.
|
|
42620
|
+
*/
|
|
42621
|
+
env: {
|
|
42622
|
+
PLAN_RUN_ID: `\${{ inputs.${PLAN_RUN_ID_INPUT} }}`
|
|
42623
|
+
},
|
|
42624
|
+
with: {
|
|
42625
|
+
script: renderPlanValidationScript({
|
|
42626
|
+
planWorkflowPath: `.github/workflows/${this.buildWorkflow.name}.yml`,
|
|
42627
|
+
allowedBranches,
|
|
42628
|
+
requireCurrentHead,
|
|
42629
|
+
verifyArtifactDigest
|
|
42630
|
+
})
|
|
42631
|
+
}
|
|
42632
|
+
}
|
|
42633
|
+
]
|
|
42634
|
+
});
|
|
42635
|
+
return workflow;
|
|
42636
|
+
};
|
|
42637
|
+
/**
|
|
42638
|
+
* Register one target's apply job on the apply workflow.
|
|
42639
|
+
*
|
|
42640
|
+
* Differences from the `single`-gate deploy job, all of them forced by the
|
|
42641
|
+
* apply run having no build job of its own:
|
|
42642
|
+
*
|
|
42643
|
+
* - `needs` starts at the validation job rather than `build`, so a plan run
|
|
42644
|
+
* that fails any check skips every apply job instead of deploying.
|
|
42645
|
+
* - `actions: read` is added, which is what lets `actions/download-artifact`
|
|
42646
|
+
* reach across runs.
|
|
42647
|
+
* - No `pull-requests: write`, and no sticky PR comment step: an apply is
|
|
42648
|
+
* always a `workflow_dispatch`, so the comment could never fire.
|
|
42649
|
+
* - No branch filter on `github.ref`. The ref an operator happens to
|
|
42650
|
+
* dispatch from is unrelated to what was planned; the branch that matters
|
|
42651
|
+
* is the plan run's, and the validation job checks that one.
|
|
42652
|
+
*
|
|
42653
|
+
* When `environmentName` is also supplied, it lands here rather than on the
|
|
42654
|
+
* plan's jobs — a second approver on top of whoever dispatched the apply.
|
|
42655
|
+
* `validate-plan` stays ungated so its verdict is available to read *before*
|
|
42656
|
+
* the approval is given.
|
|
42657
|
+
*/
|
|
42658
|
+
this.addApplyJob = (workflow, target, homeRepositoryCondition) => {
|
|
42659
|
+
const applyJobName = this.buildApplyJobName(target);
|
|
42660
|
+
const { verifyArtifactDigest } = this.planApplyOptions;
|
|
42661
|
+
const artifactsDirectory = this.rootProject.artifactsDirectory;
|
|
42662
|
+
workflow.addJob(applyJobName, {
|
|
42663
|
+
name: `Apply ${this.project.name} ${target.awsStageType}/${target.deploymentTargetRole}/${target.account}/${target.region}`,
|
|
42664
|
+
needs: [
|
|
42665
|
+
VALIDATE_PLAN_JOB_ID,
|
|
42666
|
+
...this.deployAfterTargets.map((p) => this.buildApplyJobName(p))
|
|
42667
|
+
],
|
|
42668
|
+
runsOn: ["ubuntu-latest"],
|
|
42669
|
+
permissions: {
|
|
42670
|
+
actions: import_workflows_model5.JobPermission.READ,
|
|
42671
|
+
contents: import_workflows_model5.JobPermission.READ,
|
|
42672
|
+
idToken: import_workflows_model5.JobPermission.WRITE
|
|
42673
|
+
},
|
|
42674
|
+
...this.environmentName ? { environment: this.environmentName } : void 0,
|
|
42675
|
+
/**
|
|
42676
|
+
* Shares the deploy job's group name so an apply can never overlap a
|
|
42677
|
+
* same-target deploy. `cancel-in-progress` is spelled out rather than
|
|
42678
|
+
* left to GitHub's default: cancelling a half-finished `cdk deploy`
|
|
42679
|
+
* strands a CloudFormation stack mid-update.
|
|
42680
|
+
*/
|
|
42681
|
+
concurrency: {
|
|
42682
|
+
group: this.buildJobName(target),
|
|
42683
|
+
"cancel-in-progress": false
|
|
42684
|
+
},
|
|
42685
|
+
...homeRepositoryCondition ? { if: `\${{ ${homeRepositoryCondition} }}` } : {},
|
|
42686
|
+
steps: [
|
|
42687
|
+
/**
|
|
42688
|
+
* Cross-run download of the plan's assembly. `run-id` plus an explicit
|
|
42689
|
+
* `github-token` is what makes `actions/download-artifact` look outside
|
|
42690
|
+
* the current run; without both it silently searches this run and finds
|
|
42691
|
+
* nothing.
|
|
42692
|
+
*/
|
|
42693
|
+
{
|
|
42694
|
+
name: "Download plan build artifacts",
|
|
42695
|
+
uses: "actions/download-artifact@v8",
|
|
42696
|
+
with: {
|
|
42697
|
+
name: BUILD_ARTIFACT_NAME,
|
|
42698
|
+
path: artifactsDirectory,
|
|
42699
|
+
"run-id": `\${{ inputs.${PLAN_RUN_ID_INPUT} }}`,
|
|
42700
|
+
"github-token": "${{ secrets.GITHUB_TOKEN }}",
|
|
42701
|
+
...verifyArtifactDigest ? {
|
|
42702
|
+
"artifact-digest": `\${{ needs.${VALIDATE_PLAN_JOB_ID}.outputs.artifact_digest }}`
|
|
42703
|
+
} : {}
|
|
42704
|
+
}
|
|
42705
|
+
},
|
|
42706
|
+
{
|
|
42707
|
+
name: "Restore build artifact permissions",
|
|
42708
|
+
continueOnError: true,
|
|
42709
|
+
run: `cd ${artifactsDirectory} && setfacl --restore=${PERMISSION_BACKUP_FILE}`
|
|
42710
|
+
},
|
|
42711
|
+
...this.deploySteps(target, { stickyPrComment: false })
|
|
42712
|
+
]
|
|
42713
|
+
});
|
|
42714
|
+
};
|
|
42430
42715
|
/**
|
|
42431
42716
|
* Builds a GitHub Actions condition string that checks if the current branch
|
|
42432
42717
|
* matches any of the provided branch patterns.
|
|
@@ -42455,7 +42740,15 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends import_projen26.Compone
|
|
|
42455
42740
|
}
|
|
42456
42741
|
return conditions.join(" || ");
|
|
42457
42742
|
};
|
|
42458
|
-
|
|
42743
|
+
/**
|
|
42744
|
+
* Steps for a target's deploy job.
|
|
42745
|
+
*
|
|
42746
|
+
* `stickyPrComment` drops the sticky-PR-comment step when false. Apply jobs
|
|
42747
|
+
* pass false: they only ever run on `workflow_dispatch` and so could never
|
|
42748
|
+
* satisfy that step's own `pull_request` guard.
|
|
42749
|
+
*/
|
|
42750
|
+
this.deploySteps = (target, options = {}) => {
|
|
42751
|
+
const { stickyPrComment = true } = options;
|
|
42459
42752
|
const {
|
|
42460
42753
|
awsStageType,
|
|
42461
42754
|
deploymentTargetRole,
|
|
@@ -42470,14 +42763,6 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends import_projen26.Compone
|
|
|
42470
42763
|
return [
|
|
42471
42764
|
...this.setupPnpm(),
|
|
42472
42765
|
...this.setupNode(),
|
|
42473
|
-
/**
|
|
42474
|
-
* Install CDK, pinned to the same version that synthesized the cloud
|
|
42475
|
-
* assembly being deployed. See {@link CdkCli.cliVersion}.
|
|
42476
|
-
*/
|
|
42477
|
-
{
|
|
42478
|
-
name: "Install CDK",
|
|
42479
|
-
run: `pnpm add "aws-cdk@${cdkCli.cliVersion}"`
|
|
42480
|
-
},
|
|
42481
42766
|
/**
|
|
42482
42767
|
* Configure AWS creds.
|
|
42483
42768
|
*/
|
|
@@ -42534,23 +42819,25 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends import_projen26.Compone
|
|
|
42534
42819
|
* comment is keyed by the deploy job name so dev/stage/prod comments
|
|
42535
42820
|
* don't collide on the same PR.
|
|
42536
42821
|
*/
|
|
42537
|
-
|
|
42538
|
-
|
|
42539
|
-
|
|
42540
|
-
|
|
42541
|
-
|
|
42542
|
-
|
|
42543
|
-
|
|
42822
|
+
...stickyPrComment ? [
|
|
42823
|
+
{
|
|
42824
|
+
name: "Sticky PR comment with deploy endpoints",
|
|
42825
|
+
if: "github.event_name == 'pull_request' && hashFiles('deploy-urls.md') != ''",
|
|
42826
|
+
uses: "marocchino/sticky-pull-request-comment@v3",
|
|
42827
|
+
with: {
|
|
42828
|
+
header: deployJobName,
|
|
42829
|
+
path: "deploy-urls.md"
|
|
42830
|
+
}
|
|
42544
42831
|
}
|
|
42545
|
-
|
|
42832
|
+
] : []
|
|
42546
42833
|
];
|
|
42547
42834
|
};
|
|
42548
42835
|
/**
|
|
42549
42836
|
* Steps for a target's optional `cdk diff` job.
|
|
42550
42837
|
*
|
|
42551
42838
|
* Mirrors {@link deploySteps}' toolchain and credential setup — same pnpm /
|
|
42552
|
-
* Node setup, same version-pinned `aws-cdk`
|
|
42553
|
-
*
|
|
42839
|
+
* Node setup, same version-pinned `aws-cdk` CLI, same OIDC role — so a diff
|
|
42840
|
+
* is computed by the same CLI that will run the deploy.
|
|
42554
42841
|
*
|
|
42555
42842
|
* The `cdk diff` flags come from the {@link CdkCli} precedence chain via
|
|
42556
42843
|
* `diffOptionsFor(target)`, so `method`, `securityOnly`, `fail`, and the rest
|
|
@@ -42578,14 +42865,6 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends import_projen26.Compone
|
|
|
42578
42865
|
return [
|
|
42579
42866
|
...this.setupPnpm(),
|
|
42580
42867
|
...this.setupNode(),
|
|
42581
|
-
/**
|
|
42582
|
-
* Install CDK, pinned to the same version that synthesized the cloud
|
|
42583
|
-
* assembly being diffed. See {@link CdkCli.cliVersion}.
|
|
42584
|
-
*/
|
|
42585
|
-
{
|
|
42586
|
-
name: "Install CDK",
|
|
42587
|
-
run: `pnpm add "aws-cdk@${cdkCli.cliVersion}"`
|
|
42588
|
-
},
|
|
42589
42868
|
/**
|
|
42590
42869
|
* Configure AWS creds.
|
|
42591
42870
|
*/
|
|
@@ -42686,8 +42965,15 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends import_projen26.Compone
|
|
|
42686
42965
|
(target) => target.awsStageType === this.awsStageType && target.ciDeployment
|
|
42687
42966
|
) ?? [];
|
|
42688
42967
|
this.deployAfterTargets = options.deployAfterTargets ?? [];
|
|
42968
|
+
this.gate = options.gate;
|
|
42969
|
+
const isPlanApply = this.gate === DEPLOY_GATE.PLAN_APPLY;
|
|
42970
|
+
if (isPlanApply && options.diff?.enabled === false) {
|
|
42971
|
+
throw new Error(
|
|
42972
|
+
"AwsDeployWorkflow cannot disable `diff` under the `plan-apply` gate: the diff jobs are what keep the plan workflow publishing the build artifact the apply workflow deploys."
|
|
42973
|
+
);
|
|
42974
|
+
}
|
|
42689
42975
|
this.diffOptions = {
|
|
42690
|
-
enabled: options.diff?.enabled ??
|
|
42976
|
+
enabled: options.diff?.enabled ?? isPlanApply,
|
|
42691
42977
|
artifact: options.diff?.artifact ?? true,
|
|
42692
42978
|
summary: options.diff?.summary ?? true
|
|
42693
42979
|
};
|
|
@@ -42773,6 +43059,17 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends import_projen26.Compone
|
|
|
42773
43059
|
...buildWorkflowOptions?.preBuildSteps ?? []
|
|
42774
43060
|
]
|
|
42775
43061
|
});
|
|
43062
|
+
this.planApplyOptions = {
|
|
43063
|
+
applyWorkflowName: options.planApply?.applyWorkflowName ?? `${this.buildWorkflow.name}-apply`,
|
|
43064
|
+
requireCurrentHead: options.planApply?.requireCurrentHead ?? false,
|
|
43065
|
+
verifyArtifactDigest: options.planApply?.verifyArtifactDigest ?? false
|
|
43066
|
+
};
|
|
43067
|
+
if (isPlanApply) {
|
|
43068
|
+
this.applyWorkflow = this.createApplyWorkflow(
|
|
43069
|
+
github,
|
|
43070
|
+
homeRepositoryCondition
|
|
43071
|
+
);
|
|
43072
|
+
}
|
|
42776
43073
|
this.awsDeploymentTargets.forEach((target) => {
|
|
42777
43074
|
const deployJobName = this.buildJobName(target);
|
|
42778
43075
|
const branchFilterCondition = this.buildBranchFilterCondition(
|
|
@@ -42783,27 +43080,31 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends import_projen26.Compone
|
|
|
42783
43080
|
...homeRepositoryCondition ? [homeRepositoryCondition] : [],
|
|
42784
43081
|
...branchFilterCondition ? [`(${branchFilterCondition})`] : []
|
|
42785
43082
|
].join(" && ") + " }}";
|
|
42786
|
-
|
|
42787
|
-
|
|
42788
|
-
|
|
42789
|
-
|
|
42790
|
-
|
|
42791
|
-
|
|
42792
|
-
|
|
42793
|
-
|
|
42794
|
-
|
|
42795
|
-
|
|
42796
|
-
|
|
42797
|
-
|
|
42798
|
-
|
|
42799
|
-
|
|
42800
|
-
|
|
42801
|
-
|
|
42802
|
-
|
|
42803
|
-
|
|
42804
|
-
|
|
42805
|
-
|
|
42806
|
-
|
|
43083
|
+
if (this.applyWorkflow) {
|
|
43084
|
+
this.addApplyJob(this.applyWorkflow, target, homeRepositoryCondition);
|
|
43085
|
+
} else {
|
|
43086
|
+
const gatedOnDiff = !!this.environmentName && this.diffOptions.enabled;
|
|
43087
|
+
this.buildWorkflow.addPostBuildJob(deployJobName, {
|
|
43088
|
+
name: `Deploy ${this.project.name} ${target.awsStageType}/${target.deploymentTargetRole}/${target.account}/${target.region}`,
|
|
43089
|
+
needs: [
|
|
43090
|
+
"build",
|
|
43091
|
+
...gatedOnDiff ? [this.buildDiffJobName(target)] : [],
|
|
43092
|
+
...this.deployAfterTargets.map((p) => {
|
|
43093
|
+
return this.buildJobName(p);
|
|
43094
|
+
})
|
|
43095
|
+
],
|
|
43096
|
+
runsOn: ["ubuntu-latest"],
|
|
43097
|
+
permissions: {
|
|
43098
|
+
contents: import_workflows_model5.JobPermission.READ,
|
|
43099
|
+
idToken: import_workflows_model5.JobPermission.WRITE,
|
|
43100
|
+
pullRequests: import_workflows_model5.JobPermission.WRITE
|
|
43101
|
+
},
|
|
43102
|
+
...this.environmentName ? { environment: this.environmentName } : void 0,
|
|
43103
|
+
concurrency: deployJobName,
|
|
43104
|
+
if: jobCondition,
|
|
43105
|
+
steps: [...this.deploySteps(target)]
|
|
43106
|
+
});
|
|
43107
|
+
}
|
|
42807
43108
|
if (this.diffOptions.enabled) {
|
|
42808
43109
|
const diffJobName = this.buildDiffJobName(target);
|
|
42809
43110
|
this.buildWorkflow.addPostBuildJob(diffJobName, {
|
|
@@ -43713,6 +44014,7 @@ export const collections = {
|
|
|
43713
44014
|
AwsDeploymentConfig,
|
|
43714
44015
|
AwsDeploymentTarget,
|
|
43715
44016
|
AwsTeardownWorkflow,
|
|
44017
|
+
BUILD_ARTIFACT_NAME,
|
|
43716
44018
|
BUILT_IN_BUNDLES,
|
|
43717
44019
|
BUNDLE_OWNERSHIP,
|
|
43718
44020
|
CDK_BOOTSTRAP_DEFAULTS_BY_STAGE,
|
|
@@ -43811,7 +44113,9 @@ export const collections = {
|
|
|
43811
44113
|
MONOREPO_LAYOUT,
|
|
43812
44114
|
MonorepoProject,
|
|
43813
44115
|
Nvmrc,
|
|
44116
|
+
PERMISSION_BACKUP_FILE,
|
|
43814
44117
|
PHASE_LABEL_TYPE_MAP,
|
|
44118
|
+
PLAN_RUN_ID_INPUT,
|
|
43815
44119
|
PROD_DEPLOY_NAME,
|
|
43816
44120
|
PROGRESS_FILES_FORMAT_VALUES,
|
|
43817
44121
|
PnpmWorkspace,
|
|
@@ -43845,6 +44149,7 @@ export const collections = {
|
|
|
43845
44149
|
TypeScriptConfig,
|
|
43846
44150
|
TypeScriptProject,
|
|
43847
44151
|
UNKNOWN_TYPE_FALLBACK_TIER,
|
|
44152
|
+
VALIDATE_PLAN_JOB_ID,
|
|
43848
44153
|
VALID_PRIORITY_VALUES,
|
|
43849
44154
|
VALID_STATUS_VALUES,
|
|
43850
44155
|
VERSION,
|
|
@@ -43989,6 +44294,7 @@ export const collections = {
|
|
|
43989
44294
|
renderNextRequirementIdProcedure,
|
|
43990
44295
|
renderPhaseTypeInvariantSection,
|
|
43991
44296
|
renderPhaseTypeInvariantShellHelpers,
|
|
44297
|
+
renderPlanValidationScript,
|
|
43992
44298
|
renderPriorityRulesSection,
|
|
43993
44299
|
renderProgressFileName,
|
|
43994
44300
|
renderProgressFilePath,
|