@stacksjs/buddy 0.70.205 → 0.70.207
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/commands/deploy.js +18 -32
- package/package.json +2 -2
package/dist/commands/deploy.js
CHANGED
|
@@ -690,7 +690,7 @@ async function runHetznerDeploy(args) {
|
|
|
690
690
|
process.exit(ExitCode.FatalError);
|
|
691
691
|
}
|
|
692
692
|
const attachTo = tsCloudConfig.cloud?.attachTo;
|
|
693
|
-
let ip;
|
|
693
|
+
let ip, ipv6;
|
|
694
694
|
if (attachTo) {
|
|
695
695
|
const box = await resolveAttachTargetBox(attachTo, environment);
|
|
696
696
|
if (!box?.publicIp) {
|
|
@@ -698,6 +698,7 @@ async function runHetznerDeploy(args) {
|
|
|
698
698
|
process.exit(ExitCode.FatalError);
|
|
699
699
|
}
|
|
700
700
|
ip = box.publicIp;
|
|
701
|
+
ipv6 = box.publicIpv6;
|
|
701
702
|
log.info(`Attaching to '${attachTo}' box '${box.serverName}' (${ip}) \u2014 skipping provisioning`);
|
|
702
703
|
const compute = (tsCloudConfig.infrastructure ??= {}).compute ??= {};
|
|
703
704
|
compute.webServer = "rpx";
|
|
@@ -717,6 +718,7 @@ async function runHetznerDeploy(args) {
|
|
|
717
718
|
log.info("Provisioning Hetzner compute infrastructure...");
|
|
718
719
|
const outputs = await driver.provisionComputeInfrastructure({ config: scrubLoopbackSitePortsForFirewall(tsCloudConfig), environment });
|
|
719
720
|
ip = outputs.appPublicIp;
|
|
721
|
+
ipv6 = outputs.appPublicIpv6;
|
|
720
722
|
log.success("Hetzner compute infrastructure ready");
|
|
721
723
|
if (outputs.appInstanceId)
|
|
722
724
|
log.info(`Server ID: ${outputs.appInstanceId}`);
|
|
@@ -815,7 +817,7 @@ async function runHetznerDeploy(args) {
|
|
|
815
817
|
}
|
|
816
818
|
});
|
|
817
819
|
if (ok)
|
|
818
|
-
await reconcileHetznerDns(onlySite ? { [onlySite]: sites[onlySite] } : sites, ip, log);
|
|
820
|
+
await reconcileHetznerDns(onlySite ? { [onlySite]: sites[onlySite] } : sites, ip, log, ipv6);
|
|
819
821
|
if (ok)
|
|
820
822
|
await reconcileConfigDns(onlySite ? { [onlySite]: sites[onlySite] } : sites, log);
|
|
821
823
|
if (ok) {
|
|
@@ -921,7 +923,13 @@ async function resolveAttachTargetBox(owner, environment) {
|
|
|
921
923
|
}, byLabel = await req(`label_selector=${encodeURIComponent(`ts-cloud/project=${owner},ts-cloud/environment=${environment},ts-cloud/role=app`)}`), chosen = pick(byLabel) || pick(await req(`name=${encodeURIComponent(`${owner}-${environment}-app`)}`));
|
|
922
924
|
if (!chosen)
|
|
923
925
|
return null;
|
|
924
|
-
|
|
926
|
+
const { hetznerBoxIpv6 } = await import("@stacksjs/ts-cloud");
|
|
927
|
+
return {
|
|
928
|
+
serverId: chosen.id,
|
|
929
|
+
serverName: chosen.name,
|
|
930
|
+
publicIp: chosen.public_net?.ipv4?.ip,
|
|
931
|
+
publicIpv6: hetznerBoxIpv6?.(chosen.public_net?.ipv6?.ip)
|
|
932
|
+
};
|
|
925
933
|
}
|
|
926
934
|
export async function provisionMailTenant(ip, logger) {
|
|
927
935
|
if (!hasExplicitEmailConfig())
|
|
@@ -1291,22 +1299,7 @@ async function reconcileConfigDns(sites, logger) {
|
|
|
1291
1299
|
logger.warn(`DNS (config/dns.ts) reconcile for ${domain} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1292
1300
|
}
|
|
1293
1301
|
}
|
|
1294
|
-
async function
|
|
1295
|
-
try {
|
|
1296
|
-
if (typeof provider?.listRecords !== "function")
|
|
1297
|
-
return !0;
|
|
1298
|
-
const res = await provider.listRecords(domain);
|
|
1299
|
-
if (!res?.success || !Array.isArray(res.records))
|
|
1300
|
-
return !0;
|
|
1301
|
-
return res.records.some((r) => {
|
|
1302
|
-
const name = typeof r?.name === "string" ? r.name.replace(/\.$/, "") : "";
|
|
1303
|
-
return r?.type === "A" && name === fqdn && r?.content === ip;
|
|
1304
|
-
});
|
|
1305
|
-
} catch {
|
|
1306
|
-
return !0;
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
|
-
async function reconcileHetznerDns(sites, ip, logger) {
|
|
1302
|
+
async function reconcileHetznerDns(sites, ip, logger, ipv6) {
|
|
1310
1303
|
const domains = new Set;
|
|
1311
1304
|
for (const site of Object.values(sites))
|
|
1312
1305
|
if (site?.domain && typeof site.domain === "string")
|
|
@@ -1331,7 +1324,7 @@ async function reconcileHetznerDns(sites, ip, logger) {
|
|
|
1331
1324
|
const {
|
|
1332
1325
|
createDnsProvider,
|
|
1333
1326
|
detectDnsProvider,
|
|
1334
|
-
|
|
1327
|
+
reconcileAddressRecords
|
|
1335
1328
|
} = await import("@stacksjs/ts-cloud");
|
|
1336
1329
|
logger.info("Reconciling DNS records...");
|
|
1337
1330
|
const resolveA = async (fqdn) => {
|
|
@@ -1370,18 +1363,11 @@ async function reconcileHetznerDns(sites, ip, logger) {
|
|
|
1370
1363
|
continue;
|
|
1371
1364
|
}
|
|
1372
1365
|
for (const sub of ["", "www"]) {
|
|
1373
|
-
const fqdn = sub ? `${sub}.${domain}` : domain,
|
|
1374
|
-
|
|
1375
|
-
logger.
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
const cleanupWarnings = await removeStaleServerAddressRecords(provider, domain, fqdn, ip);
|
|
1379
|
-
for (const warning of cleanupWarnings)
|
|
1380
|
-
logger.warn(` DNS: ${fqdn} cleanup: ${warning}`);
|
|
1381
|
-
if (await verifyDnsRecord(provider, domain, fqdn, ip))
|
|
1382
|
-
logger.success(` DNS: ${fqdn} \u2192 ${ip} (${provider.name})`);
|
|
1383
|
-
else
|
|
1384
|
-
logger.warn(` DNS: ${fqdn} \u2192 ${ip} reported success at ${provider.name} but no matching A record exists \u2014 create it manually: A ${fqdn} \u2192 ${ip}`);
|
|
1366
|
+
const fqdn = sub ? `${sub}.${domain}` : domain, report = await reconcileAddressRecords({ provider, zone: domain, fqdn, ipv4: ip, ipv6 });
|
|
1367
|
+
for (const record of report.published)
|
|
1368
|
+
logger.success(` DNS: ${record.fqdn} \u2192 ${record.content} (${provider.name})`);
|
|
1369
|
+
for (const warning of report.warnings)
|
|
1370
|
+
logger.warn(` DNS: ${warning}`);
|
|
1385
1371
|
}
|
|
1386
1372
|
} catch (err) {
|
|
1387
1373
|
logger.warn(` DNS: ${domain} reconciliation failed: ${err?.message || err}`);
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/buddy",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.70.
|
|
5
|
+
"version": "0.70.207",
|
|
6
6
|
"description": "Meet Buddy. The Stacks runtime.",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
"@stacksjs/ui": "^0.70.180",
|
|
138
138
|
"@stacksjs/utils": "^0.70.180",
|
|
139
139
|
"@stacksjs/validation": "^0.70.180",
|
|
140
|
-
"@stacksjs/ts-cloud": "^0.7.
|
|
140
|
+
"@stacksjs/ts-cloud": "^0.7.86",
|
|
141
141
|
"ajv": "^8.20.0",
|
|
142
142
|
"ajv-formats": "^3.0.1"
|
|
143
143
|
},
|