@stacksjs/ts-cloud 0.7.60 → 0.7.62
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 +365 -365
- package/dist/{chunk-cz17nhnx.js → chunk-ff77qy0c.js} +1 -1
- package/dist/{chunk-sd9h1baj.js → chunk-vx2yva1a.js} +55 -9
- package/dist/deploy/index.js +2 -2
- package/dist/drivers/index.js +1 -1
- package/dist/drivers/shared/releases.d.ts +43 -0
- package/dist/index.js +2 -2
- package/dist/ui/account/automation.html +3 -3
- package/dist/ui/account/security.html +2 -2
- package/dist/ui/applications/compose.html +4 -4
- package/dist/ui/applications/new.html +2 -2
- package/dist/ui/data/backups.html +4 -4
- package/dist/ui/data/services.html +4 -4
- package/dist/ui/data/volumes.html +4 -4
- package/dist/ui/index.html +4 -4
- package/dist/ui/operations/alerts.html +4 -4
- package/dist/ui/operations/configuration.html +4 -4
- package/dist/ui/operations/jobs.html +4 -4
- package/dist/ui/operations/maintenance.html +3 -3
- package/dist/ui/operations/observability.html +4 -4
- package/dist/ui/operations/previews.html +3 -3
- package/dist/ui/operations/queue.html +3 -3
- package/dist/ui/operations/regions.html +3 -3
- package/dist/ui/operations/releases.html +3 -3
- package/dist/ui/operations/workloads.html +4 -4
- package/dist/ui/security.html +2 -2
- package/dist/ui/server/actions.html +3 -3
- package/dist/ui/server/activity.html +2 -2
- package/dist/ui/server/capacity.html +4 -4
- package/dist/ui/server/database.html +3 -3
- package/dist/ui/server/deployments.html +4 -4
- package/dist/ui/server/diagnostics.html +2 -2
- package/dist/ui/server/firewall.html +4 -4
- package/dist/ui/server/fleet.html +4 -4
- package/dist/ui/server/logs.html +4 -4
- package/dist/ui/server/metrics.html +2 -2
- package/dist/ui/server/security.html +2 -2
- package/dist/ui/server/services.html +2 -2
- package/dist/ui/server/sites.html +4 -4
- package/dist/ui/server/ssh-keys.html +4 -4
- package/dist/ui/server/team.html +4 -4
- package/dist/ui/server/terminal.html +2 -2
- package/dist/ui/serverless/alarms.html +4 -4
- package/dist/ui/serverless/assets.html +2 -2
- package/dist/ui/serverless/cost.html +2 -2
- package/dist/ui/serverless/data.html +4 -4
- package/dist/ui/serverless/deployments.html +2 -2
- package/dist/ui/serverless/functions.html +4 -4
- package/dist/ui/serverless/logs.html +4 -4
- package/dist/ui/serverless/metrics.html +2 -2
- package/dist/ui/serverless/queues.html +4 -4
- package/dist/ui/serverless/secrets.html +4 -4
- package/dist/ui/serverless/traces.html +4 -4
- package/dist/ui/serverless.html +4 -4
- package/package.json +3 -3
|
@@ -3808,6 +3808,48 @@ function buildEnsureReleaseLayout(paths, sharedPaths = DEFAULT_SHARED_PATHS) {
|
|
|
3808
3808
|
}
|
|
3809
3809
|
return lines;
|
|
3810
3810
|
}
|
|
3811
|
+
function buildDeployLock(paths, waitSeconds = 900) {
|
|
3812
|
+
const lock = `${deployMetaDir(paths.base)}/deploy.lock`;
|
|
3813
|
+
return [
|
|
3814
|
+
`mkdir -p "$(dirname ${lock})"`,
|
|
3815
|
+
`exec 9>${lock}`,
|
|
3816
|
+
`flock -w ${waitSeconds} 9 || { echo "[ts-cloud] another deploy of this site has held the lock for ${waitSeconds}s — refusing to race it" >&2; exit 1; }`
|
|
3817
|
+
];
|
|
3818
|
+
}
|
|
3819
|
+
function buildResetReleaseDir(paths) {
|
|
3820
|
+
const staging = `${paths.release}.incoming`;
|
|
3821
|
+
return [
|
|
3822
|
+
`rm -rf ${staging}`,
|
|
3823
|
+
`mkdir -p ${staging}`,
|
|
3824
|
+
...buildIsReleaseLive(paths),
|
|
3825
|
+
'if [ "$TS_CLOUD_IS_LIVE" = "yes" ]; then',
|
|
3826
|
+
` TS_CLOUD_STAGED=${staging}`,
|
|
3827
|
+
"else",
|
|
3828
|
+
` rm -rf ${paths.release}`,
|
|
3829
|
+
` mkdir -p ${paths.release}`,
|
|
3830
|
+
` rmdir ${staging}`,
|
|
3831
|
+
` TS_CLOUD_STAGED=${paths.release}`,
|
|
3832
|
+
"fi"
|
|
3833
|
+
];
|
|
3834
|
+
}
|
|
3835
|
+
function buildIsReleaseLive(paths) {
|
|
3836
|
+
return [
|
|
3837
|
+
`TS_CLOUD_LIVE_PATH="$(readlink -f ${paths.current} 2>/dev/null || true)"`,
|
|
3838
|
+
`TS_CLOUD_RELEASE_PATH="$(readlink -f ${paths.release} 2>/dev/null || echo ${paths.release})"`,
|
|
3839
|
+
'if [ -n "$TS_CLOUD_LIVE_PATH" ] && [ "$TS_CLOUD_LIVE_PATH" = "$TS_CLOUD_RELEASE_PATH" ]; then TS_CLOUD_IS_LIVE=yes; else TS_CLOUD_IS_LIVE=no; fi'
|
|
3840
|
+
];
|
|
3841
|
+
}
|
|
3842
|
+
function buildPromoteStagedRelease(paths) {
|
|
3843
|
+
const staging = `${paths.release}.incoming`;
|
|
3844
|
+
return [
|
|
3845
|
+
`if [ "$TS_CLOUD_STAGED" = "${staging}" ]; then`,
|
|
3846
|
+
` rm -rf ${paths.release}.previous`,
|
|
3847
|
+
` mv ${paths.release} ${paths.release}.previous`,
|
|
3848
|
+
` mv ${staging} ${paths.release}`,
|
|
3849
|
+
` rm -rf ${paths.release}.previous`,
|
|
3850
|
+
"fi"
|
|
3851
|
+
];
|
|
3852
|
+
}
|
|
3811
3853
|
function buildLinkSharedPaths(paths, sharedPaths = DEFAULT_SHARED_PATHS) {
|
|
3812
3854
|
const lines = [];
|
|
3813
3855
|
for (const p of sharedPaths) {
|
|
@@ -3921,17 +3963,19 @@ function buildSiteDeployScript(options) {
|
|
|
3921
3963
|
const preStart = preStartCommands.length > 0 ? [`cd ${paths.release}`, ...preStartCommands] : [];
|
|
3922
3964
|
const stageRelease = [
|
|
3923
3965
|
"set -euo pipefail",
|
|
3924
|
-
|
|
3966
|
+
...buildDeployLock(paths),
|
|
3967
|
+
...buildIsReleaseLive(paths),
|
|
3968
|
+
`trap 'if [ $? -ne 0 ] && [ "$TS_CLOUD_IS_LIVE" != "yes" ]; then rm -rf ${paths.release}; fi' EXIT`,
|
|
3925
3969
|
...artifactFetch,
|
|
3926
3970
|
...buildEnsureReleaseLayout(paths, sharedPaths),
|
|
3927
|
-
|
|
3928
|
-
`
|
|
3929
|
-
`tar xzf ${tarball} -C ${paths.release}`,
|
|
3971
|
+
...buildResetReleaseDir(paths),
|
|
3972
|
+
`tar xzf ${tarball} -C "$TS_CLOUD_STAGED"`,
|
|
3930
3973
|
`rm -f ${tarball}`,
|
|
3931
3974
|
`cat > ${paths.shared}/.env <<'TS_CLOUD_ENV_EOF'`,
|
|
3932
3975
|
envFile,
|
|
3933
3976
|
"TS_CLOUD_ENV_EOF",
|
|
3934
3977
|
`chmod 600 ${paths.shared}/.env`,
|
|
3978
|
+
...buildPromoteStagedRelease(paths),
|
|
3935
3979
|
`for TS_CLOUD_ENV in ${paths.shared}/.env ${paths.release}/.env ${paths.release}/.env.*; do [ -f "$TS_CLOUD_ENV" ] && sed -i -E '/^[[:space:]]*(PORT|PORT_BACKEND|PORT_ADMIN|PORT_FRONTEND)[[:space:]]*=/d' "$TS_CLOUD_ENV" 2>/dev/null || true; done`,
|
|
3936
3980
|
...buildLinkSharedPaths(paths, sharedPaths),
|
|
3937
3981
|
...preStart
|
|
@@ -3962,7 +4006,7 @@ function buildSiteDeployScript(options) {
|
|
|
3962
4006
|
"systemctl daemon-reload",
|
|
3963
4007
|
`TS_CLOUD_OLD_UNITS=$(systemctl list-units --plain --no-legend --type=service "${unitBase}@*.service" 2>/dev/null | awk '{print $1}' | grep -v "^${instance}$" || true)`,
|
|
3964
4008
|
`if [ -f /etc/systemd/system/${serviceName} ] && systemctl is-active --quiet ${serviceName}; then echo "[ts-cloud] retiring pre-zero-downtime unit ${serviceName} (one-time restart cutover)"; systemctl stop ${serviceName}; fi`,
|
|
3965
|
-
`systemctl
|
|
4009
|
+
`systemctl restart ${instance}`,
|
|
3966
4010
|
`TS_CLOUD_GATE_OK=1; for TS_CLOUD_I in $(seq 1 ${Math.max(1, healthGateSeconds)}); do sleep 1; systemctl is-active --quiet ${instance} || { TS_CLOUD_GATE_OK=0; break; }; done`,
|
|
3967
4011
|
`if [ "$TS_CLOUD_GATE_OK" -ne 1 ]; then echo "[ts-cloud] release ${releaseId} could not overlap the previous release (no SO_REUSEPORT?) — retiring old instances and retrying" >&2; for TS_CLOUD_RU in \${TS_CLOUD_OLD_UNITS}; do systemctl stop "$TS_CLOUD_RU" 2>/dev/null || true; done; systemctl restart ${instance}; for TS_CLOUD_I in $(seq 1 ${Math.max(1, healthGateSeconds)}); do sleep 1; systemctl is-active --quiet ${instance} || ${failGate}; done; fi`,
|
|
3968
4012
|
...gatePath ? [`curl -sf -o /dev/null --max-time 10 "http://127.0.0.1:${port}${gatePath}" || ${failGate}`] : [],
|
|
@@ -4009,12 +4053,14 @@ function buildStaticSiteDeployScript(options) {
|
|
|
4009
4053
|
const preStart = preStartCommands.length > 0 ? [`cd ${paths.release}`, ...preStartCommands] : [];
|
|
4010
4054
|
return [
|
|
4011
4055
|
"set -euo pipefail",
|
|
4012
|
-
|
|
4056
|
+
...buildDeployLock(paths),
|
|
4057
|
+
...buildIsReleaseLive(paths),
|
|
4058
|
+
`trap 'if [ $? -ne 0 ] && [ "$TS_CLOUD_IS_LIVE" != "yes" ]; then rm -rf ${paths.release}; fi' EXIT`,
|
|
4013
4059
|
...artifactFetch,
|
|
4014
4060
|
...buildEnsureReleaseLayout(paths, []),
|
|
4015
|
-
|
|
4016
|
-
`
|
|
4017
|
-
|
|
4061
|
+
...buildResetReleaseDir(paths),
|
|
4062
|
+
`tar xzf ${tarball} -C "$TS_CLOUD_STAGED"`,
|
|
4063
|
+
...buildPromoteStagedRelease(paths),
|
|
4018
4064
|
`rm -f ${tarball}`,
|
|
4019
4065
|
...preStart,
|
|
4020
4066
|
...buildActivateRelease(paths),
|
package/dist/deploy/index.js
CHANGED
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
synchronizeDashboardUsers,
|
|
33
33
|
trackDashboardOperation,
|
|
34
34
|
verifyStaticApiOrigin
|
|
35
|
-
} from "../chunk-
|
|
35
|
+
} from "../chunk-ff77qy0c.js";
|
|
36
36
|
import {
|
|
37
37
|
deleteStaticSite,
|
|
38
38
|
deployStaticSite,
|
|
@@ -65,7 +65,7 @@ import {
|
|
|
65
65
|
shipsARelease,
|
|
66
66
|
siteInstallBase,
|
|
67
67
|
validateDeploymentConfig
|
|
68
|
-
} from "../chunk-
|
|
68
|
+
} from "../chunk-vx2yva1a.js";
|
|
69
69
|
import"../chunk-tq46tnxv.js";
|
|
70
70
|
import"../chunk-703nkybg.js";
|
|
71
71
|
import"../chunk-4cjrg98a.js";
|
package/dist/drivers/index.js
CHANGED
|
@@ -43,6 +43,49 @@ export declare function releasePaths(base: string, releaseId: string): ReleasePa
|
|
|
43
43
|
* `storage` tree and an empty shared `.env` so symlinks never dangle.
|
|
44
44
|
*/
|
|
45
45
|
export declare function buildEnsureReleaseLayout(paths: ReleasePaths, sharedPaths?: readonly string[]): string[];
|
|
46
|
+
/**
|
|
47
|
+
* Take the site's deploy lock for the rest of the script.
|
|
48
|
+
*
|
|
49
|
+
* Two deploys of one site used to be free to run at the same time, and they
|
|
50
|
+
* write to the same directories: the second one's `rm -rf releases/<id>` ran
|
|
51
|
+
* against a tree the first was still extracting into, which fails with
|
|
52
|
+
* "Directory not empty" — an error that reads like a permissions problem and
|
|
53
|
+
* is really a race. It happens more easily than it sounds, because a deploy
|
|
54
|
+
* whose *client* is interrupted keeps running on the box; the operator sees a
|
|
55
|
+
* dead terminal and re-runs.
|
|
56
|
+
*
|
|
57
|
+
* `flock` on a descriptor held by the shell serializes them, and the lock is
|
|
58
|
+
* released when the script exits however it exits. Waiting rather than failing
|
|
59
|
+
* outright, because the common case is a retry that is only a few seconds
|
|
60
|
+
* ahead of itself.
|
|
61
|
+
*/
|
|
62
|
+
export declare function buildDeployLock(paths: ReleasePaths, waitSeconds?: number): string[];
|
|
63
|
+
/**
|
|
64
|
+
* Clear the release directory, unless it is the one currently being served.
|
|
65
|
+
*
|
|
66
|
+
* Re-deploying a release id that is already live — the same commit twice, a
|
|
67
|
+
* retry after an interrupted run — used to `rm -rf` the directory `current`
|
|
68
|
+
* points at, so the site was serving a half-deleted tree until the new
|
|
69
|
+
* extraction finished. The replacement is staged beside it and swapped in with
|
|
70
|
+
* two renames, which is atomic enough that no request lands mid-swap.
|
|
71
|
+
*/
|
|
72
|
+
export declare function buildResetReleaseDir(paths: ReleasePaths): string[];
|
|
73
|
+
/**
|
|
74
|
+
* Set `TS_CLOUD_IS_LIVE` to "yes" when `current` resolves to this release.
|
|
75
|
+
*
|
|
76
|
+
* Both sides are resolved before comparing. Comparing a resolved `current`
|
|
77
|
+
* against the literal release path looks equivalent and is not: one symlinked
|
|
78
|
+
* ancestor anywhere above the site — `/var/www` moved onto a data volume, a
|
|
79
|
+
* `/tmp` that is really `/private/tmp` — makes the two spellings differ, the
|
|
80
|
+
* guard misses, and the branch it was guarding deletes the directory the site
|
|
81
|
+
* is being served from.
|
|
82
|
+
*/
|
|
83
|
+
export declare function buildIsReleaseLive(paths: ReleasePaths): string[];
|
|
84
|
+
/**
|
|
85
|
+
* Move a staged release into place, if it was staged (see
|
|
86
|
+
* {@link buildResetReleaseDir}). A no-op when the deploy extracted directly.
|
|
87
|
+
*/
|
|
88
|
+
export declare function buildPromoteStagedRelease(paths: ReleasePaths): string[];
|
|
46
89
|
/**
|
|
47
90
|
* Symlink every shared path from `shared/` into the freshly checked-out release,
|
|
48
91
|
* replacing whatever the checkout shipped (e.g. the repo's empty `storage`).
|
package/dist/index.js
CHANGED
|
@@ -285,7 +285,7 @@ import {
|
|
|
285
285
|
volumeCapabilities,
|
|
286
286
|
webhookEndpoint,
|
|
287
287
|
zeroCapacity
|
|
288
|
-
} from "./chunk-
|
|
288
|
+
} from "./chunk-ff77qy0c.js";
|
|
289
289
|
import {
|
|
290
290
|
deleteStaticSite,
|
|
291
291
|
deployStaticSite,
|
|
@@ -398,7 +398,7 @@ import {
|
|
|
398
398
|
waitForCloudInit,
|
|
399
399
|
waitForSsh,
|
|
400
400
|
wrapCloudInitUserData
|
|
401
|
-
} from "./chunk-
|
|
401
|
+
} from "./chunk-vx2yva1a.js";
|
|
402
402
|
import {
|
|
403
403
|
ABTestManager,
|
|
404
404
|
AI,
|