diff options
author | Elizabeth Hunt <me@liz.coffee> | 2025-07-20 13:03:39 -0700 |
---|---|---|
committer | Elizabeth Hunt <me@liz.coffee> | 2025-07-20 13:03:39 -0700 |
commit | dc4ac7742690f8f2bd759d57108ac4455e717fe9 (patch) | |
tree | f138ba41dd44bf703087eaa8ec43a22fe842923d /u/process/exec.ts | |
parent | dccb99505e92685ba8ade7c3be84555f2b539a47 (diff) | |
download | ci-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.ts | 59 |
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>>([])), + ); |