hatchkit 0.1.39 → 0.1.41
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.map +1 -1
- package/dist/adopt.js +311 -77
- package/dist/adopt.js.map +1 -1
- package/dist/deploy/coolify-app.d.ts +9 -9
- package/dist/deploy/coolify-app.d.ts.map +1 -1
- package/dist/deploy/coolify-app.js +14 -19
- package/dist/deploy/coolify-app.js.map +1 -1
- package/dist/deploy/coolify.d.ts.map +1 -1
- package/dist/deploy/coolify.js +6 -2
- package/dist/deploy/coolify.js.map +1 -1
- package/dist/deploy/keys.d.ts +7 -2
- package/dist/deploy/keys.d.ts.map +1 -1
- package/dist/deploy/keys.js +27 -7
- package/dist/deploy/keys.js.map +1 -1
- package/dist/deploy/pages.d.ts +41 -0
- package/dist/deploy/pages.d.ts.map +1 -1
- package/dist/deploy/pages.js +360 -13
- package/dist/deploy/pages.js.map +1 -1
- package/dist/deploy/regen-infra.js +4 -0
- package/dist/deploy/regen-infra.js.map +1 -1
- package/dist/deploy/rollback.d.ts.map +1 -1
- package/dist/deploy/rollback.js +94 -22
- package/dist/deploy/rollback.js.map +1 -1
- package/dist/deploy/sync.d.ts +10 -7
- package/dist/deploy/sync.d.ts.map +1 -1
- package/dist/deploy/sync.js +13 -9
- package/dist/deploy/sync.js.map +1 -1
- package/dist/index.js +269 -23
- package/dist/index.js.map +1 -1
- package/dist/inventory.d.ts +144 -0
- package/dist/inventory.d.ts.map +1 -0
- package/dist/inventory.js +1980 -0
- package/dist/inventory.js.map +1 -0
- package/dist/overview.d.ts +101 -0
- package/dist/overview.d.ts.map +1 -0
- package/dist/overview.js +852 -0
- package/dist/overview.js.map +1 -0
- package/dist/prompts.d.ts +22 -7
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +240 -40
- package/dist/prompts.js.map +1 -1
- package/dist/scaffold/app.js +1 -1
- package/dist/scaffold/app.js.map +1 -1
- package/dist/scaffold/infra.d.ts.map +1 -1
- package/dist/scaffold/infra.js +8 -2
- package/dist/scaffold/infra.js.map +1 -1
- package/dist/scaffold/manifest.d.ts +6 -0
- package/dist/scaffold/manifest.d.ts.map +1 -1
- package/dist/scaffold/manifest.js +1 -0
- package/dist/scaffold/manifest.js.map +1 -1
- package/dist/scaffold/pages-heuristics.d.ts +17 -0
- package/dist/scaffold/pages-heuristics.d.ts.map +1 -0
- package/dist/scaffold/pages-heuristics.js +344 -0
- package/dist/scaffold/pages-heuristics.js.map +1 -0
- package/dist/scaffold/pages-mode.d.ts +10 -0
- package/dist/scaffold/pages-mode.d.ts.map +1 -0
- package/dist/scaffold/pages-mode.js +109 -0
- package/dist/scaffold/pages-mode.js.map +1 -0
- package/dist/scaffold/surfaces.d.ts.map +1 -1
- package/dist/scaffold/surfaces.js +12 -1
- package/dist/scaffold/surfaces.js.map +1 -1
- package/dist/utils/cloudflare-api.d.ts +19 -0
- package/dist/utils/cloudflare-api.d.ts.map +1 -1
- package/dist/utils/cloudflare-api.js +16 -0
- package/dist/utils/cloudflare-api.js.map +1 -1
- package/dist/utils/coolify-api.d.ts +20 -0
- package/dist/utils/coolify-api.d.ts.map +1 -1
- package/dist/utils/coolify-api.js +51 -0
- package/dist/utils/coolify-api.js.map +1 -1
- package/dist/utils/coolify-server-ips.d.ts +6 -12
- package/dist/utils/coolify-server-ips.d.ts.map +1 -1
- package/dist/utils/coolify-server-ips.js +26 -81
- package/dist/utils/coolify-server-ips.js.map +1 -1
- package/dist/utils/run-ledger.d.ts +20 -0
- package/dist/utils/run-ledger.d.ts.map +1 -1
- package/dist/utils/run-ledger.js.map +1 -1
- package/package.json +1 -1
package/dist/deploy/keys.js
CHANGED
|
@@ -178,8 +178,13 @@ export async function rotateProjectKey(projectName, opts = {}) {
|
|
|
178
178
|
return { envProductionPath, envKeysPath, rotated: true, set, pushedCoolify, pushedGh };
|
|
179
179
|
}
|
|
180
180
|
/** Push DOTENV_PRIVATE_KEY_PRODUCTION onto a Coolify application.
|
|
181
|
-
* Resolves the application by name
|
|
182
|
-
*
|
|
181
|
+
* Resolves the application by name. When `appName` is omitted, walks
|
|
182
|
+
* the same candidate list `findCoolifyAppsForProject` understands so
|
|
183
|
+
* the key push works across every layout hatchkit can produce —
|
|
184
|
+
* the bare project name `<project>` (current convention from both
|
|
185
|
+
* `create` and `adopt`), the legacy `<project>-web` suffix, and the
|
|
186
|
+
* `<project>-server`/`-client` shape from the (currently unused)
|
|
187
|
+
* starter-split layout. */
|
|
183
188
|
export async function pushProjectKeyToCoolify(projectName, options = {}) {
|
|
184
189
|
const key = await getSecret(SECRET_KEYS.dotenvxPrivateKey(projectName));
|
|
185
190
|
if (!key) {
|
|
@@ -190,16 +195,31 @@ export async function pushProjectKeyToCoolify(projectName, options = {}) {
|
|
|
190
195
|
throw new Error("Coolify is not configured. Run `hatchkit config add coolify` first.");
|
|
191
196
|
}
|
|
192
197
|
const api = new CoolifyApi({ url: coolify.url, token: coolify.token });
|
|
193
|
-
|
|
194
|
-
|
|
198
|
+
// Candidates in priority order: caller-supplied appName wins; then
|
|
199
|
+
// the bare project name (current `create`/`adopt` output); then the
|
|
200
|
+
// legacy `-web` suffix; then the starter-split shape for projects
|
|
201
|
+
// that landed in that layout. The dotenvx key only lives on the
|
|
202
|
+
// server-side app, so `-server` outranks `-client`.
|
|
203
|
+
const candidates = options.appName
|
|
204
|
+
? [options.appName]
|
|
205
|
+
: [projectName, `${projectName}-web`, `${projectName}-server`, `${projectName}-client`];
|
|
206
|
+
const spinner = ora(`Resolving Coolify app for "${projectName}"`).start();
|
|
207
|
+
let appName;
|
|
195
208
|
let uuid;
|
|
196
209
|
try {
|
|
197
210
|
const apps = await api.listApplications();
|
|
198
|
-
const match =
|
|
211
|
+
const match = candidates
|
|
212
|
+
.map((name) => {
|
|
213
|
+
const app = apps.find((a) => a.name === name);
|
|
214
|
+
return app ? { name, uuid: app.uuid } : undefined;
|
|
215
|
+
})
|
|
216
|
+
.find((m) => m !== undefined);
|
|
199
217
|
if (!match) {
|
|
200
|
-
|
|
201
|
-
|
|
218
|
+
const tried = candidates.join(", ");
|
|
219
|
+
spinner.fail(`No Coolify application found for project "${projectName}" (tried: ${tried}). Run \`hatchkit create\` with runDeployment first.`);
|
|
220
|
+
throw new Error(`Coolify app not found for project: ${projectName}`);
|
|
202
221
|
}
|
|
222
|
+
appName = match.name;
|
|
203
223
|
uuid = match.uuid;
|
|
204
224
|
spinner.succeed(`Found app ${appName} (${uuid})`);
|
|
205
225
|
}
|
package/dist/deploy/keys.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/deploy/keys.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/deploy/keys.ts"],"names":[],"mappings":"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"}
|
package/dist/deploy/pages.d.ts
CHANGED
|
@@ -1,2 +1,43 @@
|
|
|
1
|
+
/** What kind of site lives in a folder — determines the build workflow. */
|
|
2
|
+
export type SiteKind = "static" | "node-build" | "docusaurus" | "jekyll";
|
|
3
|
+
export interface Detected {
|
|
4
|
+
kind: SiteKind;
|
|
5
|
+
/** Folder uploaded to Pages. Relative to repo root. */
|
|
6
|
+
publishDir: string;
|
|
7
|
+
/** Package manager for node-build sites. */
|
|
8
|
+
packageManager?: "pnpm" | "npm" | "yarn" | "bun";
|
|
9
|
+
/** npm script name used for the build (usually "build"). */
|
|
10
|
+
buildScript?: string;
|
|
11
|
+
/** Working directory for the build. Empty string = repo root. */
|
|
12
|
+
workDir: string;
|
|
13
|
+
}
|
|
1
14
|
export declare function runPagesSetup(cwd: string): Promise<void>;
|
|
15
|
+
/** Programmatic entrypoint for the create/adopt flows.
|
|
16
|
+
*
|
|
17
|
+
* Takes already-resolved values (detected site shape, optional
|
|
18
|
+
* custom domain) and runs the same enable / workflow / DNS / cert
|
|
19
|
+
* pipeline as the interactive flow. Skips the pickSite + promptDomain
|
|
20
|
+
* steps so it's safe to call from within a larger non-interactive
|
|
21
|
+
* scaffold.
|
|
22
|
+
*
|
|
23
|
+
* Returns the public URL the site will be served from so callers
|
|
24
|
+
* can include it in their summary. */
|
|
25
|
+
export declare function runPagesSetupProgrammatic(cwd: string, opts: {
|
|
26
|
+
detected: Detected;
|
|
27
|
+
domain: string | null;
|
|
28
|
+
}): Promise<{
|
|
29
|
+
pageUrl: string;
|
|
30
|
+
}>;
|
|
31
|
+
interface UndoOptions {
|
|
32
|
+
dryRun: boolean;
|
|
33
|
+
yes: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Reverse what `hatchkit gh-pages` did: disables Pages, deletes the
|
|
37
|
+
* Cloudflare records it created, removes the workflow file, removes any
|
|
38
|
+
* CNAME files matching the registered domain. Idempotent — safe to run
|
|
39
|
+
* even if some pieces are already gone.
|
|
40
|
+
*/
|
|
41
|
+
export declare function runPagesUndo(cwd: string, opts: UndoOptions): Promise<void>;
|
|
42
|
+
export {};
|
|
2
43
|
//# sourceMappingURL=pages.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../src/deploy/pages.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../src/deploy/pages.ts"],"names":[],"mappings":"AAuBA,2EAA2E;AAC3E,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,YAAY,GAAG,YAAY,GAAG,QAAQ,CAAC;AAEzE,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,QAAQ,CAAC;IACf,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;IACjD,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;CACjB;AA4BD,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB9D;AAED;;;;;;;;;uCASuC;AACvC,wBAAsB,yBAAyB,CAC7C,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAClD,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAS9B;AAuzBD,UAAU,WAAW;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,EAAE,OAAO,CAAC;CACd;AAgBD;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA0ChF"}
|
package/dist/deploy/pages.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolve4 } from "node:dns/promises";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
2
3
|
import { join } from "node:path";
|
|
4
|
+
import { setTimeout as sleep } from "node:timers/promises";
|
|
3
5
|
import { confirm, input, select } from "@inquirer/prompts";
|
|
4
6
|
import chalk from "chalk";
|
|
7
|
+
import ora from "ora";
|
|
5
8
|
import { ensureDns, getDnsConfig } from "../config.js";
|
|
6
9
|
import { CloudflareApi } from "../utils/cloudflare-api.js";
|
|
7
10
|
import { exec } from "../utils/exec.js";
|
|
@@ -18,16 +21,47 @@ export async function runPagesSetup(cwd) {
|
|
|
18
21
|
console.log(chalk.bold("\n ── hatchkit gh-pages ──────────────────────────────────────\n"));
|
|
19
22
|
// 1. Repo — must be a git repo with an `origin` pointing at GitHub.
|
|
20
23
|
const repo = await detectRepo(cwd);
|
|
21
|
-
|
|
22
|
-
if (repo.private) {
|
|
23
|
-
console.log(chalk.yellow(" ⚠ Private repos need a paid GitHub plan (Pro/Team/Enterprise) for Pages.\n Continuing anyway — will fail at API call if unsupported."));
|
|
24
|
-
}
|
|
24
|
+
printRepoHeader(repo);
|
|
25
25
|
// 2. Pick a site. Auto-confirm when there's one obvious candidate;
|
|
26
26
|
// ask when zero or many. Also let the user override the detected
|
|
27
27
|
// publish folder before we commit to writing anything.
|
|
28
28
|
const confirmed = await pickSite(cwd);
|
|
29
29
|
// 3. Custom domain (optional).
|
|
30
30
|
const domain = await promptDomain();
|
|
31
|
+
await executePagesSetup(cwd, repo, confirmed, domain);
|
|
32
|
+
}
|
|
33
|
+
/** Programmatic entrypoint for the create/adopt flows.
|
|
34
|
+
*
|
|
35
|
+
* Takes already-resolved values (detected site shape, optional
|
|
36
|
+
* custom domain) and runs the same enable / workflow / DNS / cert
|
|
37
|
+
* pipeline as the interactive flow. Skips the pickSite + promptDomain
|
|
38
|
+
* steps so it's safe to call from within a larger non-interactive
|
|
39
|
+
* scaffold.
|
|
40
|
+
*
|
|
41
|
+
* Returns the public URL the site will be served from so callers
|
|
42
|
+
* can include it in their summary. */
|
|
43
|
+
export async function runPagesSetupProgrammatic(cwd, opts) {
|
|
44
|
+
const repo = await detectRepo(cwd);
|
|
45
|
+
printRepoHeader(repo);
|
|
46
|
+
await executePagesSetup(cwd, repo, opts.detected, opts.domain);
|
|
47
|
+
return {
|
|
48
|
+
pageUrl: opts.domain
|
|
49
|
+
? `https://${opts.domain}`
|
|
50
|
+
: `https://${repo.owner}.github.io/${repo.repo}/`,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function printRepoHeader(repo) {
|
|
54
|
+
console.log(chalk.dim(` Repo: ${repo.fullName} (${repo.private ? "private" : "public"})`));
|
|
55
|
+
if (repo.private) {
|
|
56
|
+
console.log(chalk.yellow(" ⚠ Private repos need a paid GitHub plan (Pro/Team/Enterprise) for Pages.\n Continuing anyway — will fail at API call if unsupported."));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** The shared execution pipeline used by both the interactive
|
|
60
|
+
* `runPagesSetup` and the programmatic `runPagesSetupProgrammatic`.
|
|
61
|
+
* Everything from "we know what to deploy and where" onwards lives
|
|
62
|
+
* here — anything *before* that (site detection, domain prompt) is
|
|
63
|
+
* caller-specific. */
|
|
64
|
+
async function executePagesSetup(cwd, repo, confirmed, domain) {
|
|
31
65
|
// 4. Enable Pages via GitHub API.
|
|
32
66
|
await enablePages(repo);
|
|
33
67
|
// 5. Write the workflow — unless the repo already has a Pages-deploying
|
|
@@ -36,10 +70,23 @@ export async function runPagesSetup(cwd) {
|
|
|
36
70
|
// 6. CNAME file — only when a custom domain is chosen.
|
|
37
71
|
if (domain)
|
|
38
72
|
writeCnameFile(cwd, confirmed, domain);
|
|
39
|
-
// 7. Pages CNAME +
|
|
73
|
+
// 7. DNS + Pages CNAME + HTTPS.
|
|
74
|
+
//
|
|
75
|
+
// Order matters: GitHub validates the cname by resolving DNS the moment
|
|
76
|
+
// we PUT it. If DNS isn't in place yet, validation fails silently, cert
|
|
77
|
+
// provisioning is never kicked off, and GitHub doesn't retry. So:
|
|
78
|
+
// a. Wire DNS first.
|
|
79
|
+
// b. Wait for DNS to actually resolve (only when we wrote it ourselves).
|
|
80
|
+
// c. Then tell GitHub the cname — bouncing it first if a prior run
|
|
81
|
+
// left it stuck without a cert.
|
|
82
|
+
// d. Wait for the Let's Encrypt cert to be issued, then flip
|
|
83
|
+
// `https_enforced` so http:// redirects to https://.
|
|
40
84
|
if (domain) {
|
|
85
|
+
const { wired } = await configureDns(domain);
|
|
86
|
+
if (wired)
|
|
87
|
+
await waitForDnsResolves(domain);
|
|
41
88
|
await setPagesCname(repo, domain);
|
|
42
|
-
await
|
|
89
|
+
await provisionHttps(repo, wired);
|
|
43
90
|
}
|
|
44
91
|
printSummary(repo, confirmed, domain);
|
|
45
92
|
}
|
|
@@ -280,12 +327,121 @@ async function enablePages(repo) {
|
|
|
280
327
|
throw new Error(`Couldn't enable Pages: ${res.stderr.trim() || res.stdout.trim()}`);
|
|
281
328
|
}
|
|
282
329
|
async function setPagesCname(repo, domain) {
|
|
330
|
+
// If the cname is already correct but no cert exists, GitHub is stuck
|
|
331
|
+
// (most often because an earlier run set the cname before DNS was live,
|
|
332
|
+
// so the validation+cert flow ran against missing DNS and never retried).
|
|
333
|
+
// Bounce the cname — clear, then re-set — to force a fresh validation
|
|
334
|
+
// pass now that DNS is in place. Idempotent on the happy path: if a cert
|
|
335
|
+
// is already issued we skip the bounce entirely.
|
|
336
|
+
const current = await getPagesInfo(repo);
|
|
337
|
+
const stuck = current?.cname === domain && !current?.https_certificate;
|
|
338
|
+
if (stuck) {
|
|
339
|
+
await exec("gh", ["api", "-X", "PUT", `repos/${repo.fullName}/pages`, "-f", "cname="], {
|
|
340
|
+
silent: true,
|
|
341
|
+
spinner: "Resetting Pages CNAME to retry cert provisioning...",
|
|
342
|
+
});
|
|
343
|
+
await sleep(2000);
|
|
344
|
+
}
|
|
283
345
|
const res = await exec("gh", ["api", "-X", "PUT", `repos/${repo.fullName}/pages`, "-f", `cname=${domain}`], { silent: true, spinner: `Registering ${domain} with Pages...` });
|
|
284
346
|
if (res.exitCode !== 0) {
|
|
285
|
-
// Non-fatal: DNS might not be
|
|
347
|
+
// Non-fatal: DNS might still not be visible to GitHub yet.
|
|
286
348
|
console.log(chalk.yellow(` ⚠ Couldn't set Pages CNAME to ${domain} (${res.stderr.trim()}).\n Set it manually in Settings → Pages once DNS resolves.`));
|
|
287
349
|
}
|
|
288
350
|
}
|
|
351
|
+
async function getPagesInfo(repo) {
|
|
352
|
+
const res = await exec("gh", ["api", `repos/${repo.fullName}/pages`], { silent: true });
|
|
353
|
+
if (res.exitCode !== 0)
|
|
354
|
+
return null;
|
|
355
|
+
try {
|
|
356
|
+
return JSON.parse(res.stdout);
|
|
357
|
+
}
|
|
358
|
+
catch {
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
// ---------------------------------------------------------------------------
|
|
363
|
+
// HTTPS provisioning
|
|
364
|
+
// ---------------------------------------------------------------------------
|
|
365
|
+
/**
|
|
366
|
+
* Wait for `domain` to resolve to one of GitHub's Pages IPs. Important when
|
|
367
|
+
* we just wrote DNS records via API — GitHub validates the cname by hitting
|
|
368
|
+
* authoritative DNS, and Cloudflare propagation is usually a few seconds
|
|
369
|
+
* but can briefly lag. Bounded wait; on timeout we proceed anyway.
|
|
370
|
+
*/
|
|
371
|
+
async function waitForDnsResolves(domain, timeoutMs = 60_000) {
|
|
372
|
+
const githubIps = new Set(GITHUB_APEX_A);
|
|
373
|
+
const spinner = ora(`Waiting for DNS for ${domain} to resolve to GitHub...`).start();
|
|
374
|
+
const start = Date.now();
|
|
375
|
+
while (Date.now() - start < timeoutMs) {
|
|
376
|
+
try {
|
|
377
|
+
const ips = await resolve4(domain);
|
|
378
|
+
if (ips.some((ip) => githubIps.has(ip))) {
|
|
379
|
+
spinner.succeed(`DNS resolves: ${domain} → ${ips[0]}`);
|
|
380
|
+
return true;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
catch {
|
|
384
|
+
// ENOTFOUND / SERVFAIL — keep polling.
|
|
385
|
+
}
|
|
386
|
+
await sleep(3000);
|
|
387
|
+
}
|
|
388
|
+
spinner.warn(`DNS for ${domain} hasn't propagated yet — continuing anyway`);
|
|
389
|
+
return false;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Drive GitHub's HTTPS state machine to completion: poll until the Let's
|
|
393
|
+
* Encrypt cert is `issued`, then flip `https_enforced=true` so http://
|
|
394
|
+
* redirects to https://. Pre-existing fully-configured sites short-circuit
|
|
395
|
+
* on the first poll.
|
|
396
|
+
*
|
|
397
|
+
* If the user added DNS records manually we don't know when they'll land,
|
|
398
|
+
* so we skip the wait and print the finishing commands instead of blocking
|
|
399
|
+
* the CLI for what could be hours.
|
|
400
|
+
*/
|
|
401
|
+
async function provisionHttps(repo, autoDns) {
|
|
402
|
+
if (!autoDns) {
|
|
403
|
+
console.log(chalk.dim(`\n Once your DNS records resolve, GitHub will provision an HTTPS cert (usually <5 min).`));
|
|
404
|
+
console.log(chalk.dim(` Check: gh api repos/${repo.fullName}/pages | jq .https_certificate`));
|
|
405
|
+
console.log(chalk.dim(` Enforce: gh api -X PUT repos/${repo.fullName}/pages -F https_enforced=true`));
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
const issued = await waitForCertIssued(repo);
|
|
409
|
+
if (!issued) {
|
|
410
|
+
console.log(chalk.yellow(`\n ⚠ HTTPS cert wasn't issued within the wait window — leaving https_enforced off.`));
|
|
411
|
+
console.log(chalk.dim(` Check: gh api repos/${repo.fullName}/pages | jq .https_certificate`));
|
|
412
|
+
console.log(chalk.dim(` Enforce: gh api -X PUT repos/${repo.fullName}/pages -F https_enforced=true`));
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
const info = await getPagesInfo(repo);
|
|
416
|
+
if (info?.https_enforced) {
|
|
417
|
+
console.log(chalk.dim(" HTTPS already enforced."));
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
const res = await exec("gh", ["api", "-X", "PUT", `repos/${repo.fullName}/pages`, "-F", "https_enforced=true"], { silent: true, spinner: "Enabling Enforce HTTPS..." });
|
|
421
|
+
if (res.exitCode !== 0) {
|
|
422
|
+
console.log(chalk.yellow(` ⚠ Couldn't enable HTTPS enforcement: ${res.stderr.trim() || res.stdout.trim()}`));
|
|
423
|
+
console.log(chalk.dim(` Run later: gh api -X PUT repos/${repo.fullName}/pages -F https_enforced=true`));
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
async function waitForCertIssued(repo, timeoutMs = 5 * 60_000) {
|
|
427
|
+
const spinner = ora("Waiting for GitHub to provision the HTTPS certificate...").start();
|
|
428
|
+
const start = Date.now();
|
|
429
|
+
let lastState = "pending";
|
|
430
|
+
while (Date.now() - start < timeoutMs) {
|
|
431
|
+
const info = await getPagesInfo(repo);
|
|
432
|
+
const state = info?.https_certificate?.state;
|
|
433
|
+
if (state)
|
|
434
|
+
lastState = state;
|
|
435
|
+
if (state === "issued" || state === "approved") {
|
|
436
|
+
spinner.succeed(`HTTPS certificate ${state}`);
|
|
437
|
+
return true;
|
|
438
|
+
}
|
|
439
|
+
spinner.text = `Waiting for HTTPS certificate (state: ${lastState})...`;
|
|
440
|
+
await sleep(15_000);
|
|
441
|
+
}
|
|
442
|
+
spinner.warn(`HTTPS cert not ready after ${Math.round(timeoutMs / 1000)}s (last: ${lastState})`);
|
|
443
|
+
return false;
|
|
444
|
+
}
|
|
289
445
|
// ---------------------------------------------------------------------------
|
|
290
446
|
// Workflow + CNAME file
|
|
291
447
|
// ---------------------------------------------------------------------------
|
|
@@ -474,20 +630,20 @@ async function configureDns(domain) {
|
|
|
474
630
|
}
|
|
475
631
|
if (!dns || dns.provider === "manual") {
|
|
476
632
|
printManualDnsRecords(baseDomain, subdomain, target, isApex);
|
|
477
|
-
return;
|
|
633
|
+
return { wired: false };
|
|
478
634
|
}
|
|
479
635
|
if (dns.provider === "cloudflare") {
|
|
480
636
|
if (!dns.apiToken) {
|
|
481
637
|
console.log(chalk.yellow(" ⚠ Cloudflare token missing from keychain."));
|
|
482
638
|
printManualDnsRecords(baseDomain, subdomain, target, isApex);
|
|
483
|
-
return;
|
|
639
|
+
return { wired: false };
|
|
484
640
|
}
|
|
485
|
-
|
|
486
|
-
return;
|
|
641
|
+
return configureCloudflareDns(dns.apiToken, baseDomain, subdomain, target, isApex);
|
|
487
642
|
}
|
|
488
643
|
// INWX auto-wiring isn't implemented — XML-RPC + rarely used for Pages.
|
|
489
644
|
console.log(chalk.dim(" INWX auto-configure isn't implemented for Pages — showing manual records:"));
|
|
490
645
|
printManualDnsRecords(baseDomain, subdomain, target, isApex);
|
|
646
|
+
return { wired: false };
|
|
491
647
|
}
|
|
492
648
|
async function getGitHubUser() {
|
|
493
649
|
const res = await exec("gh", ["api", "user", "--jq", ".login"], { silent: true });
|
|
@@ -514,7 +670,7 @@ async function configureCloudflareDns(token, baseDomain, subdomain, target, isAp
|
|
|
514
670
|
if (!zone) {
|
|
515
671
|
console.log(chalk.yellow(` ⚠ No Cloudflare zone found for ${baseDomain}. Falling back to manual records.`));
|
|
516
672
|
printManualDnsRecords(baseDomain, subdomain, target, isApex);
|
|
517
|
-
return;
|
|
673
|
+
return { wired: false };
|
|
518
674
|
}
|
|
519
675
|
const recordName = isApex ? baseDomain : `${subdomain}.${baseDomain}`;
|
|
520
676
|
// GitHub Pages apex needs A records for all four IPs (round-robin
|
|
@@ -535,6 +691,7 @@ async function configureCloudflareDns(token, baseDomain, subdomain, target, isAp
|
|
|
535
691
|
const line = ` ${rec.type} ${recordName} → ${rec.content} (${status})`;
|
|
536
692
|
console.log(result.created || result.updated ? chalk.green(`✓ ${line.trimStart()}`) : chalk.dim(line));
|
|
537
693
|
}
|
|
694
|
+
return { wired: true };
|
|
538
695
|
}
|
|
539
696
|
// ---------------------------------------------------------------------------
|
|
540
697
|
// Summary
|
|
@@ -554,4 +711,194 @@ function printSummary(repo, d, domain) {
|
|
|
554
711
|
}
|
|
555
712
|
console.log(chalk.yellow(`\n Next: commit & push the new workflow (and CNAME file) to ${repo.defaultBranch}.\n`));
|
|
556
713
|
}
|
|
714
|
+
/**
|
|
715
|
+
* Reverse what `hatchkit gh-pages` did: disables Pages, deletes the
|
|
716
|
+
* Cloudflare records it created, removes the workflow file, removes any
|
|
717
|
+
* CNAME files matching the registered domain. Idempotent — safe to run
|
|
718
|
+
* even if some pieces are already gone.
|
|
719
|
+
*/
|
|
720
|
+
export async function runPagesUndo(cwd, opts) {
|
|
721
|
+
console.log(chalk.bold("\n ── hatchkit gh-pages --undo ───────────────────────────────\n"));
|
|
722
|
+
const repo = await detectRepo(cwd);
|
|
723
|
+
console.log(chalk.dim(` Repo: ${repo.fullName}`));
|
|
724
|
+
const plan = await buildUndoPlan(cwd, repo);
|
|
725
|
+
if (!isAnythingToUndo(plan)) {
|
|
726
|
+
console.log(chalk.dim("\n Nothing to undo — no Pages config, workflow, or CNAME files found.\n"));
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
printUndoPlan(plan);
|
|
730
|
+
if (opts.dryRun) {
|
|
731
|
+
console.log(chalk.dim("\n --dry-run set, nothing changed.\n"));
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
734
|
+
if (!opts.yes) {
|
|
735
|
+
const ok = await confirm({
|
|
736
|
+
message: "Proceed with the steps above?",
|
|
737
|
+
default: false,
|
|
738
|
+
});
|
|
739
|
+
if (!ok) {
|
|
740
|
+
console.log(chalk.dim("\n Aborted — nothing changed.\n"));
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
await executeUndo(repo, plan);
|
|
745
|
+
console.log(chalk.bold("\n ── Done ───────────────────────────────────────────────────\n"));
|
|
746
|
+
if (plan.cname) {
|
|
747
|
+
console.log(chalk.dim(` DNS at other providers (registrar caches, AAAA records, etc.) may need manual cleanup.\n`));
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
async function buildUndoPlan(cwd, repo) {
|
|
751
|
+
const info = await getPagesInfo(repo);
|
|
752
|
+
const cname = info?.cname ?? null;
|
|
753
|
+
// Workflow: only the one we write. Hand-written Pages workflows
|
|
754
|
+
// (e.g. docs.yml) belong to the user — don't touch them.
|
|
755
|
+
const wfPath = join(cwd, ".github", "workflows", WORKFLOW_FILENAME);
|
|
756
|
+
const workflowPath = existsSync(wfPath) ? wfPath : null;
|
|
757
|
+
// CNAME files: scan the spots `writeCnameFile` could have written.
|
|
758
|
+
// Only flag files whose content matches the registered cname so we
|
|
759
|
+
// never delete a CNAME the user wrote for some other purpose.
|
|
760
|
+
const cnamePaths = cname ? findCnameFiles(cwd, cname) : [];
|
|
761
|
+
// Cloudflare records: present only if a cname was registered AND
|
|
762
|
+
// we have a Cloudflare token AND the zone is in this account.
|
|
763
|
+
const cloudflare = { available: false, records: [] };
|
|
764
|
+
if (cname) {
|
|
765
|
+
const dns = await getDnsConfig();
|
|
766
|
+
if (dns?.provider === "cloudflare" && dns.apiToken) {
|
|
767
|
+
const { baseDomain, subdomain } = parseDomain(cname);
|
|
768
|
+
const recordName = subdomain === "" ? baseDomain : `${subdomain}.${baseDomain}`;
|
|
769
|
+
const api = new CloudflareApi({ token: dns.apiToken });
|
|
770
|
+
const zone = await api.getZoneByName(baseDomain);
|
|
771
|
+
if (zone) {
|
|
772
|
+
const ghUser = await getGitHubUser().catch(() => "");
|
|
773
|
+
const target = ghUser ? `${ghUser}.github.io` : "";
|
|
774
|
+
const all = await api.findRecordsByName(zone.id, recordName);
|
|
775
|
+
// Only delete records that match what hatchkit could plausibly
|
|
776
|
+
// have written: A records pointing at GitHub's Pages IPs, or a
|
|
777
|
+
// CNAME pointing at <user>.github.io. Anything else stays.
|
|
778
|
+
const records = all.filter((r) => (r.type === "A" && GITHUB_APEX_A.includes(r.content)) ||
|
|
779
|
+
(r.type === "CNAME" && target && r.content === target));
|
|
780
|
+
cloudflare.available = true;
|
|
781
|
+
cloudflare.zoneId = zone.id;
|
|
782
|
+
cloudflare.baseDomain = baseDomain;
|
|
783
|
+
cloudflare.records = records.map((r) => ({
|
|
784
|
+
id: r.id,
|
|
785
|
+
type: r.type,
|
|
786
|
+
name: r.name,
|
|
787
|
+
content: r.content,
|
|
788
|
+
}));
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
return {
|
|
793
|
+
pagesEnabled: info !== null,
|
|
794
|
+
cname,
|
|
795
|
+
workflowPath,
|
|
796
|
+
cnamePaths,
|
|
797
|
+
cloudflare,
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
function isAnythingToUndo(plan) {
|
|
801
|
+
return (plan.pagesEnabled ||
|
|
802
|
+
plan.workflowPath !== null ||
|
|
803
|
+
plan.cnamePaths.length > 0 ||
|
|
804
|
+
plan.cloudflare.records.length > 0);
|
|
805
|
+
}
|
|
806
|
+
function printUndoPlan(plan) {
|
|
807
|
+
console.log(chalk.bold("\n Will undo:\n"));
|
|
808
|
+
if (plan.pagesEnabled) {
|
|
809
|
+
const suffix = plan.cname ? ` (cname: ${plan.cname})` : "";
|
|
810
|
+
console.log(chalk.yellow(` • Disable GitHub Pages${suffix}`));
|
|
811
|
+
}
|
|
812
|
+
for (const rec of plan.cloudflare.records) {
|
|
813
|
+
console.log(chalk.yellow(` • Delete Cloudflare ${rec.type} ${rec.name} → ${rec.content}`));
|
|
814
|
+
}
|
|
815
|
+
if (plan.workflowPath) {
|
|
816
|
+
console.log(chalk.yellow(` • Delete ${relPath(plan.workflowPath)}`));
|
|
817
|
+
}
|
|
818
|
+
for (const p of plan.cnamePaths) {
|
|
819
|
+
console.log(chalk.yellow(` • Delete ${relPath(p)}`));
|
|
820
|
+
}
|
|
821
|
+
if (plan.cname && !plan.cloudflare.available) {
|
|
822
|
+
console.log(chalk.dim(`\n (Cloudflare records for ${plan.cname} can't be auto-deleted — no token / zone not in this account.\n Remove them manually at your DNS provider.)`));
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
async function executeUndo(repo, plan) {
|
|
826
|
+
if (plan.pagesEnabled) {
|
|
827
|
+
const res = await exec("gh", ["api", "-X", "DELETE", `repos/${repo.fullName}/pages`], {
|
|
828
|
+
silent: true,
|
|
829
|
+
spinner: "Disabling GitHub Pages...",
|
|
830
|
+
});
|
|
831
|
+
if (res.exitCode !== 0) {
|
|
832
|
+
console.log(chalk.yellow(` ⚠ Couldn't disable Pages: ${res.stderr.trim() || res.stdout.trim()}`));
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
if (plan.cloudflare.records.length > 0 && plan.cloudflare.zoneId) {
|
|
836
|
+
const dns = await getDnsConfig();
|
|
837
|
+
if (dns?.provider === "cloudflare" && dns.apiToken) {
|
|
838
|
+
const api = new CloudflareApi({ token: dns.apiToken });
|
|
839
|
+
for (const rec of plan.cloudflare.records) {
|
|
840
|
+
const result = await api.deleteRecord(plan.cloudflare.zoneId, rec.id);
|
|
841
|
+
const tag = result === "deleted" ? chalk.green("✓") : chalk.dim("—");
|
|
842
|
+
console.log(` ${tag} Cloudflare ${rec.type} ${rec.name} → ${rec.content} (${result})`);
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
if (plan.workflowPath) {
|
|
847
|
+
try {
|
|
848
|
+
unlinkSync(plan.workflowPath);
|
|
849
|
+
console.log(chalk.green(` ✓ Removed ${relPath(plan.workflowPath)}`));
|
|
850
|
+
}
|
|
851
|
+
catch (err) {
|
|
852
|
+
console.log(chalk.yellow(` ⚠ Couldn't remove ${relPath(plan.workflowPath)}: ${err.message}`));
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
for (const p of plan.cnamePaths) {
|
|
856
|
+
try {
|
|
857
|
+
unlinkSync(p);
|
|
858
|
+
console.log(chalk.green(` ✓ Removed ${relPath(p)}`));
|
|
859
|
+
}
|
|
860
|
+
catch (err) {
|
|
861
|
+
console.log(chalk.yellow(` ⚠ Couldn't remove ${relPath(p)}: ${err.message}`));
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
/**
|
|
866
|
+
* Look for `CNAME` files in the places `writeCnameFile` could have put
|
|
867
|
+
* one, in the current working dir and each candidate scan dir. Only
|
|
868
|
+
* returns files whose content matches `expected` (trimmed, case-insensitive)
|
|
869
|
+
* so we never delete an unrelated CNAME file.
|
|
870
|
+
*/
|
|
871
|
+
function findCnameFiles(cwd, expected) {
|
|
872
|
+
const target = expected.trim().toLowerCase();
|
|
873
|
+
const out = [];
|
|
874
|
+
const seen = new Set();
|
|
875
|
+
const bases = ["", ...SCAN_DIRS.filter((d) => d !== "")];
|
|
876
|
+
for (const base of bases) {
|
|
877
|
+
const baseAbs = base ? join(cwd, base) : cwd;
|
|
878
|
+
if (base && !existsSync(baseAbs))
|
|
879
|
+
continue;
|
|
880
|
+
for (const sub of ["", "public", "static"]) {
|
|
881
|
+
const subAbs = sub ? join(baseAbs, sub) : baseAbs;
|
|
882
|
+
const candidate = join(subAbs, "CNAME");
|
|
883
|
+
if (seen.has(candidate))
|
|
884
|
+
continue;
|
|
885
|
+
seen.add(candidate);
|
|
886
|
+
if (!existsSync(candidate))
|
|
887
|
+
continue;
|
|
888
|
+
try {
|
|
889
|
+
const content = readFileSync(candidate, "utf8").trim().toLowerCase();
|
|
890
|
+
if (content === target)
|
|
891
|
+
out.push(candidate);
|
|
892
|
+
}
|
|
893
|
+
catch {
|
|
894
|
+
// unreadable — skip
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
return out;
|
|
899
|
+
}
|
|
900
|
+
function relPath(p) {
|
|
901
|
+
const cwd = process.cwd();
|
|
902
|
+
return p.startsWith(cwd) ? p.slice(cwd.length + 1) : p;
|
|
903
|
+
}
|
|
557
904
|
//# sourceMappingURL=pages.js.map
|