Rolls back the HTML-tool side of the Codeberg-as-canonical refactor (commits2dc9ad2,b28c4ae,bdac8dc) in favor of a simpler model: per-version HTML files committed under website/releases/ as immutable real files; partial-version pins (<tool>_v<X.Y>.html, <tool>_v<X>.html) and channel mirrors (<tool>_<channel>.html) are checked-in symlinks. Docker-tag pattern: :1.2.3 is pinned, :1.2 floats, :1 floats further, :stable floats furthest. URL scheme — every URL resolves to actual HTML via the symlink chain; no JS indirection, no manifest.json, no Caddy regex-rewrite: /releases/<tool>_v<X.Y.Z>.html exact version (real file) /releases/<tool>_v<X.Y>.html latest patch within X.Y.* (symlink) /releases/<tool>_v<X>.html latest within X.*.* (symlink) /releases/<tool>_stable.html current stable (symlink) /releases/<tool>_beta.html current beta (symlink to stable when no active beta; real file when beta is in flight) /releases/<tool>_alpha.html current alpha (similar — symlink to beta or stable when no active alpha) Cascade rule (in shared/build-lib.sh promote_release): --release [version] (stable cut) → write per-version file; refresh 5 symlinks (_v<X.Y>, _v<X>, _stable, _beta, _alpha) → new versioned file; tag <tool>-v<X.Y.Z>. --release beta → overwrite <tool>_beta.html with real bytes; cascade _alpha.html → _beta.html (symlink). No tag — channel URLs are stable URLs by design; counters defeat that. --release alpha → overwrite <tool>_alpha.html with real bytes. No tag, no other side-effects. Plain `sh tool/build.sh` → dist/ only. No website/releases/ side-effect, no commit. Code changes: - .gitignore — drop website/releases/*.html and website/releases/zddc-server-* exclusions; HTML tool files are tracked again. Replace the comment with the new model description. - shared/build-lib.sh — drop next_prerelease (no -alpha.N / -beta.N counter tags). Drop the Codeberg-upload path for HTML tools (no longer sourcing publish-codeberg-release.sh from build-lib). promote_release rewritten with two helpers: _promote_stable (per-version file + 5 symlinks + tag) and _promote_channel (overwrite mirror + cascade alpha→beta on beta cut). - zddc/release.sh — drop alpha/beta channel path entirely; binaries publish only on stable cuts. zddc-server's beta/alpha builds-from-source via the helm charts (next phase) — no binary distribution needed for those channels. - bootstrap/level2.html.tmpl — drop manifest.json fetch; resolve ?v= to a static URL via the symlink chain. New suffixFor() handles channel names, exact versions, and partial-version pins (?v=0.0, ?v=0). Same logic in level1.html.tmpl already works because the local-staging files (e.g. ../<tool>_v0.0.html) exist via the same symlink scheme. - build.sh build_releases_index — revert to filesystem scan of website/releases/ instead of Codeberg API call. Drop manifest.json generation. Per-tool sections list channel chips + per-version pin links; zddc-server section links to Codeberg release pages directly. - tests/build-label.spec.js — fix the channel-label regex to match the pre-release-semver format introduced in commit9459139("v0.0.3-alpha · ..."). Pre-existing test failure that wasn't caught at the time. Storage: - 30 new committed files under website/releases/ — 10 real (per-version) + 20 symlinks (5 tools × 4 partial/channel variants, plus alpha as a real file by default). - Initial state: stable v0.0.2 across all 5 tools; alpha/beta/v0.0/v0 symlinks all point at <tool>_v0.0.2.html. - manifest.json deleted (no longer needed). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
70 lines
3.4 KiB
JavaScript
70 lines
3.4 KiB
JavaScript
/**
|
|
* build-label.spec.js
|
|
*
|
|
* Verifies that the {{BUILD_LABEL}} placeholder is correctly substituted in all
|
|
* four tool dist and website files:
|
|
*
|
|
* - No placeholder text leaks through
|
|
* - The .build-timestamp element is present and visible in the browser
|
|
* - The label content is either a timestamp ("Built: 20...") or a version ("v...")
|
|
* - website/ files (when present) always show the version format
|
|
*
|
|
* Note: dist/ files may show either format depending on whether the last build
|
|
* was a dev build (timestamp) or a release build (version). Both are valid.
|
|
*/
|
|
import { test, expect } from '@playwright/test';
|
|
import * as path from 'path';
|
|
import * as fs from 'fs';
|
|
|
|
const tools = ['archive', 'transmittal', 'classifier', 'mdedit'];
|
|
|
|
for (const tool of tools) {
|
|
const distPath = path.resolve(`${tool}/dist/${tool}.html`);
|
|
const websitePath = path.resolve(`website/${tool}.html`);
|
|
|
|
test.describe(`${tool}: build-label`, () => {
|
|
|
|
test(`dist file: no placeholder text leaks through`, async () => {
|
|
const html = fs.readFileSync(distPath, 'utf8');
|
|
expect(html).not.toContain('{{BUILD_LABEL}}');
|
|
expect(html).not.toContain('{{BUILD_TIMESTAMP}}');
|
|
});
|
|
|
|
test(`dist file: .build-timestamp element is visible in browser`, async ({ page }) => {
|
|
const waitUntil = tool === 'mdedit' ? 'load' : 'domcontentloaded';
|
|
await page.goto(`file://${distPath}`, { waitUntil });
|
|
const el = page.locator('.build-timestamp');
|
|
await expect(el).toBeVisible({ timeout: 10000 });
|
|
});
|
|
|
|
test(`dist file: label is a valid channel or version string`, async () => {
|
|
const html = fs.readFileSync(distPath, 'utf8');
|
|
// Channel labels (alpha/beta) are wrapped in an inner <span style="color:red...">;
|
|
// stable version labels are bare text.
|
|
const match = html.match(/class="build-timestamp">(?:<span[^>]*>)?([^<]+?)(?:<\/span>)?</);
|
|
expect(match, 'build-timestamp element must have text content').toBeTruthy();
|
|
const label = match[1];
|
|
// Plain dev builds and --release alpha|beta carry the next-stable
|
|
// target as a pre-release suffix:
|
|
// "v0.0.3-alpha · 2026-04-29 00:50:17 · 714faf6-dirty" (plain dev)
|
|
// "v0.0.3-alpha · 2026-04-29 · 714faf6" (--release alpha)
|
|
// "v0.0.3-beta · 2026-04-29 · 714faf6" (--release beta)
|
|
const isChannel = /^v\d+\.\d+\.\d+-(alpha|beta) · 20\d\d-\d\d-\d\d( \d\d:\d\d:\d\d)? · [0-9a-f]+(-dirty)?$/.test(label);
|
|
const isVersion = /^v\d+\.\d+\.\d+$/.test(label);
|
|
expect(isChannel || isVersion,
|
|
`Expected channel or version label, got: "${label}"`
|
|
).toBe(true);
|
|
});
|
|
|
|
test(`website file: label shows version format (release build)`, async () => {
|
|
if (!fs.existsSync(websitePath)) {
|
|
test.skip(true, `website/${tool}.html not present — run sh ${tool}/build.sh --release first`);
|
|
return;
|
|
}
|
|
const html = fs.readFileSync(websitePath, 'utf8');
|
|
expect(html).not.toContain('{{BUILD_LABEL}}');
|
|
expect(html).not.toContain('{{BUILD_TIMESTAMP}}');
|
|
expect(html).toMatch(/class="build-timestamp">(?:<span[^>]*>)?v\d+\.\d+\.\d+( BETA)?(?:<\/span>)?</);
|
|
});
|
|
});
|
|
}
|