@flit/cdk-pipeline 2.0.0 → 2.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": "2.0.0",
3
+ "version": "2.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",
@@ -143,7 +143,7 @@ export class PipelineSegmentConstructed extends SegmentConstructed {
143
143
  stackName: props.stackName ? props.stackName : props.stack.stackName,
144
144
  account: props.stack.account,
145
145
  region: props.stack.region,
146
- changeSetName: `${props.stack.stackName}Changes`,
146
+ changeSetName: `${this.name}Changes`,
147
147
  adminPermissions: true,
148
148
  templatePath: buildArtifact.atPath(
149
149
  path.join(scope.buildDir, props.stack.templateFile),
@@ -163,7 +163,7 @@ export class PipelineSegmentConstructed extends SegmentConstructed {
163
163
  stackName: props.stackName ? props.stackName : props.stack.stackName,
164
164
  account: props.stack.account,
165
165
  region: props.stack.region,
166
- changeSetName: `${props.stack.stackName}Changes`,
166
+ changeSetName: `${this.name}Changes`,
167
167
  }),
168
168
  ];
169
169
  }
package/src/pipeline.ts CHANGED
@@ -7,10 +7,15 @@ import {
7
7
  } from "aws-cdk-lib/aws-codepipeline";
8
8
  import * as path from "path";
9
9
 
10
- import { Segment, SegmentConstructed } from "./segment";
10
+ import { isSegment, Segment, SegmentConstructed } from "./segment";
11
11
  import { isSource } from "./source-segment";
12
12
  import { isPipeline } from "./pipeline-segment";
13
13
 
14
+ export interface SegmentGroup {
15
+ readonly stageName?: string;
16
+ readonly segments: Segment[];
17
+ }
18
+
14
19
  export interface PipelineProps extends StackProps {
15
20
  /**
16
21
  * The name of the generated pipeline.
@@ -26,7 +31,7 @@ export interface PipelineProps extends StackProps {
26
31
  /**
27
32
  * The segments to populating the pipeline.
28
33
  */
29
- readonly segments: (Segment | Segment[])[];
34
+ readonly segments: (Segment | Segment[] | SegmentGroup)[];
30
35
  }
31
36
 
