hatchkit 0.1.4 → 0.1.6
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/dist/adopt.d.ts +2 -0
- package/dist/adopt.d.ts.map +1 -0
- package/dist/adopt.js +819 -0
- package/dist/adopt.js.map +1 -0
- package/dist/completion.d.ts.map +1 -1
- package/dist/completion.js +3 -0
- package/dist/completion.js.map +1 -1
- package/dist/config.d.ts +30 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +108 -0
- package/dist/config.js.map +1 -1
- package/dist/deploy/coolify-app.d.ts +35 -0
- package/dist/deploy/coolify-app.d.ts.map +1 -0
- package/dist/deploy/coolify-app.js +238 -0
- package/dist/deploy/coolify-app.js.map +1 -0
- package/dist/deploy/pages.js +50 -9
- package/dist/deploy/pages.js.map +1 -1
- package/dist/deploy/rename-domain.d.ts.map +1 -1
- package/dist/deploy/rename-domain.js +26 -6
- package/dist/deploy/rename-domain.js.map +1 -1
- package/dist/deploy/rollback.d.ts +10 -0
- package/dist/deploy/rollback.d.ts.map +1 -0
- package/dist/deploy/rollback.js +295 -0
- package/dist/deploy/rollback.js.map +1 -0
- package/dist/deploy/terraform.d.ts +10 -1
- package/dist/deploy/terraform.d.ts.map +1 -1
- package/dist/deploy/terraform.js +177 -42
- package/dist/deploy/terraform.js.map +1 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +25 -0
- package/dist/doctor.js.map +1 -1
- package/dist/explain.d.ts.map +1 -1
- package/dist/explain.js +5 -0
- package/dist/explain.js.map +1 -1
- package/dist/index.js +377 -122
- package/dist/index.js.map +1 -1
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +283 -11
- package/dist/prompts.js.map +1 -1
- package/dist/provision/stripe.d.ts +19 -0
- package/dist/provision/stripe.d.ts.map +1 -0
- package/dist/provision/stripe.js +58 -0
- package/dist/provision/stripe.js.map +1 -0
- package/dist/scaffold/dotenvx.d.ts.map +1 -1
- package/dist/scaffold/dotenvx.js +35 -11
- package/dist/scaffold/dotenvx.js.map +1 -1
- package/dist/scaffold/infra.d.ts +21 -1
- package/dist/scaffold/infra.d.ts.map +1 -1
- package/dist/scaffold/infra.js +66 -20
- package/dist/scaffold/infra.js.map +1 -1
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +7 -0
- package/dist/status.js.map +1 -1
- package/dist/utils/cloudflare-api.d.ts +23 -0
- package/dist/utils/cloudflare-api.d.ts.map +1 -1
- package/dist/utils/cloudflare-api.js +31 -0
- package/dist/utils/cloudflare-api.js.map +1 -1
- package/dist/utils/coolify-api.d.ts +64 -3
- package/dist/utils/coolify-api.d.ts.map +1 -1
- package/dist/utils/coolify-api.js +99 -3
- package/dist/utils/coolify-api.js.map +1 -1
- package/dist/utils/run-ledger.d.ts +68 -0
- package/dist/utils/run-ledger.d.ts.map +1 -0
- package/dist/utils/run-ledger.js +99 -0
- package/dist/utils/run-ledger.js.map +1 -0
- package/dist/utils/secrets.d.ts +2 -0
- package/dist/utils/secrets.d.ts.map +1 -1
- package/dist/utils/secrets.js +2 -0
- package/dist/utils/secrets.js.map +1 -1
- package/package.json +2 -2
- package/scripts/release-prep.mjs +130 -95
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Rollback — print a tailored cleanup recipe for a partial `hatchkit
|
|
3
|
+
* create` and (optionally) execute it.
|
|
4
|
+
*
|
|
5
|
+
* Two entry points:
|
|
6
|
+
* - `handleCreateFailure(ledger, err)` — called from the create-flow
|
|
7
|
+
* try/catch. Prints the error, the recipe, and a 3-way prompt:
|
|
8
|
+
* roll back now / show recipe again / leave it. Destructive steps
|
|
9
|
+
* (rm -rf appDir, github repo delete, terraform destroy) get a
|
|
10
|
+
* per-step confirmation before they run, so a single 'y' at the
|
|
11
|
+
* top doesn't unleash a cascade of irreversible operations.
|
|
12
|
+
* - `runRollback(ledger, opts)` — used by `hatchkit destroy` for the
|
|
13
|
+
* same execution path, with `--yes` to skip per-step prompts.
|
|
14
|
+
*
|
|
15
|
+
* Steps undo in reverse order. Failures within an undo are logged but
|
|
16
|
+
* don't abort the rest of the rollback — we want to claw back as much
|
|
17
|
+
* state as we can and surface what's left.
|
|
18
|
+
*/
|
|
19
|
+
import { existsSync, rmSync, unlinkSync } from "node:fs";
|
|
20
|
+
import { confirm, select } from "@inquirer/prompts";
|
|
21
|
+
import chalk from "chalk";
|
|
22
|
+
import { getCoolifyConfig, getDnsConfig } from "../config.js";
|
|
23
|
+
import { CoolifyApi } from "../utils/coolify-api.js";
|
|
24
|
+
import { exec } from "../utils/exec.js";
|
|
25
|
+
import { RunLedger } from "../utils/run-ledger.js";
|
|
26
|
+
import { deleteSecret } from "../utils/secrets.js";
|
|
27
|
+
/* ─────────────────────────────────────────────────────────────────────── */
|
|
28
|
+
/* Failure handler — called from the create-flow try/catch */
|
|
29
|
+
/* ─────────────────────────────────────────────────────────────────────── */
|
|
30
|
+
export async function handleCreateFailure(ledger, err) {
|
|
31
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
32
|
+
console.log(chalk.bold.red(`\n ✗ hatchkit create failed: ${message}`));
|
|
33
|
+
if (ledger.steps.length === 0) {
|
|
34
|
+
console.log(chalk.dim(" No steps completed before failure — nothing to clean up.\n"));
|
|
35
|
+
ledger.delete();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
console.log(chalk.dim(` Completed ${ledger.steps.length} step${ledger.steps.length === 1 ? "" : "s"} before failing. ` +
|
|
39
|
+
`Ledger: ${ledger.path}\n`));
|
|
40
|
+
printRecipe(ledger);
|
|
41
|
+
// Loop the prompt so "show recipe" doesn't drop the user back into
|
|
42
|
+
// an unreviewed default.
|
|
43
|
+
for (;;) {
|
|
44
|
+
const choice = await select({
|
|
45
|
+
message: "How would you like to handle the partial state?",
|
|
46
|
+
choices: [
|
|
47
|
+
{ name: "Roll back now (with confirmation per destructive step)", value: "rollback" },
|
|
48
|
+
{ name: "Show the recipe again", value: "recipe" },
|
|
49
|
+
{ name: "Leave it — I'll clean up later", value: "leave" },
|
|
50
|
+
],
|
|
51
|
+
default: "leave",
|
|
52
|
+
});
|
|
53
|
+
if (choice === "recipe") {
|
|
54
|
+
printRecipe(ledger);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (choice === "leave") {
|
|
58
|
+
console.log(chalk.dim(`\n Ledger preserved at ${ledger.path}. Run \`hatchkit destroy ${ledger.name}\` later to undo.\n`));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
await runRollback(ledger, { yes: false });
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/* ─────────────────────────────────────────────────────────────────────── */
|
|
66
|
+
/* Recipe printer — copy-pasteable bash commands */
|
|
67
|
+
/* ─────────────────────────────────────────────────────────────────────── */
|
|
68
|
+
export function printRecipe(ledger) {
|
|
69
|
+
console.log(chalk.bold(" ── Cleanup recipe ──────────────────────────────────────────\n"));
|
|
70
|
+
console.log(chalk.dim(" Run these in order to manually undo the partial create:\n"));
|
|
71
|
+
// Reverse order: undo the latest step first.
|
|
72
|
+
const lines = [];
|
|
73
|
+
for (const step of [...ledger.steps].reverse()) {
|
|
74
|
+
const cmd = recipeFor(step);
|
|
75
|
+
if (cmd)
|
|
76
|
+
lines.push(cmd);
|
|
77
|
+
}
|
|
78
|
+
for (const line of lines) {
|
|
79
|
+
console.log(` ${line}`);
|
|
80
|
+
}
|
|
81
|
+
console.log();
|
|
82
|
+
}
|
|
83
|
+
function recipeFor(step) {
|
|
84
|
+
switch (step.kind) {
|
|
85
|
+
case "mlService":
|
|
86
|
+
return chalk.dim(`# manual: delete ${step.name} from your ${step.platform} dashboard`);
|
|
87
|
+
case "coolifyDb":
|
|
88
|
+
return chalk.dim(`# manual: delete database ${step.uuid} from the Coolify dashboard`);
|
|
89
|
+
case "coolifyApp":
|
|
90
|
+
return chalk.dim(`# manual: delete application ${step.uuid} from the Coolify dashboard`);
|
|
91
|
+
case "terraformApplied":
|
|
92
|
+
return `cd ${shellEscape(step.stackDir)} && terraform destroy -var-file=${shellEscape(step.tfvarsPath)}`;
|
|
93
|
+
case "coolifyEnv":
|
|
94
|
+
return `rm ${shellEscape(step.path)}`;
|
|
95
|
+
case "tfvars":
|
|
96
|
+
return `rm ${shellEscape(step.path)}`;
|
|
97
|
+
case "glitchtip":
|
|
98
|
+
return `hatchkit remove ${shellEscape(step.project)} glitchtip --yes`;
|
|
99
|
+
case "github":
|
|
100
|
+
return `gh repo delete ${shellEscape(step.repo)} --yes`;
|
|
101
|
+
case "scaffold":
|
|
102
|
+
return `rm -rf ${shellEscape(step.path)}`;
|
|
103
|
+
case "keychain":
|
|
104
|
+
return `security delete-generic-password -s hatchkit -a ${shellEscape(step.account)}`;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function shellEscape(s) {
|
|
108
|
+
if (/^[A-Za-z0-9_./:@%+=,-]+$/.test(s))
|
|
109
|
+
return s;
|
|
110
|
+
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
111
|
+
}
|
|
112
|
+
/* ─────────────────────────────────────────────────────────────────────── */
|
|
113
|
+
/* Executor — reverse-order undo */
|
|
114
|
+
/* ─────────────────────────────────────────────────────────────────────── */
|
|
115
|
+
export async function runRollback(ledger, opts = {}) {
|
|
116
|
+
console.log(chalk.bold("\n ── Rolling back ────────────────────────────────────────────\n"));
|
|
117
|
+
let undone = 0;
|
|
118
|
+
let skipped = 0;
|
|
119
|
+
let failed = 0;
|
|
120
|
+
const remaining = [];
|
|
121
|
+
for (const step of [...ledger.steps].reverse()) {
|
|
122
|
+
const label = describeStep(step);
|
|
123
|
+
// Per-step confirmation for the irreversible ones unless --yes.
|
|
124
|
+
if (!opts.yes && isDestructive(step)) {
|
|
125
|
+
const ok = await confirm({
|
|
126
|
+
message: `${chalk.red("Destructive:")} ${label}. Proceed?`,
|
|
127
|
+
default: false,
|
|
128
|
+
});
|
|
129
|
+
if (!ok) {
|
|
130
|
+
console.log(chalk.dim(` skipped: ${label}`));
|
|
131
|
+
skipped += 1;
|
|
132
|
+
remaining.push(step);
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
process.stdout.write(` ${label} … `);
|
|
137
|
+
try {
|
|
138
|
+
const result = await undoStep(step);
|
|
139
|
+
if (result === "skipped") {
|
|
140
|
+
console.log(chalk.dim("skipped"));
|
|
141
|
+
skipped += 1;
|
|
142
|
+
remaining.push(step);
|
|
143
|
+
}
|
|
144
|
+
else if (result === "not-found") {
|
|
145
|
+
console.log(chalk.dim("already gone"));
|
|
146
|
+
undone += 1;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
console.log(chalk.green("✓"));
|
|
150
|
+
undone += 1;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
console.log(chalk.red(`✗ ${err.message}`));
|
|
155
|
+
failed += 1;
|
|
156
|
+
remaining.push(step);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
console.log(chalk.bold("\n ── Rollback summary ────────────────────────────────────────\n"));
|
|
160
|
+
console.log(` Undone: ${chalk.green(undone)}`);
|
|
161
|
+
console.log(` Skipped: ${chalk.dim(skipped)}`);
|
|
162
|
+
console.log(` Failed: ${failed > 0 ? chalk.red(failed) : chalk.dim(failed)}`);
|
|
163
|
+
if (remaining.length === 0) {
|
|
164
|
+
ledger.delete();
|
|
165
|
+
console.log(chalk.dim(`\n Ledger removed.\n`));
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
// Replace the ledger with what's left so the next `hatchkit destroy`
|
|
169
|
+
// run picks up where we paused.
|
|
170
|
+
rewriteRemaining(ledger, remaining);
|
|
171
|
+
console.log(chalk.yellow(`\n ${remaining.length} step(s) still pending. Re-run \`hatchkit destroy ${ledger.name}\` to retry.\n`));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/** Rewrite the on-disk ledger to keep only the steps that weren't
|
|
175
|
+
* undone (because they failed or the user skipped them). Done by
|
|
176
|
+
* calling `start` to clobber the file, then re-recording each
|
|
177
|
+
* remaining step in original (forward) order. */
|
|
178
|
+
function rewriteRemaining(ledger, remaining) {
|
|
179
|
+
// Steps were processed in reverse; remaining is in reverse too.
|
|
180
|
+
// Restore original order so a future rollback walks them correctly.
|
|
181
|
+
const fresh = RunLedger.start(ledger.name);
|
|
182
|
+
for (const step of [...remaining].reverse()) {
|
|
183
|
+
fresh.record(step);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function isDestructive(step) {
|
|
187
|
+
return (step.kind === "scaffold" ||
|
|
188
|
+
step.kind === "github" ||
|
|
189
|
+
step.kind === "terraformApplied" ||
|
|
190
|
+
step.kind === "coolifyApp" ||
|
|
191
|
+
step.kind === "coolifyDb");
|
|
192
|
+
}
|
|
193
|
+
function describeStep(step) {
|
|
194
|
+
switch (step.kind) {
|
|
195
|
+
case "scaffold":
|
|
196
|
+
return `delete local repo ${chalk.cyan(step.path)}`;
|
|
197
|
+
case "github":
|
|
198
|
+
return `delete GitHub repo ${chalk.cyan(step.repo)}`;
|
|
199
|
+
case "glitchtip":
|
|
200
|
+
return `delete GlitchTip project ${chalk.cyan(step.project)}`;
|
|
201
|
+
case "tfvars":
|
|
202
|
+
return `remove ${chalk.cyan(step.path)}`;
|
|
203
|
+
case "coolifyEnv":
|
|
204
|
+
return `remove ${chalk.cyan(step.path)}`;
|
|
205
|
+
case "keychain":
|
|
206
|
+
return `delete keychain entry ${chalk.cyan(step.account)}`;
|
|
207
|
+
case "terraformApplied":
|
|
208
|
+
return `terraform destroy in ${chalk.cyan(step.stackDir)}`;
|
|
209
|
+
case "coolifyApp":
|
|
210
|
+
return `delete Coolify app ${chalk.cyan(step.uuid)}`;
|
|
211
|
+
case "coolifyDb":
|
|
212
|
+
return `delete Coolify db ${chalk.cyan(step.uuid)}`;
|
|
213
|
+
case "mlService":
|
|
214
|
+
return `${chalk.cyan(step.platform)} ML service ${chalk.cyan(step.name)}`;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
async function undoStep(step) {
|
|
218
|
+
switch (step.kind) {
|
|
219
|
+
case "scaffold": {
|
|
220
|
+
if (!existsSync(step.path))
|
|
221
|
+
return "not-found";
|
|
222
|
+
rmSync(step.path, { recursive: true, force: true });
|
|
223
|
+
return "done";
|
|
224
|
+
}
|
|
225
|
+
case "github": {
|
|
226
|
+
const res = await exec("gh", ["repo", "delete", step.repo, "--yes"], { silent: true });
|
|
227
|
+
if (res.exitCode !== 0) {
|
|
228
|
+
// Already gone, or the user lacks delete:repo scope.
|
|
229
|
+
if (/not found|404/i.test(res.stderr ?? ""))
|
|
230
|
+
return "not-found";
|
|
231
|
+
throw new Error(`gh repo delete failed: ${res.stderr || res.stdout}`);
|
|
232
|
+
}
|
|
233
|
+
return "done";
|
|
234
|
+
}
|
|
235
|
+
case "glitchtip": {
|
|
236
|
+
const { deleteGlitchtipClient } = await import("../provision/glitchtip.js");
|
|
237
|
+
const result = await deleteGlitchtipClient(step.project);
|
|
238
|
+
return result === "not-found" ? "not-found" : "done";
|
|
239
|
+
}
|
|
240
|
+
case "tfvars":
|
|
241
|
+
case "coolifyEnv": {
|
|
242
|
+
if (!existsSync(step.path))
|
|
243
|
+
return "not-found";
|
|
244
|
+
unlinkSync(step.path);
|
|
245
|
+
return "done";
|
|
246
|
+
}
|
|
247
|
+
case "keychain": {
|
|
248
|
+
const ok = await deleteSecret(step.account);
|
|
249
|
+
return ok ? "done" : "not-found";
|
|
250
|
+
}
|
|
251
|
+
case "terraformApplied": {
|
|
252
|
+
// We need the same env vars `runTerraform` used. Re-derive from
|
|
253
|
+
// the user's saved DNS config; if creds aren't there anymore,
|
|
254
|
+
// the destroy won't work and we say so.
|
|
255
|
+
const dns = await getDnsConfig();
|
|
256
|
+
const env = {};
|
|
257
|
+
if (dns?.provider === "cloudflare" && dns.apiToken) {
|
|
258
|
+
env.TF_VAR_cloudflare_api_token = dns.apiToken;
|
|
259
|
+
}
|
|
260
|
+
else if (dns?.provider === "inwx" && dns.username && dns.password) {
|
|
261
|
+
env.TF_VAR_inwx_username = dns.username;
|
|
262
|
+
env.TF_VAR_inwx_password = dns.password;
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
throw new Error("DNS credentials no longer in keychain — re-add them, then retry");
|
|
266
|
+
}
|
|
267
|
+
const res = await exec("terraform", ["destroy", "-auto-approve", `-var-file=${step.tfvarsPath}`], { cwd: step.stackDir, env, silent: true });
|
|
268
|
+
if (res.exitCode !== 0) {
|
|
269
|
+
throw new Error(`terraform destroy failed: ${res.stderr || res.stdout}`);
|
|
270
|
+
}
|
|
271
|
+
return "done";
|
|
272
|
+
}
|
|
273
|
+
case "coolifyApp": {
|
|
274
|
+
const cfg = await getCoolifyConfig();
|
|
275
|
+
if (!cfg)
|
|
276
|
+
throw new Error("Coolify config no longer present");
|
|
277
|
+
const api = new CoolifyApi({ url: cfg.url, token: cfg.token });
|
|
278
|
+
const result = await api.deleteApplication(step.uuid);
|
|
279
|
+
return result === "not-found" ? "not-found" : "done";
|
|
280
|
+
}
|
|
281
|
+
case "coolifyDb": {
|
|
282
|
+
const cfg = await getCoolifyConfig();
|
|
283
|
+
if (!cfg)
|
|
284
|
+
throw new Error("Coolify config no longer present");
|
|
285
|
+
const api = new CoolifyApi({ url: cfg.url, token: cfg.token });
|
|
286
|
+
const result = await api.deleteDatabase(step.uuid);
|
|
287
|
+
return result === "not-found" ? "not-found" : "done";
|
|
288
|
+
}
|
|
289
|
+
case "mlService":
|
|
290
|
+
// Per-platform delete is platform-specific (Modal/RunPod/HF/Replicate).
|
|
291
|
+
// Surface in the recipe but skip auto-undo for now.
|
|
292
|
+
return "skipped";
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
//# sourceMappingURL=rollback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rollback.js","sourceRoot":"","sources":["../../src/deploy/rollback.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import type { ProjectConfig } from "../prompts.js";
|
|
2
|
+
/** Result of `runTerraform`. Returns metadata the caller can record in
|
|
3
|
+
* the run ledger so a later rollback knows which stack to destroy. */
|
|
4
|
+
export interface RunTerraformResult {
|
|
5
|
+
/** Set when an apply actually ran. Undefined for manual-DNS or skip. */
|
|
6
|
+
applied?: {
|
|
7
|
+
stackDir: string;
|
|
8
|
+
tfvarsPath: string;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
2
11
|
/** Run Terraform for the project. */
|
|
3
|
-
export declare function runTerraform(config: ProjectConfig, repoRoot: string): Promise<
|
|
12
|
+
export declare function runTerraform(config: ProjectConfig, repoRoot: string): Promise<RunTerraformResult>;
|
|
4
13
|
//# sourceMappingURL=terraform.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terraform.d.ts","sourceRoot":"","sources":["../../src/deploy/terraform.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"terraform.d.ts","sourceRoot":"","sources":["../../src/deploy/terraform.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAiBnD;uEACuE;AACvE,MAAM,WAAW,kBAAkB;IACjC,wEAAwE;IACxE,OAAO,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CACpD;AAED,qCAAqC;AACrC,wBAAsB,YAAY,CAChC,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,CAAC,CAoI7B"}
|
package/dist/deploy/terraform.js
CHANGED
|
@@ -1,37 +1,66 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { promises as dnsPromises } from "node:dns";
|
|
2
|
+
import { select } from "@inquirer/prompts";
|
|
2
3
|
import chalk from "chalk";
|
|
3
|
-
import { getDnsConfig, getHetznerToken, getS3Config } from "../config.js";
|
|
4
|
+
import { getDnsConfig, getHetznerToken, getS3Config, promptAndSaveInwxRegistrarCreds, } from "../config.js";
|
|
5
|
+
import { resolveStackDir } from "../scaffold/infra.js";
|
|
6
|
+
import { CloudflareApi } from "../utils/cloudflare-api.js";
|
|
4
7
|
import { exec, execStream } from "../utils/exec.js";
|
|
5
8
|
import { InwxApi } from "../utils/inwx-api.js";
|
|
6
9
|
/** Run Terraform for the project. */
|
|
7
10
|
export async function runTerraform(config, repoRoot) {
|
|
8
11
|
const hetznerToken = await getHetznerToken();
|
|
9
12
|
const dnsConfig = await getDnsConfig();
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
const dnsProvider = (dnsConfig?.provider ?? "inwx");
|
|
14
|
+
console.log(chalk.bold("\n ── Terraform ──────────────────────────────────────────────\n"));
|
|
15
|
+
// Manual DNS on an existing server: nothing for Terraform to do.
|
|
16
|
+
if (config.deployTarget === "existing" && dnsProvider === "manual") {
|
|
17
|
+
console.log(chalk.dim(" Manual DNS — no Terraform stack to apply. Set DNS records yourself."));
|
|
18
|
+
return {};
|
|
19
|
+
}
|
|
20
|
+
const stackDir = resolveStackDir(repoRoot, config.deployTarget, dnsProvider);
|
|
21
|
+
if (!stackDir) {
|
|
22
|
+
console.log(chalk.dim(" No matching Terraform stack — skipping."));
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
const tfvarsFile = `${stackDir}/${config.name}.tfvars`;
|
|
26
|
+
// Build env vars for Terraform — only what the chosen stack needs.
|
|
15
27
|
const env = {};
|
|
16
28
|
if (hetznerToken) {
|
|
17
29
|
env.TF_VAR_hcloud_token = hetznerToken;
|
|
18
30
|
}
|
|
19
|
-
// DNS
|
|
20
|
-
// provider
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
// Preflight + DNS creds. The dns-only-* stacks each only declare one
|
|
32
|
+
// DNS provider, so we pass only that provider's creds. The legacy
|
|
33
|
+
// node-realtime stack still bundles both providers (count-gated
|
|
34
|
+
// modules) and inherits the older "INWX creds required even for CF"
|
|
35
|
+
// footgun — fixing that is a follow-up.
|
|
36
|
+
let registrarPlan = null;
|
|
37
|
+
if (dnsProvider === "inwx") {
|
|
38
|
+
if (!dnsConfig?.username || !dnsConfig.password) {
|
|
39
|
+
throw new Error("INWX is configured as the DNS provider but credentials are missing. Re-run `hatchkit config add dns`.");
|
|
40
|
+
}
|
|
41
|
+
env.TF_VAR_inwx_username = dnsConfig.username;
|
|
42
|
+
env.TF_VAR_inwx_password = dnsConfig.password;
|
|
43
|
+
}
|
|
44
|
+
else if (dnsProvider === "cloudflare") {
|
|
45
|
+
if (!dnsConfig?.apiToken) {
|
|
46
|
+
throw new Error("Cloudflare is configured as the DNS provider but the API token is missing from the keychain.");
|
|
47
|
+
}
|
|
48
|
+
env.TF_VAR_cloudflare_api_token = dnsConfig.apiToken;
|
|
49
|
+
// dns-only-cloudflare doesn't ask for INWX creds at all. The
|
|
50
|
+
// node-realtime path still does (legacy footgun) — we mirror the
|
|
51
|
+
// old behavior there until that stack is split too.
|
|
52
|
+
if (config.deployTarget === "new") {
|
|
53
|
+
if (dnsConfig.registrarUsername && dnsConfig.registrarPassword) {
|
|
54
|
+
env.TF_VAR_inwx_username = dnsConfig.registrarUsername;
|
|
55
|
+
env.TF_VAR_inwx_password = dnsConfig.registrarPassword;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// dns-only-cloudflare: figure out whether a registrar NS-flip is
|
|
60
|
+
// even needed *before* terraform runs, and prompt for INWX creds
|
|
61
|
+
// inline if it is. We only block on a working answer here so that
|
|
62
|
+
// the post-apply step has what it needs (or knows to skip).
|
|
63
|
+
registrarPlan = await preflightRegistrarFlip(config.baseDomain, dnsConfig);
|
|
35
64
|
}
|
|
36
65
|
}
|
|
37
66
|
if (config.features.includes("s3") &&
|
|
@@ -43,7 +72,6 @@ export async function runTerraform(config, repoRoot) {
|
|
|
43
72
|
env.TF_VAR_s3_secret_key = s3.secretKey;
|
|
44
73
|
}
|
|
45
74
|
}
|
|
46
|
-
console.log(chalk.bold("\n ── Terraform ──────────────────────────────────────────────\n"));
|
|
47
75
|
// Init
|
|
48
76
|
const initResult = await exec("terraform", ["init"], {
|
|
49
77
|
cwd: stackDir,
|
|
@@ -66,24 +94,136 @@ export async function runTerraform(config, repoRoot) {
|
|
|
66
94
|
throw new Error("Terraform apply failed");
|
|
67
95
|
}
|
|
68
96
|
console.log(chalk.green("\n ✓ Terraform apply complete"));
|
|
69
|
-
// Post-apply: if
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
97
|
+
// Post-apply: NS-flip if dns-only-cloudflare path decided one was
|
|
98
|
+
// needed and we now have creds. Both decisions live in registrarPlan
|
|
99
|
+
// so this code doesn't re-derive intent.
|
|
100
|
+
if (registrarPlan?.action === "flip") {
|
|
101
|
+
await updateInwxNameserversFromTfOutput(stackDir, env, {
|
|
102
|
+
username: registrarPlan.registrarUsername,
|
|
103
|
+
password: registrarPlan.registrarPassword,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
else if (registrarPlan?.action === "skip") {
|
|
107
|
+
console.log(chalk.dim(` (registrar NS-flip skipped — ${registrarPlan.reason})`));
|
|
108
|
+
}
|
|
109
|
+
else if (config.deployTarget === "new" &&
|
|
110
|
+
dnsProvider === "cloudflare" &&
|
|
111
|
+
dnsConfig?.registrarUsername &&
|
|
75
112
|
dnsConfig.registrarPassword) {
|
|
76
|
-
|
|
113
|
+
// Legacy node-realtime path — preserve the original behavior.
|
|
114
|
+
await updateInwxNameserversFromTfOutput(stackDir, env, {
|
|
115
|
+
username: dnsConfig.registrarUsername,
|
|
116
|
+
password: dnsConfig.registrarPassword,
|
|
117
|
+
});
|
|
77
118
|
}
|
|
119
|
+
return { applied: { stackDir, tfvarsPath: tfvarsFile } };
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Decide whether the registrar NS-flip is worth doing for this deploy:
|
|
123
|
+
*
|
|
124
|
+
* 1. Look the domain up in Cloudflare → its assigned name_servers.
|
|
125
|
+
* 2. Resolve the current public NS for the domain.
|
|
126
|
+
* 3. If they already match → skip (NS already pointed at Cloudflare).
|
|
127
|
+
* 4. If they don't match → a flip is needed. Use saved INWX registrar
|
|
128
|
+
* creds if present; otherwise prompt for them inline (with an
|
|
129
|
+
* "I'll do it manually" escape hatch).
|
|
130
|
+
*
|
|
131
|
+
* Returns a plan describing what post-apply should do. Network errors
|
|
132
|
+
* during the lookup (CF API down, no internet) degrade gracefully into
|
|
133
|
+
* "skip" with a note — the user can re-run `hatchkit dns
|
|
134
|
+
* link-to-cloudflare` later.
|
|
135
|
+
*/
|
|
136
|
+
async function preflightRegistrarFlip(domain, dnsConfig) {
|
|
137
|
+
console.log(chalk.dim("\n Checking whether the registrar NS-flip is needed..."));
|
|
138
|
+
// Strip subdomain — registrar delegation is at the apex.
|
|
139
|
+
const apex = apexDomain(domain);
|
|
140
|
+
let expectedNs;
|
|
141
|
+
try {
|
|
142
|
+
if (!dnsConfig.apiToken) {
|
|
143
|
+
return { action: "skip", reason: "no Cloudflare token to look up zone" };
|
|
144
|
+
}
|
|
145
|
+
const cf = new CloudflareApi({ token: dnsConfig.apiToken, accountId: dnsConfig.accountId });
|
|
146
|
+
const zone = await cf.getZoneByName(apex);
|
|
147
|
+
if (!zone) {
|
|
148
|
+
return {
|
|
149
|
+
action: "skip",
|
|
150
|
+
reason: `${apex} isn't in your Cloudflare account yet — add the zone, then re-run`,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
expectedNs = zone.name_servers.map((n) => n.toLowerCase()).sort();
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
return { action: "skip", reason: `Cloudflare lookup failed: ${err.message}` };
|
|
157
|
+
}
|
|
158
|
+
let currentNs;
|
|
159
|
+
try {
|
|
160
|
+
const ns = await dnsPromises.resolveNs(apex);
|
|
161
|
+
currentNs = ns.map((n) => n.toLowerCase()).sort();
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
// ENOTFOUND on a brand-new domain just means "no NS yet" — we
|
|
165
|
+
// definitely need the flip.
|
|
166
|
+
currentNs = [];
|
|
167
|
+
}
|
|
168
|
+
const same = currentNs.length === expectedNs.length && currentNs.every((n, i) => n === expectedNs[i]);
|
|
169
|
+
if (same) {
|
|
170
|
+
return { action: "skip", reason: "NS already point at Cloudflare" };
|
|
171
|
+
}
|
|
172
|
+
console.log(chalk.dim(` expected NS: ${expectedNs.join(", ")}`));
|
|
173
|
+
console.log(chalk.dim(` current NS: ${currentNs.length ? currentNs.join(", ") : "(none)"}`));
|
|
174
|
+
// Need a flip. Try saved creds first.
|
|
175
|
+
if (dnsConfig.registrarUsername && dnsConfig.registrarPassword) {
|
|
176
|
+
return {
|
|
177
|
+
action: "flip",
|
|
178
|
+
registrarUsername: dnsConfig.registrarUsername,
|
|
179
|
+
registrarPassword: dnsConfig.registrarPassword,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
// No saved creds — ask inline.
|
|
183
|
+
console.log(chalk.yellow(`\n ${apex} needs its registrar NS pointed at Cloudflare, but INWX registrar creds aren't configured.`));
|
|
184
|
+
const choice = await select({
|
|
185
|
+
message: "How would you like to proceed?",
|
|
186
|
+
choices: [
|
|
187
|
+
{
|
|
188
|
+
name: "Provide INWX registrar credentials now (saved to keychain for reuse)",
|
|
189
|
+
value: "provide",
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
name: "Skip — I'll point NS at Cloudflare manually (or my registrar isn't INWX)",
|
|
193
|
+
value: "skip",
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
});
|
|
197
|
+
if (choice === "skip") {
|
|
198
|
+
return { action: "skip", reason: "user opted to flip NS manually" };
|
|
199
|
+
}
|
|
200
|
+
const creds = await promptAndSaveInwxRegistrarCreds();
|
|
201
|
+
return {
|
|
202
|
+
action: "flip",
|
|
203
|
+
registrarUsername: creds.username,
|
|
204
|
+
registrarPassword: creds.password,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
/** "ai.example.com" → "example.com". TLDs with second-level domains
|
|
208
|
+
* (".co.uk") aren't auto-detected — registrar lookups only happen on
|
|
209
|
+
* the apex anyway, so we just take the last two labels. Good enough
|
|
210
|
+
* for >99% of cases; users with country-code 2LDs can pre-configure
|
|
211
|
+
* registrar creds. */
|
|
212
|
+
function apexDomain(domain) {
|
|
213
|
+
const parts = domain.split(".");
|
|
214
|
+
if (parts.length <= 2)
|
|
215
|
+
return domain;
|
|
216
|
+
return parts.slice(-2).join(".");
|
|
78
217
|
}
|
|
79
218
|
/**
|
|
80
219
|
* Read the stack's dns_provider + dns_domain + dns_nameservers outputs
|
|
81
220
|
* and push them to INWX as the new delegated NS for that domain. No-op
|
|
82
|
-
* if the stack didn't actually apply a Cloudflare zone (e.g.
|
|
83
|
-
* dns_provider = "inwx" in tfvars
|
|
84
|
-
*
|
|
221
|
+
* if the stack didn't actually apply a Cloudflare zone (e.g. legacy
|
|
222
|
+
* node-realtime stack with dns_provider = "inwx" in tfvars). Caller is
|
|
223
|
+
* responsible for the decision to call this — the registrar plan in
|
|
224
|
+
* `runTerraform` handles preflight + creds.
|
|
85
225
|
*/
|
|
86
|
-
async function updateInwxNameserversFromTfOutput(stackDir, env,
|
|
226
|
+
async function updateInwxNameserversFromTfOutput(stackDir, env, registrarCreds) {
|
|
87
227
|
const out = await exec("terraform", ["output", "-json"], {
|
|
88
228
|
cwd: stackDir,
|
|
89
229
|
env,
|
|
@@ -116,14 +256,9 @@ async function updateInwxNameserversFromTfOutput(stackDir, env, dnsConfig) {
|
|
|
116
256
|
console.log(chalk.bold("\n ── INWX registrar: pointing NS at Cloudflare ────────────\n"));
|
|
117
257
|
console.log(chalk.dim(` Domain: ${domain}`));
|
|
118
258
|
console.log(chalk.dim(` New NS: ${nameservers.join(", ")}`));
|
|
119
|
-
// registrarUsername/Password presence is guaranteed by the caller's
|
|
120
|
-
// guard — assert here to keep the types clean.
|
|
121
|
-
if (!dnsConfig.registrarUsername || !dnsConfig.registrarPassword) {
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
259
|
const inwx = new InwxApi({
|
|
125
|
-
username:
|
|
126
|
-
password:
|
|
260
|
+
username: registrarCreds.username,
|
|
261
|
+
password: registrarCreds.password,
|
|
127
262
|
sandbox: process.env.INWX_SANDBOX === "1",
|
|
128
263
|
});
|
|
129
264
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terraform.js","sourceRoot":"","sources":["../../src/deploy/terraform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"terraform.js","sourceRoot":"","sources":["../../src/deploy/terraform.ts"],"names":[],"mappings":"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"}
|
package/dist/doctor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAsBA,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAsBA,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AA6WD,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAanE;AAED,wBAAsB,SAAS,CAAC,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA8C5E"}
|