import { useState } from "react"; import { Badge } from "~/ui/Badge"; import { EmptyState } from "~/ui/EmptyState"; import { Panel } from "~/ui/Panel"; import { RelativeTime } from "~/ui/RelativeTime"; import { Button } from "~/ui/Button"; import { SelectField, TextField } from "~/ui/Field"; import { ErrorBanner } from "~/ui/Callout"; import type { RunnerSummary } from "~/server/ci/runner-registration"; import { Callout } from "~/ui/Callout"; export type RunnerIsolation = "container" | "none"; type Minted = { token: string; expiresAt: number }; type MintInput = { labels: string[]; isolation: RunnerIsolation; scope: string }; /** Mints a single-use registration token; the admin, not the runner, declares its labels and isolation. */ export function RegisterRunnerPanel({ serverUrl, scopes, pending, error, onMint, }: { serverUrl: string; scopes?: Array<{ value: string; label: string }>; pending: boolean; error: string | null; onMint: (input: MintInput) => Promise; }) { const [minted, setMinted] = useState(null); return (
{ event.preventDefault(); const form = new FormData(event.currentTarget); const labels = String(form.get("labels") ?? "") .split(",") .map((label) => label.trim()) .filter(Boolean); const result = await onMint({ labels, isolation: form.get("isolation") === "none" ? "none" : "container", scope: String(form.get("scope") ?? ""), }); if (result) setMinted(result); }} > {scopes && } {minted && (

Run this on the runner machine. The token is single-use, shown once and expires{" "} .

{`gfd runner register --url ${serverUrl} --token ${minted.token}\ngfd runner run`}
)}
); } export function RunnerList({ runners, error, onRemove, }: { runners: RunnerSummary[]; error: string | null; onRemove: (id: string) => void; }) { return ( {runners.length === 0 ? ( ) : (
    {runners.map((runner) => (
  • {runner.name} {runner.online ? "online" : "offline"} {runner.labels.map((label) => ( {label} ))} {runner.scope} {runner.isolation === "none" ? ( no isolation ) : ( {runner.attested ? `${runner.isolation} (admin-declared)` : `${runner.isolation} (unverified)`} )} {runner.busyJobs > 0 && ( {runner.busyJobs}/{runner.maxJobs} busy )} {runner.lastSeenAt ? : "never connected"}
  • ))}
)}
); }