hatchkit 0.1.8 → 0.1.10

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.
@@ -24,6 +24,7 @@
24
24
  * provider whose record CRUD is wired up today). INWX users get
25
25
  * a clear "add an A record yourself" hint.
26
26
  */
27
+ import { resolve4, resolve6 } from "node:dns/promises";
27
28
  import chalk from "chalk";
28
29
  import ora from "ora";
29
30
  import { getCoolifyConfig, getDnsConfig } from "../config.js";
@@ -100,34 +101,48 @@ export async function wireProjectIntoCoolify(input) {
100
101
  });
101
102
  }
102
103
  }
103
- // ── 4. Create the app. ─────────────────────────────────────────────
104
- const baseInput = {
105
- projectUuid,
106
- serverUuid: resolveServer.uuid,
107
- gitRepository: input.gitRepository,
108
- gitBranch: input.gitBranch ?? "main",
109
- portsExposes: input.portsExposes ?? "3000",
110
- buildPack: input.buildPack ?? "nixpacks",
111
- name: input.projectName,
112
- description: "Adopted by hatchkit",
113
- domains: [`https://${input.domain}`],
114
- instantDeploy: false,
115
- };
116
- const createApp = ora(`Coolify: creating app for ${input.gitRepository}`).start();
104
+ // ── 4. Create the app — or reuse an existing one with the same
105
+ // name. Coolify doesn't enforce name uniqueness, but creating
106
+ // a duplicate on every `--resume` is loud and confusing. ───
117
107
  let appUuid;
