feat: build runtime releases from pinned Git branch commits

This commit is contained in:
2026-10-14 14:25:27 +08:00
parent 9a71772771
commit 20635ffaec
23 changed files with 999 additions and 31 deletions
+4 -3
View File
@@ -1,6 +1,7 @@
import { useState, type FormEvent } from 'react';
import { api, normalBuildAllowed, type AdmissionState, type Build } from './api';
import { Panel, ResourceState, Empty, Status, date, useAction, useResource } from './ui';
import { BuildProvenance, ReleasePanel } from './ReleasePanel';
export const activeBuild = (build: Build) => ['queued', 'running', 'validating'].includes(build.status);
function BuildLogs({id, close}: {id: string; close: () => void}) {
const logs = useResource(() => api.build(id), id, 5000, activeBuild);
@@ -9,7 +10,7 @@ function BuildLogs({id, close}: {id: string; close: () => void}) {
<button onClick={close}>关闭日志</button>
<ResourceState resource={logs}/>{logs.data && <>
<p>{logs.data.experimental && <strong className="alert">实验构建 · 不自动准入</strong>}{logs.data.version} · <Status value={logs.data.status}/>
</p>{logs.data.error && <p className="alert">{logs.data.error}</p>}<pre className="logs">{logs.data.logs || '任务尚未输出日志'}</pre>
</p><BuildProvenance build={logs.data}/>{logs.data.error && <p className="alert">{logs.data.error}</p>}<pre className="logs">{logs.data.logs || '任务尚未输出日志'}</pre>
</>}</div>;
}
function Admission({imageId, refresh}: {imageId:string; refresh:() => Promise<void>}) {
@@ -42,7 +43,7 @@ export function Images({admin = false}: {admin?:boolean}) {
function build(e: FormEvent) {e.preventDefault(); void action.run(async () => {if (!(admin && experimental) && !normalBuildAllowed(await api.compatibility(), version)) throw new Error('此版本不支持普通构建,请管理员选择实验构建;实验构建不会自动准入。'); await api.startBuild(version, admin && experimental); if (page === 0) await builds.refresh(); else setPage(0);}, '构建任务已提交,请查看任务的实际状态。', (experimental ? '实验构建不会自动准入或用于创建。确认实验构建精确版本 ' : '确认在本机手动构建精确版本 ') + version + '?构建会消耗磁盘、网络与 CPU,不会自动升级实例。');}
const rows = builds.data?.slice(0, 20);
function changePage(next: number) { setSelected(undefined); setPage(next); }
return <>{action.feedback}<Panel title="查询与手动构建">
return <>{action.feedback}{admin && <ReleasePanel onBuilt={async () => {if (page === 0) await builds.refresh(); else changePage(0);}}/>}<Panel title="查询与手动构建">
<ResourceState resource={compatibility}/>{version && compatibility.data && !normalBuildAllowed(compatibility.data, version) && <p className="alert">此版本不支持普通构建。仅管理员可实验构建,不会自动准入。</p>}<div className="split">
<div>
<p className="muted">从 npm 查询 dist-tags.latest,仅查询,不自动构建。</p>
@@ -104,7 +105,7 @@ export function Images({admin = false}: {admin?:boolean}) {
</thead>
<tbody>{rows!.map(b => <tr key={b.id}>
<td className="mono">{b.id}</td>
<td>{b.version}{b.experimental && <strong className="alert">实验构建 · 不自动准入</strong>}</td>
<td>{b.version}{b.experimental && <strong className="alert">实验构建 · 不自动准入</strong>}<BuildProvenance build={b}/></td>
<td>
<Status value={b.status}/>
</td>