@geekmidas/cli 10.0.0-alpha.87 → 10.0.0-alpha.89
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/GoDaddyProvider--36rw8cP.mjs +387 -0
- package/dist/GoDaddyProvider--36rw8cP.mjs.map +1 -0
- package/dist/GoDaddyProvider-DnRor066.cjs +387 -0
- package/dist/GoDaddyProvider-DnRor066.cjs.map +1 -0
- package/dist/{HostingerProvider-CVc3rLPB.mjs → HostingerProvider-BI6J7oJr.mjs} +2 -2
- package/dist/{HostingerProvider-CVc3rLPB.mjs.map → HostingerProvider-BI6J7oJr.mjs.map} +1 -1
- package/dist/{HostingerProvider-BCB1QJj1.cjs → HostingerProvider-CyTpG_jy.cjs} +2 -2
- package/dist/{HostingerProvider-BCB1QJj1.cjs.map → HostingerProvider-CyTpG_jy.cjs.map} +1 -1
- package/dist/{LegacyStateStore-CWG_HVC0.cjs → LegacyStateStore-BaBoYl59.cjs} +2 -2
- package/dist/{LegacyStateStore-CWG_HVC0.cjs.map → LegacyStateStore-BaBoYl59.cjs.map} +1 -1
- package/dist/{LegacyStateStore-B0R4LlX_.mjs → LegacyStateStore-CO7bzJCU.mjs} +2 -2
- package/dist/{LegacyStateStore-B0R4LlX_.mjs.map → LegacyStateStore-CO7bzJCU.mjs.map} +1 -1
- package/dist/{LocalStateStore-CLwa2DpK.cjs → LocalStateStore-CUWh2BWU.cjs} +2 -2
- package/dist/{LocalStateStore-CLwa2DpK.cjs.map → LocalStateStore-CUWh2BWU.cjs.map} +1 -1
- package/dist/{LocalStateStore-Q4vXg2ua.mjs → LocalStateStore-C_hYDv6I.mjs} +2 -2
- package/dist/{LocalStateStore-Q4vXg2ua.mjs.map → LocalStateStore-C_hYDv6I.mjs.map} +1 -1
- package/dist/{S3StateStore-Cea9_5gF.cjs → S3StateStore-O8EYfjfG.cjs} +2 -2
- package/dist/{S3StateStore-Cea9_5gF.cjs.map → S3StateStore-O8EYfjfG.cjs.map} +1 -1
- package/dist/{S3StateStore-CksKYKRa.mjs → S3StateStore-hIm8Rrmu.mjs} +2 -2
- package/dist/{S3StateStore-CksKYKRa.mjs.map → S3StateStore-hIm8Rrmu.mjs.map} +1 -1
- package/dist/{SSMStateStore-aBOTF018.cjs → SSMStateStore-DIzbiqCz.cjs} +2 -2
- package/dist/{SSMStateStore-aBOTF018.cjs.map → SSMStateStore-DIzbiqCz.cjs.map} +1 -1
- package/dist/{SSMStateStore-BszSCAS2.mjs → SSMStateStore-IvcjTk8h.mjs} +2 -2
- package/dist/{SSMStateStore-BszSCAS2.mjs.map → SSMStateStore-IvcjTk8h.mjs.map} +1 -1
- package/dist/SubscriberGenerator-BPqQf8fB.mjs.map +1 -1
- package/dist/SubscriberGenerator-BVn7cQ-2.cjs.map +1 -1
- package/dist/{add-5MZAXybv.cjs → add-C9qX4Juc.cjs} +30 -7
- package/dist/add-C9qX4Juc.cjs.map +1 -0
- package/dist/{add-D_jNqnfZ.mjs → add-v3tCbrpE.mjs} +30 -7
- package/dist/add-v3tCbrpE.mjs.map +1 -0
- package/dist/{bundler-1REMhKps.cjs → bundler-C4NmpRTD.cjs} +5 -5
- package/dist/{bundler-1REMhKps.cjs.map → bundler-C4NmpRTD.cjs.map} +1 -1
- package/dist/{bundler-BMo-JP5s.mjs → bundler-C_fCgcVO.mjs} +5 -5
- package/dist/{bundler-BMo-JP5s.mjs.map → bundler-C_fCgcVO.mjs.map} +1 -1
- package/dist/{cli-BL8ZHsLQ.cjs → cli-C85Dut8K.cjs} +6 -5
- package/dist/cli-C85Dut8K.cjs.map +1 -0
- package/dist/{cli-7edNFwGk.mjs → cli-REdO9X5b.mjs} +7 -6
- package/dist/cli-REdO9X5b.mjs.map +1 -0
- package/dist/{compose-xw86kVYi.cjs → compose-BvrhDwJ6.cjs} +556 -30
- package/dist/compose-BvrhDwJ6.cjs.map +1 -0
- package/dist/{compose-DbJhRQlh.mjs → compose-Dn0oAgQ0.mjs} +509 -31
- package/dist/compose-Dn0oAgQ0.mjs.map +1 -0
- package/dist/{config-DrCAyoH5.d.mts → config-CdEcTrjG.d.mts} +3 -3
- package/dist/{config-CpjsVxru.d.cts.map → config-CdEcTrjG.d.mts.map} +1 -1
- package/dist/{config-CpjsVxru.d.cts → config-pST7E0CS.d.cts} +3 -3
- package/dist/{config-DrCAyoH5.d.mts.map → config-pST7E0CS.d.cts.map} +1 -1
- package/dist/config.cjs +1 -1
- package/dist/config.d.cts +3 -3
- package/dist/config.d.mts +3 -3
- package/dist/config.mjs +1 -1
- package/dist/{credentials-tr26-KML.cjs → credentials-BKfIugu2.cjs} +47 -2
- package/dist/credentials-BKfIugu2.cjs.map +1 -0
- package/dist/{credentials-BgJ5mS_d.mjs → credentials-CnVqoXMb.mjs} +30 -3
- package/dist/credentials-CnVqoXMb.mjs.map +1 -0
- package/dist/databases-BY-pEImp.cjs.map +1 -1
- package/dist/databases-CzszQV0N.mjs.map +1 -1
- package/dist/deploy/public.cjs +10 -10
- package/dist/deploy/public.d.cts +9 -3
- package/dist/deploy/public.d.cts.map +1 -1
- package/dist/deploy/public.d.mts +9 -3
- package/dist/deploy/public.d.mts.map +1 -1
- package/dist/deploy/public.mjs +10 -10
- package/dist/{deploy-BTfmXd3g.mjs → deploy-BaERRh0Q.mjs} +10 -8
- package/dist/deploy-BaERRh0Q.mjs.map +1 -0
- package/dist/{deploy-CtbZj4zN.cjs → deploy-DbBGo3a6.cjs} +10 -8
- package/dist/deploy-DbBGo3a6.cjs.map +1 -0
- package/dist/{dokploy-r69yZaIt.mjs → dokploy-CMmD_ddX.mjs} +2 -2
- package/dist/{dokploy-r69yZaIt.mjs.map → dokploy-CMmD_ddX.mjs.map} +1 -1
- package/dist/{dokploy-TGk3oPwr.cjs → dokploy-DwAaKA9B.cjs} +2 -2
- package/dist/{dokploy-TGk3oPwr.cjs.map → dokploy-DwAaKA9B.cjs.map} +1 -1
- package/dist/{encryption-C-8Tt5Hh.mjs → encryption-BQmhq9_y.mjs} +3 -3
- package/dist/{encryption-C-8Tt5Hh.mjs.map → encryption-BQmhq9_y.mjs.map} +1 -1
- package/dist/{encryption-CDn7BH5O.cjs → encryption-BrN_9_CM.cjs} +3 -3
- package/dist/{encryption-CDn7BH5O.cjs.map → encryption-BrN_9_CM.cjs.map} +1 -1
- package/dist/{engine-jAINgiOB.mjs → engine-DILocOOH.mjs} +23 -404
- package/dist/engine-DILocOOH.mjs.map +1 -0
- package/dist/{engine-Bt5k_UMq.cjs → engine-DgHoFBMw.cjs} +25 -406
- package/dist/engine-DgHoFBMw.cjs.map +1 -0
- package/dist/{github-DFhuJQlp.cjs → github-Bf7pz6AV.cjs} +3 -3
- package/dist/{github-DFhuJQlp.cjs.map → github-Bf7pz6AV.cjs.map} +1 -1
- package/dist/{github-CZHAtwPT.mjs → github-xzg99wz8.mjs} +3 -3
- package/dist/{github-CZHAtwPT.mjs.map → github-xzg99wz8.mjs.map} +1 -1
- package/dist/{index-MnUJuUlj.d.mts → index-D-F_hTDz.d.cts} +21 -4
- package/dist/index-D-F_hTDz.d.cts.map +1 -0
- package/dist/{index-elsLJTUv.d.cts → index-YFNxR5Ns.d.mts} +21 -4
- package/dist/index-YFNxR5Ns.d.mts.map +1 -0
- package/dist/index.cjs +305 -69
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +306 -71
- package/dist/index.mjs.map +1 -1
- package/dist/{local-Cq8qdgNX.cjs → local-BjxDfPvy.cjs} +2 -2
- package/dist/{local-Cq8qdgNX.cjs.map → local-BjxDfPvy.cjs.map} +1 -1
- package/dist/{local-Ciq-bTPr.mjs → local-IuoIF3CT.mjs} +2 -2
- package/dist/{local-Ciq-bTPr.mjs.map → local-IuoIF3CT.mjs.map} +1 -1
- package/dist/{migrate-B1rVlwj1.cjs → migrate-7xayVtzL.cjs} +3 -3
- package/dist/{migrate-B1rVlwj1.cjs.map → migrate-7xayVtzL.cjs.map} +1 -1
- package/dist/{migrate-ggkPVJRC.mjs → migrate-CKLJ73OO.mjs} +4 -4
- package/dist/{migrate-ggkPVJRC.mjs.map → migrate-CKLJ73OO.mjs.map} +1 -1
- package/dist/{migrate-Dn7nK6sh.mjs → migrate-CpmO5qnl.mjs} +3 -3
- package/dist/{migrate-Dn7nK6sh.mjs.map → migrate-CpmO5qnl.mjs.map} +1 -1
- package/dist/{migrate-B16qgYTn.cjs → migrate-DPF7ZF8M.cjs} +3 -3
- package/dist/{migrate-B16qgYTn.cjs.map → migrate-DPF7ZF8M.cjs.map} +1 -1
- package/dist/openapi.cjs +1 -1
- package/dist/openapi.d.cts +1 -1
- package/dist/openapi.d.mts +1 -1
- package/dist/openapi.mjs +1 -1
- package/dist/ready-BpNbORRB.cjs.map +1 -1
- package/dist/ready-b6vm0-W-.mjs.map +1 -1
- package/dist/reconcile/public.d.cts +1 -1
- package/dist/reconcile/public.d.mts +1 -1
- package/dist/{reconcile--I7V4Klj.mjs → reconcile-Dh1Jk7WE.mjs} +2 -2
- package/dist/{reconcile--I7V4Klj.mjs.map → reconcile-Dh1Jk7WE.mjs.map} +1 -1
- package/dist/{resolve-BSke45k6.mjs → resolve-Dv_weZoh.mjs} +4 -4
- package/dist/{resolve-BSke45k6.mjs.map → resolve-Dv_weZoh.mjs.map} +1 -1
- package/dist/{resolve-BXeXzpmU.cjs → resolve-dlKPFNgv.cjs} +4 -4
- package/dist/{resolve-BXeXzpmU.cjs.map → resolve-dlKPFNgv.cjs.map} +1 -1
- package/dist/{rollback-DFMiBWf0.cjs → rollback-65VVIdBM.cjs} +6 -6
- package/dist/{rollback-DFMiBWf0.cjs.map → rollback-65VVIdBM.cjs.map} +1 -1
- package/dist/{rollback-CEE6dse4.mjs → rollback-DpSU2DsD.mjs} +6 -6
- package/dist/{rollback-CEE6dse4.mjs.map → rollback-DpSU2DsD.mjs.map} +1 -1
- package/dist/{runtime-HabiNBtJ.d.mts → runtime-CN_kmqxo.d.cts} +2 -2
- package/dist/{runtime-D48ZKk8_.d.cts.map → runtime-CN_kmqxo.d.cts.map} +1 -1
- package/dist/{runtime-D48ZKk8_.d.cts → runtime-Cjvon3oj.d.mts} +2 -2
- package/dist/{runtime-HabiNBtJ.d.mts.map → runtime-Cjvon3oj.d.mts.map} +1 -1
- package/dist/{seeds-CsI0A_Ef.cjs → seeds-CN6tB-va.cjs} +646 -187
- package/dist/{seeds-CsI0A_Ef.cjs.map → seeds-CN6tB-va.cjs.map} +1 -1
- package/dist/{seeds-BYdrtZsC.mjs → seeds-perzdN81.mjs} +599 -164
- package/dist/seeds-perzdN81.mjs.map +1 -0
- package/dist/{sniffer-B0EU73bj.mjs → sniffer-BTtX3NUM.mjs} +3 -3
- package/dist/{sniffer-B0EU73bj.mjs.map → sniffer-BTtX3NUM.mjs.map} +1 -1
- package/dist/{sniffer-DJYupBeK.cjs → sniffer-IAQEpsQb.cjs} +3 -3
- package/dist/{sniffer-DJYupBeK.cjs.map → sniffer-IAQEpsQb.cjs.map} +1 -1
- package/dist/{sst-DAqUoZKG.cjs → sst-BgcOsaBi.cjs} +3 -3
- package/dist/{sst-DAqUoZKG.cjs.map → sst-BgcOsaBi.cjs.map} +1 -1
- package/dist/{sst-D1Qj4sIs.mjs → sst-CJzvyrEz.mjs} +3 -3
- package/dist/{sst-D1Qj4sIs.mjs.map → sst-CJzvyrEz.mjs.map} +1 -1
- package/dist/{stages-Brn3vcdy.cjs → stages-CUn6gvXL.cjs} +2 -2
- package/dist/{stages-Brn3vcdy.cjs.map → stages-CUn6gvXL.cjs.map} +1 -1
- package/dist/{stages-DoHHz6pS.mjs → stages-CnZRYmkI.mjs} +2 -2
- package/dist/{stages-DoHHz6pS.mjs.map → stages-CnZRYmkI.mjs.map} +1 -1
- package/dist/target/public.cjs +1 -1
- package/dist/target/public.d.cts +2 -2
- package/dist/target/public.d.mts +2 -2
- package/dist/target/public.mjs +1 -1
- package/dist/{terminal-BTbZlrFV.mjs → terminal-D8TPK7o9.mjs} +3 -3
- package/dist/{terminal-BTbZlrFV.mjs.map → terminal-D8TPK7o9.mjs.map} +1 -1
- package/dist/{terminal-COv23heb.cjs → terminal-DuapRxh6.cjs} +2 -2
- package/dist/{terminal-COv23heb.cjs.map → terminal-DuapRxh6.cjs.map} +1 -1
- package/dist/{types-0oAyFOfR.d.cts → types-NqX1Hz4P.d.cts} +210 -205
- package/dist/types-NqX1Hz4P.d.cts.map +1 -0
- package/dist/{types-BZ01tZs-.d.mts → types-ZHuZ89hv.d.mts} +210 -205
- package/dist/types-ZHuZ89hv.d.mts.map +1 -0
- package/dist/workspace/index.cjs +3 -1
- package/dist/workspace/index.d.cts +3 -3
- package/dist/workspace/index.d.mts +3 -3
- package/dist/workspace/index.mjs +2 -2
- package/dist/{workspace-D2CYLMCW.mjs → workspace-CJ0lKFq-.mjs} +231 -10
- package/dist/workspace-CJ0lKFq-.mjs.map +1 -0
- package/dist/{workspace-CT0JM3Y8.cjs → workspace-CwW3Gkru.cjs} +266 -9
- package/dist/workspace-CwW3Gkru.cjs.map +1 -0
- package/package.json +15 -15
- package/dist/add-5MZAXybv.cjs.map +0 -1
- package/dist/add-D_jNqnfZ.mjs.map +0 -1
- package/dist/cli-7edNFwGk.mjs.map +0 -1
- package/dist/cli-BL8ZHsLQ.cjs.map +0 -1
- package/dist/compose-DbJhRQlh.mjs.map +0 -1
- package/dist/compose-xw86kVYi.cjs.map +0 -1
- package/dist/credentials-BgJ5mS_d.mjs.map +0 -1
- package/dist/credentials-tr26-KML.cjs.map +0 -1
- package/dist/deploy-BTfmXd3g.mjs.map +0 -1
- package/dist/deploy-CtbZj4zN.cjs.map +0 -1
- package/dist/engine-Bt5k_UMq.cjs.map +0 -1
- package/dist/engine-jAINgiOB.mjs.map +0 -1
- package/dist/index-MnUJuUlj.d.mts.map +0 -1
- package/dist/index-elsLJTUv.d.cts.map +0 -1
- package/dist/seeds-BYdrtZsC.mjs.map +0 -1
- package/dist/types-0oAyFOfR.d.cts.map +0 -1
- package/dist/types-BZ01tZs-.d.mts.map +0 -1
- package/dist/workspace-CT0JM3Y8.cjs.map +0 -1
- package/dist/workspace-D2CYLMCW.mjs.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
const require_rolldown_runtime = require("./rolldown-runtime-C0BPl7ul.cjs");
|
|
2
|
-
const require_credentials = require("./credentials-
|
|
2
|
+
const require_credentials = require("./credentials-BKfIugu2.cjs");
|
|
3
3
|
const require_discover = require("./discover-D1It5r_h.cjs");
|
|
4
4
|
const require_derive = require("./derive-DAbo49sm.cjs");
|
|
5
|
-
const require_workspace = require("./workspace-
|
|
5
|
+
const require_workspace = require("./workspace-CwW3Gkru.cjs");
|
|
6
6
|
const require_define = require("./define-DzRz8FgH.cjs");
|
|
7
|
-
const require_seeds = require("./seeds-
|
|
7
|
+
const require_seeds = require("./seeds-CN6tB-va.cjs");
|
|
8
8
|
const require_SubscriberGenerator = require("./SubscriberGenerator-BVn7cQ-2.cjs");
|
|
9
9
|
const require_drivers = require("./drivers-LYSdQDmd.cjs");
|
|
10
10
|
const require_databases = require("./databases-BY-pEImp.cjs");
|
|
@@ -14,10 +14,428 @@ let node_fs = require("node:fs");
|
|
|
14
14
|
let node_fs_promises = require("node:fs/promises");
|
|
15
15
|
let node_os = require("node:os");
|
|
16
16
|
let _geekmidas_manifest = require("@geekmidas/manifest");
|
|
17
|
+
let node_net = require("node:net");
|
|
17
18
|
let node_child_process = require("node:child_process");
|
|
18
19
|
let node_crypto = require("node:crypto");
|
|
19
20
|
let yaml = require("yaml");
|
|
21
|
+
let node_dns_promises = require("node:dns/promises");
|
|
20
22
|
let node_https = require("node:https");
|
|
23
|
+
//#region src/compose/dns.ts
|
|
24
|
+
/**
|
|
25
|
+
* A compose stage's DNS: the records its public hosts need, and the check that
|
|
26
|
+
* they resolve to its server before a certificate is asked for.
|
|
27
|
+
*
|
|
28
|
+
* - **The server** (`serverAddress`): the stage's own secrets hold its public
|
|
29
|
+
* addresses — `GKM_SERVER_IPV4`, and `GKM_SERVER_IPV6` where it has one.
|
|
30
|
+
* Reserved for gkm: never handed to an app.
|
|
31
|
+
* - **The plan** (`planStackDns`, pure): every public host the stack serves —
|
|
32
|
+
* its apex, each app, each file server, the public log UI — pointed at the
|
|
33
|
+
* server. An A record per host (and an AAAA with an IPv6 address), or, where
|
|
34
|
+
* the domain's `dns` entry says `records: { mode: 'cname', target }`, one A
|
|
35
|
+
* record for the target and a CNAME to it for every other host but the
|
|
36
|
+
* apex, which DNS forbids a CNAME at.
|
|
37
|
+
* - **Applying it** (`applyStackDns`): through the domain's provider in `dns`,
|
|
38
|
+
* a record set at a time. A record with the right value is left alone; one
|
|
39
|
+
* with another value is replaced and the change printed. A `manual` domain
|
|
40
|
+
* is printed and nothing else. A dry run reads, prints and writes nothing.
|
|
41
|
+
* - **The check** (`checkStackDns`): each host resolved with the system
|
|
42
|
+
* resolver. One that is not the server stops the deploy with
|
|
43
|
+
* {@link HostNotPointingAtServer}, before Caddy or Traefik ask Let's Encrypt
|
|
44
|
+
* for a certificate it cannot get — and use up the rate limit trying.
|
|
45
|
+
*/
|
|
46
|
+
/** The line that says how to set the server's address. */
|
|
47
|
+
function serverAddressHint(stage) {
|
|
48
|
+
return `gkm secrets:set ${require_workspace.SERVER_IPV4_KEY} '<ip>' --stage ${stage}`;
|
|
49
|
+
}
|
|
50
|
+
/** A server address in the stage's secrets that is not an address. */
|
|
51
|
+
var ServerAddressInvalid = class extends Error {
|
|
52
|
+
stage;
|
|
53
|
+
key;
|
|
54
|
+
value;
|
|
55
|
+
constructor(stage, key, value) {
|
|
56
|
+
const ipv4 = key === require_workspace.SERVER_IPV4_KEY;
|
|
57
|
+
super(`${key} in the '${stage}' stage's secrets is ${JSON.stringify(value)}, which is not an ${ipv4 ? "IPv4 address (like 203.0.113.10)" : "IPv6 address (like 2001:db8::10)"}. Set the server's public address: gkm secrets:set ${key} '<ip>' --stage ${stage}.`);
|
|
58
|
+
this.stage = stage;
|
|
59
|
+
this.key = key;
|
|
60
|
+
this.value = value;
|
|
61
|
+
this.name = "ServerAddressInvalid";
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* A compose stage that serves real domains with no server address: its hosts
|
|
66
|
+
* cannot be pointed or checked, and a certificate would be asked for blind.
|
|
67
|
+
*/
|
|
68
|
+
var ServerAddressMissing = class extends Error {
|
|
69
|
+
stage;
|
|
70
|
+
domain;
|
|
71
|
+
constructor(stage, domain) {
|
|
72
|
+
super(`The '${stage}' stage serves ${domain} and its secrets hold no ${require_workspace.SERVER_IPV4_KEY} — the public address of the server its stack runs on, which its hosts' DNS records point at and every deploy checks before asking for certificates. Set it: ${serverAddressHint(stage)} (and ${require_workspace.SERVER_IPV6_KEY} for an IPv6 address).`);
|
|
73
|
+
this.stage = stage;
|
|
74
|
+
this.domain = domain;
|
|
75
|
+
this.name = "ServerAddressMissing";
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* The server's address from the stage's secrets, checked — `undefined` when
|
|
80
|
+
* `GKM_SERVER_IPV4` is not set.
|
|
81
|
+
*
|
|
82
|
+
* @throws {ServerAddressInvalid} for a value that is not an address
|
|
83
|
+
*/
|
|
84
|
+
function serverAddress(stage, custom) {
|
|
85
|
+
const ipv4 = custom?.[require_workspace.SERVER_IPV4_KEY]?.trim();
|
|
86
|
+
const ipv6 = custom?.[require_workspace.SERVER_IPV6_KEY]?.trim();
|
|
87
|
+
if (ipv6 && !(0, node_net.isIPv6)(ipv6)) throw new ServerAddressInvalid(stage, require_workspace.SERVER_IPV6_KEY, ipv6);
|
|
88
|
+
if (!ipv4) return void 0;
|
|
89
|
+
if (!(0, node_net.isIPv4)(ipv4)) throw new ServerAddressInvalid(stage, require_workspace.SERVER_IPV4_KEY, ipv4);
|
|
90
|
+
return {
|
|
91
|
+
ipv4,
|
|
92
|
+
...ipv6 ? { ipv6 } : {}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* A name that resolves to this machine by definition — `localhost` and every
|
|
97
|
+
* `*.localhost` — and is in nobody's DNS.
|
|
98
|
+
*/
|
|
99
|
+
function isLocalHost(host) {
|
|
100
|
+
const name = host.toLowerCase().replace(/\.$/, "");
|
|
101
|
+
return name === "localhost" || name.endsWith(".localhost");
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* The server's address, required where the stage serves real domains — not
|
|
105
|
+
* `*.localhost` ones, which point at this machine already.
|
|
106
|
+
*
|
|
107
|
+
* @throws {ServerAddressMissing} when the stage has a domain and no address
|
|
108
|
+
* @throws {ServerAddressInvalid} for a value that is not an address
|
|
109
|
+
*/
|
|
110
|
+
function requiredServerAddress(stage, domain, custom) {
|
|
111
|
+
const server = serverAddress(stage, custom);
|
|
112
|
+
if (!server && domain && !isLocalHost(domain)) throw new ServerAddressMissing(stage, domain);
|
|
113
|
+
return server;
|
|
114
|
+
}
|
|
115
|
+
const MANAGED = [
|
|
116
|
+
"A",
|
|
117
|
+
"AAAA",
|
|
118
|
+
"CNAME"
|
|
119
|
+
];
|
|
120
|
+
/** Every public host the stack serves, once each, sorted. */
|
|
121
|
+
function stackHosts(stack) {
|
|
122
|
+
return [...new Set(stack.routes.map((route) => route.host))].sort();
|
|
123
|
+
}
|
|
124
|
+
/** The TTL a domain's records are written with. */
|
|
125
|
+
function recordTtl(config) {
|
|
126
|
+
const ttl = "ttl" in config ? config.ttl : void 0;
|
|
127
|
+
if (ttl) return ttl;
|
|
128
|
+
return config.provider === "godaddy" ? 600 : 300;
|
|
129
|
+
}
|
|
130
|
+
function providerName(config) {
|
|
131
|
+
return typeof config.provider === "string" ? config.provider : "custom";
|
|
132
|
+
}
|
|
133
|
+
/** The records a stage's hosts need — pure. */
|
|
134
|
+
function planStackDns(input) {
|
|
135
|
+
const { stage, server } = input;
|
|
136
|
+
const dns = input.dns ? require_seeds.normalizeDnsConfig(input.dns) : {};
|
|
137
|
+
const records = /* @__PURE__ */ new Map();
|
|
138
|
+
const uncovered = [];
|
|
139
|
+
const add = (host, domain, type, value) => {
|
|
140
|
+
const name = require_seeds.extractSubdomain(host, domain);
|
|
141
|
+
records.set(`${domain} ${name} ${type}`, {
|
|
142
|
+
host,
|
|
143
|
+
domain,
|
|
144
|
+
name,
|
|
145
|
+
type,
|
|
146
|
+
value,
|
|
147
|
+
ttl: recordTtl(dns[domain])
|
|
148
|
+
});
|
|
149
|
+
};
|
|
150
|
+
const pointAt = (host, domain) => {
|
|
151
|
+
add(host, domain, "A", server.ipv4);
|
|
152
|
+
if (server.ipv6) add(host, domain, "AAAA", server.ipv6);
|
|
153
|
+
};
|
|
154
|
+
for (const raw of input.hosts) {
|
|
155
|
+
const host = raw.toLowerCase();
|
|
156
|
+
const domain = require_seeds.findRootDomain(host, dns);
|
|
157
|
+
if (!domain) {
|
|
158
|
+
uncovered.push(host);
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
const target = require_workspace.cnameTarget(dns[domain].records, stage);
|
|
162
|
+
if (target) pointAt(target, domain);
|
|
163
|
+
if (target && host !== domain && host !== target) add(host, domain, "CNAME", target);
|
|
164
|
+
else pointAt(host, domain);
|
|
165
|
+
}
|
|
166
|
+
const domains = /* @__PURE__ */ new Map();
|
|
167
|
+
for (const record of [...records.values()].sort((a, b) => a.domain.localeCompare(b.domain) || a.name.localeCompare(b.name) || a.type.localeCompare(b.type))) {
|
|
168
|
+
const config = dns[record.domain];
|
|
169
|
+
const plan = domains.get(record.domain) ?? {
|
|
170
|
+
domain: record.domain,
|
|
171
|
+
provider: providerName(config),
|
|
172
|
+
config,
|
|
173
|
+
records: []
|
|
174
|
+
};
|
|
175
|
+
plan.records.push(record);
|
|
176
|
+
domains.set(record.domain, plan);
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
stage,
|
|
180
|
+
server,
|
|
181
|
+
domains: [...domains.values()],
|
|
182
|
+
uncovered: uncovered.sort()
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/** `api.example.com A 203.0.113.10 (TTL 600)` */
|
|
186
|
+
function describe(record) {
|
|
187
|
+
return `${record.host.padEnd(32)} ${record.type.padEnd(5)} ${record.value} (TTL ${record.ttl})`;
|
|
188
|
+
}
|
|
189
|
+
function printManual(plan, log, why) {
|
|
190
|
+
log(` ${plan.domain}: ${why} — create these records at its DNS host:`);
|
|
191
|
+
for (const record of plan.records) log(` ${describe(record)}`);
|
|
192
|
+
return plan.records.map((r) => ({
|
|
193
|
+
domain: r.domain,
|
|
194
|
+
name: r.name,
|
|
195
|
+
type: r.type,
|
|
196
|
+
action: "manual",
|
|
197
|
+
value: r.value,
|
|
198
|
+
ttl: r.ttl
|
|
199
|
+
}));
|
|
200
|
+
}
|
|
201
|
+
/** The existing records of every planned name, for the types gkm manages. */
|
|
202
|
+
async function existingRecords(provider, plan) {
|
|
203
|
+
const names = [...new Set(plan.records.map((r) => r.name))];
|
|
204
|
+
const wanted = names.flatMap((name) => MANAGED.map((type) => ({
|
|
205
|
+
name,
|
|
206
|
+
type
|
|
207
|
+
})));
|
|
208
|
+
if (provider.readRecords) return provider.readRecords(plan.domain, wanted);
|
|
209
|
+
return (await provider.getRecords(plan.domain)).filter((r) => names.includes(r.name) && MANAGED.includes(r.type));
|
|
210
|
+
}
|
|
211
|
+
const same = (a, b) => a.trim().replace(/\.$/, "").toLowerCase() === b.trim().replace(/\.$/, "").toLowerCase();
|
|
212
|
+
/**
|
|
213
|
+
* What each domain's records need, compared with what is there: creates,
|
|
214
|
+
* updates, and the deletes a change of mode needs — a name moving from an A
|
|
215
|
+
* record to a CNAME, or back, cannot hold both. Nothing else is deleted.
|
|
216
|
+
*/
|
|
217
|
+
function diffDomainDns(plan, existing) {
|
|
218
|
+
const changes = [];
|
|
219
|
+
const find = (name, type) => existing.find((r) => r.name === name && r.type === type);
|
|
220
|
+
const planned = /* @__PURE__ */ new Map();
|
|
221
|
+
for (const record of plan.records) {
|
|
222
|
+
const types = planned.get(record.name) ?? /* @__PURE__ */ new Set();
|
|
223
|
+
types.add(record.type);
|
|
224
|
+
planned.set(record.name, types);
|
|
225
|
+
}
|
|
226
|
+
for (const [name, types] of planned) {
|
|
227
|
+
const conflicting = types.has("CNAME") ? ["A", "AAAA"] : ["CNAME"];
|
|
228
|
+
for (const type of conflicting) {
|
|
229
|
+
const found = find(name, type);
|
|
230
|
+
if (!found || found.values.length === 0) continue;
|
|
231
|
+
changes.push({
|
|
232
|
+
domain: plan.domain,
|
|
233
|
+
name,
|
|
234
|
+
type,
|
|
235
|
+
action: "delete",
|
|
236
|
+
previous: found.values.join(", ")
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
for (const record of plan.records) {
|
|
241
|
+
const found = find(record.name, record.type);
|
|
242
|
+
const base = {
|
|
243
|
+
domain: plan.domain,
|
|
244
|
+
name: record.name,
|
|
245
|
+
type: record.type,
|
|
246
|
+
value: record.value,
|
|
247
|
+
ttl: record.ttl
|
|
248
|
+
};
|
|
249
|
+
if (!found || found.values.length === 0) changes.push({
|
|
250
|
+
...base,
|
|
251
|
+
action: "create"
|
|
252
|
+
});
|
|
253
|
+
else if (found.values.length === 1 && same(found.values[0], record.value)) changes.push({
|
|
254
|
+
...base,
|
|
255
|
+
action: "unchanged"
|
|
256
|
+
});
|
|
257
|
+
else changes.push({
|
|
258
|
+
...base,
|
|
259
|
+
action: "update",
|
|
260
|
+
previous: found.values.join(", ")
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
return changes;
|
|
264
|
+
}
|
|
265
|
+
/** A host's full name from a domain and a relative name. */
|
|
266
|
+
function fullName(domain, name) {
|
|
267
|
+
return name === "@" ? domain : `${name}.${domain}`;
|
|
268
|
+
}
|
|
269
|
+
function printChange(change, dryRun, log) {
|
|
270
|
+
const host = fullName(change.domain, change.name).padEnd(32);
|
|
271
|
+
const type = change.type.padEnd(5);
|
|
272
|
+
const would = dryRun ? "would " : "";
|
|
273
|
+
switch (change.action) {
|
|
274
|
+
case "unchanged":
|
|
275
|
+
log(` ✓ ${host} ${type} ${change.value} (TTL ${change.ttl}) — up to date`);
|
|
276
|
+
break;
|
|
277
|
+
case "create":
|
|
278
|
+
log(` + ${host} ${type} ${change.value} (TTL ${change.ttl}) — ${would}create`);
|
|
279
|
+
break;
|
|
280
|
+
case "update":
|
|
281
|
+
log(` ~ ${host} ${type} ${change.previous} → ${change.value} (TTL ${change.ttl}) — ${would}update`);
|
|
282
|
+
break;
|
|
283
|
+
case "write":
|
|
284
|
+
log(dryRun ? ` ? ${host} ${type} ${change.value} (TTL ${change.ttl}) — would write; current value unknown (key cannot read DNS)` : ` ! ${host} ${type} ${change.value} (TTL ${change.ttl}) — written (not diffed)`);
|
|
285
|
+
break;
|
|
286
|
+
case "delete": log(` - ${host} ${type} ${change.previous} — ${would}delete (a name cannot hold a CNAME and an A record)`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Each domain's records, through its provider. Returns every change, the
|
|
291
|
+
* unchanged included; a dry run makes none of them.
|
|
292
|
+
*/
|
|
293
|
+
async function applyStackDns(plan, options = {}) {
|
|
294
|
+
const dryRun = options.dryRun === true;
|
|
295
|
+
const log = options.log ?? ((line) => console.log(line));
|
|
296
|
+
const providerFor = options.providerFor ?? ((config) => require_seeds.createDnsProvider({
|
|
297
|
+
config,
|
|
298
|
+
...options.credentials ? { godaddy: options.credentials } : {}
|
|
299
|
+
}));
|
|
300
|
+
const changes = [];
|
|
301
|
+
for (const host of plan.uncovered) log(` ⚠ ${host} is under no domain in dns — point it at ${plan.server.ipv4} yourself`);
|
|
302
|
+
for (const domain of plan.domains) {
|
|
303
|
+
if (domain.provider === "manual") {
|
|
304
|
+
changes.push(...printManual(domain, log, "manual"));
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
const provider = await providerFor(domain.config);
|
|
308
|
+
if (!provider) {
|
|
309
|
+
changes.push(...printManual(domain, log, "manual"));
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
log(` ${domain.domain} (${provider.name})${dryRun ? " — dry run" : ""}`);
|
|
313
|
+
let existing;
|
|
314
|
+
let diff;
|
|
315
|
+
try {
|
|
316
|
+
existing = await existingRecords(provider, domain);
|
|
317
|
+
diff = diffDomainDns(domain, existing);
|
|
318
|
+
} catch (error) {
|
|
319
|
+
if (!(error instanceof require_seeds.DnsRecordsUnreadable)) throw error;
|
|
320
|
+
log(` ℹ The ${provider.name} key cannot read ${domain.domain}'s DNS records, so changes cannot be diffed: every record is written (idempotent).`);
|
|
321
|
+
existing = [];
|
|
322
|
+
diff = domain.records.map((r) => ({
|
|
323
|
+
domain: r.domain,
|
|
324
|
+
name: r.name,
|
|
325
|
+
type: r.type,
|
|
326
|
+
action: "write",
|
|
327
|
+
value: r.value,
|
|
328
|
+
ttl: r.ttl
|
|
329
|
+
}));
|
|
330
|
+
}
|
|
331
|
+
for (const change of diff) printChange(change, dryRun, log);
|
|
332
|
+
if (!plan.server.ipv6) for (const name of new Set(domain.records.map((r) => r.name))) {
|
|
333
|
+
const aaaa = existing.find((r) => r.name === name && r.type === "AAAA");
|
|
334
|
+
const planned = domain.records.find((r) => r.name === name && r.type === "A");
|
|
335
|
+
if (aaaa && planned && aaaa.values.length > 0) log(` ⚠ ${fullName(domain.domain, name)} also has AAAA ${aaaa.values.join(", ")}: set ${require_workspace.SERVER_IPV6_KEY} in the '${plan.stage}' stage's secrets to the server's IPv6 address, or remove that record, or IPv6 clients go elsewhere`);
|
|
336
|
+
}
|
|
337
|
+
changes.push(...diff);
|
|
338
|
+
if (dryRun) continue;
|
|
339
|
+
const deletes = diff.filter((c) => c.action === "delete");
|
|
340
|
+
if (deletes.length > 0) await provider.deleteRecords(domain.domain, deletes.map((c) => ({
|
|
341
|
+
name: c.name,
|
|
342
|
+
type: c.type
|
|
343
|
+
})));
|
|
344
|
+
const writes = diff.filter((c) => c.action === "create" || c.action === "update" || c.action === "write");
|
|
345
|
+
if (writes.length > 0) await provider.upsertRecords(domain.domain, writes.map((c) => ({
|
|
346
|
+
name: c.name,
|
|
347
|
+
type: c.type,
|
|
348
|
+
value: c.value,
|
|
349
|
+
ttl: c.ttl
|
|
350
|
+
})));
|
|
351
|
+
}
|
|
352
|
+
return changes;
|
|
353
|
+
}
|
|
354
|
+
/** The system resolver: what the server's own clients would be told. */
|
|
355
|
+
const systemLookup = async (host) => {
|
|
356
|
+
return (await (0, node_dns_promises.lookup)(host, { all: true })).map((a) => a.address);
|
|
357
|
+
};
|
|
358
|
+
/** Hosts that do not resolve to the stage's server. */
|
|
359
|
+
var HostNotPointingAtServer = class extends Error {
|
|
360
|
+
stage;
|
|
361
|
+
hosts;
|
|
362
|
+
expected;
|
|
363
|
+
fix;
|
|
364
|
+
constructor(stage, hosts, expected, fix) {
|
|
365
|
+
const want = expected.ipv6 ? `${expected.ipv4} (and ${expected.ipv6})` : expected.ipv4;
|
|
366
|
+
const lines = hosts.map((h) => ` - ${h.host} → ${h.resolved.length > 0 ? h.resolved.join(", ") : `nothing${h.error ? ` (${h.error})` : ""}`}, expected ${want}`);
|
|
367
|
+
super(`${hosts.length === 1 ? "A host" : `${hosts.length} hosts`} of '${stage}' do${hosts.length === 1 ? "es" : ""} not resolve to its server, so a certificate for ${hosts.length === 1 ? "it" : "them"} cannot be issued:\n${lines.join("\n")}\n${fix}\nRecords can take a few minutes to propagate. With a CDN or proxy in front of the server, pass --skip-dns-check.`);
|
|
368
|
+
this.stage = stage;
|
|
369
|
+
this.hosts = hosts;
|
|
370
|
+
this.expected = expected;
|
|
371
|
+
this.fix = fix;
|
|
372
|
+
this.name = "HostNotPointingAtServer";
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
/**
|
|
376
|
+
* Every host resolved: each must resolve to the server's IPv4 address and to
|
|
377
|
+
* nothing but the server's addresses.
|
|
378
|
+
*
|
|
379
|
+
* @throws {HostNotPointingAtServer} naming every host that does not
|
|
380
|
+
*/
|
|
381
|
+
async function checkStackDns(input) {
|
|
382
|
+
const lookup = input.lookup ?? systemLookup;
|
|
383
|
+
const { server } = input;
|
|
384
|
+
const ours = new Set([server.ipv4, server.ipv6].filter(Boolean).map((a) => a.toLowerCase()));
|
|
385
|
+
const bad = [];
|
|
386
|
+
const ok = [];
|
|
387
|
+
for (const host of input.hosts) {
|
|
388
|
+
let resolved;
|
|
389
|
+
try {
|
|
390
|
+
resolved = [...new Set(await lookup(host))];
|
|
391
|
+
} catch (error) {
|
|
392
|
+
const code = error && typeof error === "object" && "code" in error ? String(error.code) : error instanceof Error ? error.message : String(error);
|
|
393
|
+
bad.push({
|
|
394
|
+
host,
|
|
395
|
+
resolved: [],
|
|
396
|
+
error: code
|
|
397
|
+
});
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
if (resolved.some((a) => a.toLowerCase() === server.ipv4.toLowerCase()) && resolved.every((a) => ours.has(a.toLowerCase()))) ok.push(host);
|
|
401
|
+
else bad.push({
|
|
402
|
+
host,
|
|
403
|
+
resolved
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
if (bad.length > 0) throw new HostNotPointingAtServer(input.stage, bad, {
|
|
407
|
+
ipv4: server.ipv4,
|
|
408
|
+
...server.ipv6 ? { ipv6: server.ipv6 } : {}
|
|
409
|
+
}, dnsFix(input, bad));
|
|
410
|
+
return ok;
|
|
411
|
+
}
|
|
412
|
+
/** How to fix it: `gkm setup`, or the records to create by hand. */
|
|
413
|
+
function dnsFix(input, bad) {
|
|
414
|
+
const hosts = bad.map((h) => h.host);
|
|
415
|
+
let plan;
|
|
416
|
+
try {
|
|
417
|
+
plan = planStackDns({
|
|
418
|
+
stage: input.stage,
|
|
419
|
+
hosts,
|
|
420
|
+
server: input.server,
|
|
421
|
+
dns: input.dns
|
|
422
|
+
});
|
|
423
|
+
} catch {
|
|
424
|
+
plan = {
|
|
425
|
+
stage: input.stage,
|
|
426
|
+
server: input.server,
|
|
427
|
+
domains: [],
|
|
428
|
+
uncovered: hosts
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
const automatic = plan.domains.filter((d) => d.provider !== "manual");
|
|
432
|
+
const byHand = [...plan.domains.filter((d) => d.provider === "manual").flatMap((d) => d.records.map(describe)), ...plan.uncovered.flatMap((host) => [`${host.padEnd(32)} A ${input.server.ipv4}`, ...input.server.ipv6 ? [`${host.padEnd(32)} AAAA ${input.server.ipv6}`] : []])];
|
|
433
|
+
const lines = [];
|
|
434
|
+
if (automatic.length > 0) lines.push(`Fix: gkm setup --stage ${input.stage} writes the records for ${automatic.map((d) => d.domain).join(", ")} (gkm setup --stage ${input.stage} --dry-run shows them first).`);
|
|
435
|
+
if (byHand.length > 0) lines.push(`${automatic.length > 0 ? "And create" : "Fix: create"} these records at the DNS host:`, ...byHand.map((line) => ` ${line}`));
|
|
436
|
+
return lines.join("\n");
|
|
437
|
+
}
|
|
438
|
+
//#endregion
|
|
21
439
|
//#region src/compose/docker.ts
|
|
22
440
|
/**
|
|
23
441
|
* The Docker operations `gkm compose` needs, behind an interface.
|
|
@@ -794,6 +1212,36 @@ function pinImages(file, digests, images) {
|
|
|
794
1212
|
});
|
|
795
1213
|
}
|
|
796
1214
|
//#endregion
|
|
1215
|
+
//#region src/compose/secrets.ts
|
|
1216
|
+
var secrets_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({ deployedStackSecrets: () => deployedStackSecrets });
|
|
1217
|
+
function deployedStackSecrets(workspace, stage, stored, manifest) {
|
|
1218
|
+
const withSeed = require_seeds.withGeneratedSecrets(stored ?? require_seeds.initStageSecrets(stage), manifest);
|
|
1219
|
+
const withLogs = require_workspace.resolveStageTelemetry({
|
|
1220
|
+
...workspace.deploy?.telemetry ? { telemetry: workspace.deploy.telemetry } : {},
|
|
1221
|
+
stage,
|
|
1222
|
+
local: false,
|
|
1223
|
+
target: "compose",
|
|
1224
|
+
runtime: "server",
|
|
1225
|
+
selfHosted: true,
|
|
1226
|
+
used: require_seeds.usesTelemetry(manifest)
|
|
1227
|
+
})?.provider === "self-hosted" ? require_seeds.withLogsPassword(withSeed.secrets) : {
|
|
1228
|
+
secrets: withSeed.secrets,
|
|
1229
|
+
generated: []
|
|
1230
|
+
};
|
|
1231
|
+
const withRedis = require_seeds.runsRedis(manifest, withLogs.secrets.custom ?? {}) ? require_seeds.withRedisPassword(withLogs.secrets) : {
|
|
1232
|
+
secrets: withLogs.secrets,
|
|
1233
|
+
generated: []
|
|
1234
|
+
};
|
|
1235
|
+
return {
|
|
1236
|
+
secrets: withRedis.secrets,
|
|
1237
|
+
generated: [
|
|
1238
|
+
...withSeed.generated,
|
|
1239
|
+
...withLogs.generated,
|
|
1240
|
+
...withRedis.generated
|
|
1241
|
+
]
|
|
1242
|
+
};
|
|
1243
|
+
}
|
|
1244
|
+
//#endregion
|
|
797
1245
|
//#region src/compose/caddyfile.ts
|
|
798
1246
|
/**
|
|
799
1247
|
* The stack's own edge, rendered for Caddy: one site block per route.
|
|
@@ -878,6 +1326,21 @@ const HEADER = `# Generated by gkm compose from the construct manifest — do no
|
|
|
878
1326
|
* address and once on the compose network, because a browser and a sibling
|
|
879
1327
|
* service reach the same API by different names.
|
|
880
1328
|
*/
|
|
1329
|
+
var stack_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
|
|
1330
|
+
EDGE_PORT_ENV: () => EDGE_PORT_ENV,
|
|
1331
|
+
EnvValueMultiline: () => EnvValueMultiline,
|
|
1332
|
+
LOGS_PORT_ENV: () => LOGS_PORT_ENV,
|
|
1333
|
+
LOG_ROTATION: () => LOG_ROTATION,
|
|
1334
|
+
LocalCredentialsMissing: () => LocalCredentialsMissing,
|
|
1335
|
+
NothingToCompose: () => NothingToCompose,
|
|
1336
|
+
StageSecretMissing: () => StageSecretMissing,
|
|
1337
|
+
StageSeedMissing: () => StageSeedMissing,
|
|
1338
|
+
composeProject: () => composeProject,
|
|
1339
|
+
composeStack: () => composeStack,
|
|
1340
|
+
derivedCredentials: () => derivedCredentials,
|
|
1341
|
+
envFile: () => envFile,
|
|
1342
|
+
stackDir: () => stackDir
|
|
1343
|
+
});
|
|
881
1344
|
/** Where a stack's files are written, relative to the workspace root. */
|
|
882
1345
|
function stackDir(stage) {
|
|
883
1346
|
return `.gkm/compose/${stage}`;
|
|
@@ -1111,7 +1574,7 @@ function composeStack(input) {
|
|
|
1111
1574
|
reads.set(app.name, site?.kind === "site" ? Object.values((0, _geekmidas_manifest.publicEnvFor)(site, manifest)) : [...require_seeds.appEnvKeys(manifest, app.name, input.runnables) ?? []]);
|
|
1112
1575
|
}
|
|
1113
1576
|
for (const worker of workers) reads.set(worker.name, [...require_seeds.workerEnvKeys(manifest, worker.id, input.runnables) ?? []]);
|
|
1114
|
-
const domain = workspace.
|
|
1577
|
+
const domain = workspace.domains?.[stage];
|
|
1115
1578
|
const telemetry = require_workspace.resolveStageTelemetry({
|
|
1116
1579
|
...workspace.deploy?.telemetry ? { telemetry: workspace.deploy.telemetry } : {},
|
|
1117
1580
|
stage,
|
|
@@ -1226,6 +1689,7 @@ function composeStack(input) {
|
|
|
1226
1689
|
* they can hold it, and the derivations otherwise.
|
|
1227
1690
|
*/
|
|
1228
1691
|
const valueFor = (app, key, owner) => {
|
|
1692
|
+
if (require_workspace.isReservedStageKey(key)) return void 0;
|
|
1229
1693
|
if (owner && SERVICE_KINDS[owner.kind]) {
|
|
1230
1694
|
if (custom[key] !== void 0) return custom[key];
|
|
1231
1695
|
if (owner.kind === "file-server") return fileServers.get(owner.id)?.url;
|
|
@@ -1509,7 +1973,7 @@ function stackWorkers(units, options) {
|
|
|
1509
1973
|
*/
|
|
1510
1974
|
function hostOf(name, app, workspace, resource, options) {
|
|
1511
1975
|
if (options.local) return require_seeds.hostFor(resource, workspace.name);
|
|
1512
|
-
return require_seeds.resolveHost(name, app, options.stage, workspace.
|
|
1976
|
+
return require_seeds.resolveHost(name, app, options.stage, workspace.domains, require_seeds.isMainFrontendApp(name, app, workspace.apps));
|
|
1513
1977
|
}
|
|
1514
1978
|
/** The compose document: the infrastructure, the apps, and the edge. */
|
|
1515
1979
|
function stackFile(options) {
|
|
@@ -1840,7 +2304,8 @@ const defaultDeps = {
|
|
|
1840
2304
|
probe: httpsProbe,
|
|
1841
2305
|
healthAttempts: 90,
|
|
1842
2306
|
healthIntervalMs: 2e3,
|
|
1843
|
-
env: process.env
|
|
2307
|
+
env: process.env,
|
|
2308
|
+
lookup: systemLookup
|
|
1844
2309
|
};
|
|
1845
2310
|
/**
|
|
1846
2311
|
* The stack the stage would run, and — for a tag — the registry's word that
|
|
@@ -1865,6 +2330,7 @@ async function validateCompose(ctx, deps, options = {}) {
|
|
|
1865
2330
|
background
|
|
1866
2331
|
});
|
|
1867
2332
|
const { secrets, generated } = await stageSecrets(ctx, manifest);
|
|
2333
|
+
const server = push || stage === workspace.stages.local ? void 0 : requiredServerAddress(stage, workspace.domains?.[stage], secrets?.custom);
|
|
1868
2334
|
if (!push) {
|
|
1869
2335
|
require_seeds.assertNoStaleSecrets({
|
|
1870
2336
|
manifest,
|
|
@@ -1915,6 +2381,7 @@ async function validateCompose(ctx, deps, options = {}) {
|
|
|
1915
2381
|
if (stack.tls && !push) {
|
|
1916
2382
|
for (const file of [stack.tls.certFile, stack.tls.keyFile]) if (!(0, node_fs.existsSync)(file)) throw new require_workspace.ComposeTlsFileMissing(stage, file);
|
|
1917
2383
|
}
|
|
2384
|
+
if (!push && !stack.local) await checkDns(ctx, deps, stackHosts(stack).filter((host) => !isLocalHost(host)), server);
|
|
1918
2385
|
if (stack.redis && !stack.local) ctx.secrets.mask(stack.redis.password);
|
|
1919
2386
|
if (stack.logs && (!stack.local || stack.logs.passwordFromSecrets)) {
|
|
1920
2387
|
ctx.secrets.mask(stack.logs.password);
|
|
@@ -1982,35 +2449,46 @@ function assertRedisClient(workspace, stack) {
|
|
|
1982
2449
|
* run goes ahead (`provision`), so a dry run, or a tag that is not there,
|
|
1983
2450
|
* leaves the stage's secrets as it found them.
|
|
1984
2451
|
*/
|
|
2452
|
+
/**
|
|
2453
|
+
* The deploy-time DNS check: each public host resolved with the system
|
|
2454
|
+
* resolver and compared with the server's address from the stage's secrets.
|
|
2455
|
+
* A dry run warns rather than stops.
|
|
2456
|
+
*/
|
|
2457
|
+
async function checkDns(ctx, deps, hosts, server) {
|
|
2458
|
+
const { workspace, stage } = ctx;
|
|
2459
|
+
if (hosts.length === 0) return;
|
|
2460
|
+
if (ctx.skipDnsCheck) {
|
|
2461
|
+
ctx.logger.info("🌐 DNS check skipped (--skip-dns-check)");
|
|
2462
|
+
return;
|
|
2463
|
+
}
|
|
2464
|
+
if (!server) {
|
|
2465
|
+
ctx.logger.info(`🌐 DNS check skipped: no ${require_workspace.SERVER_IPV4_KEY} in '${stage}''s secrets — ${serverAddressHint(stage)}`);
|
|
2466
|
+
return;
|
|
2467
|
+
}
|
|
2468
|
+
try {
|
|
2469
|
+
const ok = await checkStackDns({
|
|
2470
|
+
stage,
|
|
2471
|
+
hosts,
|
|
2472
|
+
server,
|
|
2473
|
+
dns: workspace.dns,
|
|
2474
|
+
lookup: deps.lookup ?? systemLookup
|
|
2475
|
+
});
|
|
2476
|
+
ctx.logger.info(`🌐 ${ok.length} host${ok.length === 1 ? "" : "s"} resolve${ok.length === 1 ? "s" : ""} to ${server.ipv4}`);
|
|
2477
|
+
} catch (error) {
|
|
2478
|
+
if (ctx.dryRun && error instanceof HostNotPointingAtServer) {
|
|
2479
|
+
ctx.logger.warn(`⚠ ${error.message}`);
|
|
2480
|
+
return;
|
|
2481
|
+
}
|
|
2482
|
+
throw error;
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
1985
2485
|
async function stageSecrets(ctx, manifest) {
|
|
1986
2486
|
const stored = await ctx.secrets.read();
|
|
1987
2487
|
if (ctx.stage === ctx.workspace.stages.local) return {
|
|
1988
2488
|
secrets: stored,
|
|
1989
2489
|
generated: []
|
|
1990
2490
|
};
|
|
1991
|
-
const
|
|
1992
|
-
const withLogs = require_workspace.resolveStageTelemetry({
|
|
1993
|
-
...ctx.workspace.deploy?.telemetry ? { telemetry: ctx.workspace.deploy.telemetry } : {},
|
|
1994
|
-
stage: ctx.stage,
|
|
1995
|
-
local: false,
|
|
1996
|
-
target: "compose",
|
|
1997
|
-
runtime: "server",
|
|
1998
|
-
selfHosted: true,
|
|
1999
|
-
used: require_seeds.usesTelemetry(manifest)
|
|
2000
|
-
})?.provider === "self-hosted" ? require_seeds.withLogsPassword(withSeed.secrets) : {
|
|
2001
|
-
secrets: withSeed.secrets,
|
|
2002
|
-
generated: []
|
|
2003
|
-
};
|
|
2004
|
-
const withRedis = require_seeds.runsRedis(manifest, withLogs.secrets.custom ?? {}) ? require_seeds.withRedisPassword(withLogs.secrets) : {
|
|
2005
|
-
secrets: withLogs.secrets,
|
|
2006
|
-
generated: []
|
|
2007
|
-
};
|
|
2008
|
-
const secrets = withRedis.secrets;
|
|
2009
|
-
const generated = [
|
|
2010
|
-
...withSeed.generated,
|
|
2011
|
-
...withLogs.generated,
|
|
2012
|
-
...withRedis.generated
|
|
2013
|
-
];
|
|
2491
|
+
const { secrets, generated } = deployedStackSecrets(ctx.workspace, ctx.stage, stored, manifest);
|
|
2014
2492
|
if (secrets.seed) ctx.secrets.mask(secrets.seed);
|
|
2015
2493
|
for (const value of Object.values(secrets.custom ?? {})) ctx.secrets.mask(value);
|
|
2016
2494
|
return {
|
|
@@ -2675,6 +3153,12 @@ Object.defineProperty(exports, "EDGE_PROJECT", {
|
|
|
2675
3153
|
return EDGE_PROJECT;
|
|
2676
3154
|
}
|
|
2677
3155
|
});
|
|
3156
|
+
Object.defineProperty(exports, "applyStackDns", {
|
|
3157
|
+
enumerable: true,
|
|
3158
|
+
get: function() {
|
|
3159
|
+
return applyStackDns;
|
|
3160
|
+
}
|
|
3161
|
+
});
|
|
2678
3162
|
Object.defineProperty(exports, "composeProject", {
|
|
2679
3163
|
enumerable: true,
|
|
2680
3164
|
get: function() {
|
|
@@ -2717,23 +3201,65 @@ Object.defineProperty(exports, "pinnedRef", {
|
|
|
2717
3201
|
return pinnedRef;
|
|
2718
3202
|
}
|
|
2719
3203
|
});
|
|
3204
|
+
Object.defineProperty(exports, "planStackDns", {
|
|
3205
|
+
enumerable: true,
|
|
3206
|
+
get: function() {
|
|
3207
|
+
return planStackDns;
|
|
3208
|
+
}
|
|
3209
|
+
});
|
|
2720
3210
|
Object.defineProperty(exports, "removeEdgeRoutes", {
|
|
2721
3211
|
enumerable: true,
|
|
2722
3212
|
get: function() {
|
|
2723
3213
|
return removeEdgeRoutes;
|
|
2724
3214
|
}
|
|
2725
3215
|
});
|
|
3216
|
+
Object.defineProperty(exports, "requiredServerAddress", {
|
|
3217
|
+
enumerable: true,
|
|
3218
|
+
get: function() {
|
|
3219
|
+
return requiredServerAddress;
|
|
3220
|
+
}
|
|
3221
|
+
});
|
|
3222
|
+
Object.defineProperty(exports, "secrets_exports", {
|
|
3223
|
+
enumerable: true,
|
|
3224
|
+
get: function() {
|
|
3225
|
+
return secrets_exports;
|
|
3226
|
+
}
|
|
3227
|
+
});
|
|
3228
|
+
Object.defineProperty(exports, "serverAddress", {
|
|
3229
|
+
enumerable: true,
|
|
3230
|
+
get: function() {
|
|
3231
|
+
return serverAddress;
|
|
3232
|
+
}
|
|
3233
|
+
});
|
|
3234
|
+
Object.defineProperty(exports, "serverAddressHint", {
|
|
3235
|
+
enumerable: true,
|
|
3236
|
+
get: function() {
|
|
3237
|
+
return serverAddressHint;
|
|
3238
|
+
}
|
|
3239
|
+
});
|
|
2726
3240
|
Object.defineProperty(exports, "stackDir", {
|
|
2727
3241
|
enumerable: true,
|
|
2728
3242
|
get: function() {
|
|
2729
3243
|
return stackDir;
|
|
2730
3244
|
}
|
|
2731
3245
|
});
|
|
3246
|
+
Object.defineProperty(exports, "stackHosts", {
|
|
3247
|
+
enumerable: true,
|
|
3248
|
+
get: function() {
|
|
3249
|
+
return stackHosts;
|
|
3250
|
+
}
|
|
3251
|
+
});
|
|
2732
3252
|
Object.defineProperty(exports, "stackOverrideFile", {
|
|
2733
3253
|
enumerable: true,
|
|
2734
3254
|
get: function() {
|
|
2735
3255
|
return stackOverrideFile;
|
|
2736
3256
|
}
|
|
2737
3257
|
});
|
|
3258
|
+
Object.defineProperty(exports, "stack_exports", {
|
|
3259
|
+
enumerable: true,
|
|
3260
|
+
get: function() {
|
|
3261
|
+
return stack_exports;
|
|
3262
|
+
}
|
|
3263
|
+
});
|
|
2738
3264
|
|
|
2739
|
-
//# sourceMappingURL=compose-
|
|
3265
|
+
//# sourceMappingURL=compose-BvrhDwJ6.cjs.map
|