import { getStdout, type ITraceable, LogLevel, type LogMetricTraceSupplier, memoize, Metric, TraceUtil, validateExecutionEntries, Either, type IEither, } from "@emprespresso/pengueno"; import type { Job, JobArgT, Pipeline } from "@emprespresso/ci_model"; // -- -- const jobTypeMetric = memoize((type: string) => Metric.fromName(`run.${type}`)); export const executeJob = (tJob: ITraceable) => tJob .bimap(TraceUtil.withMetricTrace(jobTypeMetric(tJob.get().type))) .peek((tJob) => tJob.trace.trace(`let's do this little job ok!! ${tJob.get()}`), ) .map((tJob) => validateExecutionEntries(tJob.get().arguments) .mapLeft((badEntries) => { tJob.trace.addTrace(LogLevel.ERROR).trace(badEntries.toString()); return new Error("invalid job arguments"); }) .flatMapAsync((args) => getStdout(tJob.move(tJob.get().type), { env: args }), ), ) .peek( TraceUtil.promiseify((q) => q.trace.trace( q .get() .fold( ({ isLeft }) => jobTypeMetric(tJob.get().type)[isLeft ? "failure" : "success"], ), ), ), ) .get(); // -- -- // -- -- const pipelinesMetric = Metric.fromName("pipelines"); export const executePipeline = ( tPipeline: ITraceable, baseEnv?: JobArgT, ): Promise> => tPipeline .bimap(TraceUtil.withFunctionTrace(executePipeline)) .bimap(TraceUtil.withMetricTrace(pipelinesMetric)) .map(async (tJobs): Promise> => { for (const [i, serialStage] of tJobs.get().serialJobs.entries()) { tJobs.trace.trace( `executing stage ${i}. do your best little stage :>\n${serialStage}`, ); const jobResults = await Promise.all( serialStage.parallelJobs.map((job) => tJobs .bimap((_) => [job, `stage ${i}`]) .map( (tJob) => { ...tJob.get(), arguments: { ...baseEnv, ...tJob.get().arguments, }, }, ) .map(executeJob) .peek( TraceUtil.promiseify((tEitherJobOutput) => tEitherJobOutput .get() .mapRight((stdout) => tEitherJobOutput.trace.addTrace("STDOUT").trace(stdout), ), ), ) .get(), ), ); const failures = jobResults.filter((e) => e.fold(( { isLeft }) => isLeft)); if (failures.length > 0) { tJobs.trace.trace(pipelinesMetric.failure); return Either.left(new Error(failures.toString())); } } tJobs.trace.trace(pipelinesMetric.success); return Either.right(undefined); }) .get(); // -- --