@flit/cdk-pipeline 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flit/cdk-pipeline",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "A highly customizable and extensible CI/CD pipeline intended as alternative to CDK's native CodePipeline",
5
5
  "keywords": [
6
6
  "aws",
@@ -51,18 +51,18 @@
51
51
  "useTabs": true
52
52
  },
53
53
  "devDependencies": {
54
- "@types/node": "^25.0.3",
55
- "aws-cdk-lib": "^2.232.0",
56
- "constructs": "^10.4.0",
57
- "jsii": "^5.9.22",
58
- "jsii-pacmak": "^1.125.0",
59
- "prettier": "^3.7.4",
60
- "prettier-plugin-packagejson": "^2.5.20",
54
+ "@types/node": "^25.5.0",
55
+ "aws-cdk-lib": "^2.244.0",
56
+ "constructs": "^10.6.0",
57
+ "jsii": "^5.9.34",
58
+ "jsii-pacmak": "^1.127.0",
59
+ "prettier": "^3.8.1",
60
+ "prettier-plugin-packagejson": "^3.0.2",
61
61
  "typescript": "^5.9.3"
62
62
  },
63
63
  "peerDependencies": {
64
- "aws-cdk-lib": "^2.232.0",
65
- "constructs": "^10.4.0"
64
+ "aws-cdk-lib": "^2.244.0",
65
+ "constructs": "^10.6.0"
66
66
  },
67
67
  "publishConfig": {
68
68
  "access": "public"
@@ -1,6 +1,8 @@
1
1
  import {
2
2
  BuildEnvironmentVariable,
3
3
  BuildSpec,
4
+ ComputeType,
5
+ LinuxBuildImage,
4
6
  mergeBuildSpecs,
5
7
  Project,
6
8
  ProjectProps,
@@ -8,17 +10,15 @@ import {
8
10
  import { Stack } from "aws-cdk-lib";
9
11
  import { IAction } from "aws-cdk-lib/aws-codepipeline";
10
12
  import {
11
- CloudFormationCreateReplaceChangeSetAction,
12
13
  CloudFormationExecuteChangeSetAction,
13
14
  CodeBuildAction,
14
15
  ManualApprovalAction,
15
16
  } from "aws-cdk-lib/aws-codepipeline-actions";
16
- import * as path from "path";
17
17
 
18
18
  import { Artifact } from "./artifact";
19
19
  import { Segment, SegmentConstructed } from "./segment";
20
20
  import { Pipeline } from "./pipeline";
21
- import { PublishAssetsAction } from "./publish-assets-action";
21
+ import { PolicyStatement } from "aws-cdk-lib/aws-iam";
22
22
 
23
23
  export interface PipelineSegmentProps {
24
24
  /**
@@ -105,6 +105,61 @@ export class PipelineSegmentConstructed extends SegmentConstructed {
105
105
 
106
106
  const buildArtifact = props.output || new Artifact();
107
107
 
108
+ const prepareChangesProject = new Project(this, "PrepareChanges", {
109
+ environment: {
110
+ computeType: ComputeType.MEDIUM,
111
+ buildImage: LinuxBuildImage.AMAZON_LINUX_2_ARM_3,
112
+ },
113
+ buildSpec: BuildSpec.fromObject({
114
+ version: 0.2,
115
+ phases: {
116
+ install: {
117
+ "runtime-versions": {
118
+ nodejs: "24",
119
+ },
120
+ commands: "npm install -g aws-cdk",
121
+ },
122
+ build: {
123
+ commands: `npx cdk deploy ${props.stackName ? props.stackName : props.stack.stackName} --app ./ --method prepare-change-set --change-set-name pipeline-${props.stackName ? props.stackName : props.stack.stackName}-${this.name} --require-approval never`,
124
+ },
125
+ },
126
+ cache: {
127
+ paths: ["/root/.npm/**/*"],
128
+ },
129
+ }),
130
+ });
131
+
132
+ prepareChangesProject.addToRolePolicy(
133
+ new PolicyStatement({
134
+ actions: [
135
+ "ssm:GetParameter",
136
+ "cloudformation:CreateChangeSet",
137
+ "cloudformation:DescribeChangeSet",
138
+ "cloudformation:DescribeStacks",
139
+ "cloudformation:GetTemplate",
140
+ "cloudformation:DeleteChangeSet",
141
+ "iam:PassRole",
142
+ ],
143
+ resources: ["*"],
144
+ }),
145
+ );
146
+
147
+ prepareChangesProject.addToRolePolicy(
148
+ new PolicyStatement({
149
+ actions: ["sts:AssumeRole"],
150
+ resources: [`arn:*:iam::${Stack.of(this).account}:role/*`],
151
+ conditions: {
152
+ "ForAnyValue:StringEquals": {
153
+ "iam:ResourceTag/aws-cdk:bootstrap-role": [
154
+ "image-publishing",
155
+ "file-publishing",
156
+ "deploy",
157
+ ],
158
+ },
159
+ },
160
+ }),
161
+ );
162
+
108
163
  this.actions = [
109
164
  new CodeBuildAction({
110
165
  actionName: "Build",
@@ -120,50 +175,40 @@ export class PipelineSegmentConstructed extends SegmentConstructed {
120
175
  props.project.buildSpec,
121
176
  BuildSpec.fromObject({
122
177
  artifacts: {
123
- files: [path.join(scope.buildDir, "**/*")],
178
+ "base-directory": scope.buildDir,
179
+ files: ["**/*"],
124
180
  },
125
181
  }),
126
- )
182
+ )
127
183
  : BuildSpec.fromObject({
128
184
  artifacts: {
129
- files: [path.join(scope.buildDir, "**/*")],
185
+ "base-directory": scope.buildDir,
186
+ files: ["**/*"],
130
187
  },
131
- }),
188
+ }),
132
189
  }),
