mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-11-11 11:57:57 +00:00
Fixes #1807. Implements the fix path from the triage (env → image-version file → baked version, zero rebuild cost): ## Changes **`cmd/server/main.go` — `resolveVersion()` fallback chain** 1. `CORESCOPE_VERSION` env (operator override) 2. `.image-version` file in the working dir (`/app` in the container) — mirrors the existing `.git-commit` pattern in `resolveCommit()` 3. ldflags-baked `Version` 4. `"unknown"` Edge builds are unaffected: no env, no file → baked `"edge"` as before. **`.github/workflows/release-fast-path.yml` — retag step** Instead of a plain `crane tag :edge → :vX.Y.Z`, the fast path now runs `crane mutate` on `:edge` with: - `--append` of a deterministic one-file layer containing `/app/.image-version` = `vX.Y.Z` - `--label org.opencontainers.image.version=vX.Y.Z` - `--tag :vX.Y.Z` `vX.Y`, `vX` and `latest` are then pointed at the mutated image. Still no rebuild — the mutation is a manifest + single ~100-byte layer operation. ## Notes - The release tags no longer share the exact digest with `:edge` (they carry one extra layer); the fallback SHA check is unaffected since it compares the `org.opencontainers.image.revision` label against `github.sha`. - The layer tar uses `--owner=0 --group=0 --mtime='UTC 2020-01-01'` for reproducibility. - Operators can also fix existing deployments immediately with `-e CORESCOPE_VERSION=v3.9.2`, no image change needed. ## Testing - `go build ./cmd/server` + `go vet` clean (golang:1.24) - Workflow YAML validated - Reporter context: running the affected v3.9.2 fast-path image in production (live.saarmesh.de), happy to verify the next tagged release end-to-end. --------- Co-authored-by: Mathias Kasper <fallisaar@gmail.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: SaarMesh-Bot <bot@saarmesh.de>
This commit is contained in:
3 files changed
+71
-4
No files matched your search
@@ -79,22 +79,41 @@ jobs:
|
||||
echo "tag SHA (github.sha) = ${{ github.sha }}"
|
||||
|
||||
# ─────────── FAST PATH: SHAs match, metadata-only retag ───────────
|
||||
# Issue #1807: a plain `crane tag` keeps the ldflags-baked
|
||||
# Version="edge" inside the binary, so /api/stats reports "edge" on
|
||||
# tagged releases. Instead of a full rebuild we append a single-file
|
||||
# layer (/app/.image-version containing the tag) and set the OCI
|
||||
# version label, then point the remaining tags at that mutated image.
|
||||
# The server reads .image-version at startup (see resolveVersion()).
|
||||
- name: Re-tag :edge → :vX.Y.Z + :vX.Y + :vX + :latest (fast path)
|
||||
if: steps.edge.outputs.no_edge == 'false' && steps.edge.outputs.edge_revision == github.sha
|
||||
run: |
|
||||
set -euo pipefail
|
||||
IMAGE="ghcr.io/kpa-clawbot/corescope"
|
||||
SRC="${IMAGE}:edge"
|
||||
TAG="${{ steps.semver.outputs.tag }}"
|
||||
echo "SHA match — fast-path re-tag from $SRC"
|
||||
|
||||
# Build a one-file layer: /app/.image-version = vX.Y.Z
|
||||
LAYER_DIR="$(mktemp -d)"
|
||||
mkdir -p "${LAYER_DIR}/app"
|
||||
printf '%s' "$TAG" > "${LAYER_DIR}/app/.image-version"
|
||||
tar --owner=0 --group=0 --mtime='UTC 2020-01-01' \
|
||||
-C "$LAYER_DIR" -cf /tmp/image-version-layer.tar app
|
||||
echo " crane mutate $SRC (+.image-version layer, +version label) → ${IMAGE}:${TAG}"
|
||||
crane mutate "$SRC" \
|
||||
--append /tmp/image-version-layer.tar \
|
||||
--label "org.opencontainers.image.version=${TAG}" \
|
||||
--tag "${IMAGE}:${TAG}"
|
||||
|
||||
for NEW_TAG in \
|
||||
"${{ steps.semver.outputs.tag }}" \
|
||||
"${{ steps.semver.outputs.vMajorMinor }}" \
|
||||
"${{ steps.semver.outputs.vMajor }}" \
|
||||
"latest"; do
|
||||
echo " crane tag $SRC $NEW_TAG"
|
||||
crane tag "$SRC" "$NEW_TAG"
|
||||
echo " crane tag ${IMAGE}:${TAG} $NEW_TAG"
|
||||
crane tag "${IMAGE}:${TAG}" "$NEW_TAG"
|
||||
done
|
||||
echo "Fast-path complete — all tags point at the :edge manifest digest."
|
||||
echo "Fast-path complete — release tags point at :edge plus a one-file version layer."
|
||||
|
||||
# ─────────── FALLBACK: SHAs differ, run the full pipeline ───────────
|
||||
- name: Dispatch full deploy.yml pipeline (fallback)
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"math"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -1042,6 +1043,39 @@ func TestResolveVersion(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveVersionFallbackChain(t *testing.T) {
|
||||
old := Version
|
||||
defer func() { Version = old }()
|
||||
|
||||
// (a) CORESCOPE_VERSION env wins over baked Version="edge"
|
||||
Version = "edge"
|
||||
t.Setenv("CORESCOPE_VERSION", "v3.9.2")
|
||||
if got := resolveVersion(); got != "v3.9.2" {
|
||||
t.Errorf("expected v3.9.2 from env, got %s", got)
|
||||
}
|
||||
|
||||
// (b) .image-version file wins over baked Version="edge" when env is unset
|
||||
t.Setenv("CORESCOPE_VERSION", "")
|
||||
Version = "edge"
|
||||
tmp := t.TempDir()
|
||||
origDir, _ := os.Getwd()
|
||||
defer os.Chdir(origDir)
|
||||
os.Chdir(tmp)
|
||||
if err := os.WriteFile(".image-version", []byte("v3.9.2\n"), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := resolveVersion(); got != "v3.9.2" {
|
||||
t.Errorf("expected v3.9.2 from .image-version, got %s", got)
|
||||
}
|
||||
|
||||
// (c) Version="edge" returned when neither env nor file present
|
||||
os.Chdir(t.TempDir())
|
||||
Version = "edge"
|
||||
if got := resolveVersion(); got != "edge" {
|
||||
t.Errorf("expected edge as fallback, got %s", got)
|
||||
}
|
||||
}
|
||||
|
||||
// --- wsOrStatic ---
|
||||
|
||||
func TestWsOrStaticNonWebSocket(t *testing.T) {
|
||||
@@ -4708,3 +4742,4 @@ func TestIngestTraceBroadcastIncludesPath(t *testing.T) {
|
||||
t.Errorf("expected hopsCompleted=2, got %d", *pathStruct.HopsCompleted)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,19 @@ func resolveCommit() string {
|
||||
}
|
||||
|
||||
func resolveVersion() string {
|
||||
// Issue #1807: the release fast-path re-tags :edge -> :vX.Y.Z without a
|
||||
// rebuild, so the ldflags-baked Version still reports "edge" on tagged
|
||||
// releases. Resolution order: operator env override, then the
|
||||
// .image-version file appended by the fast-path retag (mirrors the
|
||||
// .git-commit pattern in resolveCommit), then the baked Version.
|
||||
if v := strings.TrimSpace(os.Getenv("CORESCOPE_VERSION")); v != "" {
|
||||
return v
|
||||
}
|
||||
if data, err := os.ReadFile(".image-version"); err == nil {
|
||||
if v := strings.TrimSpace(string(data)); v != "" && v != "unknown" {
|
||||
return v
|
||||
}
|
||||
}
|
||||
if Version != "" {
|
||||
return Version
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user