118
- try {
119
- const res = input.isPrivate
120
- ? await api.createApplicationFromPrivateGithubApp({
121
- ...baseInput,
122
- githubAppUuid: githubAppUuid,
123
- })
124
- : await api.createApplicationFromPublicRepo(baseInput);
125
- appUuid = res.uuid;
126
- createApp.succeed(`Coolify app created (uuid: ${appUuid})`);
108
+ const existingApp = await api.findApplicationByName(input.projectName);
109
+ if (existingApp) {
110
+ console.log(chalk.dim(` · Coolify app "${input.projectName}" already exists (${existingApp.uuid}) — skipping create, will update env + DNS.`));
111
+ appUuid = existingApp.uuid;
127
112
  }
128
- catch (err) {
129
- createApp.fail();
130
- throw err;
113
+ else {
114
+ const baseInput = {
115
+ projectUuid,
116
+ serverUuid: resolveServer.uuid,
117
+ gitRepository: input.gitRepository,
118
+ gitBranch: input.gitBranch ?? "main",
119
+ portsExposes: input.portsExposes ?? "3000",
120
+ // hatchkit's canonical pipeline = GitHub Actions builds image →
121
+ // pushes to GHCR → Coolify pulls via docker-compose.yml. Caller
122
+ // can still override (e.g. for legacy nixpacks paths) but
123
+ // `dockercompose` is the default for any project that's gone
124
+ // through `hatchkit adopt`'s build-pipeline scaffold.
125
+ buildPack: input.buildPack ?? "dockercompose",
126
+ name: input.projectName,
127
+ description: "Adopted by hatchkit",
128
+ domains: [`https://${input.domain}`],
129
+ instantDeploy: false,
130
+ };
131
+ const createApp = ora(`Coolify: creating app for ${input.gitRepository}`).start();
132
+ try {
133
+ const res = input.isPrivate
134
+ ? await api.createApplicationFromPrivateGithubApp({
135
+ ...baseInput,
136
+ githubAppUuid: githubAppUuid,
137
+ })
138
+ : await api.createApplicationFromPublicRepo(baseInput);
139
+ appUuid = res.uuid;
140
+ createApp.succeed(`Coolify app created (uuid: ${appUuid})`);
141
+ }
142
+ catch (err) {
143
+ createApp.fail();
144
+ throw err;
145
+ }
131
146
  }
132
147
  // ── 5. Set the bare-minimum env vars on the app: the dotenvx
133
148
  // private key (so prod can decrypt .env.production) and
@@ -151,8 +166,22 @@ export async function wireProjectIntoCoolify(input) {
151
166
  console.log(chalk.yellow(" No dotenvx private key in the keychain — skipping env push.\n" +
152
167
  " Run `hatchkit keys push <project>` once one's available."));
153
168
  }
154
- // ── 6. DNS (Cloudflare only for now). ──────────────────────────────
155
- const dnsResult = await wireDns(input.domain, server.ip);
169
+ // ── 6. DNS — discover the box's public IP(s) and upsert records.
170
+ //
171
+ // Discovery order:
172
+ // 1. Coolify's `/servers/{uuid}/domains` exposes the configured
173
+ // `public_ipv4` and `public_ipv6` for localhost-Coolify
174
+ // installs (where /servers reports "host.docker.internal").
175
+ // 2. Independently resolve the Coolify dashboard URL's hostname
176
+ // via dns.resolve4 + dns.resolve6 — that hostname IS public
177
+ // (we're talking to it from the internet) so its A / AAAA
178
+ // records are by definition the right pointers for new app
179
+ // domains too.
180
+ // We use Coolify's value as primary, fall back to DNS resolution,
181
+ // and surface a warning when the two disagree (catches stale or
182
+ // misconfigured public_ipv4 / proxy setups).
183
+ const ips = await discoverPublicIps(api, resolveServer.uuid, server.ip, cfg.url);
184
+ const dnsResult = await wireDns(input.domain, ips);
156
185
  // ── 7. Trigger first deploy. ───────────────────────────────────────
157
186
  const deploy = ora("Coolify: triggering first deploy").start();
158
187
  try {
@@ -167,23 +196,138 @@ export async function wireProjectIntoCoolify(input) {
167
196
  appUuid,
168
197
  projectUuid,
169
198
  serverUuid: resolveServer.uuid,
170
- serverIp: server.ip,
171
- dnsRecordId: dnsResult.recordId,
199
+ serverIpv4: ips.v4,
200
+ serverIpv6: ips.v6,
201
+ ipMismatchWarning: ips.mismatchWarning,
202
+ dnsRecordId: dnsResult.recordIdV4,
203
+ dnsRecordIdV6: dnsResult.recordIdV6,
172
204
  dnsManaged: dnsResult.managed,
173
205
  };
174
206
  }
175
- async function wireDns(domain, serverIp) {
207
+ /** True for valid public-routable IPv4 strings. Filters out the
208
+ * values Coolify hands back on Docker installs (`host.docker.internal`,
209
+ * `localhost`, `127.0.0.1`) plus IPv6, which we don't auto-manage. */
210
+ function isPublicIpv4(s) {
211
+ if (!/^\d{1,3}(\.\d{1,3}){3}$/.test(s))
212
+ return false;
213
+ const parts = s.split(".").map((n) => Number(n));
214
+ if (parts.some((n) => n < 0 || n > 255))
215
+ return false;
216
+ if (parts[0] === 127)
217
+ return false; // loopback
218
+ if (parts[0] === 0)
219
+ return false;
220
+ return true;
221
+ }
222
+ /** True for valid public-routable IPv6 strings. Filters loopback
223
+ * (::1) and link-local. Coarse — node:net.isIPv6 would be stricter
224
+ * but the obvious filters cover the practical cases. */
225
+ function isPublicIpv6(s) {
226
+ if (!/^[0-9a-fA-F:]+$/.test(s) || !s.includes(":"))
227
+ return false;
228
+ if (s === "::" || s === "::1")
229
+ return false;
230
+ if (s.toLowerCase().startsWith("fe80:"))
231
+ return false; // link-local
232
+ return true;
233
+ }
234
+ /** Resolve the box's public IPv4 + IPv6, preferring Coolify's
235
+ * configured values (via /servers/{uuid}/domains, which surfaces the
236
+ * instance's `public_ipv4` / `public_ipv6` for localhost-Coolify
237
+ * installs that report `host.docker.internal` on /servers), falling
238
+ * back to DNS resolution of the dashboard hostname. Cross-checks
239
+ * the two IPv4 sources and surfaces a warning when they disagree. */
240
+ async function discoverPublicIps(api, serverUuid, fallbackServerIp, dashboardUrl) {
241
+ // Step 1: Coolify-reported IPs. /servers/{uuid}/domains returns
242
+ // entries with `ip` set per running domain; for localhost-Coolify
243
+ // this falls back to the configured public_ipv4 / public_ipv6.
244
+ let coolifyV4;
245
+ let coolifyV6;
246
+ try {
247
+ const domains = await api.getServerDomains(serverUuid);
248
+ for (const d of domains) {
249
+ const ip = (d.ip ?? "").trim();
250
+ if (!coolifyV4 && isPublicIpv4(ip))
251
+ coolifyV4 = ip;
252
+ if (!coolifyV6 && isPublicIpv6(ip))
253
+ coolifyV6 = ip;
254
+ }
255
+ }
256
+ catch {
257
+ // /servers/{uuid}/domains can 404 / 501 on older Coolify builds.
258
+ // Treat as "Coolify doesn't know" and fall back to DNS only.
259
+ }
260
+ // /servers itself may return a real IPv4 on non-Docker installs —
261
+ // use it as a last-resort source.
262
+ if (!coolifyV4 && isPublicIpv4(fallbackServerIp))
263
+ coolifyV4 = fallbackServerIp;
264
+ if (!coolifyV6 && isPublicIpv6(fallbackServerIp))
265
+ coolifyV6 = fallbackServerIp;
266
+ // Step 2: independent DNS resolution of the dashboard hostname.
267
+ let host;
268
+ try {
269
+ host = new URL(dashboardUrl).hostname;
270
+ }
271
+ catch {
272
+ /* ignore — dashboard URL might be malformed */
273
+ }
274
+ let dnsV4;
275
+ let dnsV6;
276
+ if (host && !isPublicIpv4(host)) {
277
+ const spinner = ora(`Resolving ${host} for cross-check`).start();
278
+ try {
279
+ const [v4, v6] = await Promise.allSettled([resolve4(host), resolve6(host)]);
280
+ if (v4.status === "fulfilled" && v4.value[0] && isPublicIpv4(v4.value[0])) {
281
+ dnsV4 = v4.value[0];
282
+ }
283
+ if (v6.status === "fulfilled" && v6.value[0] && isPublicIpv6(v6.value[0])) {
284
+ dnsV6 = v6.value[0];
285
+ }
286
+ const parts = [dnsV4 && `A ${dnsV4}`, dnsV6 && `AAAA ${dnsV6}`].filter(Boolean);
287
+ spinner.succeed(`DNS for ${host}: ${parts.length > 0 ? parts.join(", ") : "no records"}`);
288
+ }
289
+ catch {
290
+ spinner.fail(`Couldn't resolve ${host}`);
291
+ }
292
+ }
293
+ else if (host && isPublicIpv4(host)) {
294
+ dnsV4 = host;
295
+ }
296
+ // Step 3: cross-check + decide. Prefer Coolify's value when we have
297
+ // it (it's the box's self-reported truth); fall back to DNS.
298
+ const v4 = coolifyV4 ?? dnsV4;
299
+ const v6 = coolifyV6 ?? dnsV6;
300
+ let mismatchWarning;
301
+ if (coolifyV4 && dnsV4 && coolifyV4 !== dnsV4) {
302
+ mismatchWarning = `Coolify reports public IPv4 ${coolifyV4} but ${host} resolves to ${dnsV4}. Using Coolify's value; double-check the DNS records and any floating-IP / proxy setup.`;
303
+ console.log(chalk.yellow(` ⚠ ${mismatchWarning}`));
304
+ }
305
+ return { v4, v6, mismatchWarning };
306
+ }
307
+ /** Upsert A and/or AAAA records for `domain` on Cloudflare. Either
308
+ * IP being undefined is fine — we only upsert what we've got, so a
309
+ * v6-only deploy gets just an AAAA record and v4-only gets just an A. */
310
+ async function wireDns(domain, ips) {
311
+ if (!ips.v4 && !ips.v6) {
312
+ console.log(chalk.yellow(" Couldn't resolve a public IPv4 or IPv6 for the Coolify server.\n" +
313
+ ` Add an A (and optionally AAAA) record for ${domain} manually pointing at\n` +
314
+ " the box's public IP, or fix the server's IP in the Coolify dashboard so\n" +
315
+ " /servers/{uuid}/domains returns it."));
316
+ return { managed: false };
317
+ }
176
318
  const dns = await getDnsConfig();
177
319
  if (!dns) {
178
- console.log(chalk.yellow(" No DNS provider configured. Add an A record yourself for\n" +
179
- ` ${domain} → ${serverIp}\n` +
320
+ console.log(chalk.yellow(" No DNS provider configured. Add records yourself:\n" +
321
+ (ips.v4 ? ` A ${domain} → ${ips.v4}\n` : "") +
322
+ (ips.v6 ? ` AAAA ${domain} → ${ips.v6}\n` : "") +
180
323
  " Or run `hatchkit config add dns` and re-run."));
181
324
  return { managed: false };
182
325
  }
183
326
  if (dns.provider !== "cloudflare") {
184
- console.log(chalk.yellow(` DNS provider is ${dns.provider} — automatic A-record management isn't wired\n` +
185
- " up for that provider yet. Add the A record manually:\n" +
186
- ` ${domain} → ${serverIp}`));
327
+ console.log(chalk.yellow(` DNS provider is ${dns.provider} — automatic record management isn't wired\n` +
328
+ " up for that provider yet. Add records manually:\n" +
329
+ (ips.v4 ? ` A ${domain} → ${ips.v4}\n` : "") +
330
+ (ips.v6 ? ` AAAA ${domain} → ${ips.v6}\n` : "")));
187
331
  return { managed: false };
188
332
  }
189
333
  if (!dns.apiToken) {
@@ -191,44 +335,55 @@ async function wireDns(domain, serverIp) {
191
335
  return { managed: false };
192
336
  }
193
337
  const cf = new CloudflareApi({ token: dns.apiToken, accountId: dns.accountId });
194
- // Find the zone that owns this domain. The zone name is the eTLD+1
195
- // — e.g. for `protocol.trebeljahr.com` the zone is `trebeljahr.com`.
196
338
  const zoneName = inferZone(domain);
197
- const spinner = ora(`Cloudflare: locating zone "${zoneName}"`).start();
339
+ const zoneSpinner = ora(`Cloudflare: locating zone "${zoneName}"`).start();
198
340
  let zone;
199
341
  try {
200
342
  zone = await cf.getZoneByName(zoneName);
201
343
  if (!zone) {
202
- spinner.fail();
344
+ zoneSpinner.fail();
203
345
  console.log(chalk.yellow(` No Cloudflare zone matches "${zoneName}". Add one (or change the\n` +
204
- " domain) and re-run, or set the A record manually."));
346
+ " domain) and set the records manually."));
205
347
  return { managed: false };
206
348
  }
207
- spinner.succeed(`Cloudflare zone: ${zone.name}`);
349
+ zoneSpinner.succeed(`Cloudflare zone: ${zone.name}`);
208
350
  }
209
351
  catch (err) {
210
- spinner.fail(`Cloudflare zone lookup failed: ${err.message}`);
352
+ zoneSpinner.fail(`Cloudflare zone lookup failed: ${err.message}`);
211
353
  return { managed: false };
212
354
  }
213
- const upsert = ora(`Cloudflare: upserting A record ${domain} → ${serverIp}`).start();
355
+ const result = { managed: false };
356
+ if (ips.v4) {
357
+ const id = await upsertOne(cf, zone.id, "A", domain, ips.v4);
358
+ if (id) {
359
+ result.recordIdV4 = id;
360
+ result.managed = true;
361
+ }
362
+ }
363
+ if (ips.v6) {
364
+ const id = await upsertOne(cf, zone.id, "AAAA", domain, ips.v6);
365
+ if (id) {
366
+ result.recordIdV6 = id;
367
+ result.managed = true;
368
+ }
369
+ }
370
+ return result;
371
+ }
372
+ async function upsertOne(cf, zoneId, type, domain, content) {
373
+ const spinner = ora(`Cloudflare: upserting ${type} ${domain} → ${content}`).start();
214
374
  try {
215
- const res = await cf.upsertRecord(zone.id, {
216
- type: "A",
217
- name: domain,
218
- content: serverIp,
219
- proxied: true,
220
- });
375
+ const res = await cf.upsertRecord(zoneId, { type, name: domain, content, proxied: true });
221
376
  if (res.created)
222
- upsert.succeed(`Cloudflare: created A ${domain} → ${serverIp}`);
377
+ spinner.succeed(`Cloudflare: created ${type} ${domain} → ${content}`);
223
378
  else if (res.updated)
224
- upsert.succeed(`Cloudflare: updated A ${domain} → ${serverIp}`);
379
+ spinner.succeed(`Cloudflare: updated ${type} ${domain} → ${content}`);
225
380
  else
226
- upsert.succeed(`Cloudflare: A ${domain} → ${serverIp} already correct`);
227
- return { managed: true, recordId: res.id };
381
+ spinner.succeed(`Cloudflare: ${type} ${domain} → ${content} already correct`);
382
+ return res.id;
228
383
  }
229
384
  catch (err) {
230
- upsert.fail(`Cloudflare: A-record upsert failed: ${err.message}`);
231
- return { managed: false };
385
+ spinner.fail(`Cloudflare: ${type}-record upsert failed: ${err.message}`);
386
+ return undefined;
232
387
  }
233
388
  }
234
389
  /** Best-effort eTLD+1 inference. Works for the common case
@@ -1 +1 @@
1
- {"version":3,"file":"coolify-app.js","sourceRoot":"","sources":["../../src/deploy/coolify-app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"coolify-app.js","sourceRoot":"","sources":["../../src/deploy/coolify-app.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ export interface BuildPipelineState {
2
+ /** True when ANY of the recognized compose filenames is present. */
3
+ hasCompose: boolean;
4
+ /** Path to the detected compose file, if any. */
5
+ composePath?: string;
6
+ hasDockerfile: boolean;
7
+ hasDeployWorkflow: boolean;
8
+ }
9
+ export declare function detectBuildPipeline(projectDir: string): BuildPipelineState;
10
+ export interface ScaffoldBuildPipelineInput {
11
+ projectDir: string;
12
+ projectName: string;
13
+ /** GitHub `<owner>/<repo>` slug — owner is what GHCR images get
14
+ * scoped under (`ghcr.io/<owner>/<name>`). Inferred from the
15
+ * `git@github.com:owner/repo.git` or `https://github.com/owner/repo`
16
+ * remote URL by the caller. */
17
+ ghOwner: string;
18
+ /** Project-relative entrypoint script for the runtime CMD. Server /
19
+ * both layouts default to `dist/index.js`; client-only is
20
+ * irrelevant (nginx serves static files). */
21
+ entrypoint: string;
22
+ /** Container port the server listens on. Compose maps
23
+ * `<port>:<port>`. Ignored for client-only (nginx fixed at 80). */
24
+ port: number;
25
+ /** Surface from the AdoptPlan — picks the right Dockerfile flavour
26
+ * (server-only/both → Node runner; client-only → nginx). */
27
+ surfaces: "server-only" | "client-only" | "both";
28
+ /** Default branch used by the Actions workflow's `on: push: branches:`
29
+ * trigger. Detected from `git symbolic-ref refs/remotes/origin/HEAD`
30
+ * by the caller, with a `main` fallback. */
31
+ defaultBranch: string;
32
+ }
33
+ export interface ScaffoldBuildPipelineResult {
34
+ /** Files we wrote (relative to projectDir). Useful for printing a
35
+ * summary + later git-add. */
36
+ written: string[];
37
+ /** Files we skipped because they already existed. */
38
+ skipped: string[];
39
+ }
40
+ /** Idempotent: only writes files that don't exist. Returns what
41
+ * changed so the caller can print a clear "wrote X / kept Y" summary
42
+ * and add the new files to git. */
43
+ export declare function scaffoldBuildPipeline(input: ScaffoldBuildPipelineInput): ScaffoldBuildPipelineResult;
44
+ //# sourceMappingURL=build-pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-pipeline.d.ts","sourceRoot":"","sources":["../../src/scaffold/build-pipeline.ts"],"names":[],"mappings":"AA4BA,MAAM,WAAW,kBAAkB;IACjC,oEAAoE;IACpE,UAAU,EAAE,OAAO,CAAC;IACpB,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,OAAO,CAAC;IACvB,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAcD,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,CAe1E;AAED,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB;;;oCAGgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB;;kDAE8C;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB;wEACoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb;iEAC6D;IAC7D,QAAQ,EAAE,aAAa,GAAG,aAAa,GAAG,MAAM,CAAC;IACjD;;iDAE6C;IAC7C,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,2BAA2B;IAC1C;mCAC+B;IAC/B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,qDAAqD;IACrD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;oCAEoC;AACpC,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,0BAA0B,GAChC,2BAA2B,CAoD7B"}
@@ -0,0 +1,129 @@
1
+ /*
2
+ * Build pipeline scaffolder for `hatchkit adopt`.
3
+ *
4
+ * Wires a project up to the canonical hatchkit pipeline:
5
+ *
6
+ * GitHub Actions builds the Docker image → pushes to GHCR →
7
+ * triggers Coolify's per-app deploy webhook → Coolify pulls + runs
8
+ *
9
+ * Detection-aware:
10
+ * · `docker-compose.yml` present → leave it alone, Coolify uses
11
+ * the user's. Same for any of the alternate filenames Compose
12
+ * itself recognises (compose.yml, .yaml variants).
13
+ * · `Dockerfile` present → leave it alone, scaffold a
14
+ * compose around it.
15
+ * · `.github/workflows/deploy.yml` present → leave it alone.
16
+ *
17
+ * Anything missing gets scaffolded from templates under
18
+ * cli/src/templates/build-pipeline/.
19
+ *
20
+ * Mobile / desktop pipelines (Capacitor + Electron Builder) are
21
+ * scaffolded out of this module too, gated on `features.includes()`,
22
+ * but those templates land in a follow-up commit.
23
+ */
24
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
25
+ import { dirname, join } from "node:path";
26
+ import { renderTemplate } from "../utils/template.js";
27
+ /** Compose file lookups mirror what Docker Compose itself supports —
28
+ * https://docs.docker.com/compose/compose-application-model/#the-compose-file
29
+ * We respect any of these instead of forcing one shape. */
30
+ const COMPOSE_FILENAMES = [
31
+ "compose.yaml",
32
+ "compose.yml",
33
+ "docker-compose.yaml",
34
+ "docker-compose.yml",
35
+ ];
36
+ const DEPLOY_WORKFLOW_PATH = ".github/workflows/deploy.yml";
37
+ export function detectBuildPipeline(projectDir) {
38
+ let composePath;
39
+ for (const name of COMPOSE_FILENAMES) {
40
+ const p = join(projectDir, name);
41
+ if (existsSync(p)) {
42
+ composePath = p;
43
+ break;
44
+ }
45
+ }
46
+ return {
47
+ hasCompose: !!composePath,
48
+ composePath,
49
+ hasDockerfile: existsSync(join(projectDir, "Dockerfile")),
50
+ hasDeployWorkflow: existsSync(join(projectDir, DEPLOY_WORKFLOW_PATH)),
51
+ };
52
+ }
53
+ /** Idempotent: only writes files that don't exist. Returns what
54
+ * changed so the caller can print a clear "wrote X / kept Y" summary
55
+ * and add the new files to git. */
56
+ export function scaffoldBuildPipeline(input) {
57
+ const state = detectBuildPipeline(input.projectDir);
58
+ const written = [];
59
+ const skipped = [];
60
+ // Dockerfile.
61
+ if (!state.hasDockerfile) {
62
+ const tpl = input.surfaces === "client-only"
63
+ ? "build-pipeline/Dockerfile.client.hbs"
64
+ : "build-pipeline/Dockerfile.server.hbs";
65
+ const out = renderTemplate(tpl, {
66
+ name: input.projectName,
67
+ port: input.port,
68
+ entrypoint: input.entrypoint,
69
+ });
70
+ writeProjectFile(input.projectDir, "Dockerfile", out);
71
+ written.push("Dockerfile");
72
+ }
73
+ else {
74
+ skipped.push("Dockerfile");
75
+ }
76
+ // docker-compose.yml — only scaffold when no compose file (any of
77
+ // the recognised names) is present. Always write to
78
+ // `docker-compose.yml` since that's what Coolify expects by default.
79
+ if (!state.hasCompose) {
80
+ const out = renderTemplate("build-pipeline/docker-compose.yml.hbs", {
81
+ name: input.projectName,
82
+ owner: input.ghOwner,
83
+ port: input.port,
84
+ });
85
+ writeProjectFile(input.projectDir, "docker-compose.yml", out);
86
+ written.push("docker-compose.yml");
87
+ }
88
+ else {
89
+ skipped.push(state.composePath?.replace(`${input.projectDir}/`, "") ?? "compose file");
90
+ }
91
+ // GitHub Actions deploy workflow.
92
+ if (!state.hasDeployWorkflow) {
93
+ // The deploy template uses GitHub Actions' own `${{ … }}` syntax,
94
+ // which clashes with Handlebars. We render it as a plain text
95
+ // file with `__VAR__` placeholders that get substituted here
96
+ // instead — no Handlebars on this one.
97
+ const raw = readTemplateRaw("build-pipeline/deploy.yml.hbs");
98
+ const filled = raw.replace(/__DEFAULT_BRANCH__/g, input.defaultBranch);
99
+ writeProjectFile(input.projectDir, DEPLOY_WORKFLOW_PATH, filled);
100
+ written.push(DEPLOY_WORKFLOW_PATH);
101
+ }
102
+ else {
103
+ skipped.push(DEPLOY_WORKFLOW_PATH);
104
+ }
105
+ return { written, skipped };
106
+ }
107
+ function writeProjectFile(projectDir, relPath, content) {
108
+ const full = join(projectDir, relPath);
109
+ const parent = dirname(full);
110
+ if (!existsSync(parent))
111
+ mkdirSync(parent, { recursive: true });
112
+ writeFileSync(full, content, "utf-8");
113
+ }
114
+ /** Read a template file as raw text, bypassing Handlebars. Used for
115
+ * the GitHub Actions workflow whose `${{ }}` syntax conflicts with
116
+ * the Handlebars expression syntax. */
117
+ function readTemplateRaw(relPath) {
118
+ // Mirror the lookup logic in utils/template.ts: TEMPLATES_DIR is
119
+ // resolved relative to that module, which is two parents away from
120
+ // this file (../utils → ../).
121
+ const here = dirname(new URL(import.meta.url).pathname);
122
+ const templatesDir = join(here, "..", "templates");
123
+ const full = join(templatesDir, relPath);
124
+ if (!existsSync(full)) {
125
+ throw new Error(`Template not found: ${full}`);
126
+ }
127
+ return readFileSync(full, "utf-8");
128
+ }
129
+ //# sourceMappingURL=build-pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-pipeline.js","sourceRoot":"","sources":["../../src/scaffold/build-pipeline.ts"],"names":[],"mappings":"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"}
@@ -38,6 +38,13 @@ export interface ProjectManifest {
38
38
  client: number;
39
39
  nativeHmr?: number;
40
40
  };
41
+ /** What kind of project this is — server-only / client-only /
42
+ * both. Captured by `hatchkit adopt` so subsequent re-runs (and
43
+ * any future tooling that needs to know whether to look for a
44
+ * server bundle) don't have to re-infer from disk layout.
45
+ * Optional for back-compat with manifests written before this
46
+ * field existed; readers should fall back to detection. */
47
+ surfaces?: "server-only" | "client-only" | "both";
41
48
  }
42
49
  /** Build a manifest from the internal ProjectConfig, explicitly
43
50
  * whitelisting only the safe fields. Any new field on ProjectConfig
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/scaffold/manifest.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,eAAO,MAAM,iBAAiB,mBAAmB,CAAC;AAClD,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC,MAAM,WAAW,eAAe;IAC9B,qEAAqE;IACrE,OAAO,EAAE,OAAO,gBAAgB,CAAC;IACjC,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,0CAA0C;IAC1C,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB;6DACyD;IACzD,UAAU,EAAE,UAAU,CAAC;IACvB;qDACiD;IACjD,YAAY,EAAE,UAAU,GAAG,KAAK,CAAC;IACjC;;mDAE+C;IAC/C,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;IAC7B,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;oEACgE;IAChE,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/D;AAED;;oEAEoE;AACpE,wBAAgB,UAAU,CACxB,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,YAAY,EACnB,UAAU,EAAE,MAAM,GACjB,eAAe,CAoBjB;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,IAAI,CAGhF;AAED;;;gCAGgC;AAChC,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAiBvE"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/scaffold/manifest.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,eAAO,MAAM,iBAAiB,mBAAmB,CAAC;AAClD,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC,MAAM,WAAW,eAAe;IAC9B,qEAAqE;IACrE,OAAO,EAAE,OAAO,gBAAgB,CAAC;IACjC,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,0CAA0C;IAC1C,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB;6DACyD;IACzD,UAAU,EAAE,UAAU,CAAC;IACvB;qDACiD;IACjD,YAAY,EAAE,UAAU,GAAG,KAAK,CAAC;IACjC;;mDAE+C;IAC/C,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;IAC7B,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;oEACgE;IAChE,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D;;;;;gEAK4D;IAC5D,QAAQ,CAAC,EAAE,aAAa,GAAG,aAAa,GAAG,MAAM,CAAC;CACnD;AAED;;oEAEoE;AACpE,wBAAgB,UAAU,CACxB,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,YAAY,EACnB,UAAU,EAAE,MAAM,GACjB,eAAe,CAoBjB;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,IAAI,CAGhF;AAED;;;gCAGgC;AAChC,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAiBvE"}
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/scaffold/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,MAAM,CAAC,MAAM,iBAAiB,GAAG,gBAAgB,CAAC;AAClD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAoClC;;oEAEoE;AACpE,MAAM,UAAU,UAAU,CACxB,MAAqB,EACrB,KAAmB,EACnB,UAAkB;IAElB,OAAO;QACL,OAAO,EAAE,gBAAgB;QACzB,UAAU;QACV,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACtC,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC;QAC9B,UAAU,EAAE,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC;QAClC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,KAAK,EAAE;YACL,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,SAAiB,EAAE,QAAyB;IACxE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;IAChD,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;AACzE,CAAC;AAED;;;gCAGgC;AAChC,MAAM,UAAU,YAAY,CAAC,UAAkB;IAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;IACjD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,uBAAwB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,IACE,CAAC,MAAM;QACP,OAAO,MAAM,KAAK,QAAQ;QACzB,MAAgC,CAAC,OAAO,KAAK,gBAAgB,EAC9D,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,kCAAkC,gBAAgB,GAAG,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,MAAyB,CAAC;AACnC,CAAC"}
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/scaffold/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,MAAM,CAAC,MAAM,iBAAiB,GAAG,gBAAgB,CAAC;AAClD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AA2ClC;;oEAEoE;AACpE,MAAM,UAAU,UAAU,CACxB,MAAqB,EACrB,KAAmB,EACnB,UAAkB;IAElB,OAAO;QACL,OAAO,EAAE,gBAAgB;QACzB,UAAU;QACV,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACtC,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC;QAC9B,UAAU,EAAE,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC;QAClC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,KAAK,EAAE;YACL,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,SAAiB,EAAE,QAAyB;IACxE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;IAChD,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;AACzE,CAAC;AAED;;;gCAGgC;AAChC,MAAM,UAAU,YAAY,CAAC,UAAkB;IAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;IACjD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,uBAAwB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,IACE,CAAC,MAAM;QACP,OAAO,MAAM,KAAK,QAAQ;QACzB,MAAgC,CAAC,OAAO,KAAK,gBAAgB,EAC9D,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,kCAAkC,gBAAgB,GAAG,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,MAAyB,CAAC;AACnC,CAAC"}
@@ -0,0 +1,19 @@
1
+ # syntax=docker/dockerfile:1
2
+ #
3
+ # Static-site image for {{name}}.
4
+ # Built by .github/workflows/deploy.yml, pushed to GHCR, pulled by
5
+ # Coolify via docker-compose.yml. nginx serves the built bundle —
6
+ # no runtime Node, so dotenvx encryption isn't relevant here
7
+ # (anything sensitive should never reach the browser bundle anyway).
8
+ ARG NODE_VERSION=22
9
+
10
+ FROM node:${NODE_VERSION}-alpine AS build
11
+ WORKDIR /app
12
+ COPY package.json pnpm-lock.yaml* ./
13
+ RUN corepack enable && pnpm install --frozen-lockfile
14
+ COPY . .
15
+ RUN pnpm build
16
+
17
+ FROM nginx:alpine AS runner
18
+ COPY --from=build /app/dist /usr/share/nginx/html
19
+ EXPOSE 80