hub v0.29.0: Day-0 artifact manifest — version dropdowns + auto-derived sha
Operator picks a version from a Gitea-populated dropdown; the hub reads that version's sha256 from Gitea itself (files-metadata API, no artifact download) and vouches it — no hand-copied checksums. New internal/gitea read-only client (ListVersions + FileSHA256, unit-tested). Configuration UI: version <select>s + read-only sha display; handleSetArtifacts derives the sha authoritatively and refuses the save on a Gitea lookup failure. Degrades to manual text entry without registry creds. go build/vet/test clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -43,7 +43,7 @@
|
||||
<div class="flash flash-error">Invalid artifact version — use X.Y.Z (or blank to clear).</div>
|
||||
{{end}}
|
||||
{{if eq .Flash "artifact_sha_invalid"}}
|
||||
<div class="flash flash-error">Invalid sha256 — use 64 hex chars (or blank to clear).</div>
|
||||
<div class="flash flash-error">Couldn't set the checksum — the Gitea sha lookup failed (version missing / Gitea unreachable) or the manually-entered sha is invalid. Manifest unchanged.</div>
|
||||
{{end}}
|
||||
|
||||
<!-- Phase 2 managed updates: global controller-version floor (moved from the Customers page —
|
||||
@@ -71,20 +71,49 @@
|
||||
<p class="text-muted" style="margin: 0 0 0.75rem; font-size: 0.85em;">
|
||||
The current agent binary + golden archive the host-bootstrap script fetches from Gitea and
|
||||
verifies (sha256) before installing. The hub vouches for these checksums (a different trust
|
||||
root than Gitea). Paste the version + sha256 printed by <code>publish-agent.sh</code> /
|
||||
<code>build-golden.sh</code>. Blank a field to clear it.
|
||||
root than Gitea). Pick a version — the sha256 is read from Gitea automatically (no manual
|
||||
copy). Choose <em>— none —</em> to clear an artifact.
|
||||
</p>
|
||||
<form method="POST" action="/configuration/artifacts" style="display: grid; grid-template-columns: auto 8em 1fr; gap: 0.5rem; align-items: center; max-width: 56em;">
|
||||
<form method="POST" action="/configuration/artifacts" style="display: grid; grid-template-columns: auto 12em 1fr; gap: 0.5rem; align-items: center; max-width: 56em;">
|
||||
{{.CSRFField}}
|
||||
<label style="font-size: 0.9em; color: #cbd5e1;">Agent</label>
|
||||
<input type="text" name="agent_version" value="{{.Artifacts.AgentVersion}}" placeholder="0.43.0" style="padding: 0.3em 0.5em;">
|
||||
<input type="text" name="agent_sha256" value="{{.Artifacts.AgentSHA256}}" placeholder="64-hex sha256 (blank = none)" style="padding: 0.3em 0.5em; font-family: monospace;">
|
||||
{{if .AgentChoices}}
|
||||
<select name="agent_version" id="agent_version" onchange="syncArtifactSha('agent')" style="padding: 0.3em 0.5em;">
|
||||
<option value="" data-sha="">— none —</option>
|
||||
{{range .AgentChoices}}
|
||||
<option value="{{.Version}}" data-sha="{{.SHA256}}" {{if eq .Version $.Artifacts.AgentVersion}}selected{{end}}>{{.Version}}</option>
|
||||
{{end}}
|
||||
</select>
|
||||
{{else}}
|
||||
<input type="text" name="agent_version" value="{{.Artifacts.AgentVersion}}" placeholder="0.52.0" style="padding: 0.3em 0.5em;">
|
||||
{{end}}
|
||||
<input type="text" name="agent_sha256" id="agent_sha256" value="{{.Artifacts.AgentSHA256}}" {{if .AgentChoices}}readonly{{end}} placeholder="64-hex sha256 (blank = none)" style="padding: 0.3em 0.5em; font-family: monospace; {{if .AgentChoices}}opacity: 0.7;{{end}}">
|
||||
<label style="font-size: 0.9em; color: #cbd5e1;">Golden</label>
|
||||
{{if .GoldenChoices}}
|
||||
<select name="golden_version" id="golden_version" onchange="syncArtifactSha('golden')" style="padding: 0.3em 0.5em;">
|
||||
<option value="" data-sha="">— none —</option>
|
||||
{{range .GoldenChoices}}
|
||||
<option value="{{.Version}}" data-sha="{{.SHA256}}" {{if eq .Version $.Artifacts.GoldenVersion}}selected{{end}}>{{.Version}}</option>
|
||||
{{end}}
|
||||
</select>
|
||||
{{else}}
|
||||
<input type="text" name="golden_version" value="{{.Artifacts.GoldenVersion}}" placeholder="0.85.1" style="padding: 0.3em 0.5em;">
|
||||
<input type="text" name="golden_sha256" value="{{.Artifacts.GoldenSHA256}}" placeholder="64-hex sha256 (blank = none)" style="padding: 0.3em 0.5em; font-family: monospace;">
|
||||
{{end}}
|
||||
<input type="text" name="golden_sha256" id="golden_sha256" value="{{.Artifacts.GoldenSHA256}}" {{if .GoldenChoices}}readonly{{end}} placeholder="64-hex sha256 (blank = none)" style="padding: 0.3em 0.5em; font-family: monospace; {{if .GoldenChoices}}opacity: 0.7;{{end}}">
|
||||
<span></span><span></span>
|
||||
<button class="btn btn-sm" type="submit" style="justify-self: start;">Save artifact manifest</button>
|
||||
</form>
|
||||
<script>
|
||||
// When a version is picked, mirror that option's Gitea-resolved sha256 into the read-only
|
||||
// display field. The hub re-derives the sha authoritatively on save regardless of this value.
|
||||
function syncArtifactSha(kind) {
|
||||
var sel = document.getElementById(kind + '_version');
|
||||
var sha = document.getElementById(kind + '_sha256');
|
||||
if (!sel || !sha) return;
|
||||
var opt = sel.options[sel.selectedIndex];
|
||||
sha.value = (opt && opt.getAttribute('data-sha')) || '';
|
||||
}
|
||||
</script>
|
||||
</section>
|
||||
|
||||
<!-- Assets section -->
|
||||
|
||||
Reference in New Issue
Block a user