@lsts_tech/infra 1.0.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/LICENSE +21 -0
- package/README.md +158 -0
- package/dist/bin/init.d.ts +9 -0
- package/dist/bin/init.d.ts.map +1 -0
- package/dist/bin/init.js +315 -0
- package/dist/bin/init.js.map +1 -0
- package/dist/stacks/Dns.d.ts +69 -0
- package/dist/stacks/Dns.d.ts.map +1 -0
- package/dist/stacks/Dns.js +57 -0
- package/dist/stacks/Dns.js.map +1 -0
- package/dist/stacks/ExpoSite.d.ts +72 -0
- package/dist/stacks/ExpoSite.d.ts.map +1 -0
- package/dist/stacks/ExpoSite.js +49 -0
- package/dist/stacks/ExpoSite.js.map +1 -0
- package/dist/stacks/NextSite.d.ts +86 -0
- package/dist/stacks/NextSite.d.ts.map +1 -0
- package/dist/stacks/NextSite.js +60 -0
- package/dist/stacks/NextSite.js.map +1 -0
- package/dist/stacks/Pipeline.d.ts +128 -0
- package/dist/stacks/Pipeline.d.ts.map +1 -0
- package/dist/stacks/Pipeline.js +311 -0
- package/dist/stacks/Pipeline.js.map +1 -0
- package/dist/stacks/index.d.ts +41 -0
- package/dist/stacks/index.d.ts.map +1 -0
- package/dist/stacks/index.js +38 -0
- package/dist/stacks/index.js.map +1 -0
- package/docs/CLI.md +59 -0
- package/docs/CONFIGURATION.md +78 -0
- package/docs/EXAMPLES.md +9 -0
- package/examples/next-and-expo/infra.config.ts +104 -0
- package/examples/next-only/infra.config.ts +60 -0
- package/package.json +102 -0
- package/schemas/pipeline.schema.json +25 -0
- package/scripts/cleanup-orphan-lambdas.sh +102 -0
- package/scripts/delete-amplify-app.sh +50 -0
- package/scripts/ensure-pipelines.sh +144 -0
- package/scripts/ensure-secrets.sh +58 -0
- package/scripts/postdeploy-update-dns.sh +158 -0
- package/scripts/predeploy-checks.sh +192 -0
- package/scripts/pulumi-deploy.sh +29 -0
- package/scripts/sst-deploy.sh +79 -0
- package/templates/buildspec.yml +77 -0
- package/templates/ensure-pipelines.sh +117 -0
- package/templates/env.example +38 -0
- package/templates/infra.config.ts +199 -0
- package/templates/secrets.schema.json +20 -0
- package/templates/sst-env.d.ts +50 -0
- package/templates/sst.config.ts +28 -0
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline — AWS CodePipeline + CodeBuild CI/CD Construct
|
|
3
|
+
*
|
|
4
|
+
* Creates a fully managed CI/CD pipeline using AWS-native services:
|
|
5
|
+
* - CodeStar Connection → GitHub (source)
|
|
6
|
+
* - CodeBuild → builds & deploys via SST
|
|
7
|
+
* - CodePipeline → orchestrates source → build
|
|
8
|
+
*
|
|
9
|
+
* Each pipeline is branch-aware: push to a branch triggers deployment
|
|
10
|
+
* to the corresponding SST stage.
|
|
11
|
+
*
|
|
12
|
+
* Security:
|
|
13
|
+
* - No AWS credentials stored in GitHub
|
|
14
|
+
* - Secrets fetched from SSM Parameter Store at build time
|
|
15
|
+
* - IAM roles scoped per pipeline
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* createPipeline({
|
|
20
|
+
* name: "myapp-prod",
|
|
21
|
+
* repo: "myorg/myapp",
|
|
22
|
+
* branch: "main",
|
|
23
|
+
* stage: "production",
|
|
24
|
+
* region: "us-east-1",
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* Creates an AWS CodePipeline with CodeBuild for SST deployments.
|
|
30
|
+
*
|
|
31
|
+
* Architecture:
|
|
32
|
+
* GitHub (push) → CodeStar Connection → CodePipeline → CodeBuild → SST Deploy
|
|
33
|
+
*
|
|
34
|
+
* The pipeline:
|
|
35
|
+
* 1. Detects push to the configured branch via webhook
|
|
36
|
+
* 2. Pulls source code from GitHub
|
|
37
|
+
* 3. CodeBuild installs dependencies, builds the monorepo, and runs `sst deploy`
|
|
38
|
+
* 4. SST deploys the Next.js app to Lambda + CloudFront + S3
|
|
39
|
+
*/
|
|
40
|
+
export function createPipeline(config) {
|
|
41
|
+
const { name, repo, branch, stage, region = "us-east-1", nodeVersion = "22", pnpmVersion = "9.15.0", infraPath = "packages/infra", buildEnv = {}, computeType = "BUILD_GENERAL1_MEDIUM", timeoutMinutes = 30, codestarConnectionArn, projectTag, } = config;
|
|
42
|
+
// ── 1. CodeStar Connection (GitHub) ──────────────────────────────────
|
|
43
|
+
// If no existing connection ARN is provided, create a new one.
|
|
44
|
+
// NOTE: New connections require manual confirmation in the AWS Console:
|
|
45
|
+
// Developer Tools → Settings → Connections → Pending → Update pending connection
|
|
46
|
+
// Allow providing the connection ARN via config or environment for deterministic
|
|
47
|
+
// deployments. Prefer explicit `codestarConnectionArn`, then an env var, then
|
|
48
|
+
// create a new connection if neither is provided.
|
|
49
|
+
const envKey = `${name.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_CODESTAR_CONNECTION_ARN`;
|
|
50
|
+
const envConnectionArn = process.env[envKey] || process.env.CODESTAR_CONNECTION_ARN;
|
|
51
|
+
const connection = codestarConnectionArn || envConnectionArn
|
|
52
|
+
? { arn: (codestarConnectionArn || envConnectionArn) }
|
|
53
|
+
: (() => {
|
|
54
|
+
const conn = new aws.codestarconnections.Connection(`${name}-github-connection`, {
|
|
55
|
+
name: `${name}-github`,
|
|
56
|
+
providerType: "GitHub",
|
|
57
|
+
});
|
|
58
|
+
return { arn: conn.arn };
|
|
59
|
+
})();
|
|
60
|
+
// ── 2. S3 Artifact Bucket ───────────────────────────────────────────
|
|
61
|
+
const artifactBucket = new aws.s3.BucketV2(`${name}-artifacts`, {
|
|
62
|
+
bucketPrefix: `${name}-pipeline-artifacts`,
|
|
63
|
+
forceDestroy: true,
|
|
64
|
+
});
|
|
65
|
+
// tags to mark infra-managed critical resources so we can protect them
|
|
66
|
+
const commonTags = {
|
|
67
|
+
Project: projectTag ?? name.split("-")[0],
|
|
68
|
+
ManagedBy: "infra",
|
|
69
|
+
Stage: stage,
|
|
70
|
+
Protected: "true",
|
|
71
|
+
};
|
|
72
|
+
new aws.s3.BucketLifecycleConfigurationV2(`${name}-artifacts-lifecycle`, {
|
|
73
|
+
bucket: artifactBucket.id,
|
|
74
|
+
rules: [
|
|
75
|
+
{
|
|
76
|
+
id: "expire-artifacts",
|
|
77
|
+
status: "Enabled",
|
|
78
|
+
expiration: { days: 7 },
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
});
|
|
82
|
+
// ── 3. IAM Role for CodeBuild ───────────────────────────────────────
|
|
83
|
+
const codebuildRole = new aws.iam.Role(`${name}-codebuild-role`, {
|
|
84
|
+
name: `${name}-codebuild-role`,
|
|
85
|
+
assumeRolePolicy: JSON.stringify({
|
|
86
|
+
Version: "2012-10-17",
|
|
87
|
+
Statement: [
|
|
88
|
+
{
|
|
89
|
+
Effect: "Allow",
|
|
90
|
+
Principal: { Service: "codebuild.amazonaws.com" },
|
|
91
|
+
Action: "sts:AssumeRole",
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
}),
|
|
95
|
+
});
|
|
96
|
+
// CodeBuild needs broad permissions for SST deployments
|
|
97
|
+
// (CloudFormation, Lambda, S3, CloudFront, Route53, ACM, IAM, etc.)
|
|
98
|
+
new aws.iam.RolePolicyAttachment(`${name}-codebuild-admin`, {
|
|
99
|
+
role: codebuildRole.name,
|
|
100
|
+
policyArn: "arn:aws:iam::aws:policy/AdministratorAccess",
|
|
101
|
+
});
|
|
102
|
+
// ── 4. IAM Role for CodePipeline ────────────────────────────────────
|
|
103
|
+
const pipelineRole = new aws.iam.Role(`${name}-pipeline-role`, {
|
|
104
|
+
name: `${name}-pipeline-role`,
|
|
105
|
+
assumeRolePolicy: JSON.stringify({
|
|
106
|
+
Version: "2012-10-17",
|
|
107
|
+
Statement: [
|
|
108
|
+
{
|
|
109
|
+
Effect: "Allow",
|
|
110
|
+
Principal: { Service: "codepipeline.amazonaws.com" },
|
|
111
|
+
Action: "sts:AssumeRole",
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
}),
|
|
115
|
+
});
|
|
116
|
+
const pipelinePolicy = new aws.iam.RolePolicy(`${name}-pipeline-policy`, {
|
|
117
|
+
role: pipelineRole.id,
|
|
118
|
+
policy: $jsonStringify({
|
|
119
|
+
Version: "2012-10-17",
|
|
120
|
+
Statement: [
|
|
121
|
+
{
|
|
122
|
+
Effect: "Allow",
|
|
123
|
+
Action: [
|
|
124
|
+
"s3:GetObject",
|
|
125
|
+
"s3:GetObjectVersion",
|
|
126
|
+
"s3:GetBucketVersioning",
|
|
127
|
+
"s3:PutObjectAcl",
|
|
128
|
+
"s3:PutObject",
|
|
129
|
+
],
|
|
130
|
+
Resource: [$interpolate `${artifactBucket.arn}`, $interpolate `${artifactBucket.arn}/*`],
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
Effect: "Allow",
|
|
134
|
+
Action: ["codestar-connections:UseConnection"],
|
|
135
|
+
Resource: [connection.arn],
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
Effect: "Allow",
|
|
139
|
+
Action: [
|
|
140
|
+
"codebuild:BatchGetBuilds",
|
|
141
|
+
"codebuild:StartBuild",
|
|
142
|
+
],
|
|
143
|
+
Resource: ["*"],
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
}),
|
|
147
|
+
});
|
|
148
|
+
// ── 5. CodeBuild Project ────────────────────────────────────────────
|
|
149
|
+
const buildEnvVars = [
|
|
150
|
+
{ name: "SST_STAGE", value: stage },
|
|
151
|
+
{ name: "NODE_VERSION", value: nodeVersion },
|
|
152
|
+
{ name: "PNPM_VERSION", value: pnpmVersion },
|
|
153
|
+
{ name: "INFRA_PATH", value: infraPath },
|
|
154
|
+
...Object.entries(buildEnv).map(([key, value]) => ({
|
|
155
|
+
name: key,
|
|
156
|
+
value,
|
|
157
|
+
type: value.startsWith("arn:aws:ssm:") ? "PARAMETER_STORE" : "PLAINTEXT",
|
|
158
|
+
})),
|
|
159
|
+
];
|
|
160
|
+
const codebuildProject = new aws.codebuild.Project(`${name}-build`, {
|
|
161
|
+
name: `${name}-build`,
|
|
162
|
+
description: `Build & deploy ${name} (stage: ${stage}) via SST`,
|
|
163
|
+
serviceRole: codebuildRole.arn,
|
|
164
|
+
buildTimeout: timeoutMinutes,
|
|
165
|
+
environment: {
|
|
166
|
+
computeType,
|
|
167
|
+
image: "aws/codebuild/amazonlinux2-x86_64-standard:5.0",
|
|
168
|
+
type: "LINUX_CONTAINER",
|
|
169
|
+
environmentVariables: buildEnvVars,
|
|
170
|
+
},
|
|
171
|
+
source: {
|
|
172
|
+
type: "CODEPIPELINE",
|
|
173
|
+
buildspec: `${infraPath}/buildspec.yml`,
|
|
174
|
+
},
|
|
175
|
+
artifacts: {
|
|
176
|
+
type: "CODEPIPELINE",
|
|
177
|
+
},
|
|
178
|
+
logsConfig: {
|
|
179
|
+
cloudwatchLogs: {
|
|
180
|
+
groupName: `/codebuild/${name}`,
|
|
181
|
+
streamName: "build-log",
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
// tag build resources for ownership and automated checks
|
|
185
|
+
tags: commonTags,
|
|
186
|
+
});
|
|
187
|
+
// Ensure the pipeline role can start the CodeBuild project used by the pipeline.
|
|
188
|
+
// CodePipeline assumes `pipelineRole` and must be allowed to call `codebuild:StartBuild`.
|
|
189
|
+
new aws.iam.RolePolicy(`${name}-pipeline-codebuild-start`, {
|
|
190
|
+
role: pipelineRole.id,
|
|
191
|
+
policy: $jsonStringify({
|
|
192
|
+
Version: "2012-10-17",
|
|
193
|
+
Statement: [
|
|
194
|
+
{
|
|
195
|
+
Effect: "Allow",
|
|
196
|
+
Action: ["codebuild:StartBuild", "codebuild:BatchGetBuilds"],
|
|
197
|
+
Resource: [$interpolate `${codebuildProject.arn}`],
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
}),
|
|
201
|
+
});
|
|
202
|
+
// Ensure pipeline role can operate on the artifact S3 bucket (upload/download artifacts)
|
|
203
|
+
new aws.iam.RolePolicy(`${name}-pipeline-s3`, {
|
|
204
|
+
role: pipelineRole.id,
|
|
205
|
+
policy: $jsonStringify({
|
|
206
|
+
Version: "2012-10-17",
|
|
207
|
+
Statement: [
|
|
208
|
+
{
|
|
209
|
+
Effect: "Allow",
|
|
210
|
+
Action: ["s3:PutObject", "s3:PutObjectAcl", "s3:GetObject", "s3:GetObjectVersion"],
|
|
211
|
+
Resource: [$interpolate `${artifactBucket.arn}/*`],
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
Effect: "Allow",
|
|
215
|
+
Action: ["s3:ListBucket", "s3:GetBucketLocation"],
|
|
216
|
+
Resource: [$interpolate `${artifactBucket.arn}`],
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
}),
|
|
220
|
+
});
|
|
221
|
+
// Ensure pipeline role can use the CodeStar Connection (GitHub) for source actions
|
|
222
|
+
new aws.iam.RolePolicy(`${name}-pipeline-codestar`, {
|
|
223
|
+
role: pipelineRole.id,
|
|
224
|
+
policy: $jsonStringify({
|
|
225
|
+
Version: "2012-10-17",
|
|
226
|
+
Statement: [
|
|
227
|
+
{
|
|
228
|
+
Effect: "Allow",
|
|
229
|
+
Action: ["codestar-connections:UseConnection", "codestar-connections:GetConnection"],
|
|
230
|
+
Resource: [connection.arn],
|
|
231
|
+
},
|
|
232
|
+
],
|
|
233
|
+
}),
|
|
234
|
+
});
|
|
235
|
+
// ── 6. CodePipeline ─────────────────────────────────────────────────
|
|
236
|
+
const pipeline = new aws.codepipeline.Pipeline(`${name}-pipeline`, {
|
|
237
|
+
name: `${name}-pipeline`,
|
|
238
|
+
roleArn: pipelineRole.arn,
|
|
239
|
+
pipelineType: "V2",
|
|
240
|
+
artifactStores: [
|
|
241
|
+
{
|
|
242
|
+
location: artifactBucket.bucket,
|
|
243
|
+
type: "S3",
|
|
244
|
+
},
|
|
245
|
+
],
|
|
246
|
+
stages: [
|
|
247
|
+
{
|
|
248
|
+
name: "Source",
|
|
249
|
+
actions: [
|
|
250
|
+
{
|
|
251
|
+
name: "GitHub-Source",
|
|
252
|
+
category: "Source",
|
|
253
|
+
owner: "AWS",
|
|
254
|
+
provider: "CodeStarSourceConnection",
|
|
255
|
+
version: "1",
|
|
256
|
+
outputArtifacts: ["source_output"],
|
|
257
|
+
configuration: {
|
|
258
|
+
ConnectionArn: connection.arn,
|
|
259
|
+
FullRepositoryId: repo,
|
|
260
|
+
BranchName: branch,
|
|
261
|
+
OutputArtifactFormat: "CODE_ZIP",
|
|
262
|
+
DetectChanges: "true",
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
],
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
name: "Build-Deploy",
|
|
269
|
+
actions: [
|
|
270
|
+
{
|
|
271
|
+
name: "SST-Deploy",
|
|
272
|
+
category: "Build",
|
|
273
|
+
owner: "AWS",
|
|
274
|
+
provider: "CodeBuild",
|
|
275
|
+
inputArtifacts: ["source_output"],
|
|
276
|
+
version: "1",
|
|
277
|
+
configuration: {
|
|
278
|
+
ProjectName: codebuildProject.name,
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
],
|
|
282
|
+
},
|
|
283
|
+
],
|
|
284
|
+
triggers: [
|
|
285
|
+
{
|
|
286
|
+
providerType: "CodeStarSourceConnection",
|
|
287
|
+
gitConfiguration: {
|
|
288
|
+
sourceActionName: "GitHub-Source",
|
|
289
|
+
pushes: [
|
|
290
|
+
{
|
|
291
|
+
branches: {
|
|
292
|
+
includes: [branch],
|
|
293
|
+
},
|
|
294
|
+
},
|
|
295
|
+
],
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
],
|
|
299
|
+
// ensure the pipeline is tagged so it can be identified
|
|
300
|
+
tags: commonTags,
|
|
301
|
+
});
|
|
302
|
+
return {
|
|
303
|
+
pipeline,
|
|
304
|
+
codebuildProject,
|
|
305
|
+
connection,
|
|
306
|
+
artifactBucket,
|
|
307
|
+
pipelineName: pipeline.name,
|
|
308
|
+
pipelineArn: pipeline.arn,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
//# sourceMappingURL=Pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Pipeline.js","sourceRoot":"","sources":["../../stacks/Pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @lsts_tech/infra — Opinionated SST v3 Infrastructure Constructs
|
|
3
|
+
*
|
|
4
|
+
* This package provides reusable, cloud-agnostic infrastructure primitives
|
|
5
|
+
* for deploying Next.js and Expo web apps from a pnpm/Turborepo monorepo
|
|
6
|
+
* using SST v3 and AWS CodePipeline.
|
|
7
|
+
*
|
|
8
|
+
* Configure your project-specific settings in an `infra.config.ts` file
|
|
9
|
+
* at your infra package root. Run `npx @lsts_tech/infra init` to scaffold one.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* // infra.config.ts (your project)
|
|
14
|
+
* import { resolveDomain, createNextSite, createPipeline } from "@lsts_tech/infra";
|
|
15
|
+
*
|
|
16
|
+
* export function createInfrastructure() {
|
|
17
|
+
* const stage = $app.stage;
|
|
18
|
+
* const { domain, domainName } = resolveDomain({
|
|
19
|
+
* rootDomain: "example.com",
|
|
20
|
+
* stage,
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* const { site, url } = createNextSite({
|
|
24
|
+
* appPath: "../../apps/web",
|
|
25
|
+
* id: `web-${stage}`,
|
|
26
|
+
* domain,
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* return { siteUrl: url, domain: domainName };
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export { resolveDomain } from "./Dns.js";
|
|
34
|
+
export type { DnsConfig, DomainResult } from "./Dns.js";
|
|
35
|
+
export { createNextSite } from "./NextSite.js";
|
|
36
|
+
export type { NextSiteConfig } from "./NextSite.js";
|
|
37
|
+
export { createExpoSite } from "./ExpoSite.js";
|
|
38
|
+
export type { ExpoSiteConfig } from "./ExpoSite.js";
|
|
39
|
+
export { createPipeline } from "./Pipeline.js";
|
|
40
|
+
export type { PipelineConfig } from "./Pipeline.js";
|
|
41
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../stacks/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @lsts_tech/infra — Opinionated SST v3 Infrastructure Constructs
|
|
3
|
+
*
|
|
4
|
+
* This package provides reusable, cloud-agnostic infrastructure primitives
|
|
5
|
+
* for deploying Next.js and Expo web apps from a pnpm/Turborepo monorepo
|
|
6
|
+
* using SST v3 and AWS CodePipeline.
|
|
7
|
+
*
|
|
8
|
+
* Configure your project-specific settings in an `infra.config.ts` file
|
|
9
|
+
* at your infra package root. Run `npx @lsts_tech/infra init` to scaffold one.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* // infra.config.ts (your project)
|
|
14
|
+
* import { resolveDomain, createNextSite, createPipeline } from "@lsts_tech/infra";
|
|
15
|
+
*
|
|
16
|
+
* export function createInfrastructure() {
|
|
17
|
+
* const stage = $app.stage;
|
|
18
|
+
* const { domain, domainName } = resolveDomain({
|
|
19
|
+
* rootDomain: "example.com",
|
|
20
|
+
* stage,
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* const { site, url } = createNextSite({
|
|
24
|
+
* appPath: "../../apps/web",
|
|
25
|
+
* id: `web-${stage}`,
|
|
26
|
+
* domain,
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* return { siteUrl: url, domain: domainName };
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
// ── Re-exports ─────────────────────────────────────────────────────────
|
|
34
|
+
export { resolveDomain } from "./Dns.js";
|
|
35
|
+
export { createNextSite } from "./NextSite.js";
|
|
36
|
+
export { createExpoSite } from "./ExpoSite.js";
|
|
37
|
+
export { createPipeline } from "./Pipeline.js";
|
|
38
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../stacks/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,0EAA0E;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
|
package/docs/CLI.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# CLI Reference
|
|
2
|
+
|
|
3
|
+
The package ships with a bootstrap CLI:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npx @lsts_tech/infra init [options]
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Provider support in v1.0.0: AWS only.
|
|
10
|
+
|
|
11
|
+
## Options
|
|
12
|
+
|
|
13
|
+
| Option | Description | Default |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| `--provider <name>` | Cloud provider (`aws`) | `aws` |
|
|
16
|
+
| `--project <slug>` | Project prefix for app/pipelines/tags | `myapp` |
|
|
17
|
+
| `--app-name <name>` | SST app name | `--project` |
|
|
18
|
+
| `--domain <domain>` | Root domain | `example.com` |
|
|
19
|
+
| `--repo <owner/repo>` | GitHub repo for CodePipeline source | `myorg/myrepo` |
|
|
20
|
+
| `--pipelines <list>` | Comma list: `production,dev,mobile` or `none` | `production,dev` |
|
|
21
|
+
| `--branch-prod <branch>` | Production pipeline branch | `main` |
|
|
22
|
+
| `--branch-dev <branch>` | Dev pipeline branch | `develop` |
|
|
23
|
+
| `--branch-mobile <branch>` | Mobile pipeline branch | `mobile` |
|
|
24
|
+
| `--with-expo` | Enable Expo web deployment defaults | `false` |
|
|
25
|
+
| `--infra-path <path>` | Infra path from monorepo root | `packages/infra` |
|
|
26
|
+
| `--target <path>` | Scaffold destination directory | `.` |
|
|
27
|
+
| `--force` | Overwrite existing files | `false` |
|
|
28
|
+
| `--help` | Print help | - |
|
|
29
|
+
|
|
30
|
+
## Generated Files
|
|
31
|
+
|
|
32
|
+
- `sst.config.ts`
|
|
33
|
+
- `sst-env.d.ts`
|
|
34
|
+
- `infra.config.ts`
|
|
35
|
+
- `.env.example`
|
|
36
|
+
- `buildspec.yml`
|
|
37
|
+
- `schemas/secrets.schema.json`
|
|
38
|
+
- `scripts/ensure-pipelines.sh`
|
|
39
|
+
|
|
40
|
+
## Example Commands
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Next.js only, production+dev pipelines
|
|
44
|
+
npx @lsts_tech/infra init \
|
|
45
|
+
--project acme \
|
|
46
|
+
--domain acme.com \
|
|
47
|
+
--repo acme/web
|
|
48
|
+
|
|
49
|
+
# Next.js + Expo Web + mobile pipeline
|
|
50
|
+
npx @lsts_tech/infra init \
|
|
51
|
+
--project acme \
|
|
52
|
+
--domain acme.com \
|
|
53
|
+
--repo acme/web \
|
|
54
|
+
--with-expo \
|
|
55
|
+
--pipelines production,dev,mobile
|
|
56
|
+
|
|
57
|
+
# Re-generate into packages/infra and overwrite existing files
|
|
58
|
+
npx @lsts_tech/infra init --target packages/infra --force
|
|
59
|
+
```
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Configuration Guide
|
|
2
|
+
|
|
3
|
+
## Environment Variables
|
|
4
|
+
|
|
5
|
+
The scaffolded `infra.config.ts` is environment-driven.
|
|
6
|
+
|
|
7
|
+
| Variable | Required | Description |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `INFRA_APP_NAME` | No | SST app name |
|
|
10
|
+
| `INFRA_ROOT_DOMAIN` | Yes | Root domain for stage resolution |
|
|
11
|
+
| `INFRA_PIPELINE_REPO` | No | GitHub repo in `owner/repo` format |
|
|
12
|
+
| `INFRA_PIPELINE_PREFIX` | No | Prefix for pipeline names |
|
|
13
|
+
| `INFRA_PROJECT_TAG` | No | Resource tag value |
|
|
14
|
+
| `INFRA_PIPELINES` | No | Pipeline stages CSV: `production,dev,mobile` |
|
|
15
|
+
| `INFRA_PIPELINE_BRANCH_PROD` | No | Branch for production pipeline |
|
|
16
|
+
| `INFRA_PIPELINE_BRANCH_DEV` | No | Branch for dev pipeline |
|
|
17
|
+
| `INFRA_PIPELINE_BRANCH_MOBILE` | No | Branch for mobile pipeline |
|
|
18
|
+
| `INFRA_ENABLE_EXPO_SITE` | No | `true` enables Expo `StaticSite` deploy |
|
|
19
|
+
|
|
20
|
+
### Domain Overrides (Optional)
|
|
21
|
+
|
|
22
|
+
| Variable | Description |
|
|
23
|
+
|---|---|
|
|
24
|
+
| `INFRA_WEB_DOMAIN_PRODUCTION` | Web production domain |
|
|
25
|
+
| `INFRA_WEB_DOMAIN_DEV` | Web dev domain |
|
|
26
|
+
| `INFRA_WEB_DOMAIN_MOBILE` | Web mobile-stage domain |
|
|
27
|
+
| `INFRA_EXPO_DOMAIN_PRODUCTION` | Expo production domain |
|
|
28
|
+
| `INFRA_EXPO_DOMAIN_DEV` | Expo dev domain |
|
|
29
|
+
| `INFRA_EXPO_DOMAIN_MOBILE` | Expo mobile-stage domain |
|
|
30
|
+
|
|
31
|
+
## DNS Helper Script Overrides
|
|
32
|
+
|
|
33
|
+
These are consumed by `predeploy-checks.sh` and `postdeploy-update-dns.sh` (typically via `buildspec.yml`):
|
|
34
|
+
|
|
35
|
+
| Variable | Description |
|
|
36
|
+
|---|---|
|
|
37
|
+
| `DOMAIN_ROOT` | Base/root domain |
|
|
38
|
+
| `DOMAIN_PRODUCTION` | Explicit production domain override |
|
|
39
|
+
| `DOMAIN_DEV` | Explicit dev domain override |
|
|
40
|
+
| `DOMAIN_MOBILE` | Explicit mobile domain override |
|
|
41
|
+
| `DOMAIN_CUSTOM` | Explicit override for non-standard stage names |
|
|
42
|
+
|
|
43
|
+
### Certificate Reuse (Optional)
|
|
44
|
+
|
|
45
|
+
| Variable | Description |
|
|
46
|
+
|---|---|
|
|
47
|
+
| `INFRA_WEB_CERT_ARN_PRODUCTION` | Existing ACM cert ARN for web prod domain |
|
|
48
|
+
| `INFRA_WEB_CERT_ARN_DEV` | Existing ACM cert ARN for web dev domain |
|
|
49
|
+
| `INFRA_WEB_CERT_ARN_MOBILE` | Existing ACM cert ARN for web mobile-stage domain |
|
|
50
|
+
| `INFRA_EXPO_CERT_ARN_PRODUCTION` | Existing ACM cert ARN for expo prod domain |
|
|
51
|
+
| `INFRA_EXPO_CERT_ARN_DEV` | Existing ACM cert ARN for expo dev domain |
|
|
52
|
+
| `INFRA_EXPO_CERT_ARN_MOBILE` | Existing ACM cert ARN for expo mobile-stage domain |
|
|
53
|
+
|
|
54
|
+
## SST Secrets
|
|
55
|
+
|
|
56
|
+
Minimum secrets from the default template:
|
|
57
|
+
|
|
58
|
+
- `DatabaseUrl`
|
|
59
|
+
- `AuthSecret`
|
|
60
|
+
|
|
61
|
+
Set per stage:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npx sst secrets set DatabaseUrl "postgresql://..." --stage dev
|
|
65
|
+
npx sst secrets set AuthSecret "your-secret" --stage dev
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Pipeline Provisioning
|
|
69
|
+
|
|
70
|
+
1. Ensure your `INFRA_PIPELINES` and branch variables are correct.
|
|
71
|
+
2. Deploy once (`sst deploy`) from the infra package.
|
|
72
|
+
3. Run:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
APPROVE=true bash scripts/ensure-pipelines.sh
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
This script checks for missing pipelines and creates them by running stage-specific SST deploys.
|
package/docs/EXAMPLES.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
- [`next-only/infra.config.ts`](../examples/next-only/infra.config.ts)
|
|
4
|
+
Next.js site + optional production/dev pipelines.
|
|
5
|
+
|
|
6
|
+
- [`next-and-expo/infra.config.ts`](../examples/next-and-expo/infra.config.ts)
|
|
7
|
+
Next.js + Expo web static site + production/dev/mobile pipelines.
|
|
8
|
+
|
|
9
|
+
Both examples are provider-scoped to AWS for v1.0.0.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { resolveDomain, createNextSite, createExpoSite, createPipeline } from "@lsts_tech/infra";
|
|
2
|
+
|
|
3
|
+
const secrets = {
|
|
4
|
+
DatabaseUrl: new sst.Secret("DatabaseUrl"),
|
|
5
|
+
AuthSecret: new sst.Secret("AuthSecret"),
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export function createInfrastructure() {
|
|
9
|
+
const stage = $app.stage;
|
|
10
|
+
const rootDomain = process.env.INFRA_ROOT_DOMAIN ?? "example.com";
|
|
11
|
+
const repo = process.env.INFRA_PIPELINE_REPO ?? "myorg/myrepo";
|
|
12
|
+
const prefix = process.env.INFRA_PIPELINE_PREFIX ?? "myapp";
|
|
13
|
+
|
|
14
|
+
const webDomain = resolveDomain({
|
|
15
|
+
rootDomain,
|
|
16
|
+
stage,
|
|
17
|
+
stageMap: {
|
|
18
|
+
production: process.env.INFRA_WEB_DOMAIN_PRODUCTION ?? rootDomain,
|
|
19
|
+
dev: process.env.INFRA_WEB_DOMAIN_DEV ?? `dev.${rootDomain}`,
|
|
20
|
+
mobile: process.env.INFRA_WEB_DOMAIN_MOBILE ?? `api.${rootDomain}`,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const web = createNextSite({
|
|
25
|
+
appPath: "../../apps/web",
|
|
26
|
+
id: `web-${stage}`,
|
|
27
|
+
domain: webDomain.domain,
|
|
28
|
+
certificateArn: {
|
|
29
|
+
production: process.env.INFRA_WEB_CERT_ARN_PRODUCTION,
|
|
30
|
+
dev: process.env.INFRA_WEB_CERT_ARN_DEV,
|
|
31
|
+
mobile: process.env.INFRA_WEB_CERT_ARN_MOBILE,
|
|
32
|
+
}[stage],
|
|
33
|
+
environment: {
|
|
34
|
+
NEXT_PUBLIC_APP_URL: `https://${webDomain.domainName}`,
|
|
35
|
+
DATABASE_URL: secrets.DatabaseUrl.value,
|
|
36
|
+
AUTH_SECRET: secrets.AuthSecret.value,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const expoDomain = resolveDomain({
|
|
41
|
+
rootDomain,
|
|
42
|
+
stage,
|
|
43
|
+
stageMap: {
|
|
44
|
+
production: process.env.INFRA_EXPO_DOMAIN_PRODUCTION ?? `mobile.${rootDomain}`,
|
|
45
|
+
dev: process.env.INFRA_EXPO_DOMAIN_DEV ?? `dev.mobile.${rootDomain}`,
|
|
46
|
+
mobile: process.env.INFRA_EXPO_DOMAIN_MOBILE ?? `preview.mobile.${rootDomain}`,
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const expo = createExpoSite({
|
|
51
|
+
appPath: "../../apps/mobile",
|
|
52
|
+
id: `mobile-${stage}`,
|
|
53
|
+
domain: expoDomain.domain,
|
|
54
|
+
certificateArn: {
|
|
55
|
+
production: process.env.INFRA_EXPO_CERT_ARN_PRODUCTION,
|
|
56
|
+
dev: process.env.INFRA_EXPO_CERT_ARN_DEV,
|
|
57
|
+
mobile: process.env.INFRA_EXPO_CERT_ARN_MOBILE,
|
|
58
|
+
}[stage],
|
|
59
|
+
environment: {
|
|
60
|
+
EXPO_PUBLIC_API_URL: `https://${webDomain.domainName}/api`,
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const outputs: Record<string, unknown> = {
|
|
65
|
+
siteUrl: web.url,
|
|
66
|
+
domain: webDomain.domainName,
|
|
67
|
+
mobileUrl: expo.url,
|
|
68
|
+
mobileDomain: expoDomain.domainName,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
if (stage === "production") {
|
|
72
|
+
const production = createPipeline({
|
|
73
|
+
name: `${prefix}-prod`,
|
|
74
|
+
repo,
|
|
75
|
+
branch: process.env.INFRA_PIPELINE_BRANCH_PROD ?? "main",
|
|
76
|
+
stage: "production",
|
|
77
|
+
projectTag: process.env.INFRA_PROJECT_TAG ?? prefix,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const dev = createPipeline({
|
|
81
|
+
name: `${prefix}-dev`,
|
|
82
|
+
repo,
|
|
83
|
+
branch: process.env.INFRA_PIPELINE_BRANCH_DEV ?? "develop",
|
|
84
|
+
stage: "dev",
|
|
85
|
+
projectTag: process.env.INFRA_PROJECT_TAG ?? prefix,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const mobile = createPipeline({
|
|
89
|
+
name: `${prefix}-mobile`,
|
|
90
|
+
repo,
|
|
91
|
+
branch: process.env.INFRA_PIPELINE_BRANCH_MOBILE ?? "mobile",
|
|
92
|
+
stage: "mobile",
|
|
93
|
+
projectTag: process.env.INFRA_PROJECT_TAG ?? prefix,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
outputs.pipelines = {
|
|
97
|
+
production: production.pipelineName,
|
|
98
|
+
dev: dev.pipelineName,
|
|
99
|
+
mobile: mobile.pipelineName,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return outputs;
|
|
104
|
+
}
|