32
37
  /**
@@ -50,12 +55,16 @@ export class Pipeline extends Stack {
50
55
 
51
56
  if (!this.bundlingRequired) return;
52
57
 
53
- const segments = props.segments.map((segment) =>
54
- Array.isArray(segment) ? segment : [segment],
58
+ const stages = props.segments.map((segment) =>
59
+ Array.isArray(segment)
60
+ ? { stageName: undefined, segments: segment }
61
+ : isSegment(segment)
62
+ ? { stageName: undefined, segments: [segment] }
63
+ : segment,
55
64
  );
56
65
 
57
- segments.forEach((unit) => {
58
- unit.forEach((segment) => {
66
+ stages.forEach((stage) => {
67
+ stage.segments.forEach((segment) => {
59
68
  segment.inputs.forEach((artifact) => {
60
69
  if (!artifact.producer) {
61
70
  throw new Error("Artifact consumed but never produced.");
@@ -64,22 +73,28 @@ export class Pipeline extends Stack {
64
73
  });
65
74
  });
66
75
 
67
- if (segments[0].filter(isSource).length !== segments[0].length) {
76
+ if (
77
+ stages[0].segments.filter(isSource).length !== stages[0].segments.length
78
+ ) {
68
79
  throw new Error("First segment must contain only source segments");
69
80
  }
70
81
 
71
- if (segments.slice(1).find((unit) => unit.filter(isSource).length)) {
82
+ if (
83
+ stages.slice(1).find((stage) => stage.segments.filter(isSource).length)
84
+ ) {
72
85
  throw new Error("Only the first segment can contain source segments");
73
86
  }
74
87
 
75
88
  if (
76
- segments[1].length !== 1 ||
77
- segments[1].filter(isPipeline).length !== segments[1].length
89
+ stages[1].segments.length !== 1 ||
90
+ stages[1].segments.filter(isPipeline).length !== stages[1].segments.length
78
91
  ) {
79
92
  throw new Error("Second segment must be the pipeline segment");
80
93
  }
81
94
 
82
- if (segments.slice(2).find((unit) => unit.filter(isPipeline).length)) {
95
+ if (
96
+ stages.slice(2).find((stage) => stage.segments.filter(isPipeline).length)
97
+ ) {
83
98
  throw new Error("Only the second segment can be the pipeline segment");
84
99
  }
85
100
 
@@ -89,9 +104,9 @@ export class Pipeline extends Stack {
89
104
  pipelineType: PipelineType.V2,
90
105
  stages: [
91
106
  {
92
- stageName: "Source",
107
+ stageName: stages[0].stageName || "Source",
93
108
  actions: [
94
- ...segments[0].reduce(
109
+ ...stages[0].segments.reduce(
95
110
  (actions, segment) => [
96
111
  ...actions,
97
112
  ...segment.construct(this).actions,
@@ -101,9 +116,9 @@ export class Pipeline extends Stack {
101
116
  ],
102
117
  },
103
118
  {
104
- stageName: "Pipeline",
119
+ stageName: stages[1].stageName || "Pipeline",
105
120
  actions: [
106
- ...segments[1].reduce(
121
+ ...stages[1].segments.reduce(
107
122
  (actions, segment) => [
108
123
  ...actions,
109
124
  ...segment.construct(this).actions,
@@ -112,13 +127,14 @@ export class Pipeline extends Stack {
112
127
  ),
113
128
  ],
114
129
  },
115
- ...segments.slice(2).map((unit) => {
116
- const builds = unit.reduce(
130
+ ...stages.slice(2).map((stage) => {
131
+ const builds = stage.segments.reduce(
117
132
  (segments, segment) => [...segments, segment.construct(this)],
118
133
  [] as SegmentConstructed[],
119
134
  );
120
135
  return {
121
- stageName: builds.map((build) => build.name).join("-"),
136
+ stageName:
137
+ stage.stageName || builds.map((build) => build.name).join("-"),
122
138
  actions: builds.reduce(
123
139
  (actions, build) => [...actions, ...build.actions],
124
140
  [] as IAction[],
package/src/segment.ts CHANGED
@@ -11,6 +11,7 @@ export interface SegmentProps {
11
11
  }
12
12
 
13
13
  export abstract class Segment {
14
+ readonly isSegment: boolean = true;
14
15
  readonly isSource: boolean = false;
15
16
  readonly isPipeline: boolean = false;
16
17
  readonly dependencies?: Stack[];
@@ -35,3 +36,7 @@ export abstract class SegmentConstructed extends Construct {
35
36
  readonly name: string = "";
36
37
  readonly actions: IAction[] = [];
37
38
  }
39
+
40
+ export function isSegment(item: any): item is Segment {
41
+ return item.isSegment;
42
+ }
@@ -120,7 +120,7 @@ export class StackSegmentConstructed extends SegmentConstructed {
120
120
  ) {
121
121
  super(scope, id);
122
122
 
123
- this.name = props.stack.stackName;
123
+ this.name = props.stack.node.id;
124
124
 
125
125
  const buildArtifact = props.project
126
126
  ? props.buildOutput || new Artifact()
@@ -208,7 +208,7 @@ export class StackSegmentConstructed extends SegmentConstructed {
208
208
  stackName: props.stackName ? props.stackName : props.stack.stackName,
209
209
  account: props.stack.account,
210
210
  region: props.stack.region,
211
- changeSetName: `${props.stack.stackName}Changes`,
211
+ changeSetName: `${this.name}Changes`,
212
212
  adminPermissions: true,
213
213
  templatePath: (buildArtifact ? buildArtifact : props.input).atPath(
214
214
  path.join(scope.buildDir, props.stack.templateFile),
@@ -234,7 +234,7 @@ export class StackSegmentConstructed extends SegmentConstructed {
234
234
  stackName: props.stackName ? props.stackName : props.stack.stackName,
235
235
  account: props.stack.account,
236
236
  region: props.stack.region,
237
- changeSetName: `${props.stack.stackName}Changes`,
237
+ changeSetName: `${this.name}Changes`,
238
238
  output: props.stackOutput,
239
239
  outputFileName: props.outputFileName
240
240
  ? props.outputFileName