@flit/cdk-pipeline 1.1.2 → 1.2.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": "1.1.2",
3
+ "version": "1.2.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",
@@ -11,16 +11,15 @@
11
11
  "codepipeline",
12
12
  "cicd"
13
13
  ],
14
- "homepage": "https://github.com/jumper-de/cdk-pipeline",
15
- "bugs": "https://github.com/jumper-de/cdk-pipeline/issues",
14
+ "homepage": "https://github.com/vierroth/cdk-pipeline",
15
+ "bugs": "https://github.com/vierroth/cdk-pipeline/issues",
16
16
  "repository": {
17
17
  "type": "git",
18
- "url": "https://github.com/jumper-de/cdk-pipeline.git"
18
+ "url": "https://github.com/vierroth/cdk-pipeline.git"
19
19
  },
20
20
  "license": "Apache-2.0",
21
21
  "author": {
22
22
  "name": "Luis Vierroth",
23
- "email": "luis@jumper.de",
24
23
  "url": "https://github.com/p-mercury"
25
24
  },
26
25
  "main": "./dist/index.js",
@@ -32,21 +31,40 @@
32
31
  "./LICENSE.txt",
33
32
  "./README.md"
34
33
  ],
34
+ "workspaces": [
35
+ "./example"
36
+ ],
35
37
  "scripts": {
36
- "build": "jsii",
38
+ "build": "jsii && (cd example && npm run build)",
37
39
  "prepack": "jsii"
38
40
  },
41
+ "prettier": {
42
+ "plugins": [
43
+ "prettier-plugin-packagejson"
44
+ ],
45
+ "tabWidth": 2,
46
+ "overrides": [
47
+ {
48
+ "files": "*.sublime-project",
49
+ "options": {
50
+ "parser": "json"
51
+ }
52
+ }
53
+ ]
54
+ },
39
55
  "devDependencies": {
40
- "@types/node": "^22.10.2",
41
- "aws-cdk-lib": "2.173.1",
42
- "constructs": "10.4.2",
43
- "jsii": "^5.7.2",
56
+ "@types/node": "^22.10.7",
57
+ "aws-cdk-lib": "^2.174.0",
58
+ "constructs": "^10.4.0",
59
+ "jsii": "^5.7.4",
44
60
  "jsii-pacmak": "^1.106.0",
45
- "typescript": "^5.7.2"
61
+ "prettier": "^3.4.2",
62
+ "prettier-plugin-packagejson": "^2.5.8",
63
+ "typescript": "^5.7.3"
46
64
  },
47
65
  "peerDependencies": {
48
- "aws-cdk-lib": "^2.163.0",
49
- "constructs": "^10.4.2"
66
+ "aws-cdk-lib": "^2.174.0",
67
+ "constructs": "^10.4.0"
50
68
  },
