summaryrefslogtreecommitdiff
path: root/u/process/exec.ts
diff options
context:
space:
mode:
authorElizabeth Hunt <me@liz.coffee>2025-07-20 13:03:39 -0700
committerElizabeth Hunt <me@liz.coffee>2025-07-20 13:03:39 -0700
commitdc4ac7742690f8f2bd759d57108ac4455e717fe9 (patch)
treef138ba41dd44bf703087eaa8ec43a22fe842923d /u/process/exec.ts
parentdccb99505e92685ba8ade7c3be84555f2b539a47 (diff)
downloadci-dc4ac7742690f8f2bd759d57108ac4455e717fe9.tar.gz
ci-dc4ac7742690f8f2bd759d57108ac4455e717fe9.zip
Mount src directory from path on host running worker container
Diffstat (limited to 'u/process/exec.ts')
-rw-r--r--u/process/exec.ts59
1 files changed, 59 insertions, 0 deletions
diff --git a/u/process/exec.ts b/u/process/exec.ts
new file mode 100644
index 0000000..a2cdbca
--- /dev/null
+++ b/u/process/exec.ts
@@ -0,0 +1,59 @@
+import {
+ Either,
+ IEither,
+ type ITraceable,
+ LogLevel,
+ LogMetricTraceSupplier,
+ Metric,
+ TraceUtil,
+} from '@emprespresso/pengueno';
+import { promisify } from 'node:util';
+import { exec as execCallback } from 'node:child_process';
+const exec = promisify(execCallback);
+
+export type Command = string[] | string;
+export type StdStreams = { stdout: string; stderr: string };
+
+export const CmdMetric = Metric.fromName('Exec').asResult();
+type Environment = Record<string, string>;
+type Options = { env?: Environment; clearEnv?: boolean };
+export const getStdout = (
+ cmd: ITraceable<Command, LogMetricTraceSupplier>,
+ options: Options = {},
+): Promise<IEither<Error, string>> =>
+ cmd
+ .flatMap(TraceUtil.withFunctionTrace(getStdout))
+ .flatMap((tCmd) => tCmd.traceScope(() => `Command = ${tCmd.get()}`))
+ .map((tCmd) => {
+ const cmd = tCmd.get();
+ const _exec = typeof cmd === 'string' ? cmd : cmd.join(' ');
+ const env = options.clearEnv ? options.env : { ...process.env, ...options.env };
+ return Either.fromFailableAsync<Error, StdStreams>(exec(_exec, { env }));
+ })
+ .map(
+ TraceUtil.promiseify((tEitherStdStreams) =>
+ tEitherStdStreams.get().mapRight(({ stderr, stdout }) => {
+ if (stderr) tEitherStdStreams.trace.traceScope(LogLevel.DEBUG).trace(`StdErr = ${stderr}`);
+ return stdout;
+ }),
+ ),
+ )
+ .peek(TraceUtil.promiseify(TraceUtil.traceResultingEither(CmdMetric)))
+ .get();
+
+export const getStdoutMany = (
+ cmds: ITraceable<Array<Command>, LogMetricTraceSupplier>,
+ options: Options = {},
+): Promise<IEither<Error, Array<string>>> =>
+ cmds
+ .coExtend((t) => t.get())
+ .reduce(
+ async (_result, tCmd) => {
+ const result = await _result;
+ return result.joinRightAsync(
+ () => tCmd.map((cmd) => getStdout(cmd, options)).get(),
+ (stdout, pre) => pre.concat(stdout),
+ );
+ },
+ Promise.resolve(Either.right<Error, Array<string>>([])),
+ );