fix(claude): stop stale .mcp.json residue outranking a project switch, and gate stale builds #106

Merged
michal merged 3 commits from worktree-fix-statusline-project into main 2026-08-10 15:52:51 +00:00
4 changed files with 31 additions and 4 deletions
Showing only changes of commit 96e27c8716 - Show all commits

View File

@@ -890,8 +890,14 @@ ships a binary missing whatever landed on main meanwhile, and `rpm -U --force`
overwrites the good one with it. That happened on 2026-08-10: a build from a
stale checkout replaced `/usr/bin/mcpctl` with one that had no `statusline`
command, months after the status line landed. `scripts/check-main-sync.sh`
(sourced by `build-rpm.sh` and `build-deb.sh`) fetches `main`, compares, and
fails before any work happens, listing the commits you are missing.
fetches `main`, compares, and fails before any work happens, listing the commits
you are missing. It gates every path that produces something others consume:
`build-rpm.sh`, `build-deb.sh`, `build-mcpd.sh` (each is also run standalone, so
none can rely on another having checked) and `deploy-k8s.sh` — where a stale
branch would pin its sha in Pulumi and make it the cluster's source of truth.
`deploy-k8s.sh --dry-run` skips the check: it builds and cuts over nothing, and
blocking a read-only inspection only teaches people to export the escape hatch
permanently, disabling the gate for real deploys too.
```bash
git merge main # the fix

View File

@@ -16,6 +16,11 @@ if [ -f .env ]; then
set -a; source .env; set +a
fi
# This pushes an image to the registry, so the same staleness gate as the package
# builds applies. Run standalone as well as from deploy-k8s.sh, hence its own copy.
source "$SCRIPT_DIR/check-main-sync.sh"
check_main_sync
# Push directly to internal address (external proxy has body size limit)
REGISTRY="10.0.0.194:3012"
IMAGE="mcpd"

View File

@@ -84,8 +84,10 @@ check_main_sync() {
echo "" >&2
echo "ERROR: '$branch' is $behind commit(s) behind $base — refusing to build." >&2
echo "" >&2
echo " Building now would package a binary without these, and installing it" >&2
echo " would overwrite a good one with a version missing them:" >&2
# Deliberately artifact-agnostic: the same helper gates RPM/DEB packages, the
# mcpd image, and the k8s deploy.
echo " Building now would produce an artifact without these, and shipping it" >&2
echo " would replace a good one with a version missing them:" >&2
echo "" >&2
git log --oneline --no-decorate "HEAD..$ref" | head -15 | sed 's/^/ /' >&2
if [ "$behind" -gt 15 ]; then

View File

@@ -80,6 +80,20 @@ cat <<EOF
EOF
[ -f "$PULUMI_YAML" ] || die "Pulumi config not found: $PULUMI_YAML"
# ── 0. Staleness gate ──
# Same hazard as the RPM build, with the cluster on the receiving end: a branch
# behind main deploys images missing whatever landed there, and the sha pinned in
# Pulumi makes that the new source of truth. Skipped for --dry-run, which builds
# and cuts over nothing — blocking a read-only inspection only teaches people to
# export MCPCTL_ALLOW_BEHIND_MAIN=1 permanently, which would disable the gate for
# the real deploys too.
if [ "$DRY_RUN" = true ]; then
warn "dry-run: skip the main-sync check"
else
source "$SCRIPT_DIR/check-main-sync.sh"
check_main_sync || die "branch is behind main — merge it before deploying"
fi
# ── 1. Test gate ──
if [ "$SKIP_TESTS" = true ]; then warn "skipping unit tests (--skip-tests)"; else
say "1/7 Unit tests (pnpm test:run)"