feat: add runner conversion scripts and strengthen cutover automation
This commit is contained in:
89
runners-conversion/periodVault/validate-tdd.sh
Executable file
89
runners-conversion/periodVault/validate-tdd.sh
Executable file
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env bash
|
||||
# validate-tdd.sh
|
||||
# Guard that production code changes are accompanied by tests.
|
||||
set -euo pipefail
|
||||
|
||||
BASE_REF="${1:-origin/main}"
|
||||
|
||||
if ! git rev-parse --verify "$BASE_REF" >/dev/null 2>&1; then
|
||||
BASE_REF="HEAD~1"
|
||||
fi
|
||||
|
||||
CHANGED_FILES=()
|
||||
while IFS= read -r line; do
|
||||
[[ -n "$line" ]] && CHANGED_FILES+=("$line")
|
||||
done < <(git diff --name-only "$BASE_REF"...HEAD)
|
||||
|
||||
if [[ ${#CHANGED_FILES[@]} -eq 0 ]]; then
|
||||
echo "[validate-tdd] No changed files."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
is_production_file() {
|
||||
local f="$1"
|
||||
[[ "$f" == shared/src/commonMain/* ]] && return 0
|
||||
[[ "$f" == androidApp/src/main/* ]] && return 0
|
||||
[[ "$f" == iosApp/iosApp/* ]] && [[ "$f" != iosApp/iosAppUITests/* ]] && [[ "$f" != iosApp/iosAppTests/* ]] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
is_test_file() {
|
||||
local f="$1"
|
||||
[[ "$f" == shared/src/commonTest/* ]] && return 0
|
||||
[[ "$f" == shared/src/jvmTest/* ]] && return 0
|
||||
[[ "$f" == androidApp/src/androidTest/* ]] && return 0
|
||||
[[ "$f" == androidApp/src/test/* ]] && return 0
|
||||
[[ "$f" == iosApp/iosAppUITests/* ]] && return 0
|
||||
[[ "$f" == iosApp/iosAppTests/* ]] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
PROD_COUNT=0
|
||||
TEST_COUNT=0
|
||||
for file in "${CHANGED_FILES[@]}"; do
|
||||
if is_production_file "$file"; then
|
||||
PROD_COUNT=$((PROD_COUNT + 1))
|
||||
fi
|
||||
if is_test_file "$file"; then
|
||||
TEST_COUNT=$((TEST_COUNT + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$PROD_COUNT" -gt 0 && "$TEST_COUNT" -eq 0 ]]; then
|
||||
echo "[validate-tdd] Failing: production code changed without matching test updates."
|
||||
echo "[validate-tdd] Production files changed: $PROD_COUNT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CHANGED_TEST_FILES=()
|
||||
TEST_PATH_REGEX='^(shared/src/(commonTest|jvmTest)/|androidApp/src/(androidTest|test)/|iosApp/iosApp(UI)?Tests/)'
|
||||
while IFS= read -r line; do
|
||||
[[ -n "$line" ]] && CHANGED_TEST_FILES+=("$line")
|
||||
done < <(
|
||||
if command -v rg >/dev/null 2>&1; then
|
||||
printf '%s\n' "${CHANGED_FILES[@]}" | rg "$TEST_PATH_REGEX" || true
|
||||
else
|
||||
printf '%s\n' "${CHANGED_FILES[@]}" | grep -E "$TEST_PATH_REGEX" || true
|
||||
fi
|
||||
)
|
||||
for test_file in "${CHANGED_TEST_FILES[@]:-}"; do
|
||||
if [[ -f "$test_file" ]]; then
|
||||
if command -v rg >/dev/null 2>&1; then
|
||||
if rg -q 'catch[[:space:]]*\([[:space:]]*AssertionError|XCTExpectFailure|@Ignore|@Disabled' "$test_file"; then
|
||||
echo "[validate-tdd] Failing: potential weak assertion/skip anti-pattern in $test_file"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if grep -Eq 'catch[[:space:]]*\([[:space:]]*AssertionError|XCTExpectFailure|@Ignore|@Disabled' "$test_file"; then
|
||||
echo "[validate-tdd] Failing: potential weak assertion/skip anti-pattern in $test_file"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "${FORCE_AUDIT_GATES:-0}" == "1" ]]; then
|
||||
echo "[validate-tdd] FORCE_AUDIT_GATES enabled."
|
||||
fi
|
||||
|
||||
echo "[validate-tdd] PASS ($BASE_REF...HEAD)"
|
||||
Reference in New Issue
Block a user