~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/knotless

git that lives in your Atmosphere account

Forked from chadtmiller.com/knotless

0
0
124 lines · 4.2 KB Raw History
<script lang="ts">
	import {
		ago,
		capitalized,
		itemHref,
		ran,
		repoHref,
		runningSteps,
		shortRef,
		stepLogs,
		took
	} from '#lib/format.ts';
	import { followRun, followsEnd, type LiveRun } from '#lib/live.ts';
	import { checkIcon } from '#lib/icons.ts';
	import Icon from '#lib/atoms/Icon.svelte';
	import Sha from '#lib/atoms/Sha.svelte';
	import Time from '#lib/atoms/Time.svelte';
	import RunImages from '#lib/molecules/RunImages.svelte';
	import RerunMenu from '#lib/molecules/RerunMenu.svelte';
	import RepoPage from '#lib/templates/RepoPage.svelte';
	let { data } = $props();
	const run = $derived(data.run);
	const c = $derived(run.check);
	const r = $derived(data.repo);
	const base = $derived(repoHref(data.authority, r.name));
	const logs = $derived(
		run.log === undefined
			? []
			: stepLogs(
					run.log,
					run.steps.map((s) => s.name)
				)
	);
	const length = $derived(ran(c.startedAt, c.finishedAt));
	/** Whether the owner is looking, who may run it again: this workflow or all, of its pull or at its ref. */
	const owns = $derived(data.viewer?.actor?.did === r.owner.did);
	/** What it printed so far while it runs, as its runner sends it; the page draws again once it is filed. */
	let live = $state<LiveRun>();
	// Followed anew only as these change, not each time the page's answers are asked again.
	const following = $derived(c.status === 'running' ? `${r.uri} ${c.uri}` : undefined);
	$effect(() => {
		live = undefined;
		if (!following) return;
		const [repo, uri] = following.split(' ');
		return followRun(repo, uri, (heard) => (live = heard));
	});
	const going = $derived(live ? runningSteps(live.text, live.steps, live.going) : []);
</script>

<RepoPage
	repo={r}
	tab={run.pull ? 'pulls' : 'checks'}
	title="{c.workflow} · {capitalized(c.status)} · {r.name}"
>
	<div class="box run">
		<div class="run-head {c.status}">
			<span class="mark {c.status}"><Icon name={checkIcon(c.status)} /></span>
			<h2>{c.workflow}</h2>
			<span class="mute">{capitalized(c.status)}</span>
			{#if owns}<span class="end"
					><RerunMenu
						repo={r.uri}
						pull={run.pull}
						ref={run.pull ? undefined : run.ref}
						workflows={[c.workflow]}
					/></span
				>{/if}
		</div>
		<div class="boxhead boxfoot run-about mute">
			<span
				>on <b>{shortRef(run.ref)}</b> at <Sha
					sha={c.commit}
					href={`${base}/commit/${c.commit}`}
				/></span
			>
			{#if run.pull}<a class="from" href={itemHref(base, run.pull)}><Icon name="merge" />Pull</a
				>{/if}
			<span>by {run.runner.handle}</span>
			<span class="end"><Time at={c.startedAt} show={ago} />{length ? ` · ${length}` : ''}</span>
		</div>
		{#if c.error}<pre class="run-error">{c.error}</pre>{/if}
		{#if c.skipped}<div class="run-note mute">{capitalized(c.skipped)}</div>{/if}
		{#if c.status === 'queued'}<div class="run-note mute">
				It starts once its runner has a job free.
			</div>{/if}
		{#if c.status === 'running' && going.length === 0}<div class="run-note mute">
				Running: what it prints shows here as it prints it.
			</div>{/if}
		{#each going as g, i (i)}
			<details class="step" open={g.step.status !== 'success'}>
				<summary
					><span class="mark {g.step.status}"><Icon name={checkIcon(g.step.status)} /></span><b
						>{g.step.name}</b
					><span class="end mute"
						>{g.step.status === 'running'
							? 'running'
							: `${g.step.exitCode === undefined ? 'killed' : `exit ${g.step.exitCode}`} · ${took(g.step.durationMs ?? 0)}`}</span
					></summary
				>
				{#if g.log}<pre class="step-log" use:followsEnd>{g.log}</pre>{:else}<div
						class="run-note mute"
					>
						It printed nothing yet.
					</div>{/if}
			</details>
		{/each}
		{#each run.steps as s, i (i)}
			<details class="step" open={s.status === 'failure'}>
				<summary
					><span class="mark {s.status}"><Icon name={checkIcon(s.status)} /></span><b>{s.name}</b
					><span class="end mute"
						>{s.status === 'skipped'
							? 'skipped'
							: `${s.exitCode === undefined ? 'killed' : `exit ${s.exitCode}`} · ${took(s.durationMs ?? 0)}`}</span
					></summary
				>
				{#if logs[i]}<pre class="step-log">{logs[i]}</pre>{:else}<div class="run-note mute">
						It printed nothing.
					</div>{/if}
			</details>
		{/each}
		<RunImages images={c.images} />
	</div>
</RepoPage>