Skip to content
23 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Merge Actions runs: summaries, attempts and re-runs, graceful cancel, log downloads, badges (actions 0009)1/**
2 * Every job's log of a run's attempt as one zip
3 * (`actions/runs/:id/logs.zip?attempt=`), laid out as the API's archive is:
4 * `{n}_{job}.txt` whole, and `{job}/{step}_{step name}.txt`. For anyone who
5 * can see the run.
6 */
7import type { Route } from "./+types/actions-logs-download";
8import { archiveFiles } from "../../lib/log-lines";
9import { attachment, refused } from "../../lib/log-download.server";
10import { actions } from "../../lib/services.server";
11import { getViewer } from "../../lib/session.server";
12import { zip } from "../../lib/zip";
13
14export async function loader({ params, context, request }: Route.LoaderArgs) {
15 const repo = { namespace: params.owner, name: params.repo };
16 const asked = Number(new URL(request.url).searchParams.get("attempt") ?? "");
17 const attempt = Number.isInteger(asked) && asked > 0 ? asked : undefined;
18 const logs = await actions.runLogs(repo, getViewer(context), params.id, attempt);
19 if (!logs.ok) return refused(logs.error.code === "not_found" ? 404 : 400, logs.error.message);
20 const encoder = new TextEncoder();
21 const archive = await zip(archiveFiles(logs.value).map((file) => ({ path: file.path, data: encoder.encode(file.text) })));
22 return attachment(archive, "application/zip", attempt ? `logs_${params.id}_attempt_${attempt}.zip` : `logs_${params.id}.zip`);
23}

This file's history is long; its oldest lines are credited to the oldest commit read.