133
190
  }),
134
- new PublishAssetsAction(this, "PublishAssets", {
135
- actionName: "PublishAssets",
191
+ new CodeBuildAction({
192
+ actionName: "PrepareChanges",
136
193
  runOrder: 2,
137
194
  input: buildArtifact,
138
- manifestPath: scope.buildDir,
139
- }),
140
- new CloudFormationCreateReplaceChangeSetAction({
141
- actionName: "PrepareChanges",
142
- runOrder: 3,
143
- stackName: props.stackName ? props.stackName : props.stack.stackName,
144
- account: props.stack.account,
145
- region: props.stack.region,
146
- changeSetName: `${this.name}Changes`,
147
- adminPermissions: true,
148
- templatePath: buildArtifact.atPath(
149
- path.join(scope.buildDir, props.stack.templateFile),
150
- ),
195
+ project: prepareChangesProject,
151
196
  }),
152
197
  ...(props.manualApproval
153
198
  ? [
154
199
  new ManualApprovalAction({
155
200
  actionName: "ApproveChanges",
156
- runOrder: 4,
201
+ runOrder: 3,
157
202
  }),
158
- ]
203
+ ]
159
204
  : []),
160
205
  new CloudFormationExecuteChangeSetAction({
161
206
  actionName: "ExecuteChanges",
162
- runOrder: props.manualApproval ? 5 : 4,
207
+ runOrder: props.manualApproval ? 3 : 4,
163
208
  stackName: props.stackName ? props.stackName : props.stack.stackName,
164
209
  account: props.stack.account,
165
210
  region: props.stack.region,
166
- changeSetName: `${this.name}Changes`,
211
+ changeSetName: `pipeline-${props.stackName ? props.stackName : props.stack.stackName}-${this.name}`,
167
212
  }),
168
213
  ];
169
214
  }
@@ -3,13 +3,14 @@ import {
3
3
  BuildEnvironmentVariable,
4
4
  BuildEnvironmentVariableType,
5
5
  BuildSpec,
6
+ ComputeType,
7
+ LinuxBuildImage,
6
8
  mergeBuildSpecs,
7
9
  Project,
8
10
  ProjectProps,
9
11
  } from "aws-cdk-lib/aws-codebuild";
10
12
  import { IAction } from "aws-cdk-lib/aws-codepipeline";
11
13
  import {
12
- CloudFormationCreateReplaceChangeSetAction,
13
14
  CloudFormationExecuteChangeSetAction,
14
15
  CodeBuildAction,
15
16
  ManualApprovalAction,
@@ -20,7 +21,6 @@ import * as path from "path";
20
21
  import { Artifact } from "./artifact";
21
22
  import { Segment, SegmentConstructed } from "./segment";
22
23
  import { Pipeline } from "./pipeline";
23
- import { PublishAssetsAction } from "./publish-assets-action";
24
24
 
25
25
  export interface StackSegmentProps {
26
26
  /**
@@ -136,12 +136,12 @@ export class StackSegmentConstructed extends SegmentConstructed {
136
136
  files: [path.join(scope.buildDir, "**/*")],
137
137
  },
138
138
  }),
139
- )
139
+ )
140
140
  : BuildSpec.fromObject({
141
141
  artifacts: {
142
142
  files: [path.join(scope.buildDir, "**/*")],
143
143
  },
144
- }),
144
+ }),
145
145
  });
146
146
 
