import { Either, type IEither, isObject } from "@emprespresso/pengueno"; import { type FetchCodeJob, isJob, type Job } from "@emprespresso/ci-model"; export interface PipelineStage { readonly parallelJobs: Array; } export const isPipelineStage = (t: unknown): t is PipelineStage => isObject(t) && "parallelJobs" in t && Array.isArray(t.parallelJobs) && t.parallelJobs.every((j) => isJob(j)); export interface Pipeline { readonly serialJobs: Array; serialize(): string; } export const isPipeline = (t: unknown): t is Pipeline => isObject(t) && "serialJobs" in t && Array.isArray(t.serialJobs) && t.serialJobs.every((p) => isPipelineStage(p)); export interface PipelineBuilder { addStage(stage: PipelineStage): PipelineBuilder; build(): Pipeline; } export class PipelineImpl implements Pipeline { constructor(public readonly serialJobs: Array) {} public serialize() { return JSON.stringify(this.serialJobs); } public static from(s: string): IEither { return Either.fromFailable(() => JSON.parse(s)) .flatMap((eitherPipelineJson) => isPipeline(eitherPipelineJson) ? Either.right(eitherPipelineJson) : Either.left(new Error("oh noes D: its a bad pipewine :((")), ) .mapRight((pipeline) => new PipelineImpl(pipeline.serialJobs)); } } abstract class BasePipelineBuilder implements PipelineBuilder { protected readonly stages: Array = []; public addStage(stage: PipelineStage): PipelineBuilder { this.stages.push(stage); return this; } public build() { return new PipelineImpl(this.stages); } } export class DefaultGitHookPipelineBuilder extends BasePipelineBuilder { constructor( private readonly remoteUrl = Deno.env.get("remote")!, rev = Deno.env.get("rev")!, private readonly ref = Deno.env.get("ref")!, ) { super(); this.addStage({ parallelJobs: [ { type: "fetch_code", arguments: { remoteUrl, checkout: rev, path: this.getSourceDestination(), }, }, ], }); } public getSourceDestination() { return this.remoteUrl.split("/").at(-1) ?? "src"; } public getBranch(): string | undefined { const branchRefPrefix = "refs/heads/"; return this.ref.split(branchRefPrefix).at(1); } }