generated from spencerbeggs/typescript-base
-
Notifications
You must be signed in to change notification settings - Fork 2
/
pipeline.ts
133 lines (126 loc) · 4.54 KB
/
pipeline.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import slugify from "@sindresorhus/slugify";
import { SecretValue, Stack, StackProps } from "aws-cdk-lib";
import { BuildSpec } from "aws-cdk-lib/aws-codebuild";
import { HostedZone, HostedZoneAttributes, IHostedZone } from "aws-cdk-lib/aws-route53";
import { Bucket } from "aws-cdk-lib/aws-s3";
import { CodePipeline, CodePipelineSource, ShellStep } from "aws-cdk-lib/pipelines";
import { Construct } from "constructs";
import { LogsBucket } from "@base/constructs";
export interface BasePipelineProps extends StackProps {
logs?: boolean;
repo?: string;
branch?: string;
tokenName?: string;
rootZone?: HostedZoneAttributes | IHostedZone | boolean;
hostedZoneId?: string;
zoneName?: string;
dockerEnabledForSynth?: boolean;
}
export class BasePipeline extends Stack {
public readonly _app_name: string;
public pipeline: CodePipeline;
public readonly hostedZone?: IHostedZone;
public readonly logs?: Bucket;
public project: this;
constructor(scope: Construct, id: string, props?: BasePipelineProps) {
if (!props) {
props = {
rootZone: BasePipeline.rootZone,
logs: BasePipeline.logs
};
}
super(
scope,
`${id}-pipeline`,
Object.assign(
{
env: {
account: scope.node.tryGetContext("AWS_ACCOUNT_ID"),
region: scope.node.tryGetContext("AWS_REGION")
},
hostedZoneId: scope.node.tryGetContext("PIPELINE_ZONE_ID"),
zoneName: scope.node.tryGetContext("PIPELINE_ZONE_NAME")
},
props
)
);
const { rootZone, hostedZoneId, zoneName, logs, dockerEnabledForSynth = true } = props;
const repo = props.repo ?? scope.node.tryGetContext("PIPELINE_REPO");
const branch = props.branch ?? scope.node.tryGetContext("PIPELINE_BRANCH") ?? "main";
const tokenName = props.tokenName ?? scope.node.tryGetContext("PIPELINE_TOKEN_NAME") ?? "github-oauth-token";
this._app_name = id;
this.pipeline = new CodePipeline(this, this.__("pipeline"), {
pipelineName: `${id}-pipeline`,
dockerEnabledForSynth,
codeBuildDefaults: {
partialBuildSpec: BuildSpec.fromObject({
version: "0.2",
env: {
"exported-variables": ["IS_CODEBUILD"]
},
phases: {
install: {
"runtime-versions": {
nodejs: 14
},
commands: ['export IS_CODEBUILD="true"', "n 16.14.0"]
}
}
})
},
synth: new ShellStep(this.__("synth"), {
input: CodePipelineSource.gitHub(repo, branch, {
authentication: SecretValue.secretsManager(tokenName)
}),
commands: ["yarn install --frozen-lockfile", "npx cdk synth"]
})
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function isZoneLookup(object: any): object is HostedZoneAttributes {
return typeof object !== "boolean" && "hostedZoneId" in object && "zoneName" in object;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function isZone(object: any): object is IHostedZone {
return typeof object !== "boolean" && "hostedZoneId" in object && "zoneName" in object;
}
if (rootZone === true && hostedZoneId && zoneName) {
this.hostedZone = HostedZone.fromHostedZoneAttributes(this, this.__("root hosted zone"), {
hostedZoneId,
zoneName
});
} else if (rootZone && isZoneLookup(rootZone) && !hostedZoneId && !zoneName) {
this.hostedZone = HostedZone.fromHostedZoneAttributes(this, this.__("root hosted zone"), rootZone);
} else if (rootZone && isZone(rootZone) && !hostedZoneId && !zoneName) {
this.hostedZone = rootZone;
}
if (logs) {
const { bucket } = new LogsBucket(this, this.__("logs"));
this.logs = bucket;
}
this.project = this;
}
static rootZone = false;
static logs = true;
/**
* Namespace helper function to automatically generate scoped ids for child Constructs to prevent id collisions in loops or complex structures.
* Concatinates and slugifies a readable descrition with the instance of the BaseStack's stackType and stackEnv properties if the defined.
*
* @param name - The plain text description of Construct you want to transform into a scoped id, eg, "Logs Bucket"
* @param seperator - The string used seperate the parts of the scoped ID, defaults to "-"
* @returns Scoped id string to pass to child Construnct, eg, "logs-bucket-my-stack-type-production"
* @example
* Create a
* ```
* import { BaseStack, BaseStackProps } from "../lib/base";
* ```
*
*/
__(name: string, seperator: string = "-"): string {
return [this._app_name, name]
.filter((part) => typeof part === "string")
.map((part) => (part as string).trim())
.map((part) => slugify(part as string))
.join("-")
.replace(/-/g, seperator);
}
}