fix(build): commit embedded artifacts before tagging; alpha never bakes in
Two related fixes to the lockstep release flow + the project invariant
that prod must always run stable bytes (and dev only ever beta-or-stable).
1) tag-after-commit ordering. `./build release X.Y.Z` previously
regenerated zddc/internal/apps/embedded/* with stable labels but
tagged BEFORE folding those changes in. The tag landed on the
source-side commit (alpha-dirty embedded), and the operator was
expected to commit the embedded changes as a follow-up — which got
dropped in practice, leaving prod binaries with alpha-dirty bytes
baked in. (See the v0.0.9 re-anchor in the immediately preceding
commit for the manifestation.)
Refactor:
- _promote_stable / promote_zddc_server in shared/build-lib.sh
no longer call `git tag`. They keep their pre-flight check
(now: tag must be in HEAD's history rather than == HEAD, since
HEAD will advance after the release commit).
- Top-level ./build adds a new "Release commit + tag" block at
the end of stable cuts: stages the regenerated embedded files,
makes a `release: vX.Y.Z lockstep` commit, and tags all seven
artifacts at the new commit. Idempotent — no commit if there
are no changes.
2) bake-in invariant. Plain `./build` and `./build alpha` now
leave zddc/internal/apps/embedded/ untouched — the binary keeps
shipping whatever the last beta or stable cut wrote. `./build
beta` and `./build release` are the only paths that update
embedded bytes. Active dev iteration uses tool/dist/<tool>.html
directly; the binary's embedded copy is the default fallback,
not a workbench.
Verification on this commit:
./build → embedded mtime unchanged, no "M" lines for embedded/
./build alpha → embedded mtime unchanged, no "M" lines for embedded/
Docs updated to match in CLAUDE.md "Things that bite" + AGENTS.md
"Releasing — lockstep" + the leading help text in ./build itself.
This commit is contained in:
parent
b15382ba9d
commit
8dbd002727
4 changed files with 151 additions and 59 deletions
20
AGENTS.md
20
AGENTS.md
|
|
@ -213,12 +213,22 @@ Format: `trackingNumber_revision (status) - title.extension`
|
||||||
| `zddc-server_<X>.html` | generated stub page | per-version / per-channel; lists the four platform downloads. This is what the matrix-cell link points at — one stub fans out to four binaries |
|
| `zddc-server_<X>.html` | generated stub page | per-version / per-channel; lists the four platform downloads. This is what the matrix-cell link points at — one stub fans out to four binaries |
|
||||||
| `index.html` | regenerated by `build.sh` | matrix table, one column per tool, one row per release |
|
| `index.html` | regenerated by `build.sh` | matrix table, one column per tool, one row per release |
|
||||||
|
|
||||||
**Single point of truth.** `./build release` is the canonical lockstep cut. It seeds `dist/release-output/` from `/srv/zddc/releases/` (so cascades and the verifier see a complete world), forwards each HTML tool's build with the agreed version, then `promote_zddc_server` (in `shared/build-lib.sh`) copies the freshly cross-compiled binaries into `dist/release-output/` with the matching symlink chain, then `write_zddc_server_stubs_all` regenerates every stub page, then `build_releases_index` rewrites the index, then `verify_channel_links` asserts nothing dangles. `./deploy --releases` then publishes the bundle.
|
**Single point of truth.** `./build release` is the canonical lockstep cut. It seeds `dist/release-output/` from `/srv/zddc/releases/` (so cascades and the verifier see a complete world), forwards each HTML tool's build with the agreed version, then `promote_zddc_server` (in `shared/build-lib.sh`) copies the freshly cross-compiled binaries into `dist/release-output/` with the matching symlink chain, then `write_zddc_server_stubs_all` regenerates every stub page, then `build_releases_index` rewrites the index, then `verify_channel_links` asserts nothing dangles. **Then** the top-level build folds the regenerated `zddc/internal/apps/embedded/*` files into a `release: vX.Y.Z lockstep` commit and tags all seven artifacts at that commit. `./deploy --releases` then publishes the bundle.
|
||||||
|
|
||||||
- **Stable** (`./build release` or `--release X.Y.Z`): Writes per-version HTML for the six HTML tools + per-version binaries for zddc-server (real bytes, immutable). Refreshes 5 symlinks per HTML tool + 5 symlinks per zddc-server platform → the new version. Tags all seven: `<tool>-v<X.Y.Z>`. Cascade: stable cut means beta and alpha both reset to stable for every tool. Skips silently if source for an HTML tool hasn't changed since the latest stable tag (the binary always builds).
|
- **Stable** (`./build release` or `--release X.Y.Z`): Writes per-version HTML for the six HTML tools + per-version binaries for zddc-server (real bytes, immutable). Refreshes 5 symlinks per HTML tool + 5 symlinks per zddc-server platform → the new version. Updates `zddc/internal/apps/embedded/*` to stable-labeled bytes, makes a release commit, tags all seven (`<tool>-v<X.Y.Z>`) **at that commit** so binaries built from the tag embed clean stable bytes. Cascade: stable cut means beta and alpha both reset to stable for every tool.
|
||||||
- **Beta** (`./build beta`): Overwrites `<tool>_beta.html` with dist bytes for each HTML tool, and `zddc-server_beta_<platform>` with each platform's binary. Cascade: `<tool>_alpha.html` → `<tool>_beta.html` and `zddc-server_alpha_<platform>` → `zddc-server_beta_<platform>` (symlinks). No tag.
|
- **Beta** (`./build beta`): Overwrites `<tool>_beta.html` with dist bytes for each HTML tool, and `zddc-server_beta_<platform>` with each platform's binary. Updates `zddc/internal/apps/embedded/*` to beta-labeled bytes (the dev image picks them up via `ZDDC_REF=main`). Cascade: `<tool>_alpha.html` → `<tool>_beta.html` and `zddc-server_alpha_<platform>` → `zddc-server_beta_<platform>` (symlinks). No tag.
|
||||||
- **Alpha** (`./build`): Overwrites only the alpha mirrors, all seven tools. No tag, no other side-effects.
|
- **Alpha** (`./build alpha`): Overwrites only the alpha mirrors in `dist/release-output/`, all seven tools. **Does NOT update `zddc/internal/apps/embedded/`** — the project invariant is that alpha is never baked into the binary. No tag, no other side-effects.
|
||||||
- **Plain dev builds** (`./build` with no arg): produce `tool/dist/<tool>.html` for HTML tools and `zddc/dist/zddc-server-<platform>` binaries; do NOT touch `dist/release-output/` or the live site. Use it to iterate without affecting deployable state.
|
- **Plain dev builds** (`./build` with no arg): produce `tool/dist/<tool>.html` for HTML tools and `zddc/dist/zddc-server-<platform>` binaries; do NOT touch `dist/release-output/`, the live site, or `embedded/`. Use it to iterate without affecting deployable state.
|
||||||
|
|
||||||
|
**Bake-in invariant** — what zddc-server's binary embeds via `//go:embed` from `zddc/internal/apps/embedded/`:
|
||||||
|
|
||||||
|
| Image | `ZDDC_REF` | Embeds |
|
||||||
|
|---|---|---|
|
||||||
|
| Prod (Dockerfile.prod, BMCD) | `stable` (latest tag) | Stable-labeled bytes from the tagged release commit |
|
||||||
|
| Dev (Dockerfile, devshell) | `main` | Beta or stable bytes — whatever the last beta/stable cut wrote |
|
||||||
|
| Local dev iteration | n/a | Use `tool/dist/<tool>.html` directly; binary's embedded copy lags |
|
||||||
|
|
||||||
|
**Alpha is never baked in.** Active dev work uses the tool's local dist HTML opened directly in a browser; the binary's embedded copy is the "default fallback" served when no `.zddc apps:` override exists, and only ever holds beta or stable bytes.
|
||||||
|
|
||||||
On-page `{{BUILD_LABEL}}` format (HTML tools only — zddc-server's version comes from the binary itself):
|
On-page `{{BUILD_LABEL}}` format (HTML tools only — zddc-server's version comes from the binary itself):
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,8 @@ No lint/typecheck/format commands exist for the HTML tools — vanilla JS + POSI
|
||||||
- **`dist/` is gitignored.** `tool/dist/<tool>.html` is the canonical built artifact for testing and as the source for `--release` writes. `dist/release-output/` is the local-only release bundle written by `./build alpha|beta|release`. Never hand-edit a `dist/` file.
|
- **`dist/` is gitignored.** `tool/dist/<tool>.html` is the canonical built artifact for testing and as the source for `--release` writes. `dist/release-output/` is the local-only release bundle written by `./build alpha|beta|release`. Never hand-edit a `dist/` file.
|
||||||
- **Build vs deploy are separate verbs.** `./build` and `./build alpha|beta|release` produce artifacts under `dist/release-output/`. Nothing escapes the source tree until the operator runs `./deploy`, which rsyncs into `/srv/zddc/` (Caddy's bind-mount). This decouples local iteration from live state.
|
- **Build vs deploy are separate verbs.** `./build` and `./build alpha|beta|release` produce artifacts under `dist/release-output/`. Nothing escapes the source tree until the operator runs `./deploy`, which rsyncs into `/srv/zddc/` (Caddy's bind-mount). This decouples local iteration from live state.
|
||||||
- **Channel/release cuts seed from live state.** Before running per-tool promote, `./build alpha|beta|release` clears `dist/release-output/` and copies `/srv/zddc/releases/` into it (preserving symlinks). The cut then mutates the channels being cut on top. Result: `dist/release-output/` is always a complete intended-live snapshot, the verifier sees a complete world, and `./deploy --releases` (rsync `--delete-after`) replaces live state cleanly.
|
- **Channel/release cuts seed from live state.** Before running per-tool promote, `./build alpha|beta|release` clears `dist/release-output/` and copies `/srv/zddc/releases/` into it (preserving symlinks). The cut then mutates the channels being cut on top. Result: `dist/release-output/` is always a complete intended-live snapshot, the verifier sees a complete world, and `./deploy --releases` (rsync `--delete-after`) replaces live state cleanly.
|
||||||
- **Lockstep releases.** Every release cut bumps all seven artifacts (6 HTML tools + zddc-server) to the same version, even if a tool didn't change. The coordinated next-stable target is `max(latest tag across all tools) + 1`. Per-tool independent versions are no longer the norm — `./build release` is the canonical path. Workflow: alpha = active dev, beta = ready for general testing, stable = ready to ship.
|
- **Lockstep releases.** Every release cut bumps all seven artifacts (6 HTML tools + zddc-server) to the same version, even if a tool didn't change. The coordinated next-stable target is `max(latest tag across all tools) + 1`. Per-tool independent versions are no longer the norm — `./build release` is the canonical path. Workflow: alpha = active dev, beta = ready for general testing, stable = ready to ship. Stable cuts atomically (1) regenerate `zddc/internal/apps/embedded/` with stable-labeled bytes, (2) make a `release: vX.Y.Z lockstep` commit, (3) tag all seven artifacts at that commit. Tags ALWAYS point at a clean release commit — never at a source-side commit with alpha-dirty embedded files. (Fixed in May 2026; see git log around the v0.0.9 re-anchor.)
|
||||||
|
- **Bake-in invariant.** What zddc-server's binary embeds via `//go:embed`: prod images (built from `ZDDC_REF=stable`) ship the latest stable cut's bytes. Dev images (built from `ZDDC_REF=main`) ship whatever the last beta-or-stable cut wrote — no alpha. **Alpha is never baked in.** Active dev iteration uses `tool/dist/<tool>.html` opened directly, not the binary's embedded copy. The `./build` (no arg) and `./build alpha` paths intentionally leave `embedded/` untouched.
|
||||||
- **Release artifact layout** (in `dist/release-output/`, mirrored to `/srv/zddc/releases/`). HTML tools: per-version `<tool>_v<X.Y.Z>.html` (real immutable files) + partial-version pins (`<tool>_v<X.Y>.html`, `_v<X>.html`) + channel mirrors (`<tool>_{stable,beta,alpha}.html`) — all symlinks except per-version. zddc-server: `zddc-server_v<X.Y.Z>_<platform>` per-version binaries (raw bytes, no LFS), `_v<X.Y>_<platform>` / `_v<X>_<platform>` / `_<channel>_<platform>` symlinks, plus `zddc-server_<X>.html` stub pages that surface the four platform downloads in one matrix-cell link. Same cascade rule for both: stable cut → beta + alpha both reset to stable; beta cut → alpha cascades to beta.
|
- **Release artifact layout** (in `dist/release-output/`, mirrored to `/srv/zddc/releases/`). HTML tools: per-version `<tool>_v<X.Y.Z>.html` (real immutable files) + partial-version pins (`<tool>_v<X.Y>.html`, `_v<X>.html`) + channel mirrors (`<tool>_{stable,beta,alpha}.html`) — all symlinks except per-version. zddc-server: `zddc-server_v<X.Y.Z>_<platform>` per-version binaries (raw bytes, no LFS), `_v<X.Y>_<platform>` / `_v<X>_<platform>` / `_<channel>_<platform>` symlinks, plus `zddc-server_<X>.html` stub pages that surface the four platform downloads in one matrix-cell link. Same cascade rule for both: stable cut → beta + alpha both reset to stable; beta cut → alpha cascades to beta.
|
||||||
- **No tags for alpha/beta.** Channel URLs are stable URLs by design — appending counter tags would defeat the purpose. The on-page label encodes `<date> · <sha>` for traceability. Stable cuts get clean `<tool>-vX.Y.Z` tags for every tool (six tags per cut, all sharing the same X.Y.Z).
|
- **No tags for alpha/beta.** Channel URLs are stable URLs by design — appending counter tags would defeat the purpose. The on-page label encodes `<date> · <sha>` for traceability. Stable cuts get clean `<tool>-vX.Y.Z` tags for every tool (six tags per cut, all sharing the same X.Y.Z).
|
||||||
- **Pre-release semver in the on-page label.** Plain dev builds and `--release alpha|beta` cuts embed `vX.Y.Z-{alpha,beta}` in `{{BUILD_LABEL}}` where X.Y.Z is the next-stable target. Plain dev adds a full timestamp + `-dirty` marker; `--release alpha|beta` is date-only.
|
- **Pre-release semver in the on-page label.** Plain dev builds and `--release alpha|beta` cuts embed `vX.Y.Z-{alpha,beta}` in `{{BUILD_LABEL}}` where X.Y.Z is the next-stable target. Plain dev adds a full timestamp + `-dirty` marker; `--release alpha|beta` is date-only.
|
||||||
|
|
|
||||||
90
build
90
build
|
|
@ -5,16 +5,29 @@ set -eu
|
||||||
#
|
#
|
||||||
# ./build dev build: assemble tool dist/, cross-compile
|
# ./build dev build: assemble tool dist/, cross-compile
|
||||||
# zddc-server binaries. Nothing else is touched
|
# zddc-server binaries. Nothing else is touched
|
||||||
# — no release artifacts produced, no deploy.
|
# — no release artifacts produced, no deploy,
|
||||||
|
# and zddc/internal/apps/embedded/ is left alone
|
||||||
|
# (binary will embed whatever the last beta or
|
||||||
|
# stable cut committed there).
|
||||||
# ./build alpha cut alpha: produce a complete release bundle
|
# ./build alpha cut alpha: produce a complete release bundle
|
||||||
# in dist/release-output/ (cascades nothing).
|
# in dist/release-output/ (cascades nothing).
|
||||||
# ./build beta cut beta (cascades alpha → beta).
|
# Like dev, embedded/ is NOT updated — the
|
||||||
|
# invariant is that alpha labels are never baked
|
||||||
|
# into the binary.
|
||||||
|
# ./build beta cut beta (cascades alpha → beta). Updates
|
||||||
|
# embedded/ with beta-labeled tool HTMLs and
|
||||||
|
# commits them — the dev image (which builds
|
||||||
|
# from main) ships those bytes.
|
||||||
# ./build release cut coordinated stable (cascades alpha + beta
|
# ./build release cut coordinated stable (cascades alpha + beta
|
||||||
# → new stable; tags all six tools).
|
# → new stable; updates embedded/ with stable
|
||||||
|
# labels, makes a release commit, tags all
|
||||||
|
# seven tools at that commit). Prod images
|
||||||
|
# (which build from the latest stable tag)
|
||||||
|
# ship those bytes.
|
||||||
# ./build release X.Y.Z same, explicit version.
|
# ./build release X.Y.Z same, explicit version.
|
||||||
# ./build help this message.
|
# ./build help this message.
|
||||||
#
|
#
|
||||||
# Lockstep: every channel/release cut bumps all six tools (5 HTML +
|
# Lockstep: every channel/release cut bumps all seven tools (6 HTML +
|
||||||
# zddc-server) together. Coordinated next-stable = max(latest tag) + 1.
|
# zddc-server) together. Coordinated next-stable = max(latest tag) + 1.
|
||||||
#
|
#
|
||||||
# Channel/release cuts write a complete intended-live snapshot to
|
# Channel/release cuts write a complete intended-live snapshot to
|
||||||
|
|
@ -23,6 +36,14 @@ set -eu
|
||||||
# to rsync the snapshot into /srv/zddc/. The snapshot is built by seeding
|
# to rsync the snapshot into /srv/zddc/. The snapshot is built by seeding
|
||||||
# from the current live state (so cascades and the verifier see a
|
# from the current live state (so cascades and the verifier see a
|
||||||
# complete world), then mutating the channel(s) being cut on top.
|
# complete world), then mutating the channel(s) being cut on top.
|
||||||
|
#
|
||||||
|
# Bake-in invariant (what zddc-server's binary embeds via //go:embed):
|
||||||
|
# - prod image (Dockerfile.prod, ZDDC_REF=stable): always stable bytes
|
||||||
|
# - dev image (Dockerfile, ZDDC_REF=main): stable OR beta bytes
|
||||||
|
# (whatever last beta/
|
||||||
|
# stable cut wrote)
|
||||||
|
# - alpha is NEVER baked in. Active dev iteration happens via the tool's
|
||||||
|
# local dist/<tool>.html, not via the binary's embedded copy.
|
||||||
|
|
||||||
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||||
|
|
||||||
|
|
@ -158,10 +179,14 @@ cp "$SCRIPT_DIR/form/dist/form.html" "$SCRIPT_DIR/zddc/dist/web/
|
||||||
echo "Wrote zddc/dist/web/{index,archive,transmittal,classifier,mdedit,form}.html"
|
echo "Wrote zddc/dist/web/{index,archive,transmittal,classifier,mdedit,form}.html"
|
||||||
|
|
||||||
# Mirror the five cascade-served HTMLs into the apps embed source dir so the
|
# Mirror the five cascade-served HTMLs into the apps embed source dir so the
|
||||||
# next `go build` of zddc-server picks them up via //go:embed. Files are
|
# next `go build` of zddc-server picks them up via //go:embed. ONLY happens
|
||||||
# checked into git as empty placeholders; the build always overwrites them
|
# on a beta or stable cut — that's the project invariant: alpha labels are
|
||||||
# with the fresh dist/ output.
|
# never baked into the binary, beta labels go to the dev image (which builds
|
||||||
|
# from main), and stable labels go to prod (which builds from the latest
|
||||||
|
# stable tag). Plain `./build` and `./build alpha` leave the embedded files
|
||||||
|
# untouched; whatever the last beta/stable cut committed remains in place.
|
||||||
EMBED_DIR="$SCRIPT_DIR/zddc/internal/apps/embedded"
|
EMBED_DIR="$SCRIPT_DIR/zddc/internal/apps/embedded"
|
||||||
|
if [ "$RELEASE_CHANNEL" = "beta" ] || [ "$RELEASE_CHANNEL" = "stable" ]; then
|
||||||
mkdir -p "$EMBED_DIR"
|
mkdir -p "$EMBED_DIR"
|
||||||
cp "$SCRIPT_DIR/landing/dist/index.html" "$EMBED_DIR/index.html"
|
cp "$SCRIPT_DIR/landing/dist/index.html" "$EMBED_DIR/index.html"
|
||||||
cp "$SCRIPT_DIR/archive/dist/archive.html" "$EMBED_DIR/archive.html"
|
cp "$SCRIPT_DIR/archive/dist/archive.html" "$EMBED_DIR/archive.html"
|
||||||
|
|
@ -193,6 +218,7 @@ VERSIONS_FILE="$EMBED_DIR/versions.txt"
|
||||||
done
|
done
|
||||||
} > "$VERSIONS_FILE"
|
} > "$VERSIONS_FILE"
|
||||||
echo "Wrote $VERSIONS_FILE"
|
echo "Wrote $VERSIONS_FILE"
|
||||||
|
fi
|
||||||
rm -rf "$BUILD_LABELS_DIR"
|
rm -rf "$BUILD_LABELS_DIR"
|
||||||
|
|
||||||
# Cross-compiled zddc-server binaries for Linux/macOS/Windows. Always built
|
# Cross-compiled zddc-server binaries for Linux/macOS/Windows. Always built
|
||||||
|
|
@ -686,6 +712,56 @@ if [ -n "$RELEASE_CHANNEL" ]; then
|
||||||
verify_channel_links "$RELEASES_DIR"
|
verify_channel_links "$RELEASES_DIR"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# --- Release commit + tag (stable cut only) -------------------------------
|
||||||
|
# On a stable cut, fold the regenerated embedded artifacts into a release
|
||||||
|
# commit, then place all seven tool tags at that new commit. This is the
|
||||||
|
# fix for the previous tag-before-commit bug that left tags pointing at
|
||||||
|
# alpha-dirty source-side commits, baking alpha labels into prod binaries.
|
||||||
|
#
|
||||||
|
# Idempotent: if there are no embedded changes, no commit is made; tags
|
||||||
|
# are still verified to be at HEAD.
|
||||||
|
if [ "$RELEASE_CHANNEL" = "stable" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "=== Release commit + tag ==="
|
||||||
|
|
||||||
|
# Stage the artifacts that are part of the release. mdedit's dist
|
||||||
|
# file is the only force-tracked dist artifact today; the others
|
||||||
|
# are gitignored and intentionally not committed.
|
||||||
|
git -C "$SCRIPT_DIR" add "$EMBED_DIR/" \
|
||||||
|
"$SCRIPT_DIR/zddc/internal/handler/form.html"
|
||||||
|
if [ -f "$SCRIPT_DIR/mdedit/dist/mdedit.html" ]; then
|
||||||
|
git -C "$SCRIPT_DIR" add -f "$SCRIPT_DIR/mdedit/dist/mdedit.html"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! git -C "$SCRIPT_DIR" diff --cached --quiet; then
|
||||||
|
git -C "$SCRIPT_DIR" commit -m "release: v${RELEASE_VERSION} lockstep"
|
||||||
|
echo " release commit created"
|
||||||
|
else
|
||||||
|
echo " no embedded changes to commit (re-run on same source state)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Tag the seven artifacts at HEAD. Pre-flight already validated that
|
||||||
|
# any pre-existing tag is in HEAD's history, so this is safe.
|
||||||
|
_head=$(git -C "$SCRIPT_DIR" rev-parse HEAD)
|
||||||
|
for _t in archive transmittal classifier mdedit landing form zddc-server; do
|
||||||
|
_tag="${_t}-v${RELEASE_VERSION}"
|
||||||
|
if git -C "$SCRIPT_DIR" rev-parse -q --verify "refs/tags/$_tag" >/dev/null; then
|
||||||
|
_existing=$(git -C "$SCRIPT_DIR" rev-list -n 1 "$_tag")
|
||||||
|
if [ "$_existing" = "$_head" ]; then
|
||||||
|
echo " $_tag already at HEAD"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
# Pre-flight in promote_release confirmed _existing is an
|
||||||
|
# ancestor of HEAD. Move it forward to HEAD (the release commit).
|
||||||
|
git -C "$SCRIPT_DIR" tag -f "$_tag" "$_head" >/dev/null
|
||||||
|
echo " $_tag advanced to release commit"
|
||||||
|
else
|
||||||
|
git -C "$SCRIPT_DIR" tag "$_tag" "$_head"
|
||||||
|
echo " $_tag created at release commit"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "=== Build done ==="
|
echo "=== Build done ==="
|
||||||
echo ""
|
echo ""
|
||||||
|
|
|
||||||
|
|
@ -333,7 +333,12 @@ promote_release() {
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
# Stable cut: per-version file + 5 symlinks + git tag.
|
# Stable cut: per-version file + 5 symlinks. Tagging is centralized in
|
||||||
|
# the top-level ./build (it commits embedded artifacts FIRST, then tags
|
||||||
|
# at the new commit — see "Release commit + tag" block at the bottom of
|
||||||
|
# the script). _promote_stable historically created tags itself, but
|
||||||
|
# that placed them on the source-side commit before embedded files were
|
||||||
|
# folded in, leaving prod binaries with alpha-dirty bytes baked in.
|
||||||
_promote_stable() {
|
_promote_stable() {
|
||||||
_t="$1"
|
_t="$1"
|
||||||
_ver="$2"
|
_ver="$2"
|
||||||
|
|
@ -358,22 +363,22 @@ _promote_stable() {
|
||||||
echo " $_sym → $_versioned"
|
echo " $_sym → $_versioned"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Pre-flight check only: if the tag already exists pointing at a
|
||||||
|
# commit that is NOT an ancestor of HEAD, the operator needs to
|
||||||
|
# resolve manually before this cut can complete cleanly.
|
||||||
_tag="${_t}-v${_ver}"
|
_tag="${_t}-v${_ver}"
|
||||||
if git -C "$root_dir" rev-parse -q --verify "refs/tags/$_tag" >/dev/null; then
|
if git -C "$root_dir" rev-parse -q --verify "refs/tags/$_tag" >/dev/null; then
|
||||||
_existing=$(git -C "$root_dir" rev-list -n 1 "$_tag")
|
_existing=$(git -C "$root_dir" rev-list -n 1 "$_tag")
|
||||||
_head=$(git -C "$root_dir" rev-parse HEAD)
|
_head=$(git -C "$root_dir" rev-parse HEAD)
|
||||||
if [ "$_existing" != "$_head" ]; then
|
if [ "$_existing" != "$_head" ] \
|
||||||
echo "promote_release: tag $_tag exists at $_existing but HEAD is $_head" >&2
|
&& ! git -C "$root_dir" merge-base --is-ancestor "$_existing" "$_head"; then
|
||||||
|
echo "promote_release: tag $_tag exists at $_existing which is not in HEAD's history" >&2
|
||||||
|
echo " manual intervention required before re-running" >&2
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
echo "(tag $_tag already at HEAD)"
|
|
||||||
else
|
|
||||||
git -C "$root_dir" tag "$_tag"
|
|
||||||
echo "tagged $_tag"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Released ${_t} v${_ver} (stable)"
|
echo "Released ${_t} v${_ver} (stable; tagging deferred to top-level build)"
|
||||||
echo " publish git tag with: git push origin $_tag"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Alpha/beta cut: overwrite mutable channel mirror; cascade alpha → beta
|
# Alpha/beta cut: overwrite mutable channel mirror; cascade alpha → beta
|
||||||
|
|
@ -596,21 +601,21 @@ promote_zddc_server() {
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
# Tag the commit so the binary set is reproducible.
|
# Pre-flight tag check only — actual tagging happens in the
|
||||||
|
# top-level ./build after embedded artifacts are committed.
|
||||||
|
# See _promote_stable for the same rationale.
|
||||||
_tag="zddc-server-v${_ver}"
|
_tag="zddc-server-v${_ver}"
|
||||||
if git -C "$root_dir" rev-parse -q --verify "refs/tags/$_tag" >/dev/null; then
|
if git -C "$root_dir" rev-parse -q --verify "refs/tags/$_tag" >/dev/null; then
|
||||||
_existing=$(git -C "$root_dir" rev-list -n 1 "$_tag")
|
_existing=$(git -C "$root_dir" rev-list -n 1 "$_tag")
|
||||||
_head=$(git -C "$root_dir" rev-parse HEAD)
|
_head=$(git -C "$root_dir" rev-parse HEAD)
|
||||||
if [ "$_existing" != "$_head" ]; then
|
if [ "$_existing" != "$_head" ] \
|
||||||
echo "promote_zddc_server: tag $_tag exists at $_existing but HEAD is $_head" >&2
|
&& ! git -C "$root_dir" merge-base --is-ancestor "$_existing" "$_head"; then
|
||||||
|
echo "promote_zddc_server: tag $_tag exists at $_existing which is not in HEAD's history" >&2
|
||||||
|
echo " manual intervention required before re-running" >&2
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
echo "(tag $_tag already at HEAD)"
|
|
||||||
else
|
|
||||||
git -C "$root_dir" tag "$_tag"
|
|
||||||
echo "tagged $_tag"
|
|
||||||
fi
|
fi
|
||||||
echo "Released zddc-server v${_ver} (stable)"
|
echo "Released zddc-server v${_ver} (stable; tagging deferred to top-level build)"
|
||||||
;;
|
;;
|
||||||
alpha | beta)
|
alpha | beta)
|
||||||
# Mutable channel mirror per platform; cascade alpha → beta on
|
# Mutable channel mirror per platform; cascade alpha → beta on
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue