@stacksjs/ts-cloud 0.2.20 → 0.2.21
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.
|
@@ -91,10 +91,12 @@ export interface CreateSshKeyOptions {
|
|
|
91
91
|
publicKey: string;
|
|
92
92
|
labels?: Record<string, string>;
|
|
93
93
|
}
|
|
94
|
+
/** Minimal fetch signature the client relies on (always called with a string URL). */
|
|
95
|
+
export type HetznerFetch = (url: string, init?: RequestInit) => Promise<Response>;
|
|
94
96
|
export interface HetznerClientOptions {
|
|
95
97
|
apiToken: string;
|
|
96
98
|
baseUrl?: string;
|
|
97
|
-
fetchImpl?:
|
|
99
|
+
fetchImpl?: HetznerFetch;
|
|
98
100
|
}
|
|
99
101
|
export declare class HetznerClient {
|
|
100
102
|
readonly name = "hetzner";
|
|
@@ -13,5 +13,12 @@ export interface UbuntuBootstrapOptions {
|
|
|
13
13
|
export declare function generateUbuntuAppCloudInit(options?: UbuntuBootstrapOptions): string;
|
|
14
14
|
/**
|
|
15
15
|
* Wrap a bash bootstrap script as Hetzner cloud-init user_data (#cloud-config).
|
|
16
|
+
*
|
|
17
|
+
* The script is written to disk via `write_files` and then executed through an
|
|
18
|
+
* explicit `bash` invocation in `runcmd`. cloud-init runs bare `runcmd` entries
|
|
19
|
+
* with `/bin/sh` (dash on Ubuntu), which chokes on bash-only syntax like
|
|
20
|
+
* `set -o pipefail` and aborts the whole bootstrap — so embedding the script
|
|
21
|
+
* inline under `runcmd:` silently breaks bun/caddy installation. Writing the
|
|
22
|
+
* file (shebang preserved) and running `bash <file>` guarantees a bash shell.
|
|
16
23
|
*/
|
|
17
24
|
export declare function wrapCloudInitUserData(bootstrapScript: string): string;
|
|
@@ -15,6 +15,13 @@ export interface BuildSiteDeployScriptOptions {
|
|
|
15
15
|
execStart: string;
|
|
16
16
|
envEntries: Record<string, string>;
|
|
17
17
|
port?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Commands run inside `appDir` after extraction + `.env` write, before the
|
|
20
|
+
* systemd unit is (re)written and started. Typically dependency install
|
|
21
|
+
* and/or build steps (e.g. `bun install --frozen-lockfile`, `bun run build`)
|
|
22
|
+
* so the release tarball can omit `node_modules`.
|
|
23
|
+
*/
|
|
24
|
+
preStartCommands?: string[];
|
|
18
25
|
}
|
|
19
26
|
/**
|
|
20
27
|
* Build the remote shell commands that install/refresh a site on a compute target.
|
package/dist/index.js
CHANGED
|
@@ -81435,12 +81435,19 @@ echo "ts-cloud bootstrap complete — instance is ready for site deploys"
|
|
|
81435
81435
|
return script;
|
|
81436
81436
|
}
|
|
81437
81437
|
function wrapCloudInitUserData(bootstrapScript) {
|
|
81438
|
+
const scriptPath = "/var/lib/cloud/ts-cloud-bootstrap.sh";
|
|
81439
|
+
const indented = bootstrapScript.split(`
|
|
81440
|
+
`).map((line) => ` ${line}`).join(`
|
|
81441
|
+
`);
|
|
81438
81442
|
return `#cloud-config
|
|
81443
|
+
write_files:
|
|
81444
|
+
- path: ${scriptPath}
|
|
81445
|
+
permissions: '0755'
|
|
81446
|
+
owner: root:root
|
|
81447
|
+
content: |
|
|
81448
|
+
${indented}
|
|
81439
81449
|
runcmd:
|
|
81440
|
-
-
|
|
81441
|
-
${bootstrapScript.split(`
|
|
81442
|
-
`).join(`
|
|
81443
|
-
`)}
|
|
81450
|
+
- [ bash, ${scriptPath} ]
|
|
81444
81451
|
`;
|
|
81445
81452
|
}
|
|
81446
81453
|
|
|
@@ -81464,10 +81471,10 @@ function buildHetznerFirewallRules(config6) {
|
|
|
81464
81471
|
// src/drivers/hetzner/instance-sizes.ts
|
|
81465
81472
|
var HETZNER_INSTANCE_TYPES = {
|
|
81466
81473
|
micro: "cpx11",
|
|
81467
|
-
small: "
|
|
81468
|
-
medium: "
|
|
81469
|
-
large: "
|
|
81470
|
-
xlarge: "
|
|
81474
|
+
small: "cx23",
|
|
81475
|
+
medium: "cx33",
|
|
81476
|
+
large: "cx43",
|
|
81477
|
+
xlarge: "cx53",
|
|
81471
81478
|
"2xlarge": "ccx33"
|
|
81472
81479
|
};
|
|
81473
81480
|
function resolveHetznerServerType(size) {
|
|
@@ -81516,6 +81523,7 @@ async function writeDriverState(stackName, state) {
|
|
|
81516
81523
|
}
|
|
81517
81524
|
|
|
81518
81525
|
// src/drivers/hetzner/driver.ts
|
|
81526
|
+
var SSH_MAX_BUFFER = 1024 * 1024 * 256;
|
|
81519
81527
|
function expandHome(path) {
|
|
81520
81528
|
return path.startsWith("~/") ? join13(homedir7(), path.slice(2)) : path;
|
|
81521
81529
|
}
|
|
@@ -81736,13 +81744,14 @@ class HetznerDriver {
|
|
|
81736
81744
|
"BatchMode=yes",
|
|
81737
81745
|
localPath,
|
|
81738
81746
|
`${this.sshUser}@${host}:${remotePath}`
|
|
81739
|
-
].map((arg) => `"${arg.replace(/"/g, "\\\"")}"`).join(" "), { stdio: "pipe" });
|
|
81747
|
+
].map((arg) => `"${arg.replace(/"/g, "\\\"")}"`).join(" "), { stdio: "pipe", maxBuffer: SSH_MAX_BUFFER });
|
|
81740
81748
|
}
|
|
81741
81749
|
sshExec(host, script) {
|
|
81742
81750
|
const escaped = script.replace(/'/g, `'\\''`);
|
|
81743
81751
|
return execSync(`ssh ${this.sshBaseArgs(host).map((a) => `"${a.replace(/"/g, "\\\"")}"`).join(" ")} '${escaped}'`, {
|
|
81744
81752
|
encoding: "utf8",
|
|
81745
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
81753
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
81754
|
+
maxBuffer: SSH_MAX_BUFFER
|
|
81746
81755
|
});
|
|
81747
81756
|
}
|
|
81748
81757
|
}
|
|
@@ -81792,12 +81801,14 @@ function buildSiteDeployScript(options) {
|
|
|
81792
81801
|
artifactFetch,
|
|
81793
81802
|
execStart,
|
|
81794
81803
|
envEntries,
|
|
81795
|
-
port
|
|
81804
|
+
port,
|
|
81805
|
+
preStartCommands = []
|
|
81796
81806
|
} = options;
|
|
81797
81807
|
const appDir = options.appDir ?? `/var/www/${siteName}`;
|
|
81798
81808
|
const serviceName = `${slug}-${siteName}.service`;
|
|
81799
81809
|
const envFile = Object.entries(envEntries).map(([k, v]) => `${k}=${JSON.stringify(String(v))}`).join(`
|
|
81800
81810
|
`);
|
|
81811
|
+
const preStart = preStartCommands.length > 0 ? [`cd ${appDir}`, ...preStartCommands] : [];
|
|
81801
81812
|
return [
|
|
81802
81813
|
"set -euo pipefail",
|
|
81803
81814
|
...artifactFetch,
|
|
@@ -81808,6 +81819,7 @@ function buildSiteDeployScript(options) {
|
|
|
81808
81819
|
envFile,
|
|
81809
81820
|
"TS_CLOUD_ENV_EOF",
|
|
81810
81821
|
`chmod 600 ${appDir}/.env`,
|
|
81822
|
+
...preStart,
|
|
81811
81823
|
`cat > /etc/systemd/system/${serviceName} <<'TS_CLOUD_UNIT_EOF'`,
|
|
81812
81824
|
"[Unit]",
|
|
81813
81825
|
`Description=${siteName} (managed by ts-cloud)`,
|
|
@@ -81886,7 +81898,8 @@ async function deploySiteRelease(driver, options, logger4 = noopLogger) {
|
|
|
81886
81898
|
artifactFetch,
|
|
81887
81899
|
execStart: resolveExecStart(site.start, runtime),
|
|
81888
81900
|
envEntries: site.env || {},
|
|
81889
|
-
port: site.port
|
|
81901
|
+
port: site.port,
|
|
81902
|
+
preStartCommands: site.preStart
|
|
81890
81903
|
});
|
|
81891
81904
|
logger4.step(`Deploying to ${targets.length} target(s)...`);
|
|
81892
81905
|
const result = await driver.runRemoteDeploy({
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/ts-cloud",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.21",
|
|
5
5
|
"description": "A lightweight, performant infrastructure-as-code library and CLI for deploying both server-based (EC2) and serverless applications.",
|
|
6
6
|
"author": "Chris Breuer <chris@stacksjs.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -89,8 +89,8 @@
|
|
|
89
89
|
"test": "bun test"
|
|
90
90
|
},
|
|
91
91
|
"dependencies": {
|
|
92
|
-
"@ts-cloud/aws-types": "0.2.
|
|
93
|
-
"@ts-cloud/core": "0.2.
|
|
92
|
+
"@ts-cloud/aws-types": "0.2.21",
|
|
93
|
+
"@ts-cloud/core": "0.2.21",
|
|
94
94
|
"@stacksjs/ts-xml": "^0.1.0"
|
|
95
95
|
},
|
|
96
96
|
"devDependencies": {
|