@flit/cdk-pipeline 1.2.4 → 1.4.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.2.4",
3
+ "version": "1.4.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",
@@ -53,12 +53,12 @@
53
53
  ]
54
54
  },
55
55
  "devDependencies": {
56
- "@types/node": "^22.10.7",
56
+ "@types/node": "^22.13.5",
57
57
  "aws-cdk-lib": "^2.174.0",
58
58
  "constructs": "^10.4.0",
59
- "jsii": "^5.7.4",
60
- "jsii-pacmak": "^1.106.0",
61
- "prettier": "^3.4.2",
59
+ "jsii": "^5.7.6",
60
+ "jsii-pacmak": "^1.108.0",
61
+ "prettier": "^3.5.2",
62
62
  "prettier-plugin-packagejson": "^2.5.8",
63
63
  "typescript": "^5.7.3"
64
64
  },
@@ -9,7 +9,7 @@ import { SourceSegment, SourceSegmentProps } from "./source-segment";
9
9
  export interface CodeStarSourceSegmentProps extends SourceSegmentProps {
10
10
  /**
11
11
  * The owning user or organization of the repository.
12
- * @example `"aws"`
12
+ * @example "aws"
13
13
  */
14
14
  readonly owner: string;
15
15
  /**
@@ -21,12 +21,12 @@ export interface CodeStarSourceSegmentProps extends SourceSegmentProps {
21
21
  readonly connectionArn: string;
22
22
  /**
23
23
  * The name of the repository.
24
- * @example `"aws-cdk"`
24
+ * @example "aws-cdk"
25
25
  */
26
26
  readonly repository: string;
27
27
  /**
28
28
  * The branch to build.
29
- * @default `"master"`
29
+ * @default "master"
30
30
  */
31
31
  readonly branch?: string;
32
32
  readonly triggerOnPush?: boolean;
@@ -14,17 +14,17 @@ export interface GitHubSourceSegmentProps extends SourceSegmentProps {
14
14
  readonly oauthToken: SecretValue;
15
15
  /**
16
16
  * The owning user or organization of the repository.
17
- * @example `"aws"`
17
+ * @example "aws"
18
18
  */
19
19
  readonly owner: string;
20
20
  /**
21
21
  * The name of the repository.
22
- * @example `"aws-cdk"`
22
+ * @example "aws-cdk"
23
23
  */
24
24
  readonly repository: string;
25
25
  /**
26
26
  * The branch to build.
27
- * @default `"master"`
27
+ * @default "master"
28
28
  */
29
29
  readonly branch?: string;
30
30
  readonly trigger?: GitHubTrigger;
package/src/pipeline.ts CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  } from "aws-cdk-lib/aws-codepipeline";
8
8
  import * as path from "path";
9
9
 
10
- import { Segment } from "./segment";
10
+ import { Segment, SegmentConstructed } from "./segment";
11
11
  import { isSource } from "./source-segment";
12
12
  import { isPipeline } from "./pipeline-segment";
13
13
 
@@ -20,13 +20,13 @@ export interface PipelineProps extends StackProps {
20
20
  /**
21
21
  * The path to the cdk projects root directory containing the cdk.json file
22
22
  * relative to the asset root
23
- * @default `"."`
23
+ * @default "."
24
24
  */
25
25
  readonly rootDir?: string;
26
26
  /**
27
27
  * The segments to populating the pipeline.
28
28
  */
29
- readonly segments: Segment[];
29
+ readonly segments: (Segment | Segment[])[];
30
30
  }
31
31
 
32
32
  /**
@@ -50,32 +50,38 @@ export class Pipeline extends Stack {
50
50
 
51
51
  if (!this.bundlingRequired) return;
52
52
 
53
- props.segments.forEach((segment) => {
54
- segment.inputs.forEach((artifact) => {
55
- if (!artifact.producer) {
56
- throw new Error("Artifact consumed but never produced.");
57
- }
53
+ const segments = props.segments.map((segment) =>
54
+ Array.isArray(segment) ? segment : [segment],
55
+ );
56
+
57
+ segments.forEach((unit) => {
58
+ unit.forEach((segment) => {
59
+ segment.inputs.forEach((artifact) => {
60
+ if (!artifact.producer) {
61
+ throw new Error("Artifact consumed but never produced.");
62
+ }
63
+ });
58
64
  });
59
65
  });
60
66
 
61
- const sourceSegments = props.segments.filter(isSource);
62
- const pipelineSegments = props.segments.filter(isPipeline);
67
+ if (segments[0].filter(isSource).length !== segments[0].length) {
68
+ throw new Error("First segment must contain only source segments");
69
+ }
63
70
 
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
- );
71
+ if (segments.find((unit) => unit.filter(isSource).length)) {
72
+ throw new Error("Only the first segment can contain source segments");
68
73
  }
69
74
 
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
- );
75
+ if (
76
+ segments[0].length === 1 &&
77
+ segments[0].filter(isPipeline).length !== segments[0].length
78
+ ) {
79
+ throw new Error("Second segment must be the pipeline segment");
74
80
  }
75
81
 
76
- const segments: Segment[] = props.segments.filter(
77
- (segment) => !isSource(segment) && !isPipeline(segment),
78
- );
82
+ if (segments.find((unit) => unit.filter(isPipeline).length)) {
83
+ throw new Error("Only the second segment can be the pipeline segment");
84
+ }
79
85
 
80
86
  new AwsPipeline(this, "Pipeline", {
81
87
  pipelineName: props.pipelineName,
@@ -85,7 +91,7 @@ export class Pipeline extends Stack {
85
91
  {
86
92
  stageName: "Source",
87
93
  actions: [
88
- ...sourceSegments.reduce(
94
+ ...segments[0].reduce(
89
95
  (actions, segment) => [
90
96
  ...actions,
91
97
  ...segment.construct(this).actions,
@@ -96,13 +102,27 @@ export class Pipeline extends Stack {
96
102
  },
97
103
  {
98
104
  stageName: "Pipeline",
99
- actions: [...pipelineSegments[0].construct(this).actions],
105
+ actions: [
106
+ ...segments[1].reduce(
107
+ (actions, segment) => [
108
+ ...actions,
109
+ ...segment.construct(this).actions,
110
+ ],
111
+ [] as IAction[],
112
+ ),
113
+ ],
100
114
  },
101
- ...segments.map((segment) => {
102
- const build = segment.construct(this);
115
+ ...segments.slice(2).map((unit) => {
116
+ const builds = unit.reduce(
117
+ (segments, segment) => [...segments, segment.construct(this)],
118
+ [] as SegmentConstructed[],
119
+ );
103
120
  return {
104
- stageName: build.name,
105
- actions: build.actions,
121
+ stageName: builds.map((build) => build.name).join(""),
122
+ actions: builds.reduce(
123
+ (actions, build) => [...actions, ...build.actions],
124
+ [] as IAction[],
125
+ ),
106
126
  };
107
127
  }),
108
128
  ],
@@ -48,18 +48,22 @@ export interface StackSegmentProps {
48
48
  * @default The name of the given stack.
49
49
  */
50
50
  readonly stackName?: string;
51
+ /**
52
+ * The artifact to hold the output of the build if this stack includes a build.
53
+ */
54
+ readonly buildOutput?: Artifact;
51
55
  /**
52
56
  * The artifact to hold the stack deployment output file.
53
57
  */
54
- readonly output?: Artifact;
58
+ readonly stackOutput?: Artifact;
55
59
  /**
56
60
  * The filename for the file in the output artifact
57
- * @default `"artifact.json"`
61
+ * @default "artifact.json"
58
62
  */
59
63
  readonly outputFileName?: string;
60
64
  /**
61
65
  * Does this stage require manual approval of the change set?
62
- * @default `false`
66
+ * @default false
63
67
  */
64
68
  readonly manualApproval?: Boolean;
65
69
  }
