@checkstack/healthcheck-script-backend 0.3.17 → 0.4.0
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/CHANGELOG.md +116 -0
- package/package.json +2 -2
- package/src/concurrency.test.ts +147 -0
- package/src/execute-collector.test.ts +47 -9
- package/src/execute-collector.ts +80 -16
- package/src/inline-script-collector.test.ts +165 -58
- package/src/inline-script-collector.ts +152 -229
- package/src/security.test.ts +63 -7
- package/src/strategy.test.ts +7 -14
- package/src/strategy.ts +17 -72
- package/src/transport-client.ts +10 -3
package/src/strategy.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { spawn, type Subprocess } from "bun";
|
|
2
1
|
import {
|
|
3
2
|
HealthCheckStrategy,
|
|
4
3
|
HealthCheckRunForAggregation,
|
|
@@ -14,6 +13,7 @@ import {
|
|
|
14
13
|
type ConnectedClient,
|
|
15
14
|
type InferAggregatedResult,
|
|
16
15
|
baseStrategyConfigSchema,
|
|
16
|
+
defaultShellScriptRunner,
|
|
17
17
|
} from "@checkstack/backend-api";
|
|
18
18
|
import {
|
|
19
19
|
healthResultBoolean,
|
|
@@ -35,7 +35,7 @@ import { extractErrorMessage } from "@checkstack/common";
|
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* Configuration schema for Script health checks.
|
|
38
|
-
* Global defaults only - action params
|
|
38
|
+
* Global defaults only - action params live on the per-collector schema.
|
|
39
39
|
*/
|
|
40
40
|
export const scriptConfigSchema = baseStrategyConfigSchema.extend({});
|
|
41
41
|
|
|
@@ -146,83 +146,29 @@ interface ScriptExecutionResult {
|
|
|
146
146
|
|
|
147
147
|
export interface ScriptExecutor {
|
|
148
148
|
execute(config: {
|
|
149
|
-
|
|
150
|
-
args: string[];
|
|
149
|
+
script: string;
|
|
151
150
|
cwd?: string;
|
|
152
151
|
env?: Record<string, string>;
|
|
153
152
|
timeout: number;
|
|
154
153
|
}): Promise<ScriptExecutionResult>;
|
|
155
154
|
}
|
|
156
155
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
"TMPDIR",
|
|
166
|
-
"HOSTNAME",
|
|
167
|
-
"SHELL",
|
|
168
|
-
];
|
|
169
|
-
|
|
170
|
-
// Default executor using Bun.spawn
|
|
156
|
+
/**
|
|
157
|
+
* Default executor — delegates to the shared `ShellScriptRunner` in
|
|
158
|
+
* `@checkstack/backend-api`. That module is the canonical home for the
|
|
159
|
+
* `sh -c` + safe-env-vars + timeout/kill/cleanup pattern (also used by
|
|
160
|
+
* the integration shell provider). This thin adapter exists so tests
|
|
161
|
+
* can substitute a mock for `ScriptExecutor` without touching the
|
|
162
|
+
* shared runner.
|
|
163
|
+
*/
|
|
171
164
|
const defaultScriptExecutor: ScriptExecutor = {
|
|
172
165
|
async execute(config) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
timedOut = true;
|
|
179
|
-
proc?.kill();
|
|
180
|
-
reject(new Error("Script execution timed out"));
|
|
181
|
-
}, config.timeout);
|
|
166
|
+
return defaultShellScriptRunner.run({
|
|
167
|
+
script: config.script,
|
|
168
|
+
timeoutMs: config.timeout,
|
|
169
|
+
cwd: config.cwd,
|
|
170
|
+
env: config.env,
|
|
182
171
|
});
|
|
183
|
-
|
|
184
|
-
const safeEnv: Record<string, string> = {};
|
|
185
|
-
for (const key of SAFE_ENV_VARS) {
|
|
186
|
-
if (process.env[key] !== undefined) {
|
|
187
|
-
safeEnv[key] = process.env[key]!;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
try {
|
|
192
|
-
proc = spawn({
|
|
193
|
-
cmd: [config.command, ...config.args],
|
|
194
|
-
cwd: config.cwd,
|
|
195
|
-
env: { ...safeEnv, ...config.env },
|
|
196
|
-
stdout: "pipe",
|
|
197
|
-
stderr: "pipe",
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
const [stdout, stderr, exitCode] = await Promise.race([
|
|
201
|
-
Promise.all([
|
|
202
|
-
new Response(proc.stdout as ReadableStream).text(),
|
|
203
|
-
new Response(proc.stderr as ReadableStream).text(),
|
|
204
|
-
proc.exited,
|
|
205
|
-
]),
|
|
206
|
-
timeoutPromise,
|
|
207
|
-
]);
|
|
208
|
-
|
|
209
|
-
return {
|
|
210
|
-
exitCode,
|
|
211
|
-
stdout: stdout.trim(),
|
|
212
|
-
stderr: stderr.trim(),
|
|
213
|
-
timedOut: false,
|
|
214
|
-
};
|
|
215
|
-
} catch (error) {
|
|
216
|
-
if (timedOut) {
|
|
217
|
-
return {
|
|
218
|
-
exitCode: -1,
|
|
219
|
-
stdout: "",
|
|
220
|
-
stderr: "Script execution timed out",
|
|
221
|
-
timedOut: true,
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
throw error;
|
|
225
|
-
}
|
|
226
172
|
},
|
|
227
173
|
};
|
|
228
174
|
|
|
@@ -310,8 +256,7 @@ export class ScriptHealthCheckStrategy implements HealthCheckStrategy<
|
|
|
310
256
|
exec: async (request: ScriptRequest): Promise<ScriptResultType> => {
|
|
311
257
|
try {
|
|
312
258
|
const result = await this.executor.execute({
|
|
313
|
-
|
|
314
|
-
args: request.args,
|
|
259
|
+
script: request.script,
|
|
315
260
|
cwd: request.cwd,
|
|
316
261
|
env: request.env,
|
|
317
262
|
timeout: request.timeout,
|
package/src/transport-client.ts
CHANGED
|
@@ -2,12 +2,19 @@ import type { TransportClient } from "@checkstack/common";
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Script execution request.
|
|
5
|
+
*
|
|
6
|
+
* The {@link script} field is interpreted by the host shell via `sh -c`,
|
|
7
|
+
* so it can contain pipes, redirects, variable expansion, command substitution,
|
|
8
|
+
* `if` / `for` / `while` blocks, etc. — anything POSIX `sh` understands.
|
|
5
9
|
*/
|
|
6
10
|
export interface ScriptRequest {
|
|
7
|
-
|
|
8
|
-
|
|
11
|
+
/** Shell script source. Executed via `sh -c <script>`. */
|
|
12
|
+
script: string;
|
|
13
|
+
/** Optional working directory. */
|
|
9
14
|
cwd?: string;
|
|
15
|
+
/** Optional extra environment variables (merged on top of the safe-vars whitelist). */
|
|
10
16
|
env?: Record<string, string>;
|
|
17
|
+
/** Maximum execution time in milliseconds. */
|
|
11
18
|
timeout: number;
|
|
12
19
|
}
|
|
13
20
|
|
|
@@ -23,7 +30,7 @@ export interface ScriptResult {
|
|
|
23
30
|
}
|
|
24
31
|
|
|
25
32
|
/**
|
|
26
|
-
* Script transport client for
|
|
33
|
+
* Script transport client for shell-script execution.
|
|
27
34
|
*/
|
|
28
35
|
export type ScriptTransportClient = TransportClient<
|
|
29
36
|
ScriptRequest,
|