147
147
  Object.entries(
@@ -174,7 +174,7 @@ export class StackSegmentConstructed extends SegmentConstructed {
174
174
  ? v.value.split(":").slice(0, 7).join(":")
175
175
  : `arn:aws:secretsmanager:*:${
176
176
  Stack.of(this).account
177
- }:secret:${v.value}-*`,
177
+ }:secret:${v.value}-*`,
178
178
  ],
179
179
  }),
180
180
  );
@@ -182,6 +182,61 @@ export class StackSegmentConstructed extends SegmentConstructed {
182
182
  }
183
183
  });
184
184
 
185
+ const prepareChangesProject = new Project(this, "PrepareChanges", {
186
+ environment: {
187
+ computeType: ComputeType.MEDIUM,
188
+ buildImage: LinuxBuildImage.AMAZON_LINUX_2_ARM_3,
189
+ },
190
+ buildSpec: BuildSpec.fromObject({
191
+ version: 0.2,
192
+ phases: {
193
+ install: {
194
+ "runtime-versions": {
195
+ nodejs: "24",
196
+ },
197
+ commands: "npm install -g aws-cdk",
198
+ },
199
+ build: {
200
+ commands: `npx cdk deploy ${props.stackName ? props.stackName : props.stack.stackName} --app ./ --method prepare-change-set --change-set-name pipeline-${props.stackName ? props.stackName : props.stack.stackName}-${this.name} --require-approval never`,
201
+ },
202
+ },
203
+ cache: {
204
+ paths: ["/root/.npm/**/*"],
205
+ },
206
+ }),
207
+ });
208
+
209
+ prepareChangesProject.addToRolePolicy(
210
+ new PolicyStatement({
211
+ actions: [
212
+ "ssm:GetParameter",
213
+ "cloudformation:CreateChangeSet",
214
+ "cloudformation:DescribeChangeSet",
215
+ "cloudformation:DescribeStacks",
216
+ "cloudformation:GetTemplate",
217
+ "cloudformation:DeleteChangeSet",
218
+ "iam:PassRole",
219
+ ],
220
+ resources: ["*"],
221
+ }),
222
+ );
223
+
224
+ prepareChangesProject.addToRolePolicy(
225
+ new PolicyStatement({
226
+ actions: ["sts:AssumeRole"],
227
+ resources: [`arn:*:iam::${Stack.of(this).account}:role/*`],
228
+ conditions: {
229
+ "ForAnyValue:StringEquals": {
230
+ "iam:ResourceTag/aws-cdk:bootstrap-role": [
231
+ "image-publishing",
232
+ "file-publishing",
233
+ "deploy",
234
+ ],
235
+ },
236
+ },
237
+ }),
238
+ );
239
+
185
240
  this.actions = [
186
241
  ...(buildArtifact
187
242
  ? [
@@ -194,53 +249,41 @@ export class StackSegmentConstructed extends SegmentConstructed {
194
249
  environmentVariables: props.environmentVariables,
195
250
  project: codeBuildProject,
196
251
  }),
197
- new PublishAssetsAction(this, "PublishAssets", {
198
- actionName: `${this.name}PublishAssets`,
199
- runOrder: 2,
200
- input: buildArtifact,
201
- manifestPath: scope.buildDir,
202
- }),
203
- ]
252
+ ]
204
253
  : []),
205
- new CloudFormationCreateReplaceChangeSetAction({
254
+ new CodeBuildAction({
206
255
  actionName: `${this.name}PrepareChanges`,
207
- runOrder: buildArtifact ? 3 : 1,
208
- stackName: props.stackName ? props.stackName : props.stack.stackName,
209
- account: props.stack.account,
210
- region: props.stack.region,
211
- changeSetName: `${this.name}Changes`,
212
- adminPermissions: true,
213
- templatePath: (buildArtifact ? buildArtifact : props.input).atPath(
214
- path.join(scope.buildDir, props.stack.templateFile),
215
- ),
256
+ runOrder: buildArtifact ? 2 : 1,
257
+ input: buildArtifact ? buildArtifact : props.input,
258
+ project: prepareChangesProject,
216
259
  }),
217
260
  ...(props.manualApproval
218
261
  ? [
219
262
  new ManualApprovalAction({
220
263
  actionName: `${this.name}ApproveChanges`,
221
- runOrder: buildArtifact ? 4 : 2,
264
+ runOrder: buildArtifact ? 3 : 2,
222
265
  }),
223
- ]
266
+ ]
224
267
  : []),
225
268
  new CloudFormationExecuteChangeSetAction({
226
269
  actionName: `${this.name}ExecuteChanges`,
227
270
  runOrder: props.manualApproval
228
271
  ? buildArtifact
229
- ? 5
272
+ ? 4
230
273
  : 3
231
274
  : buildArtifact
232
- ? 4
233
- : 2,
275
+ ? 3
276
+ : 2,
234
277
  stackName: props.stackName ? props.stackName : props.stack.stackName,
235
278
  account: props.stack.account,
236
279
  region: props.stack.region,
237
- changeSetName: `${this.name}Changes`,
280
+ changeSetName: `pipeline-${props.stackName ? props.stackName : props.stack.stackName}-${this.name}`,
238
281
  output: props.stackOutput,
239
282
  outputFileName: props.outputFileName
240
283
  ? props.outputFileName
241
284
  : props.stackOutput
242
- ? "artifact.json"
243
- : undefined,
285
+ ? "artifact.json"
286
+ : undefined,
244
287
  }),
245
288
  ];
246
289
  }