@@ -71,7 +75,10 @@ export class StackSegment extends Segment {
71
75
  readonly props: StackSegmentProps;
72
76
 
73
77
  constructor(props: StackSegmentProps) {
74
- super(props);
78
+ super({
79
+ ...props,
80
+ output: [props.buildOutput, props.stackOutput].filter((a) => !!a),
81
+ });
75
82
  this.props = props;
76
83
  }
77
84
 
@@ -95,7 +102,8 @@ export interface StackSegmentConstructedProps {
95
102
  readonly stackName?: string;
96
103
  readonly input: Artifact;
97
104
  readonly extraInputs?: Artifact[];
98
- readonly output?: Artifact;
105
+ readonly buildOutput?: Artifact;
106
+ readonly stackOutput?: Artifact;
99
107
  readonly outputFileName?: string;
100
108
  readonly manualApproval?: Boolean;
101
109
  }
@@ -113,7 +121,9 @@ export class StackSegmentConstructed extends SegmentConstructed {
113
121
 
114
122
  this.name = props.stack.stackName;
115
123
 
116
- const buildArtifact = props.project ? new Artifact() : undefined;
124
+ const buildArtifact = props.project
125
+ ? props.buildOutput || new Artifact()
126
+ : undefined;
117
127
 
118
128
  this.actions = [
119
129
  ...(buildArtifact
@@ -184,11 +194,11 @@ export class StackSegmentConstructed extends SegmentConstructed {
184
194
  account: props.stack.account,
185
195
  region: props.stack.region,
186
196
  changeSetName: `${props.stack.stackName}Changes`,
187
- output: props.output,
197
+ output: props.stackOutput,
188
198
  outputFileName: props.outputFileName
189
199
  ? props.outputFileName
190
- : props.output
191
- ? `artifact.json`
200
+ : props.stackOutput
201
+ ? "artifact.json"
192
202
  : undefined,
193
203
  }),
194
204
  ];