Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899import { createBobbinClient, type BobbinContext, type QueryValue } from "#lib/api/client.ts";import type { XrpcRequestInit } from "#lib/api/client.ts";import { hostForKnot, jsonGet } from "#lib/api/_request.ts";import { didFromUri, rkeyFromUri } from "#lib/api/uri.ts";import { publicOnly } from "#lib/publicFetch.ts";import type * as GetPipeline from "#lib/api/lexicons/types/org/tangled/ci/getPipeline.ts";import type * as CiDefs from "#lib/api/lexicons/types/org/tangled/ci/defs.ts";import type * as QueryPipelines from "#lib/api/lexicons/types/org/tangled/ci/queryPipelines.ts";import type { PipelineSummary, PipelineTrigger } from "#lib/components/repo/types.ts";
const asParams = (params: object): Record<string, QueryValue> => params as unknown as Record<string, QueryValue>;
export const spindleUrl = (host: string): string => { const trimmed = host.trim().replace(/\/+$/, ""); if (trimmed.includes("://")) return trimmed; const bare = hostForKnot(trimmed); return bare.startsWith("localhost:") ? `http://${bare}` : `https://${bare}`;};
// the spindle is whatever the repo record names, and the server fetches from it while// rendering, so its requests only go to a public https host and follow no redirects. a// refused one rejects like an unreachable spindle, which every caller already handlesexport const createSpindleClient = (host: string, fetch: typeof globalThis.fetch): BobbinContext => createBobbinClient({ serviceUrl: spindleUrl(host), fetch: publicOnly(fetch) });
// queryPipelines filters by trigger nsidconst TRIGGER_NSIDS = { push: "org.tangled.event.push", pull_request: "org.tangled.event.pullRequest", manual: "org.tangled.ci.trigger.manual"} as const;
export const triggersOf = (filter: PipelineTrigger["kind"] | "all") => filter === "all" ? undefined : [TRIGGER_NSIDS[filter]];
export const queryPipelines = ( ctx: BobbinContext, params: QueryPipelines.$params, init?: XrpcRequestInit) => jsonGet<QueryPipelines.$output>(ctx, "org.tangled.ci.queryPipelines", asParams(params), init);
export const getPipeline = ( ctx: BobbinContext, params: GetPipeline.$params, init?: XrpcRequestInit) => jsonGet<GetPipeline.$output>(ctx, "org.tangled.ci.getPipeline", asParams(params), init);
const toTrigger = (trigger: CiDefs.Pipeline["trigger"], repoDid?: string): PipelineTrigger => { switch (trigger.$type) { case "org.tangled.event.push": return { kind: "push", targetRef: trigger.ref.replace(/^refs\/(?:heads|tags)\//, "") }; case "org.tangled.event.pullRequest": { const sourceRepo = trigger.sourceRepo ?? ""; const pull = trigger.pull; return { kind: "pull_request", targetRef: trigger.targetBranch ?? "", // fork ci labels are handled by the page resolving the name of the fork first sourceLabel: trigger.sourceBranch ?? "", ...(sourceRepo && sourceRepo !== repoDid ? { sourceRepo } : {}), // a pull lives in the repo it targets, whose did path redirects to owner/name ...(pull && repoDid && didFromUri(pull) === repoDid ? { pullPath: `/${repoDid}/pulls/${rkeyFromUri(pull)}` } : {}) }; } default: return { kind: "manual" }; }};
const durationOf = (workflow: CiDefs.WorkflowRun): number => { if (!workflow.startedAt || !workflow.finishedAt) return 0; const started = Date.parse(workflow.startedAt); const finished = Date.parse(workflow.finishedAt); if (Number.isNaN(started) || Number.isNaN(finished)) return 0; return Math.max(0, finished - started);};
export const toPipelineSummary = ( pipeline: CiDefs.Pipeline, repoDid?: string): PipelineSummary => ({ id: pipeline.id, sha: pipeline.commit, createdAt: pipeline.createdAt ?? "", trigger: toTrigger(pipeline.trigger, repoDid), workflows: (pipeline.workflows ?? []).map((workflow) => ({ // id is the key logs and getPipeline go by, name is optional name: workflow.id, status: workflow.status, duration: durationOf(workflow), error: workflow.error, startedAt: workflow.startedAt, finishedAt: workflow.finishedAt }))});