@stacksjs/ts-cloud 0.7.15 → 0.7.17
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/bin/cli.js +458 -458
- package/dist/{chunk-mbpxadga.js → chunk-pr3g0b0t.js} +12 -11
- package/dist/{chunk-6agm101w.js → chunk-qergre5a.js} +44 -17
- package/dist/deploy/index.js +4 -2
- package/dist/deploy/site-target.d.ts +17 -0
- package/dist/drivers/hetzner/driver.d.ts +8 -0
- package/dist/drivers/index.js +1 -1
- package/dist/drivers/shared/rpx-gateway.d.ts +8 -0
- package/dist/index.js +2 -2
- package/dist/ui/index.html +3 -3
- package/dist/ui/server/actions.html +3 -3
- package/dist/ui/server/backups.html +3 -3
- package/dist/ui/server/database.html +3 -3
- package/dist/ui/server/deployments.html +3 -3
- package/dist/ui/server/firewall.html +3 -3
- package/dist/ui/server/logs.html +3 -3
- package/dist/ui/server/services.html +3 -3
- package/dist/ui/server/sites.html +3 -3
- package/dist/ui/server/ssh-keys.html +3 -3
- package/dist/ui/server/terminal.html +3 -3
- package/dist/ui/server/workers.html +3 -3
- package/dist/ui/serverless/alarms.html +3 -3
- package/dist/ui/serverless/assets.html +3 -3
- package/dist/ui/serverless/data.html +3 -3
- package/dist/ui/serverless/deployments.html +3 -3
- package/dist/ui/serverless/functions.html +3 -3
- package/dist/ui/serverless/logs.html +3 -3
- package/dist/ui/serverless/queues.html +3 -3
- package/dist/ui/serverless/scheduler.html +3 -3
- package/dist/ui/serverless/secrets.html +3 -3
- package/dist/ui/serverless/traces.html +3 -3
- package/dist/ui/serverless.html +3 -3
- package/package.json +3 -3
|
@@ -25,8 +25,9 @@ import {
|
|
|
25
25
|
releasePaths,
|
|
26
26
|
resolveSiteFramework,
|
|
27
27
|
resolveSiteKind,
|
|
28
|
-
resolveUiSource
|
|
29
|
-
|
|
28
|
+
resolveUiSource,
|
|
29
|
+
siteInstallBase
|
|
30
|
+
} from "./chunk-qergre5a.js";
|
|
30
31
|
import {
|
|
31
32
|
artifactKey,
|
|
32
33
|
composeServerlessAppTemplate,
|
|
@@ -10284,13 +10285,13 @@ function shellSingleQuote(value) {
|
|
|
10284
10285
|
function sedReplacement(value) {
|
|
10285
10286
|
return value.replace(/[\\&/]/g, "\\$&");
|
|
10286
10287
|
}
|
|
10287
|
-
function deployHistoryScript(siteNames) {
|
|
10288
|
+
function deployHistoryScript(siteNames, slug) {
|
|
10288
10289
|
if (siteNames.length === 0)
|
|
10289
10290
|
return ["true"];
|
|
10290
10291
|
return [
|
|
10291
10292
|
"set +e",
|
|
10292
10293
|
...siteNames.map((siteName) => {
|
|
10293
|
-
const historyPath = shellSingleQuote(
|
|
10294
|
+
const historyPath = shellSingleQuote(`${siteInstallBase(slug, siteName)}/.ts-cloud/deploy-history.log`);
|
|
10294
10295
|
const prefix = sedReplacement(siteName);
|
|
10295
10296
|
return `TS_CLOUD_HISTORY=${historyPath}; { [ -f "$TS_CLOUD_HISTORY" ] && tail -n 24 "$TS_CLOUD_HISTORY" | sed "s/^/DEPLOY=${prefix}\\t/"; } || true`;
|
|
10296
10297
|
}),
|
|
@@ -10673,7 +10674,7 @@ function resolveConfigOnlyServerDashboardData(config6, environment) {
|
|
|
10673
10674
|
const kind = resolveSiteKind(site);
|
|
10674
10675
|
return {
|
|
10675
10676
|
...s,
|
|
10676
|
-
root: kind === "server-static" ?
|
|
10677
|
+
root: kind === "server-static" ? siteInstallBase(config6.project.slug, s.name) : `${siteInstallBase(config6.project.slug, s.name)}/current`,
|
|
10677
10678
|
branch: kind === "server-static" ? "build artifact" : "main",
|
|
10678
10679
|
build: site.build,
|
|
10679
10680
|
php: site.php ?? site.phpVersion,
|
|
@@ -10754,7 +10755,7 @@ async function resolveServerDashboardData(config6, environment) {
|
|
|
10754
10755
|
const siteNames = Object.keys(config6.sites ?? {});
|
|
10755
10756
|
const historyResult = await driver.runRemoteDeploy({
|
|
10756
10757
|
targets: [targets[0]],
|
|
10757
|
-
commands: deployHistoryScript(siteNames),
|
|
10758
|
+
commands: deployHistoryScript(siteNames, config6.project.slug),
|
|
10758
10759
|
comment: `ts-cloud dashboard:deploy-history ${config6.project.slug}`,
|
|
10759
10760
|
tags: { Project: config6.project.slug, Environment: environment, Role: "app" }
|
|
10760
10761
|
});
|
|
@@ -11013,7 +11014,7 @@ async function rollbackComputeSite(ctx, options) {
|
|
|
11013
11014
|
const targets = await findTargets(ctx);
|
|
11014
11015
|
if (targets.length === 0)
|
|
11015
11016
|
return { success: false, error: `No '${ctx.role || "app"}' servers found for ${ctx.slug}/${ctx.environment}.` };
|
|
11016
|
-
const appBase =
|
|
11017
|
+
const appBase = siteInstallBase(ctx.slug, options.siteName);
|
|
11017
11018
|
const paths = releasePaths(appBase, options.to || "unused");
|
|
11018
11019
|
const commands = [
|
|
11019
11020
|
"set -uo pipefail",
|
|
@@ -11139,8 +11140,8 @@ function serviceCommand(verb, target) {
|
|
|
11139
11140
|
function pantryEnvEval() {
|
|
11140
11141
|
return `eval "$(cd ${PANTRY_PROJECT_DIR} && pantry env 2>/dev/null)"`;
|
|
11141
11142
|
}
|
|
11142
|
-
function siteArtisanCommand(site, artisan) {
|
|
11143
|
-
const current =
|
|
11143
|
+
function siteArtisanCommand(slug, site, artisan) {
|
|
11144
|
+
const current = `${siteInstallBase(slug, site)}/current`;
|
|
11144
11145
|
return [
|
|
11145
11146
|
"set -uo pipefail",
|
|
11146
11147
|
`[ -d ${current} ] || { echo "site ${site} has no current release" >&2; exit 1; }`,
|
|
@@ -11149,7 +11150,7 @@ function siteArtisanCommand(site, artisan) {
|
|
|
11149
11150
|
}
|
|
11150
11151
|
function workerRestartCommand(framework, slug, site) {
|
|
11151
11152
|
if (framework === "laravel")
|
|
11152
|
-
return siteArtisanCommand(site, "queue:restart");
|
|
11153
|
+
return siteArtisanCommand(slug, site, "queue:restart");
|
|
11153
11154
|
const pattern = `${slug}-${site}-queue-*.service`;
|
|
11154
11155
|
return [
|
|
11155
11156
|
"set -uo pipefail",
|
|
@@ -11161,7 +11162,7 @@ function workerRestartCommand(framework, slug, site) {
|
|
|
11161
11162
|
}
|
|
11162
11163
|
function schedulerRunCommand(framework, slug, site) {
|
|
11163
11164
|
if (framework === "laravel")
|
|
11164
|
-
return siteArtisanCommand(site, "schedule:run");
|
|
11165
|
+
return siteArtisanCommand(slug, site, "schedule:run");
|
|
11165
11166
|
const unit = `${slug}-${site}-scheduler.service`;
|
|
11166
11167
|
return [
|
|
11167
11168
|
"set -uo pipefail",
|
|
@@ -1659,6 +1659,9 @@ runcmd:
|
|
|
1659
1659
|
}
|
|
1660
1660
|
|
|
1661
1661
|
// src/deploy/site-target.ts
|
|
1662
|
+
function siteInstallBase(slug, siteName) {
|
|
1663
|
+
return `/var/www/${slug}-${siteName}`;
|
|
1664
|
+
}
|
|
1662
1665
|
var PHP_SITE_TYPES = new Set([
|
|
1663
1666
|
"laravel",
|
|
1664
1667
|
"php",
|
|
@@ -1815,6 +1818,7 @@ function resolveServerAppFrom(port, appBoxes) {
|
|
|
1815
1818
|
}
|
|
1816
1819
|
function buildRpxConfigInternal(sites, options, appBoxes) {
|
|
1817
1820
|
const wwwRoot = (options.wwwRoot ?? "/var/www").replace(/\/+$/, "");
|
|
1821
|
+
const installSlug = options.slug ?? "app";
|
|
1818
1822
|
const certsDir = options.proxy.certsDir ?? DEFAULT_RPX_CERTS_DIR;
|
|
1819
1823
|
const loadBalancer = options.proxy.loadBalancer;
|
|
1820
1824
|
const proxies = [];
|
|
@@ -1849,7 +1853,7 @@ function buildRpxConfigInternal(sites, options, appBoxes) {
|
|
|
1849
1853
|
proxies.push({
|
|
1850
1854
|
to: site.domain,
|
|
1851
1855
|
path,
|
|
1852
|
-
static: `${wwwRoot}/${name}/current`,
|
|
1856
|
+
static: `${wwwRoot}/${installSlug}-${name}/current`,
|
|
1853
1857
|
cleanUrls: site.pathRewriteStyle !== "flat",
|
|
1854
1858
|
spa: site.spa ?? false,
|
|
1855
1859
|
...auth ? { auth } : {},
|
|
@@ -2302,7 +2306,7 @@ class HetznerDriver {
|
|
|
2302
2306
|
const sitePorts = this.collectUpstreamPorts(sites);
|
|
2303
2307
|
const rpxProvision = compute.proxy?.engine === "rpx" ? buildRpxProvisionScript({
|
|
2304
2308
|
proxy: compute.proxy,
|
|
2305
|
-
config: buildRpxConfig(sites, { proxy: compute.proxy }),
|
|
2309
|
+
config: buildRpxConfig(sites, { proxy: compute.proxy, slug: config.project.slug }),
|
|
2306
2310
|
slug: config.project.slug,
|
|
2307
2311
|
bunBin: compute.runtime === "node" || compute.runtime === "deno" ? undefined : "/usr/local/bin/bun"
|
|
2308
2312
|
}) : undefined;
|
|
@@ -2651,7 +2655,7 @@ class HetznerDriver {
|
|
|
2651
2655
|
const rpxProxy = compute.proxy?.engine === "rpx" ? compute.proxy : { engine: "rpx" };
|
|
2652
2656
|
const lbRpxProvision = buildRpxProvisionScript({
|
|
2653
2657
|
proxy: rpxProxy,
|
|
2654
|
-
config: buildRpxLbConfig(sites, appBoxes, { proxy: rpxProxy }),
|
|
2658
|
+
config: buildRpxLbConfig(sites, appBoxes, { proxy: rpxProxy, slug }),
|
|
2655
2659
|
slug,
|
|
2656
2660
|
bunBin: appProvisionScripts.runtime === "node" || appProvisionScripts.runtime === "deno" ? undefined : "/usr/local/bin/bun"
|
|
2657
2661
|
});
|
|
@@ -3015,11 +3019,20 @@ ${out}`);
|
|
|
3015
3019
|
"-o",
|
|
3016
3020
|
"LogLevel=ERROR"
|
|
3017
3021
|
];
|
|
3022
|
+
static SSH_KEEPALIVE_OPTS = [
|
|
3023
|
+
"-o",
|
|
3024
|
+
"ConnectTimeout=30",
|
|
3025
|
+
"-o",
|
|
3026
|
+
"ServerAliveInterval=15",
|
|
3027
|
+
"-o",
|
|
3028
|
+
"ServerAliveCountMax=4"
|
|
3029
|
+
];
|
|
3018
3030
|
sshBaseArgs(host, extra = []) {
|
|
3019
3031
|
return [
|
|
3020
3032
|
"-i",
|
|
3021
3033
|
this.sshPrivateKeyPath,
|
|
3022
3034
|
...HetznerDriver.SSH_HOST_KEY_OPTS,
|
|
3035
|
+
...HetznerDriver.SSH_KEEPALIVE_OPTS,
|
|
3023
3036
|
"-o",
|
|
3024
3037
|
"BatchMode=yes",
|
|
3025
3038
|
...extra,
|
|
@@ -3027,16 +3040,27 @@ ${out}`);
|
|
|
3027
3040
|
];
|
|
3028
3041
|
}
|
|
3029
3042
|
scpToHost(host, localPath, remotePath) {
|
|
3030
|
-
|
|
3043
|
+
const cmd = [
|
|
3031
3044
|
"scp",
|
|
3032
3045
|
"-i",
|
|
3033
3046
|
this.sshPrivateKeyPath,
|
|
3034
3047
|
...HetznerDriver.SSH_HOST_KEY_OPTS,
|
|
3048
|
+
...HetznerDriver.SSH_KEEPALIVE_OPTS,
|
|
3035
3049
|
"-o",
|
|
3036
3050
|
"BatchMode=yes",
|
|
3037
3051
|
localPath,
|
|
3038
3052
|
`${this.sshUser}@${host}:${remotePath}`
|
|
3039
|
-
].map((arg) => `"${arg.replace(/"/g, "\\\"")}"`).join(" ")
|
|
3053
|
+
].map((arg) => `"${arg.replace(/"/g, "\\\"")}"`).join(" ");
|
|
3054
|
+
const attempts = 3;
|
|
3055
|
+
for (let attempt = 1;attempt <= attempts; attempt++) {
|
|
3056
|
+
try {
|
|
3057
|
+
execSync(cmd, { stdio: "pipe", maxBuffer: SSH_MAX_BUFFER });
|
|
3058
|
+
return;
|
|
3059
|
+
} catch (error) {
|
|
3060
|
+
if (attempt === attempts)
|
|
3061
|
+
throw new Error(formatSshFailure(error));
|
|
3062
|
+
}
|
|
3063
|
+
}
|
|
3040
3064
|
}
|
|
3041
3065
|
sshExec(host, script) {
|
|
3042
3066
|
const escaped = script.replace(/'/g, `'\\''`);
|
|
@@ -4384,26 +4408,26 @@ async function deploySiteRelease(driver, options, logger = noopLogger2) {
|
|
|
4384
4408
|
if (isPhpSite(site)) {
|
|
4385
4409
|
const compute2 = config.infrastructure?.compute;
|
|
4386
4410
|
const phpVersion = site.phpVersion ?? compute2?.php?.default ?? compute2?.php?.versions?.[0];
|
|
4387
|
-
const
|
|
4411
|
+
const appBase2 = siteInstallBase(slug, siteName);
|
|
4388
4412
|
const dbEnv = outputs.servicesPrivateIp ? buildFleetServicesEnv(outputs.servicesPrivateIp, config.infrastructure?.appDatabase) : buildManagedDbEnv(config.infrastructure?.appDatabase);
|
|
4389
4413
|
const siteWithEnv = Object.keys(dbEnv).length > 0 ? { ...site, env: { ...dbEnv, ...site.env || {} } } : site;
|
|
4390
4414
|
const deployScript = buildLaravelDeployScript({
|
|
4391
4415
|
siteName,
|
|
4392
4416
|
site: siteWithEnv,
|
|
4393
4417
|
releaseId: sha,
|
|
4394
|
-
appBase,
|
|
4418
|
+
appBase: appBase2,
|
|
4395
4419
|
defaultPhpVersion: phpVersion
|
|
4396
4420
|
});
|
|
4397
4421
|
const useNginx = compute2?.webServer !== "rpx";
|
|
4398
4422
|
const sslProvider = resolveSslProvider(site);
|
|
4399
4423
|
const customCert = sslProvider === "custom" && site.ssl?.certPath && site.ssl?.keyPath ? { certPath: site.ssl.certPath, keyPath: site.ssl.keyPath } : undefined;
|
|
4400
|
-
const poolScript = site.isolation ? buildPhpFpmPoolScript({ siteName, appBase }) : [];
|
|
4424
|
+
const poolScript = site.isolation ? buildPhpFpmPoolScript({ siteName, appBase: appBase2 }) : [];
|
|
4401
4425
|
const vhostScript = useNginx ? buildNginxVhostScript({
|
|
4402
4426
|
siteName,
|
|
4403
4427
|
domain: site.domain || siteName,
|
|
4404
4428
|
aliases: site.aliases,
|
|
4405
4429
|
type: site.type,
|
|
4406
|
-
appDir: `${
|
|
4430
|
+
appDir: `${appBase2}/current`,
|
|
4407
4431
|
webDirectory: site.webDirectory,
|
|
4408
4432
|
phpVersion,
|
|
4409
4433
|
fastcgiPass: site.isolation ? phpFpmPoolListen(siteName) : undefined,
|
|
@@ -4417,12 +4441,12 @@ async function deploySiteRelease(driver, options, logger = noopLogger2) {
|
|
|
4417
4441
|
security: site.security
|
|
4418
4442
|
}) : [];
|
|
4419
4443
|
const sslScript = useNginx ? buildSslScript(site) : [];
|
|
4420
|
-
const servicesScript2 = siteHasServices(site) ? buildSiteServicesScript({ slug, siteName, site, phpVersion, appBase }) : [];
|
|
4444
|
+
const servicesScript2 = siteHasServices(site) ? buildSiteServicesScript({ slug, siteName, site, phpVersion, appBase: appBase2 }) : [];
|
|
4421
4445
|
const healthCheckScript = useNginx ? buildHealthCheckScript(site) : [];
|
|
4422
4446
|
logger.step(`Deploying PHP site '${siteName}' to ${targets.length} target(s)...`);
|
|
4423
4447
|
const phpResult = await driver.runRemoteDeploy({
|
|
4424
4448
|
targets,
|
|
4425
|
-
commands: [...buildSiteOwnerGuard(
|
|
4449
|
+
commands: [...buildSiteOwnerGuard(appBase2, slug), ...deployScript, ...poolScript, ...vhostScript, ...sslScript, ...servicesScript2, ...healthCheckScript],
|
|
4426
4450
|
comment: `ts-cloud deploy ${slug}/${siteName}@${sha}`,
|
|
4427
4451
|
tags: { Project: slug, Environment: environment, Role: "app" }
|
|
4428
4452
|
});
|
|
@@ -4455,14 +4479,17 @@ async function deploySiteRelease(driver, options, logger = noopLogger2) {
|
|
|
4455
4479
|
});
|
|
4456
4480
|
const artifactFetch = driver.name === "aws" ? buildAwsArtifactFetch(outputs.deployBucketName, remoteKey, config.project.region || "us-east-1", siteName) : buildLocalArtifactFetch(uploadResult.artifactRef, siteName);
|
|
4457
4481
|
const kind = resolveSiteKind(site);
|
|
4482
|
+
const appBase = siteInstallBase(slug, siteName);
|
|
4458
4483
|
const baseScript = kind === "server-static" ? buildStaticSiteDeployScript({
|
|
4459
4484
|
siteName,
|
|
4485
|
+
appDir: appBase,
|
|
4460
4486
|
artifactFetch,
|
|
4461
4487
|
releaseId: sha,
|
|
4462
4488
|
preStartCommands: site.preStart
|
|
4463
4489
|
}) : buildSiteDeployScript({
|
|
4464
4490
|
siteName,
|
|
4465
4491
|
slug,
|
|
4492
|
+
appDir: appBase,
|
|
4466
4493
|
artifactFetch,
|
|
4467
4494
|
releaseId: sha,
|
|
4468
4495
|
execStart: resolveExecStart(site.start, runtime),
|
|
@@ -4479,7 +4506,7 @@ async function deploySiteRelease(driver, options, logger = noopLogger2) {
|
|
|
4479
4506
|
domain: site.domain,
|
|
4480
4507
|
aliases: site.aliases,
|
|
4481
4508
|
type: site.type === "spa" ? "spa" : "static",
|
|
4482
|
-
appDir:
|
|
4509
|
+
appDir: `${appBase}/current`,
|
|
4483
4510
|
webDirectory: "",
|
|
4484
4511
|
redirects: site.redirects,
|
|
4485
4512
|
auth: site.auth && site.auth.enabled !== false && site.auth.password ? { username: site.auth.username || "admin", password: site.auth.password, realm: site.auth.realm } : undefined,
|
|
@@ -4490,14 +4517,14 @@ async function deploySiteRelease(driver, options, logger = noopLogger2) {
|
|
|
4490
4517
|
security: site.security
|
|
4491
4518
|
}) : [];
|
|
4492
4519
|
const staticSsl = wantsNginxStatic ? buildSslScript(site) : [];
|
|
4493
|
-
const servicesScript = siteHasServices(site) ? buildSiteServicesScript({ slug, siteName, site, appBase
|
|
4520
|
+
const servicesScript = siteHasServices(site) ? buildSiteServicesScript({ slug, siteName, site, appBase }) : [];
|
|
4494
4521
|
const remoteScript = [
|
|
4495
|
-
...buildDeployHistoryHeader(
|
|
4522
|
+
...buildDeployHistoryHeader(appBase, {
|
|
4496
4523
|
releaseId: sha,
|
|
4497
4524
|
commit: sha,
|
|
4498
4525
|
branch: site.branch ?? "main"
|
|
4499
4526
|
}),
|
|
4500
|
-
...buildSiteOwnerGuard(
|
|
4527
|
+
...buildSiteOwnerGuard(appBase, slug),
|
|
4501
4528
|
...baseScript,
|
|
4502
4529
|
...staticVhost,
|
|
4503
4530
|
...staticSsl,
|
|
@@ -4620,7 +4647,7 @@ async function reloadRpxGateway(options) {
|
|
|
4620
4647
|
if (proxy?.engine !== "rpx")
|
|
4621
4648
|
return true;
|
|
4622
4649
|
const sites = routeSource.sites || {};
|
|
4623
|
-
const rpxConfig = buildRpxConfig(sites, { proxy });
|
|
4650
|
+
const rpxConfig = buildRpxConfig(sites, { proxy, slug: config.project.slug });
|
|
4624
4651
|
if (rpxConfig.proxies.length === 0) {
|
|
4625
4652
|
logger.warn("rpx gateway: no server sites with a domain to route — skipping gateway reload.");
|
|
4626
4653
|
return true;
|
|
@@ -4734,4 +4761,4 @@ function buildCloudFrontOriginConfig(options) {
|
|
|
4734
4761
|
CustomErrorResponses: { Quantity: 0 }
|
|
4735
4762
|
};
|
|
4736
4763
|
}
|
|
4737
|
-
export { isPhpSite, resolveSiteDeployTarget, resolveSiteKind, validateDeploymentConfig, PANTRY_PROJECT_DIR, BACKUP_RUNNER_PATH, buildBackupRestoreScript, buildUbuntuBootstrapScript, AwsDriver, HetznerClient, resolveHetznerApiToken, normalizeSshPublicKey, wrapCloudInitUserData, DEFAULT_RPX_CERTS_DIR, normalizeRoutePath, deriveRouteId, buildRpxConfig, buildRpxLbConfig, renderRpxLauncher, RPX_DIR, RPX_LAUNCHER_PATH, RPX_SERVICE_NAME, buildRpxProvisionScript, HetznerDriver, LocalBoxDriver, isBoxMode, createCloudDriver, CloudDriverFactory, cloudDrivers, ensureSshKey, ensureFirewall, ensureServer, serverPublicIpv4, buildSshArgs, sshExec, sshExecOrThrow, scpUpload, waitForSsh, waitForCloudInit, UBUNTU_2404_AMI_PARAM, buildBoxUserData, HetznerBoxProvisioner, AwsBoxProvisioner, createBoxProvisioner, releasePaths, buildRollbackScript, resolveExecStart, buildSiteDeployScript, buildStaticSiteDeployScript, buildAwsArtifactFetch, buildLocalArtifactFetch, MANAGEMENT_DASHBOARD_SITE, DASHBOARD_CREDENTIALS_FILE, resolveDashboardAuth, resolveUiSource, ensureManagementDashboard, buildManagementDashboardArtifact, resolveSiteFramework, deploySiteRelease, deployAllComputeSites, reloadRpxGateway, MANAGED_CACHE_POLICY_OPTIMIZED, MANAGED_CACHE_POLICY_DISABLED, MANAGED_ORIGIN_REQUEST_POLICY_ALL_VIEWER, buildCloudFrontOriginConfig };
|
|
4764
|
+
export { siteInstallBase, isPhpSite, resolveSiteDeployTarget, resolveSiteKind, validateDeploymentConfig, PANTRY_PROJECT_DIR, BACKUP_RUNNER_PATH, buildBackupRestoreScript, buildUbuntuBootstrapScript, AwsDriver, HetznerClient, resolveHetznerApiToken, normalizeSshPublicKey, wrapCloudInitUserData, DEFAULT_RPX_CERTS_DIR, normalizeRoutePath, deriveRouteId, buildRpxConfig, buildRpxLbConfig, renderRpxLauncher, RPX_DIR, RPX_LAUNCHER_PATH, RPX_SERVICE_NAME, buildRpxProvisionScript, HetznerDriver, LocalBoxDriver, isBoxMode, createCloudDriver, CloudDriverFactory, cloudDrivers, ensureSshKey, ensureFirewall, ensureServer, serverPublicIpv4, buildSshArgs, sshExec, sshExecOrThrow, scpUpload, waitForSsh, waitForCloudInit, UBUNTU_2404_AMI_PARAM, buildBoxUserData, HetznerBoxProvisioner, AwsBoxProvisioner, createBoxProvisioner, releasePaths, buildRollbackScript, resolveExecStart, buildSiteDeployScript, buildStaticSiteDeployScript, buildAwsArtifactFetch, buildLocalArtifactFetch, MANAGEMENT_DASHBOARD_SITE, DASHBOARD_CREDENTIALS_FILE, resolveDashboardAuth, resolveUiSource, ensureManagementDashboard, buildManagementDashboardArtifact, resolveSiteFramework, deploySiteRelease, deployAllComputeSites, reloadRpxGateway, MANAGED_CACHE_POLICY_OPTIMIZED, MANAGED_CACHE_POLICY_DISABLED, MANAGED_ORIGIN_REQUEST_POLICY_ALL_VIEWER, buildCloudFrontOriginConfig };
|
package/dist/deploy/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
sanitizeCloudConfig,
|
|
13
13
|
setMaintenance,
|
|
14
14
|
startLocalDashboardServer
|
|
15
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-pr3g0b0t.js";
|
|
16
16
|
import {
|
|
17
17
|
buildAndPushServerlessImage
|
|
18
18
|
} from "../chunk-qgnyzfmx.js";
|
|
@@ -28,8 +28,9 @@ import {
|
|
|
28
28
|
resolveSiteDeployTarget,
|
|
29
29
|
resolveSiteKind,
|
|
30
30
|
resolveUiSource,
|
|
31
|
+
siteInstallBase,
|
|
31
32
|
validateDeploymentConfig
|
|
32
|
-
} from "../chunk-
|
|
33
|
+
} from "../chunk-qergre5a.js";
|
|
33
34
|
import"../chunk-49nmy775.js";
|
|
34
35
|
import"../chunk-93hjhs78.js";
|
|
35
36
|
import {
|
|
@@ -54,6 +55,7 @@ export {
|
|
|
54
55
|
validateDeploymentConfig,
|
|
55
56
|
uploadStaticFiles,
|
|
56
57
|
startLocalDashboardServer,
|
|
58
|
+
siteInstallBase,
|
|
57
59
|
setMaintenance,
|
|
58
60
|
sanitizeCloudConfig,
|
|
59
61
|
runRemoteCommand,
|
|
@@ -10,6 +10,23 @@ import type { CloudConfig, SiteConfig, SiteDeployTarget } from '@ts-cloud/core';
|
|
|
10
10
|
* the gateway answers `domain` with an HTTP redirect.
|
|
11
11
|
*/
|
|
12
12
|
export type SiteDeployKind = 'bucket' | 'server-app' | 'server-static' | 'server-php' | 'redirect';
|
|
13
|
+
/**
|
|
14
|
+
* On-disk base directory for a site's atomic release tree
|
|
15
|
+
* (`<base>/releases/<sha>` + `<base>/current`).
|
|
16
|
+
*
|
|
17
|
+
* Namespaced by the project **slug** so that on a shared / multi-tenant box
|
|
18
|
+
* (`cloud.attachTo`) two projects — or a tenant and the box owner — can never
|
|
19
|
+
* collide on the same `/var/www/<name>` path. A bare `/var/www/<siteName>`
|
|
20
|
+
* meant that e.g. every project with a `main` site fought over `/var/www/main`,
|
|
21
|
+
* silently overwriting each other's releases and round-robining stale responses
|
|
22
|
+
* on the shared port. This mirrors the systemd unit naming (`<slug>-<siteName>`)
|
|
23
|
+
* so a release directory and the service that runs it share one identity.
|
|
24
|
+
*
|
|
25
|
+
* MUST be the single source of truth for the install path — deploy, rpx routing
|
|
26
|
+
* (server-static), rollback/ops, and dashboard data all derive from it, so they
|
|
27
|
+
* can never diverge.
|
|
28
|
+
*/
|
|
29
|
+
export declare function siteInstallBase(slug: string, siteName: string): string;
|
|
13
30
|
/**
|
|
14
31
|
* A PHP/Laravel site: deployed to the compute box via git clone into atomic
|
|
15
32
|
* release directories and served by nginx + php-fpm. Identified by a PHP
|
|
@@ -135,6 +135,14 @@ export declare class HetznerDriver implements CloudDriver {
|
|
|
135
135
|
* `REMOTE HOST IDENTIFICATION HAS CHANGED`.
|
|
136
136
|
*/
|
|
137
137
|
private static readonly SSH_HOST_KEY_OPTS;
|
|
138
|
+
/**
|
|
139
|
+
* Keepalive + connect timeout for every ssh/scp. Without these a connection
|
|
140
|
+
* that stalls mid-transfer (a flaky network, an sshd hiccup) hangs the deploy
|
|
141
|
+
* FOREVER — execSync has no timeout, so a dead socket blocks the whole run.
|
|
142
|
+
* ServerAlive probes abort a silent connection after ~60s (15s × 4) so the
|
|
143
|
+
* transfer fails loudly (and, for scp, is retried) instead of wedging.
|
|
144
|
+
*/
|
|
145
|
+
private static readonly SSH_KEEPALIVE_OPTS;
|
|
138
146
|
private sshBaseArgs;
|
|
139
147
|
private scpToHost;
|
|
140
148
|
private sshExec;
|
package/dist/drivers/index.js
CHANGED
|
@@ -138,6 +138,14 @@ export interface BuildRpxConfigOptions {
|
|
|
138
138
|
proxy: ComputeProxyConfig;
|
|
139
139
|
/** Directory static sites are shipped to. @default '/var/www' */
|
|
140
140
|
wwwRoot?: string;
|
|
141
|
+
/**
|
|
142
|
+
* Project slug — server-static routes are served from the slug-namespaced
|
|
143
|
+
* install dir (`<wwwRoot>/<slug>-<name>/current`), matching where the deploy
|
|
144
|
+
* ships them (see {@link siteInstallBase}). Omitted ⇒ `app` (single-tenant
|
|
145
|
+
* back-compat). MUST be set on a shared box or static routes point at the
|
|
146
|
+
* wrong directory.
|
|
147
|
+
*/
|
|
148
|
+
slug?: string;
|
|
141
149
|
}
|
|
142
150
|
/**
|
|
143
151
|
* Normalize a path prefix to a leading-slash, no-trailing-slash form, or
|
package/dist/index.js
CHANGED
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
sanitizeCloudConfig,
|
|
56
56
|
setMaintenance,
|
|
57
57
|
startLocalDashboardServer
|
|
58
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-pr3g0b0t.js";
|
|
59
59
|
import {
|
|
60
60
|
buildAndPushServerlessImage
|
|
61
61
|
} from "./chunk-qgnyzfmx.js";
|
|
@@ -105,7 +105,7 @@ import {
|
|
|
105
105
|
waitForCloudInit,
|
|
106
106
|
waitForSsh,
|
|
107
107
|
wrapCloudInitUserData
|
|
108
|
-
} from "./chunk-
|
|
108
|
+
} from "./chunk-qergre5a.js";
|
|
109
109
|
import {
|
|
110
110
|
ABTestManager,
|
|
111
111
|
AI,
|