From 6fabdba961c7b53f7c4f41f41dd2a0433569e46e Mon Sep 17 00:00:00 2001 From: Rongsong Shen Date: Thu, 3 Sep 2026 15:52:13 +0000 Subject: [PATCH] feat(eliminate-frontend-makefile): task 4.2 - delete src/frontend/Makefile The terminal step: src/frontend/Makefile (194 lines, the second, independently-maintained build/test path this whole spec exists to eliminate) is deleted. Re-ran the full task 4.1 validation suite with the file genuinely absent (build, meson test --suite apiserver, and -- going beyond citing task 3.5 -- a real live run-resource-verify.sh end-to-end run: VERDICT result=PASS, closing design.md's Testing Strategy "Discovery-path regression" check specifically). Full-repo sweep: 181 hits, zero unaccounted, byte-identical to task 4.1's non-Makefile hits (the only delta is the Makefile's own 8 self-referential lines, now gone since the file doesn't exist). Independently re-verified by the task reviewer. Meson is now the single build/test system for apiserver and xcecli. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01XYdtrEWWZfKRRGED7raEYg --- src/frontend/Makefile | 194 ------------------------------------------ 1 file changed, 194 deletions(-) delete mode 100644 src/frontend/Makefile diff --git a/src/frontend/Makefile b/src/frontend/Makefile deleted file mode 100644 index 0b44e3c4..00000000 --- a/src/frontend/Makefile +++ /dev/null @@ -1,194 +0,0 @@ -# XCE project — test targets -# Usage: -# make test # unit tests only (no server needed, CGO_ENABLED=0) -# make test-backend # backend CGO conversion tests (requires nix dev shell + build dir) -# make test-integration # regression suite against live server -# make test-all # unit + integration tests - -XCE_BIN ?= /tmp/xce_static -SRV_URL ?= http://localhost:8080 -GOFLAGS := CGO_ENABLED=0 - -# build-time-versioning task 4.3: dev-loop -ldflags path. Computes commit id -# (git, -dirty suffixed) and build time (UTC) directly -- independent of -# meson -- mirroring xce-build.sh's (task 2.1) git/dirty-check logic and -# passing the identical -ldflags shape go_build (task 4.1) appends. `:=` -# (simply expanded: the $(shell ...) calls run once, immediately, when this -# line is parsed) rather than `=` (recursively expanded: would re-invoke git -# and date on every reference to these variables) -- this computes each -# value exactly once per `make` invocation, matching xce-build.sh's own -# single-computation-per-invocation model, so build-server and build-cli -# (and multiple references within one recipe) all see the same values. -GIT_COMMIT_HASH := $(shell git rev-parse --short HEAD 2>/dev/null) -GIT_STATUS := $(shell git status --porcelain 2>/dev/null) -ifeq ($(GIT_COMMIT_HASH),) -# git itself failed (e.g. no .git present) -- Requirement 1.4/4.1's fallback -# discipline: record as unknown rather than fail the build. -GIT_COMMIT := unknown -else ifeq ($(GIT_STATUS),) -GIT_COMMIT := $(GIT_COMMIT_HASH) -else -GIT_COMMIT := $(GIT_COMMIT_HASH)-dirty -endif -BUILD_TIME := $(shell date -u +%Y-%m-%dT%H:%M:%SZ) - -# dirty-content-fingerprint task 4.3: independent DIRTY_FINGERPRINT -# computation for this same dev-loop -ldflags path -- a NEW, sibling value -# alongside GIT_COMMIT_HASH/GIT_STATUS/GIT_COMMIT/BUILD_TIME above, which -# this block does not read or modify. Mirrors xce-build.sh's (task 2.1) -# dirty_fingerprint algorithm exactly: empty when the tree is clean, or when -# the hash computation itself fails (never fabricated -- Requirement 5.1); -# otherwise a sha256 prefix (8 hex chars, matching xce-build.sh's -# `cut -c1-8`) over `git diff HEAD` concatenated with the sorted raw content -# of every file `git ls-files -z --others --exclude-standard` lists. -# -# DIRTY_FP_SRC_DIR mirrors xce-build.sh's own SRC_DIR (its script's parent -# directory, i.e. src/ -- one level above this Makefile's src/frontend/): -# `git status --porcelain`/`git diff HEAD` are repo-wide with root-relative -# path display regardless of invocation cwd, but a plain, pathspec-less -# `git ls-files --others` is genuinely SCOPED to (and shows paths relative -# to) the invocation cwd -- confirmed empirically. Running every git call -# from DIRTY_FP_SRC_DIR (via `cd`, not just `git -C`, since the untracked -# filenames `git ls-files` prints must also resolve on disk relative to that -# same directory for `cat` to read them) reproduces xce-build.sh's exact -# untracked-file scope regardless of where `make` itself is invoked from -- -# required for this task's Observable ("same fingerprint ... as a -# meson-built binary from the identical tree state"). -# -# Uses `git ls-files -z ... | sort -z | xargs -0 -r cat --` instead of -# xce-build.sh's bash `while IFS= read -r -d '' f; do cat -- "$f"; done` -# loop -- both concatenate the same sorted files' raw bytes in the same -# order (verified byte-identical), but this form needs no embedded -# single-quote characters (bash's `-d ''`), which would otherwise be -# fragile to escape inside a Make `$(shell ...)` argument. A real mktemp -# scratch file (not command-substitution capture) collects the combined -# diff+file bytes before hashing, so no trailing-newline stripping skews -# the digest versus xce-build.sh's own temp-file-based approach. Zero -# working-tree/index mutation -- reads only. -# -# `git diff HEAD` and the ls-files/sort/xargs step are gated as SEPARATE, -# individually-checked steps (fp_ok, mirroring xce-build.sh's own fp_ok -# tracking) rather than one `{ cmd1; cmd2; } >"$$fp_tmp"` group -- a POSIX -# sequence/group's exit status reflects only its LAST command, so a grouped -# form would silently swallow a `git diff HEAD` failure whenever the -# ls-files/sort/xargs step still succeeded, hashing incomplete data into a -# fabricated non-empty fingerprint instead of degrading to empty -# (Requirement 5.1). -# -# round-2 remediation: `git ls-files -z --others --exclude-standard` is ALSO -# pulled out of any pipe and run as its own directly-redirected command into -# a second temp file (list_tmp), with its OWN individually-checked `$?` -- -# it is no longer the first stage of a 3-stage -# `ls-files | sort -z | xargs -0 -r cat --` pipe. That pipe had the exact -# same class of bug as the grouped-form one above: a POSIX pipe's exit -# status reflects only its LAST stage, and `sort -z`/`xargs -0 -r` both -# exit 0 on the empty stdin a failed `git ls-files` produces, so a -# `git ls-files` failure was silently swallowed and fp_tmp was hashed with -# only the `git diff HEAD` bytes in it -- a real but fabricated/incomplete -# fingerprint, not the required empty fallback. -# -# Two options were considered: (a) prefix this whole $(shell ...) body with -# `set -o pipefail;`, which empirically works in THIS repo's dev shell -# (GNU Make's $(shell) here runs under /bin/sh, itself a symlink into the -# nix store's bash-interactive package -- confirmed via `ls -la /bin/sh`), -# or (b) the restructuring below, which sidesteps pipe-exit propagation -# entirely instead of depending on it. (b) was chosen: this same repo's own -# `.kiro/steering/build-deployment.md` documents this exact codebase having -# been bitten before by code that silently depended on "/bin/sh happens to -# be symlinked to bash" (deploy-ha.sh's shebang was found locally altered to -# `#!/bin/sh` while still using bash-only syntax, and only kept working by -# that coincidence) -- its own fix was to stop relying on that coincidence -# rather than to keep depending on it, and this Makefile does not pin -# `SHELL := bash` to turn the coincidence into a guarantee. Since $(shell) -# here has no such pin either, (a)'s `pipefail` would rely on the identical -# unpinned coincidence for a build-portability property (dirty-fingerprint -# accuracy) rather than a dev-loop-only convenience script, so (b) is the -# more conservative choice. `git`, the highest-risk command (failure here -# is exactly the case under test), is now entirely outside any pipe. The -# residual `LC_ALL=C sort -z <"$$list_tmp" | xargs -0 -r cat --` pipe keeps -# a narrower gap -- a `sort` failure specifically could still be masked by -# `xargs`'s own (last-stage) exit status -- but `xargs -r cat --` DOES -# propagate an individual `cat` failure (e.g. an unreadable file `git -# ls-files` listed): GNU xargs exits non-zero (123) whenever any invoked -# command exits 1-125, so that sub-case is still caught without pipefail. -# This matches the reviewer's own assessment: a `sort` failure is a far -# lower-risk residual than the `git` failure this fix targets. -DIRTY_FP_SRC_DIR := $(CURDIR)/.. -DIRTY_FINGERPRINT := $(shell \ - cd "$(DIRTY_FP_SRC_DIR)" 2>/dev/null && \ - if [ -n "$$(git status --porcelain 2>/dev/null)" ]; then \ - fp_tmp=$$(mktemp 2>/dev/null); \ - if [ -n "$$fp_tmp" ]; then \ - fp_ok=1; \ - list_tmp=""; \ - if ! git diff HEAD >"$$fp_tmp" 2>/dev/null; then fp_ok=0; fi; \ - if [ "$$fp_ok" = 1 ]; then \ - list_tmp=$$(mktemp 2>/dev/null); \ - if [ -z "$$list_tmp" ]; then \ - fp_ok=0; \ - elif ! git ls-files -z --others --exclude-standard >"$$list_tmp" 2>/dev/null; then \ - fp_ok=0; \ - fi; \ - fi; \ - if [ "$$fp_ok" = 1 ] && ! LC_ALL=C sort -z <"$$list_tmp" | xargs -0 -r cat -- >>"$$fp_tmp" 2>/dev/null; then fp_ok=0; fi; \ - if [ "$$fp_ok" = 1 ]; then \ - fp=$$(sha256sum <"$$fp_tmp" 2>/dev/null | cut -c1-8); \ - if [ -n "$$fp" ]; then printf "%s" "$$fp"; fi; \ - fi; \ - rm -f "$$fp_tmp" "$$list_tmp" 2>/dev/null; \ - fi; \ - fi) - -VERSION_LDFLAGS := -ldflags "-X main.GitCommit=$(GIT_COMMIT) -X main.BuildTime=$(BUILD_TIME) -X main.DirtyFingerprint=$(DIRTY_FINGERPRINT)" - -# bug-1558: test-backend's CGO_CFLAGS/CGO_LDFLAGS, self-derived via -# pkg-config so `make test-backend` works standalone instead of only inside -# meson's custom_target env (apiserver/meson.build is the source of truth -# this mirrors -- librtti/c-capnproto/openssl/tinylog resolve via -# pkg-config there; math/rt are cc.find_library() results with no -# pkg-config package, added directly as -lm/-lrt to match). -# BUILD_DIR defaults to the tree tools/xce-build.sh produces (profile asan); -# override for a non-ASAN build, e.g. -# make test-backend BUILD_DIR=$(CURDIR)/../build.dbg FRONTEND_CGO_SANITIZE= -BUILD_DIR ?= $(CURDIR)/../xce.build -FRONTEND_CGO_PKGS := librtti c-capnproto openssl tinylog -FRONTEND_CGO_SANITIZE ?= -fsanitize=address -g -FRONTEND_CGO_CFLAGS := $(FRONTEND_CGO_SANITIZE) $(shell pkg-config --cflags $(FRONTEND_CGO_PKGS)) -I$(CURDIR)/../include -I$(BUILD_DIR)/lib -FRONTEND_CGO_LDFLAGS := $(FRONTEND_CGO_SANITIZE) $(shell pkg-config --libs $(FRONTEND_CGO_PKGS)) -lm -lrt -L$(BUILD_DIR)/lib -lxce - -.PHONY: build-cli build-server test test-backend test-integration test-all - -build-cli: - cd xcecli && $(GOFLAGS) go build $(VERSION_LDFLAGS) -o $(XCE_BIN) ./cmd/main.go - -build-server: - cd apiserver && go build $(VERSION_LDFLAGS) -o /tmp/apiserver ./cmd/main.go - -## Run all Go unit tests that do not require CGO or a live server. -test: - @echo "=== Unit tests: apiserver ===" - cd apiserver && $(GOFLAGS) go test ./store/... ./utils/... ./controllers/... ./backend/... -count=1 - @echo "" - @echo "=== Unit tests: xcecli ===" - cd xcecli && $(GOFLAGS) go test ./... -count=1 - -## Run backend CGO conversion tests. Standalone-runnable: CGO_CFLAGS/ -## CGO_LDFLAGS are self-derived above via pkg-config (bug-1558) -- no manual -## env setup needed. Still requires the nix develop shell (for pkg-config's -## .pc files) and a prior `xce-build.sh lib` (or any component that builds -## libxce.a) so BUILD_DIR/lib/libxce.a and BUILD_DIR/lib's generated headers -## exist. -test-backend: - @echo "=== Backend CGO tests: apiserver/backend ===" - cd apiserver && CGO_ENABLED=1 \ - CGO_CFLAGS="$(FRONTEND_CGO_CFLAGS)" \ - CGO_LDFLAGS="$(FRONTEND_CGO_LDFLAGS)" \ - go test ./backend/... -count=1 - -## Run regression suite against a live server (requires XCE_BIN and SRV_URL) -test-integration: build-cli - @echo "=== Integration regression: $(SRV_URL) ===" - XCE=$(XCE_BIN) URL=$(SRV_URL) bash tests/regression/run.sh - -## Run everything -test-all: test test-integration