mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-26 08:18:18 +00:00
ci: add count-floor guard to migration-critical test gate (#4673)
The migration-proof step in ci.yml selects tests by name substring (data_movement / rebalance / decommission / source_cleanup / delete_marker), so a rename can silently thin the gate to zero with no CI signal. Move the filter expression into scripts/check_migration_gate_count.sh as its single source of truth: the script counts the selected tests with cargo nextest list, fails if the count drops below the committed floor in .config/migration-gate-floor.txt, and then runs the gate with the same filter so the check and the run cannot drift. The floor equals the exact selected-test count at landing (571), so any reduction fails CI and intentional shrinks must edit the floor file in the same PR, keeping gate changes visible in diffs. Refs rustfs/backlog#1153 (infra-12), rustfs/backlog#1155. Signed-off-by: Zhengchao An <anzhengchao@gmail.com>
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
# Committed floor for the number of tests selected by the migration-critical
|
||||
# CI gate (see scripts/check_migration_gate_count.sh, backlog#1153 infra-12).
|
||||
#
|
||||
# The floor equals the exact count of rustfs-ecstore --lib tests matching the
|
||||
# gate filter (name substrings: data_movement, rebalance, decommission,
|
||||
# source_cleanup, delete_marker) at the time this file was last updated.
|
||||
# CI fails if the selected count drops below this number, so renames or
|
||||
# removals that thin the gate must update this file in the same PR.
|
||||
# Adding tests does not require a bump, but bumping keeps the guard tight.
|
||||
571
|
||||
@@ -170,13 +170,18 @@ jobs:
|
||||
# Explicit gate for migration-critical suites. These tests already ran in
|
||||
# the full nextest pass above; a single filtered nextest invocation keeps
|
||||
# the named gate without rebuilding or re-running them one package at a time.
|
||||
#
|
||||
# The gate selects tests by name substring (data_movement / rebalance /
|
||||
# decommission / source_cleanup / delete_marker), so renames can silently
|
||||
# thin it. The script owns the filter expression and first verifies the
|
||||
# selected-test count against the committed floor in
|
||||
# .config/migration-gate-floor.txt before running the gate; renames or
|
||||
# removals must update that file consciously (see the script header).
|
||||
# Kept on the default profile (no --profile ci): a second --profile ci run
|
||||
# would clobber target/nextest/ci/junit.xml, and none of these tests are
|
||||
# quarantined so they gain nothing from the ci profile's retry overrides.
|
||||
- name: Run rebalance/decommission migration proofs
|
||||
run: |
|
||||
cargo nextest run -p rustfs-ecstore --lib \
|
||||
-E 'test(data_movement) or test(rebalance) or test(decommission) or test(source_cleanup) or test(delete_marker)'
|
||||
run: ./scripts/check_migration_gate_count.sh
|
||||
|
||||
test-and-lint-rio-v2:
|
||||
name: Test and Lint (rio-v2)
|
||||
|
||||
Executable
+79
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env bash
|
||||
# Count-floor guard for the migration-critical test gate (backlog#1153 infra-12).
|
||||
#
|
||||
# ci.yml's migration gate selects tests BY NAME SUBSTRING. A rename that drops
|
||||
# a test out of the filter silently thins the gate — potentially to zero —
|
||||
# without any CI signal (this is how the layered gate died when #878 closed).
|
||||
# This script owns the filter expression so the count check and the test run
|
||||
# cannot drift, and fails fast when the number of selected tests drops below
|
||||
# the committed floor in .config/migration-gate-floor.txt.
|
||||
#
|
||||
# NAMING CONVENTION DEPENDENCY: migration-gate tests are matched by these
|
||||
# reserved name substrings:
|
||||
#
|
||||
# data_movement, rebalance, decommission, source_cleanup, delete_marker
|
||||
#
|
||||
# Renaming a test away from all of these substrings removes it from the gate.
|
||||
# The floor equals the exact selected-test count at the time it was last
|
||||
# committed, so ANY reduction fails CI. To shrink the gate intentionally
|
||||
# (test removed or consciously renamed), update the floor file in the same PR
|
||||
# so the reduction is visible in the diff. Adding tests never requires a floor
|
||||
# bump (the floor is a lower bound), but bumping it keeps the guard tight.
|
||||
#
|
||||
# Per-pattern floors are deliberately omitted: with an exact-count total floor,
|
||||
# a single test dropping out of any pattern already fails the check, so
|
||||
# per-pattern bookkeeping would add churn without detection power.
|
||||
#
|
||||
# Usage:
|
||||
# scripts/check_migration_gate_count.sh # count check + run the gate
|
||||
# scripts/check_migration_gate_count.sh check # count check only
|
||||
# scripts/check_migration_gate_count.sh run # run the gate only
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
# Single source of truth for the migration-gate filter. ci.yml must invoke
|
||||
# this script instead of inlining the expression.
|
||||
MIGRATION_GATE_FILTER='test(data_movement) or test(rebalance) or test(decommission) or test(source_cleanup) or test(delete_marker)'
|
||||
FLOOR_FILE=".config/migration-gate-floor.txt"
|
||||
|
||||
mode="${1:-all}"
|
||||
case "$mode" in
|
||||
all | check | run) ;;
|
||||
*)
|
||||
echo "usage: $0 [all|check|run]" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ "$mode" == "all" || "$mode" == "check" ]]; then
|
||||
floor="$(grep -Ev '^[[:space:]]*(#|$)' "$FLOOR_FILE" | head -n1 | tr -d '[:space:]')"
|
||||
if ! [[ "$floor" =~ ^[0-9]+$ ]]; then
|
||||
echo "error: $FLOOR_FILE does not contain a numeric floor (got: '$floor')" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Human-format list: binary headers start at column 0, one test per
|
||||
# 4-space-indented line. A nextest failure aborts via set -e with its
|
||||
# stderr visible; an output-format change collapses the count to 0 and
|
||||
# fails loudly rather than silently passing.
|
||||
list_output="$(cargo nextest list -p rustfs-ecstore --lib -E "$MIGRATION_GATE_FILTER")"
|
||||
count="$(printf '%s\n' "$list_output" | grep -c '^ ' || true)"
|
||||
|
||||
if ((count < floor)); then
|
||||
echo "error: migration gate selects $count tests, below the committed floor of $floor." >&2
|
||||
echo "" >&2
|
||||
echo "The gate matches tests by name substring (data_movement / rebalance /" >&2
|
||||
echo "decommission / source_cleanup / delete_marker). A rename or removal has" >&2
|
||||
echo "thinned the selection. Either restore the test names, or — if the" >&2
|
||||
echo "reduction is intentional — update $FLOOR_FILE in this PR so the" >&2
|
||||
echo "gate change is explicit and reviewable." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "migration gate count OK: $count selected tests (floor: $floor)"
|
||||
fi
|
||||
|
||||
if [[ "$mode" == "all" || "$mode" == "run" ]]; then
|
||||
cargo nextest run -p rustfs-ecstore --lib -E "$MIGRATION_GATE_FILTER"
|
||||
fi
|
||||
Reference in New Issue
Block a user