rastack 0.0.35 → 0.0.37
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/CHANGELOG.md +4 -0
- package/dist/deploy/config.d.ts +33 -5
- package/dist/deploy/config.js +98 -24
- package/dist/deploy/index.d.ts +1 -0
- package/dist/deploy/index.js +1 -0
- package/dist/deploy/io.d.ts +19 -0
- package/dist/deploy/io.js +81 -0
- package/dist/deploy/zip.d.ts +24 -0
- package/dist/deploy/zip.js +95 -0
- package/dist/rastack-ci.js +1 -1
- package/dist/rastack-init.d.ts +18 -7
- package/dist/rastack-init.js +187 -18
- package/dist/rastack-update.d.ts +18 -0
- package/dist/rastack-update.js +139 -0
- package/dist/rastack.d.ts +3 -2
- package/dist/rastack.js +16 -8
- package/dist/update.d.ts +48 -0
- package/dist/update.js +110 -0
- package/package.json +1 -1
- package/src/deploy/config.ts +126 -22
- package/src/deploy/index.ts +1 -0
- package/src/deploy/io.ts +88 -1
- package/src/deploy/zip.ts +109 -0
- package/src/rastack-ci.ts +1 -1
- package/src/rastack-init.ts +271 -21
- package/src/rastack-update.ts +124 -0
- package/src/rastack.ts +16 -8
- package/src/update.ts +114 -0
- package/test/deploy.spec.ts +100 -12
- package/test/update.spec.ts +95 -0
- package/dist/rastack-deploy.d.ts +0 -20
- package/dist/rastack-deploy.js +0 -196
- package/src/rastack-deploy.ts +0 -257
package/src/rastack-deploy.ts
DELETED
|
@@ -1,257 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* `rastack deploy` — configure a repo's serverless deployment.
|
|
5
|
-
*
|
|
6
|
-
* rastack deploy [--app <slug>] [--region <r>] [--owner <o>] [--repo <r>]
|
|
7
|
-
* [--branch <b>] [--namespace <n>] [--templates-bucket <b>]
|
|
8
|
-
* [--artifacts-bucket <b>] [--arch arm64|x86_64]
|
|
9
|
-
* [--print] [--run] [--yes]
|
|
10
|
-
*
|
|
11
|
-
* Writes/updates `.rastack/deploy.json` (creating it if `rastack init` has not
|
|
12
|
-
* run) and prints exactly how to stand the app up: the one-time
|
|
13
|
-
* `aws cloudformation deploy` that creates all infrastructure, the GitHub repo
|
|
14
|
-
* Variables CI reads, and the Lambda's runtime env. Infra is created once by a
|
|
15
|
-
* human — this command *configures* that step, it does not silently mutate the
|
|
16
|
-
* cloud. `--run` executes the launch command for you; `--print` is
|
|
17
|
-
* non-interactive (config as-is).
|
|
18
|
-
*
|
|
19
|
-
* The recurring code deploy is CI's job (`rastack ci deploy`), not this command.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
import { execFileSync } from "child_process";
|
|
23
|
-
import {
|
|
24
|
-
DeployConfig,
|
|
25
|
-
PartialDeployConfig,
|
|
26
|
-
deployStackCommand,
|
|
27
|
-
lambdaEnv,
|
|
28
|
-
mergeConfig,
|
|
29
|
-
normalizeConfig,
|
|
30
|
-
repoVariables,
|
|
31
|
-
stackParameters,
|
|
32
|
-
templateUrl,
|
|
33
|
-
validateConfig,
|
|
34
|
-
} from "./deploy/config";
|
|
35
|
-
import {
|
|
36
|
-
ask,
|
|
37
|
-
canPrompt,
|
|
38
|
-
loadConfig,
|
|
39
|
-
saveConfig,
|
|
40
|
-
withPrompt,
|
|
41
|
-
} from "./deploy/io";
|
|
42
|
-
|
|
43
|
-
interface Flags {
|
|
44
|
-
patch: PartialDeployConfig;
|
|
45
|
-
print: boolean;
|
|
46
|
-
run: boolean;
|
|
47
|
-
nonInteractive: boolean;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function parseFlags(argv: string[]): Flags {
|
|
51
|
-
const patch: PartialDeployConfig = { github: {}, lambda: {} };
|
|
52
|
-
let print = false;
|
|
53
|
-
let run = false;
|
|
54
|
-
let nonInteractive = false;
|
|
55
|
-
for (let i = 0; i < argv.length; i++) {
|
|
56
|
-
const a = argv[i];
|
|
57
|
-
const next = () => argv[++i] ?? "";
|
|
58
|
-
switch (a) {
|
|
59
|
-
case "--app":
|
|
60
|
-
patch.app = next();
|
|
61
|
-
break;
|
|
62
|
-
case "--region":
|
|
63
|
-
patch.region = next();
|
|
64
|
-
break;
|
|
65
|
-
case "--owner":
|
|
66
|
-
patch.github!.owner = next();
|
|
67
|
-
break;
|
|
68
|
-
case "--repo":
|
|
69
|
-
patch.github!.repo = next();
|
|
70
|
-
break;
|
|
71
|
-
case "--branch":
|
|
72
|
-
patch.github!.branch = next();
|
|
73
|
-
break;
|
|
74
|
-
case "--prefix":
|
|
75
|
-
patch.namePrefix = next();
|
|
76
|
-
break;
|
|
77
|
-
case "--namespace":
|
|
78
|
-
patch.namespace = next();
|
|
79
|
-
break;
|
|
80
|
-
case "--stack-name":
|
|
81
|
-
patch.stackName = next();
|
|
82
|
-
break;
|
|
83
|
-
case "--templates-bucket":
|
|
84
|
-
patch.templatesBucket = next();
|
|
85
|
-
break;
|
|
86
|
-
case "--artifacts-bucket":
|
|
87
|
-
patch.artifactsBucket = next();
|
|
88
|
-
break;
|
|
89
|
-
case "--arch":
|
|
90
|
-
patch.lambda!.arch = next() as DeployConfig["lambda"]["arch"];
|
|
91
|
-
break;
|
|
92
|
-
case "--print":
|
|
93
|
-
print = true;
|
|
94
|
-
nonInteractive = true;
|
|
95
|
-
break;
|
|
96
|
-
case "--run":
|
|
97
|
-
run = true;
|
|
98
|
-
break;
|
|
99
|
-
case "--yes":
|
|
100
|
-
case "-y":
|
|
101
|
-
case "--non-interactive":
|
|
102
|
-
nonInteractive = true;
|
|
103
|
-
break;
|
|
104
|
-
default:
|
|
105
|
-
if (a.startsWith("-")) {
|
|
106
|
-
console.error(`Unknown flag: ${a}`);
|
|
107
|
-
process.exit(1);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return { patch, print, run, nonInteractive };
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function seedConfig(patch: PartialDeployConfig): DeployConfig {
|
|
115
|
-
const existing = loadConfig();
|
|
116
|
-
return existing ? mergeConfig(existing, patch) : normalizeConfig(patch);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
async function promptMissing(cfg: DeployConfig): Promise<DeployConfig> {
|
|
120
|
-
return withPrompt(async (rl) => {
|
|
121
|
-
const app = await ask(rl, "App slug", cfg.app);
|
|
122
|
-
const owner = await ask(rl, "GitHub owner", cfg.github.owner);
|
|
123
|
-
const repo = await ask(rl, "GitHub repo", cfg.github.repo);
|
|
124
|
-
const branch = await ask(rl, "Deploy branch", cfg.github.branch);
|
|
125
|
-
const region = await ask(rl, "AWS region", cfg.region);
|
|
126
|
-
const namespace = await ask(rl, "Iceberg namespace", cfg.namespace);
|
|
127
|
-
const artifactsBucket = await ask(
|
|
128
|
-
rl,
|
|
129
|
-
"Artifacts bucket (from bootstrap stack)",
|
|
130
|
-
cfg.artifactsBucket ?? "",
|
|
131
|
-
);
|
|
132
|
-
const templatesBucket = await ask(
|
|
133
|
-
rl,
|
|
134
|
-
"Templates bucket (from bootstrap stack, optional)",
|
|
135
|
-
cfg.templatesBucket ?? "",
|
|
136
|
-
);
|
|
137
|
-
return mergeConfig(cfg, {
|
|
138
|
-
app,
|
|
139
|
-
region,
|
|
140
|
-
namespace,
|
|
141
|
-
artifactsBucket,
|
|
142
|
-
templatesBucket,
|
|
143
|
-
github: { owner, repo, branch },
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/** Pad a list of `Key=Value` rows into an aligned table. */
|
|
149
|
-
function table(rows: { key: string; value: string }[]): string {
|
|
150
|
-
const width = Math.max(0, ...rows.map((r) => r.key.length));
|
|
151
|
-
return rows.map((r) => ` ${r.key.padEnd(width)} ${r.value}`).join("\n");
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function printSummary(cfg: DeployConfig): void {
|
|
155
|
-
const src = templateUrl(cfg);
|
|
156
|
-
console.log(`\n Deployment config (${cfg.stackName} @ ${cfg.region})\n`);
|
|
157
|
-
console.log(" ── 1. Create the infrastructure (once, by a human) ──");
|
|
158
|
-
if (!cfg.artifactsBucket) {
|
|
159
|
-
console.log(
|
|
160
|
-
" ⚠ artifactsBucket is unset — app.yaml requires it. Run the bootstrap\n" +
|
|
161
|
-
" stack first, then set --artifacts-bucket (its ArtifactsBucketName output).",
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
if (!src) {
|
|
165
|
-
console.log(
|
|
166
|
-
" (launching from the in-repo template; set --templates-bucket to launch\n" +
|
|
167
|
-
" the hosted app.yaml by URL instead)",
|
|
168
|
-
);
|
|
169
|
-
}
|
|
170
|
-
console.log("\n" + deployStackCommand(cfg) + "\n");
|
|
171
|
-
|
|
172
|
-
console.log(
|
|
173
|
-
" ── 2. Wire the GitHub repo Variables (from the stack Outputs) ──",
|
|
174
|
-
);
|
|
175
|
-
console.log(
|
|
176
|
-
table(
|
|
177
|
-
repoVariables(cfg).map((v) => ({
|
|
178
|
-
key: v.name,
|
|
179
|
-
value: v.value || `<${v.from}>`,
|
|
180
|
-
})),
|
|
181
|
-
),
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
console.log("\n ── 3. The Lambda runtime env (set by the stack) ──");
|
|
185
|
-
console.log(table(lambdaEnv(cfg)));
|
|
186
|
-
|
|
187
|
-
console.log(
|
|
188
|
-
`\n ── 4. Then every push to ${cfg.github.branch} runs \`rastack ci deploy\`. ──\n`,
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
function runLaunch(cfg: DeployConfig): void {
|
|
193
|
-
const params = stackParameters(cfg).map((p) => `${p.key}=${p.value}`);
|
|
194
|
-
const src = templateUrl(cfg);
|
|
195
|
-
const args = [
|
|
196
|
-
"cloudformation",
|
|
197
|
-
"deploy",
|
|
198
|
-
...(src
|
|
199
|
-
? ["--template-url", src]
|
|
200
|
-
: ["--template-file", "deploy/cloudformation/app.yaml"]),
|
|
201
|
-
"--stack-name",
|
|
202
|
-
cfg.stackName,
|
|
203
|
-
"--capabilities",
|
|
204
|
-
"CAPABILITY_NAMED_IAM",
|
|
205
|
-
"--region",
|
|
206
|
-
cfg.region,
|
|
207
|
-
"--parameter-overrides",
|
|
208
|
-
...params,
|
|
209
|
-
];
|
|
210
|
-
console.log(`\n ▸ aws ${args.join(" ")}\n`);
|
|
211
|
-
try {
|
|
212
|
-
// Runs the developer's own AWS CLI with args built from their config — no
|
|
213
|
-
// untrusted input, and `execFileSync` (no shell) avoids any injection.
|
|
214
|
-
execFileSync("aws", args, { stdio: "inherit" });
|
|
215
|
-
} catch (err) {
|
|
216
|
-
console.error(
|
|
217
|
-
`\n ✗ aws cloudformation deploy failed. Is the AWS CLI installed and are` +
|
|
218
|
-
` your credentials configured?\n ${(err as Error).message}`,
|
|
219
|
-
);
|
|
220
|
-
process.exit(1);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
async function main(argv: string[]): Promise<void> {
|
|
225
|
-
const flags = parseFlags(argv);
|
|
226
|
-
let cfg = seedConfig(flags.patch);
|
|
227
|
-
|
|
228
|
-
if (canPrompt(flags.nonInteractive)) {
|
|
229
|
-
console.log("\n rastack deploy — configure the serverless deployment\n");
|
|
230
|
-
cfg = await promptMissing(cfg);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const errors = validateConfig(cfg);
|
|
234
|
-
if (errors.length) {
|
|
235
|
-
for (const e of errors) console.error(` ✗ ${e}`);
|
|
236
|
-
console.error(
|
|
237
|
-
`\n ${errors.length} problem(s) — fix the config and re-run.`,
|
|
238
|
-
);
|
|
239
|
-
process.exit(1);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
if (!flags.print) {
|
|
243
|
-
const file = saveConfig(cfg);
|
|
244
|
-
console.log(` ✓ saved ${file}`);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
printSummary(cfg);
|
|
248
|
-
|
|
249
|
-
if (flags.run) runLaunch(cfg);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
if (require.main === module) {
|
|
253
|
-
main(process.argv.slice(2)).catch((err) => {
|
|
254
|
-
console.error(` ✗ ${(err as Error).message}`);
|
|
255
|
-
process.exit(1);
|
|
256
|
-
});
|
|
257
|
-
}
|