mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-06 17:49:47 +00:00
The test-impact engine certifies the history it diffs and refuses a shallow
clone ("Graft or shallow state prevents history certification"). The shadow
job, the gate-mode select-tests job and the main-branch producer all checked
out with fetch-depth 2. So every shadow answer since #2458 was run_all:
GIT_UNAVAILABLE, then POLICY_UNAVAILABLE, because the merge base's
.codebase-memory.json is read through the same git facts. That was 24 of 24
measured PR runs. All three jobs now check out full history (about 400 MiB,
these jobs only).
The producer never published a bundle either. coverage-map.py exits 1 when a
suite fails under coverage: the map is still written and that suite's tests
are incomplete. test-impact-publish.sh ran it under set -e, so the publish
aborted. The failing suite was test_impact_git. Its hostile-diff probe
re-enters the runner as a child, which inherited CBM_TEST_COVERAGE_DIR,
started a coverage run of its own, and refused the per-test LLVM_PROFILE_FILE
it inherits.
Two changes:
- The probe now clears CBM_TEST_COVERAGE_DIR, as it already clears
CBM_TEST_ONLY_FILE. The child's profile then goes to the spawning test, like
any other child process.
- publish treats exit 1 as a written, conservative map (incomplete tests run
whole), with a warning that names the suite. It fails only on exit 2.
Proof:
- Depth-2 clone at f9ce3865: test-impact select answers run_all
[GIT_UNAVAILABLE, POLICY_UNAVAILABLE] with "Graft or shallow state ...", as
in CI. Same commit with full history: graph certified, run_all
[RUNNER_REACHED] (the change reaches the runner's main).
- Coverage runner (Homebrew LLVM, macOS), test_impact_git: before, 43 passed
and 2 failed ("a coverage run starts with LLVM_PROFILE_FILE=/dev/null");
after, 45 passed. coverage-map.py --suite test_impact_git: 45 tests,
0 incomplete, exit 0.
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
125 lines
5.6 KiB
Bash
Executable File
125 lines
5.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# test-impact-publish.sh — publish the team artifact bundle of the checked-out
|
|
# main commit (.github/workflows/test-impact-artifact.yml).
|
|
#
|
|
# Incremental (a push): the previous commit's bundle is the graph base and its
|
|
# coverage map the starting point; only the suites the push's own selection
|
|
# picks are re-run with coverage and merged in (scripts/test-impact/
|
|
# coverage-merge.py). The oldest observation is carried forward, so an
|
|
# incremental map ages out unless a full refresh runs.
|
|
# Full (weekly, manual, or no usable previous bundle): every suite is re-run
|
|
# and the graph is built from scratch. A weekly run ALSO builds the graph
|
|
# incrementally from the previous bundle and fails when the two graphs'
|
|
# content digests differ: an incremental index must equal a full one.
|
|
#
|
|
# Usage: scripts/ci/test-impact-publish.sh --binary PATH --runner PATH --out DIR
|
|
# --mode incremental|full [--before SHA] [--llvm-bin DIR] [--platform LABEL]
|
|
# Exit: 0 = published · 1 = failed · 2 = usage error.
|
|
set -euo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
BINARY="" RUNNER="" OUT="" MODE="" BEFORE="" LLVM_BIN="" PLATFORM="linux-x86_64-clang21"
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--binary) BINARY="$2"; shift 2 ;;
|
|
--runner) RUNNER="$2"; shift 2 ;;
|
|
--out) OUT="$2"; shift 2 ;;
|
|
--mode) MODE="$2"; shift 2 ;;
|
|
--before) BEFORE="$2"; shift 2 ;;
|
|
--llvm-bin) LLVM_BIN="$2"; shift 2 ;;
|
|
--platform) PLATFORM="$2"; shift 2 ;;
|
|
*) sed -n '2,18p' "$0" | sed 's/^# \{0,1\}//' >&2; exit 2 ;;
|
|
esac
|
|
done
|
|
[ -n "$BINARY" ] && [ -n "$RUNNER" ] && [ -n "$OUT" ] || exit 2
|
|
case "$MODE" in incremental | full) ;; *) exit 2 ;; esac
|
|
|
|
WORK="$(mktemp -d)"
|
|
trap 'rm -rf "$WORK"' EXIT
|
|
# A private daemon rendezvous: the socket path must fit sun_path.
|
|
export CBM_RUNTIME_DIR="$(mktemp -d /tmp/cbm-rt.XXXXXX)"
|
|
export CBM_CACHE_DIR="$WORK/cache"
|
|
mkdir -p "$WORK/engine" && chmod 700 "$WORK/engine"
|
|
HEAD_SHA="$(git -C "$ROOT" rev-parse HEAD)"
|
|
PREVIOUS=""
|
|
|
|
if [ -n "$BEFORE" ]; then
|
|
if scripts/ci/test-impact-bundle.sh --fetch "$BEFORE" "$WORK/previous"; then
|
|
PREVIOUS="$WORK/previous"
|
|
fi
|
|
fi
|
|
if [ "$MODE" = incremental ] && [ -z "$PREVIOUS" ]; then
|
|
echo "test-impact-publish: no previous bundle for ${BEFORE:-?}: full refresh"
|
|
MODE=full
|
|
fi
|
|
|
|
map() { # out [suite...]
|
|
local out="$1"; shift
|
|
local args=()
|
|
local rc=0
|
|
for suite in "$@"; do args+=(--suite "$suite"); done
|
|
python3 "$ROOT/scripts/test-impact/coverage-map.py" --runner "$RUNNER" --out "$out" \
|
|
${LLVM_BIN:+--llvm-bin "$LLVM_BIN"} ${args[@]+"${args[@]}"} || rc=$?
|
|
# 1 = a suite failed or timed out under coverage: the map is still written
|
|
# and that suite's tests are `incomplete`, which only ever selects MORE
|
|
# tests (an incomplete test runs whole). Publish it, but say which suite.
|
|
# 2 = usage or toolchain error: no trustworthy map, fail.
|
|
if [ "$rc" -eq 1 ]; then
|
|
echo "::warning::coverage map: a suite failed under coverage; its tests stay incomplete ($(python3 -c 'import json,sys; print(", ".join(s["suite"] for s in json.load(open(sys.argv[1]))["suites"] if s["exit"] != 0))' "$out/meta.json"))"
|
|
return 0
|
|
fi
|
|
return "$rc"
|
|
}
|
|
|
|
OBSERVED=""
|
|
if [ "$MODE" = full ]; then
|
|
OBSERVED="$(date +%s)"
|
|
map "$WORK/coverage"
|
|
else
|
|
# The push's own selection decides what to re-run (whole suites).
|
|
"$BINARY" test-impact select --repo "$ROOT" --base "$BEFORE" --work "$WORK/engine" \
|
|
--artifact "$PREVIOUS" --artifact-commit "$BEFORE" --artifact-verified \
|
|
--platform "$PLATFORM" > "$WORK/selection.json"
|
|
python3 "$ROOT/scripts/test-impact/selection.py" suites "$WORK/selection.json" > "$WORK/suites.txt"
|
|
"$RUNNER" --list-suites > "$WORK/listed.txt"
|
|
if grep -qx '\*' "$WORK/suites.txt"; then
|
|
OBSERVED="$(date +%s)"
|
|
map "$WORK/coverage"
|
|
else
|
|
mapfile -t rerun < <(sort -u "$WORK/suites.txt")
|
|
map "$WORK/fresh" ${rerun[@]+"${rerun[@]}"}
|
|
python3 "$ROOT/scripts/test-impact/coverage-merge.py" --previous "$PREVIOUS/coverage" \
|
|
--fresh "$WORK/fresh" --suites "$WORK/listed.txt" --commit "$HEAD_SHA" \
|
|
--out "$WORK/coverage"
|
|
fi
|
|
fi
|
|
|
|
publish() { # out [previous]
|
|
"$BINARY" test-impact publish --repo "$ROOT" --out "$1" --work "$WORK/engine" \
|
|
--coverage "$WORK/coverage" ${OBSERVED:+--observed-at "$OBSERVED"} \
|
|
--platform "$PLATFORM" ${2:+--previous "$2"}
|
|
}
|
|
if [ "$MODE" = full ]; then
|
|
publish "$OUT"
|
|
if [ -n "$PREVIOUS" ]; then
|
|
publish "$WORK/incremental" "$PREVIOUS"
|
|
field() { python3 -c 'import json,sys;print(json.load(open(sys.argv[1]))[sys.argv[2]])' "$1" "$2"; }
|
|
# Topology (what selection reads) must be equal; edge properties and the
|
|
# corpus-statistical edges are reported, not gated (recorded defects).
|
|
full_topology="$(field "$OUT/receipt.json" graph_topology_sha256)"
|
|
incr_topology="$(field "$WORK/incremental/receipt.json" graph_topology_sha256)"
|
|
if [ "$full_topology" != "$incr_topology" ]; then
|
|
echo "test-impact-publish: incremental topology differs from the full one ($incr_topology != $full_topology)" >&2
|
|
exit 1
|
|
fi
|
|
if [ "$(field "$OUT/receipt.json" graph_content_sha256)" != \
|
|
"$(field "$WORK/incremental/receipt.json" graph_content_sha256)" ]; then
|
|
echo "::warning::incremental graph content (edge properties, similarity edges) differs from the full one; topology is equal"
|
|
fi
|
|
echo "test-impact-publish: incremental topology equals the full one ($full_topology)"
|
|
fi
|
|
else
|
|
publish "$OUT" "$PREVIOUS"
|
|
fi
|
|
echo "test-impact-publish: bundle of $HEAD_SHA in $OUT ($MODE)"
|