ZDDC/website/bootstrap/track-stable/classifier.html
ZDDC 2dc9ad240c refactor: distribute via Codeberg release assets, drop the upstream image
Removes the codeberg.org/varasys/zddc-server registry image, which had
no remaining consumer outside this shop. The two chart Dockerfiles
(tnd-zddc-chart) now compile zddc-server from source at build time,
fetching the right tag from a Codeberg release. release-image.sh,
zddc/Containerfile, and zddc/podman-compose.yaml are gone.

Build artifacts (HTML tools + zddc-server binaries) move from
website/releases/ in this repo to Codeberg release assets attached to
git tags. The website at zddc.varasys.io serves them by reverse-
proxying /releases/<tag>/<asset> to the corresponding Codeberg URL,
so consumers (zddc-use, level-2 bootstrap stubs, the chart
Dockerfiles) only ever talk to zddc.varasys.io.

Releases page becomes server-rendered static HTML regenerated on each
build via a single Codeberg API call. A small website/releases/manifest.json
maps <tool>-<channel> → tag for runtime channel resolution by zddc-use
and the level-2 stubs.

Files added:
- shared/publish-codeberg-release.sh — POSIX-sh helper that creates a
  Codeberg release for a tag (sets prerelease flag from tag suffix)
  and uploads/replaces release assets idempotently. Sourced by
  build-lib.sh and zddc/release.sh.
- zddc/release.sh — replaces release-image.sh. Tags + cross-compiles
  binaries via native Go (no podman needed; install Go) + uploads to
  Codeberg release assets. No image build, no registry push.

Files modified:
- shared/build-lib.sh — promote_release tags + uploads via the helper
  for stable AND alpha/beta now (alpha/beta were untagged before).
  update_alpha removed; per-tool build.sh files no longer mirror to
  website/releases/<tool>_alpha.html on plain dev builds.
- build.sh — prefers native go build over the old podman-based
  cross-compile (which is gone with Containerfile). build_releases_index
  queries the Codeberg API once and writes static HTML + manifest.json,
  with graceful fallback when the API is unreachable.
- bootstrap/level2.html.tmpl — fetches manifest.json to resolve
  channel → tag, then fetches the asset from /releases/<tag>/<asset>
  (Caddy proxy). Replaces the old /releases/<tool>_<channel>.html flat
  URL pattern. Operators with curl'd level-2 stubs need to re-issue
  them — this is a breaking change.
- AGENTS.md, CLAUDE.md — rewritten to describe the new flow.
- .gitignore — releases/ artifacts now expected to be on Codeberg, not
  committed locally.

NOT in this commit (deferred until $CODEBERG_TOKEN is provisioned):
- Backfilling existing tags as Codeberg releases.
- Cleanup commit: git rm-ing the existing artifacts in website/releases/.
  Until backfill happens, those files are how operators with old
  bootstrap stubs still get content. Once Codeberg has the assets,
  drop them.
- The Caddy reverse-proxy config on zddc.varasys.io.

Operator-side changes (not in this repo):
- tnd-zddc-chart Dockerfile.prod and Dockerfile (dev) need updating
  to compile from source rather than `FROM codeberg.org/...:stable`.
  Done in a separate commit on that repo.
- Caddyfile rule for the /releases/<tag>/<asset> reverse-proxy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 21:18:26 -05:00

70 lines
3.2 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Loading Classifier…</title>
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+CiAgPHJlY3Qgd2lkdGg9IjY0IiBoZWlnaHQ9IjY0IiByeD0iMTIiIGZpbGw9IiMxZTNhNWYiLz4KICA8ZyBmaWxsPSIjZmZmIj4KICAgIDxyZWN0IHg9IjE0IiB5PSIxOCIgd2lkdGg9IjM2IiBoZWlnaHQ9IjciLz4KICAgIDxwb2x5Z29uIHBvaW50cz0iNDMsMjUgNTAsMjUgMjEsNDMgMTQsNDMiLz4KICAgIDxyZWN0IHg9IjE0IiB5PSI0MyIgd2lkdGg9IjM2IiBoZWlnaHQ9IjciLz4KICA8L2c+Cjwvc3ZnPgo=">
<style>html,body{margin:0;font:14px system-ui,sans-serif;color:#666;padding:1rem}</style>
</head>
<body>
Loading…
<script>
// Level-2 bootstrap. Fetches classifier from zddc.varasys.io and
// document.write()s it in place. The default upstream is the
// stable channel; the URL parameter ?v= overrides it:
//
// ?v=alpha|beta|stable switches to that channel
// ?v=0.0.4 (or v0.0.4) pins to that exact stable version
// (none) uses the stable default
//
// Resolution path:
// 1. Channel mode (no ?v= or ?v={alpha,beta,stable}): fetch
// manifest.json from the same origin, look up
// "<tool>-<channel>" → tag, then fetch the asset.
// 2. Version pin: build the URL directly (skip manifest).
//
// The asset URL is /releases/<tag>/<tool>_v<version>.html. Caddy on
// zddc.varasys.io reverse-proxies that to the Codeberg release-asset
// URL — neither this stub nor the user's browser hits codeberg.org
// directly.
(async function () {
const params = new URLSearchParams(location.search);
const v = params.get('v');
const tool = 'classifier';
const defaultChannel = 'stable';
const channels = ['alpha', 'beta', 'stable'];
const base = 'https://zddc.varasys.io/releases/';
function isChannel(s) { return channels.indexOf(s) >= 0; }
try {
let assetUrl;
if (v && !isChannel(v)) {
// Explicit version pin (e.g. ?v=0.0.4 or ?v=v0.0.4).
const ver = v.replace(/^v/, '');
const tag = tool + '-v' + ver;
assetUrl = base + tag + '/' + tool + '_v' + ver + '.html';
} else {
// Channel mode: resolve via manifest.
const channel = (v && isChannel(v)) ? v : defaultChannel;
const manifest = await (await fetch(base + 'manifest.json', { cache: 'no-cache', credentials: 'omit' })).json();
const tag = manifest[tool + '-' + channel];
if (!tag) throw new Error('manifest has no entry for ' + tool + '-' + channel);
const ver = tag.replace(tool + '-v', '');
assetUrl = base + tag + '/' + tool + '_v' + ver + '.html';
}
const resp = await fetch(assetUrl, { cache: 'no-cache', credentials: 'omit' });
if (!resp.ok) throw new Error(resp.status + ' ' + resp.statusText);
const html = await resp.text();
document.open();
document.write(html);
document.close();
} catch (err) {
document.body.textContent = 'Failed to load ' + tool + ': ' + err.message;
}
})();
</script>
</body>
</html>