From aba7152097ebc1b6fcf254c47a6117c4cc398256 Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Fri, 22 May 2026 23:51:47 -0700 Subject: [PATCH] fix(scripts): make ui-drift-audit work without ripgrep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The audit script silently passed on hosts without ripgrep installed because 'rg -n ...' would fail, '|| true' swallowed the failure, 'matches' would be empty, and report() would print 'ok: no matches'. This hid genuine UI drift from local 'pnpm run audit:ui' runs. Changes: - Detect ripgrep availability at startup and emit a stderr note when falling back. - Add a grep-based fallback that translates rg '--glob !path' exclusions into 'grep --exclude=' so caller-side exclusions (e.g. the @bytelyst/ui adapter file at Primitives.tsx) still apply. - Guard the optional 'extra_excludes' array expansion against 'set -u' when no exclusions are configured. Result: on this host (no rg) the audit now correctly reports 2 categories with matches — raw interactive controls and legacy global surface classes — instead of the false 'all green' it produced before. 'pnpm run audit:ui:strict' exits non-zero when matches remain, ready to wire into CI once UI5–UI8 finish migrating the remaining call sites. --- scripts/ui-drift-audit.sh | 51 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/scripts/ui-drift-audit.sh b/scripts/ui-drift-audit.sh index 04cc518..da9cb06 100644 --- a/scripts/ui-drift-audit.sh +++ b/scripts/ui-drift-audit.sh @@ -9,12 +9,61 @@ fi ROOT="$(git rev-parse --show-toplevel)" cd "$ROOT" +# Detect whether ripgrep is available. Fall back to grep so the audit cannot +# silently pass on hosts without rg (which was hiding regressions until now). +if command -v rg >/dev/null 2>&1; then + SEARCH_BACKEND="rg" +else + SEARCH_BACKEND="grep" + echo "[ui-drift-audit] note: ripgrep not found, falling back to grep" >&2 +fi + +# Build a search command that maps rg --glob exclusions to grep --exclude. +search() { + local pattern="$1" + shift + if [[ "$SEARCH_BACKEND" == "rg" ]]; then + rg -n "$pattern" "$@" --glob '!**/*.test.*' || true + else + # grep equivalent: -rnE with --exclude for test files. Translate + # rg-style --glob '!path' arguments into grep --exclude entries so the + # caller's exclusions (e.g. the @bytelyst/ui adapter file) still apply. + local targets=() + local extra_excludes=() + while [[ $# -gt 0 ]]; do + case "$1" in + --glob) + local glob_arg="${2:-}" + if [[ "$glob_arg" == "!"* ]]; then + local glob_path="${glob_arg#!}" + # grep --exclude matches against the basename, so reduce the + # exclusion to a filename pattern. If callers exclude paths + # like 'web/src/components/ui/Primitives.tsx', the basename + # 'Primitives.tsx' is the exclusion key. + extra_excludes+=("--exclude=$(basename "$glob_path")") + fi + shift 2 + ;; + *) + targets+=("$1") + shift + ;; + esac + done + grep -rnE "$pattern" "${targets[@]}" \ + --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" \ + --exclude="*.test.*" --exclude="*.spec.*" \ + --exclude-dir=node_modules --exclude-dir=.next \ + ${extra_excludes[@]+"${extra_excludes[@]}"} 2>/dev/null || true + fi +} + report() { local title="$1" local pattern="$2" shift 2 local matches - matches="$(rg -n "$pattern" "$@" --glob '!**/*.test.*' || true)" + matches="$(search "$pattern" "$@")" echo "=== $title ===" if [[ -z "$matches" ]]; then