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.
| Actions: OIDC tokens, the toolkit's cache and artifact services, and artifacts in R2 | 1 | import { redirect } from "react-router"; |
| 2 | ||
| Actions: workflow_run, workflow.completed, artifacts on the run page, Node 24 | 3 | import type { Route } from "./+types/actions-artifact"; |
| Actions: OIDC tokens, the toolkit's cache and artifact services, and artifacts in R2 | 4 | import { addresses } from "../../lib/addresses.server"; |
| Merge g1tusercontent.com: registry answers run nothing in a browser, the site's pages run only their own scripts, repository files and avatars on their own origin, raw files rate limited per address | 5 | import { contentDisposition } from "../../lib/content-safety"; |
| Actions: workflow_run, workflow.completed, artifacts on the run page, Node 24 | 6 | import { readArtifact } from "../../lib/artifacts.server"; |
| 7 | import { actions } from "../../lib/services.server"; | |
| 8 | import { getViewer } from "../../lib/session.server"; | |
| 9 | ||
| Actions: OIDC tokens, the toolkit's cache and artifact services, and artifacts in R2 | 10 | /** |
| 11 | * One artifact of a run, for anyone who can see the run: a redirect to a | |
| 12 | * link the API signed for a few minutes, or, for one an older runner kept | |
| 13 | * in KV, its bytes. | |
| 14 | */ | |
| Actions: workflow_run, workflow.completed, artifacts on the run page, Node 24 | 15 | export async function loader({ params, context }: Route.LoaderArgs) { |
| Actions: OIDC tokens, the toolkit's cache and artifact services, and artifacts in R2 | 16 | const repo = { namespace: params.owner, name: params.repo }; |
| 17 | const viewer = getViewer(context); | |
| 18 | const found = await actions.artifactDownload(repo, viewer, { run: params.id, name: params.name }); | |
| 19 | if (found.ok && found.value.blob) { | |
| 20 | throw redirect(`${addresses().api}/actions/toolkit/blobs/${found.value.blob}`); | |
| 21 | } | |
| 22 | const seen = await actions.run(repo, viewer, params.id); | |
| Actions: workflow_run, workflow.completed, artifacts on the run page, Node 24 | 23 | if (!seen.ok) throw new Response("Not found.", { status: 404 }); |
| 24 | const bytes = await readArtifact(params.id, params.name); | |
| Actions: OIDC tokens, the toolkit's cache and artifact services, and artifacts in R2 | 25 | if (!bytes) throw new Response("That artifact is gone: it expired or was deleted.", { status: 404 }); |
| Actions: workflow_run, workflow.completed, artifacts on the run page, Node 24 | 26 | return new Response(bytes.buffer as ArrayBuffer, { |
| 27 | headers: { | |
| 28 | "content-type": "application/gzip", | |
| Merge g1tusercontent.com: registry answers run nothing in a browser, the site's pages run only their own scripts, repository files and avatars on their own origin, raw files rate limited per address | 29 | "content-disposition": contentDisposition(`${params.name}.tar.gz`), |
| Actions: workflow_run, workflow.completed, artifacts on the run page, Node 24 | 30 | }, |
| 31 | }); | |
| 32 | } |
This file's history is long; its oldest lines are credited to the oldest commit read.