51
69
  "publishConfig": {
52
70
  "access": "public"
package/src/artifact.ts CHANGED
@@ -3,22 +3,22 @@ import { Artifact as AwsArtifact } from "aws-cdk-lib/aws-codepipeline";
3
3
  import { Segment } from "./segment";
4
4
 
5
5
  export class Artifact extends AwsArtifact {
6
- private producer?: Segment;
7
- private consumers: Segment[] = [];
6
+ private _producer?: Segment;
7
+ private _consumers: Segment[] = [];
8
8
  constructor(artifactName?: string) {
9
9
  super(artifactName);
10
10
  }
11
11
  produce(producer: Segment) {
12
- if (this.producer) throw new Error("Artifact is already produced");
13
- this.producer = producer;
12
+ if (this._producer) throw new Error("Artifact is already produced");
13
+ this._producer = producer;
14
14
  }
15
15
  consume(producer: Segment) {
16
16
  this.consumers.push(producer);
17
17
  }
18
- obtainProducer(): Segment | undefined {
19
- return this.producer;
18
+ get producer(): Segment | undefined {
19
+ return this._producer;
20
20
  }
21
- obtainConsumers(): Segment[] {
22
- return this.consumers;
21
+ get consumers(): Segment[] {
22
+ return this._consumers;
23
23
  }
24
24
  }
@@ -39,14 +39,6 @@ export interface PipelineSegmentProps {
39
39
  * @deafult The name of the given stack.
40
40
  */
41
41
  readonly stackName?: string;
42
- /**
43
- * The AWS account this Action is supposed to operate in.
44
- */
45
- readonly account?: string;
46
- /**
47
- * The AWS region the given Action resides in.
48
- */
49
- readonly region?: string;
50
42
  /**
51
43
  * The artifact to hold the stack deployment output file.
52
44
  * @default no output artifact
@@ -68,7 +60,7 @@ export interface PipelineSegmentProps {
68
60
  * @category Segments
69
61
  */
70
62
  export class PipelineSegment extends Segment {
71
- readonly isPipeline: boolean = true;
63
+ readonly isPipeline = true;
72
64
  readonly props: PipelineSegmentProps;
73
65
 
74
66
  constructor(props: PipelineSegmentProps) {
@@ -91,8 +83,6 @@ export interface PipelineSegmentConstructedProps {
91
83
  readonly project: ProjectProps;
92
84
  readonly environmentVariables?: { [key: string]: BuildEnvironmentVariable };
93
85
  readonly stackName?: string;
94
- readonly account?: string;
95
- readonly region?: string;
96
86
  readonly input: Artifact;
97
87
  readonly extraInputs?: Artifact[];
98
88
  readonly output?: Artifact;
@@ -151,8 +141,8 @@ export class PipelineSegmentConstructed extends SegmentConstructed {
151
141
  actionName: "PrepareChanges",
152
142
  runOrder: 3,
153
143
  stackName: props.stackName ? props.stackName : props.stack.stackName,
154
- account: props.account,
155
- region: props.region,
144
+ account: props.stack.account,
145
+ region: props.stack.region,
156
146
  changeSetName: `${props.stack.stackName}Changes`,
157
147
  adminPermissions: true,
158
148
  templatePath: buildArtifact.atPath(
@@ -171,10 +161,14 @@ export class PipelineSegmentConstructed extends SegmentConstructed {
171
161
  actionName: "ExecuteChanges",
172
162
  runOrder: props.manualApproval ? 5 : 4,
173
163
  stackName: props.stackName ? props.stackName : props.stack.stackName,
174
- account: props.account,
175
- region: props.region,
164
+ account: props.stack.account,
165
+ region: props.stack.region,
176
166
  changeSetName: `${props.stack.stackName}Changes`,
177
167
  }),
178
168
  ];
179
169
  }
180
170
  }
171
+
172
+ export function isPipeline(item: Segment): item is PipelineSegment {
173
+ return item.isPipeline;
174
+ }
package/src/pipeline.ts CHANGED
@@ -7,22 +7,22 @@ import {
7
7
  } from "aws-cdk-lib/aws-codepipeline";
8
8
  import * as path from "path";
9
9
 
10
- import { Artifact } from "./artifact";
11
10
  import { Segment } from "./segment";
12
- import { SourceSegment } from "./source-segment";
13
- import { PipelineSegment } from "./pipeline-segment";
11
+ import { isSource } from "./source-segment";
12
+ import { isPipeline } from "./pipeline-segment";
14
13
 
15
14
  export interface PipelineProps extends StackProps {
16
15
  /**
17
16
  * The name of the generated pipeline.
18
- * @default Stack ID
17
+ * @defaultValue Stack ID
19
18
  */
20
19
  readonly pipelineName?: string;
21
20
  /**
22
21
  * The path to the cdk projects root directory containing the cdk.json file
23
22
  * relative to the asset root
23
+ * @defaultValue `"."`
24
24
  */
25
- readonly rootDir: string;
25
+ readonly rootDir?: string;
26
26
  /**
27
27
  * The segments to populating the pipeline.
28
28
  */
@@ -44,29 +44,37 @@ export class Pipeline extends Stack {
44
44
  ) {
45
45
  super(scope, id, props);
46
46
 
47
- this.pipelineName = props.pipelineName ? props.pipelineName : id;
48
- this.rootDir = props.rootDir;
47
+ this.pipelineName = props.pipelineName || id;
48
+ this.rootDir = props.rootDir || ".";
49
49
  this.buildDir = path.join(this.rootDir, (this.node.root as App).outdir);
50
50
 
51
51
  if (!this.bundlingRequired) return;
52
52
 
53
- props.segments.forEach((segment: Segment) => {
54
- segment.inputs.forEach((artifact: Artifact) => {
55
- if (!artifact.obtainProducer())
53
+ props.segments.forEach((segment) => {
54
+ segment.inputs.forEach((artifact) => {
55
+ if (!artifact.producer) {
56
56
  throw new Error("Artifact consumed but never produced.");
57
+ }
57
58
  });
58
59
  });
59
60
 
60
- const sourceSegments: SourceSegment[] = props.segments.filter(
61
- (segment: Segment) => segment.isSource,
62
- ) as SourceSegment[];
61
+ const sourceSegments = props.segments.filter(isSource);
62
+ const pipelineSegments = props.segments.filter(isPipeline);
63
+
64
+ if (pipelineSegments.length < 1) {
65
+ throw new Error(
66
+ "Missing pipeline segment, one instance of the pipeline segment is required in the segments array.",
67
+ );
68
+ }
63
69
 
64
- const pipelineSegment: PipelineSegment | undefined = props.segments.find(
65
- (segment: Segment) => segment.isPipeline,
66
- ) as PipelineSegment;
70
+ if (pipelineSegments.length > 1) {
71
+ throw new Error(
72
+ "To many pipeline segment, only one instance of the pipeline segment can be present in the segments array.",
73
+ );
74
+ }
67
75
 
68
76
  const segments: Segment[] = props.segments.filter(
69
- (segment: Segment) => !segment.isSource && !segment.isPipeline,
77
+ (segment) => !isSource(segment) && !isPipeline(segment),
70
78
  );
71
79
 
72
80
  new AwsPipeline(this, "Pipeline", {
@@ -78,19 +86,19 @@ export class Pipeline extends Stack {
78
86
  stageName: "Source",
79
87
  actions: [
80
88
  ...sourceSegments.reduce(
81
- (actions: IAction[], segment: SourceSegment) => [
89
+ (actions, segment) => [
82
90
  ...actions,
83
91
  ...segment.construct(this).actions,
84
92
  ],
85
- [],
93
+ [] as IAction[],
86
94
  ),
87
95
  ],
88
96
  },
89
97
  {
90
98
  stageName: "Pipeline",
91
- actions: [...pipelineSegment.construct(this).actions],
99
+ actions: [...pipelineSegments[0].construct(this).actions],
92
100
  },
93
- ...segments.map((segment: Segment) => {
101
+ ...segments.map((segment) => {
94
102
  const build = segment.construct(this);
95
103
  return {
96
104
  stageName: build.name,
package/src/segment.ts CHANGED
@@ -18,22 +18,14 @@ export abstract class Segment {
18
18
  readonly outputs: Artifact[] = [];
19
19
  constructor(props: SegmentProps) {
20
20
  if (props.input) {
21
- this.inputs = (
22
- props.input.constructor.name === "Array" ? props.input : [props.input]
23
- ) as Artifact[];
24
- this.inputs.forEach((artifact: Artifact) => {
25
- artifact.consume(this);
26
- }, this);
21
+ this.inputs = Array.isArray(props.input) ? props.input : [props.input];
22
+ this.inputs.forEach((artifact) => artifact.consume(this), this);
27
23
  }
28
24
  if (props.output) {
29
- this.outputs = (
30
- props.output.constructor.name === "Array"
31
- ? props.output
32
- : [props.output]
33
- ) as Artifact[];
34
- this.outputs.forEach((artifact: Artifact) => {
35
- artifact.produce(this);
36
- }, this);
25
+ this.outputs = Array.isArray(props.output)
26
+ ? props.output
27
+ : [props.output];
28
+ this.outputs.forEach((artifact) => artifact.produce(this), this);
37
29
  }
38
30
  }
39
31
  abstract construct(scope: Pipeline): SegmentConstructed;
@@ -6,5 +6,9 @@ export interface SourceSegmentProps {
6
6
  }
7
7
 
8
8
  export abstract class SourceSegment extends Segment {
9
- readonly isSource: boolean = true;
9
+ readonly isSource = true;
10
+ }
11
+
12
+ export function isSource(item: Segment): item is SourceSegment {
13
+ return item.isSource;
10
14
  }
@@ -45,30 +45,21 @@ export interface StackSegmentProps {
45
45
  readonly environmentVariables?: { [key: string]: BuildEnvironmentVariable };
46
46
  /**
47
47
  * The name of the stack to deploy the changes to.
48
- * @deafult The name of the given stack.
48
+ * @defaultValue The name of the given stack.
49
49
  */
50
50
  readonly stackName?: string;
51
- /**
52
- * The AWS account this Action is supposed to operate in.
53
- */
54
- readonly account?: string;
55
- /**
56
- * The AWS region the given Action resides in.
57
- */
58
- readonly region?: string;
59
51
  /**
60
52
  * The artifact to hold the stack deployment output file.
61
- * @default no output artifact
62
53
  */
63
54
  readonly output?: Artifact;
64
55
  /**
65
56
  * The filename for the file in the output artifact
66
- * @default artifact.json
57
+ * @defaultValue `"artifact.json"``
67
58
  */
68
59
  readonly outputFileName?: string;
69
60
  /**
70
61
  * Does this stage require manual approval of the change set?
71
- * @default false
62
+ * @defaultValue `false``
72
63
  */
73
64
  readonly manualApproval?: Boolean;
74
65
  }
@@ -102,8 +93,6 @@ export interface StackSegmentConstructedProps {
102
93
  readonly project?: ProjectProps;
103
94
  readonly environmentVariables?: { [key: string]: BuildEnvironmentVariable };
104
95
  readonly stackName?: string;
105
- readonly account?: string;
106
- readonly region?: string;
107
96
  readonly input: Artifact;
108
97
  readonly extraInputs?: Artifact[];
109
98
  readonly output?: Artifact;
@@ -166,8 +155,8 @@ export class StackSegmentConstructed extends SegmentConstructed {
166
155
  actionName: "PrepareChanges",
167
156
  runOrder: buildArtifact ? 3 : 1,
168
157
  stackName: props.stackName ? props.stackName : props.stack.stackName,
169
- account: props.account,
170
- region: props.region,
158
+ account: props.stack.account,
159
+ region: props.stack.region,
171
160
  changeSetName: `${props.stack.stackName}Changes`,
172
161
  adminPermissions: true,
173
162
  templatePath: (buildArtifact ? buildArtifact : props.input).atPath(
@@ -192,8 +181,8 @@ export class StackSegmentConstructed extends SegmentConstructed {
192
181
  ? 4
193
182
  : 2,
194
183
  stackName: props.stackName ? props.stackName : props.stack.stackName,
195
- account: props.account,
196
- region: props.region,
184
+ account: props.stack.account,
185
+ region: props.stack.region,
197
186
  changeSetName: `${props.stack.stackName}Changes`,
198
187
  output: props.output,
199
188
  outputFileName: props.outputFileName