un-inception/scripts/detect-changes.sh
russell@unturf.com 8695578d89 feat: add smart multi-language testing strategy for client SDK growth
Add comprehensive testing infrastructure for UN clients:

1. Smart Change Detection (detect-changes.sh)
   - Detects changes in BOTH root-level (un.py, un.go) AND clients/ directory
   - Maps file extensions and directory names to languages
   - Triggers test_all when infrastructure changes

2. Language-Specific CI Matrix (generate-matrix.sh compatible)
   - Only runs tests for languages with changes
   - Example: modify clients/python/ → pytest runs, Go/Ruby skipped

3. Testing Strategy Document (TESTING-STRATEGY.md)
   - Complete testing matrix by language tier (compiled, interpreted, inception)
   - Unit, integration, embedding, and parity tests
   - Inception pattern for languages without local interpreters
   - Common failures and fixes
   - Rollout schedule for client/ migration

4. Makefile Targets
   - 'make test-python', 'make test-go', etc. for local development
   - 'make test-all' for comprehensive testing
   - 'make test-integration' for API contract validation
   - 'make test-ci-locally' to simulate CI pipeline

5. Updated CLAUDE.md
   - Documents SDK architecture (in growth state)
   - Explains three purposes: CLI, library, embeddable
   - References TESTING-STRATEGY.md for details

This enables:
✓ Per-language testing (only run what changed)
✓ Local developer workflow (make test-LANG)
✓ 42+ language feature parity validation
✓ Cross-language integration testing
2026-01-15 15:52:40 -05:00

158 lines
3.8 KiB
Bash
Executable file

#!/bin/bash
# Detect which SDKs changed in this commit/PR
# Output: JSON array of changed languages
set -e
# Get the base branch for comparison
if [ -n "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
# MR context
BASE="origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
elif [ "$CI_COMMIT_BRANCH" = "main" ]; then
# Push to main - compare with previous commit
BASE="HEAD~1"
else
# Fallback
BASE="origin/main"
fi
# Get all changed files in this commit
CHANGED_FILES=$(git diff --name-only "$BASE...HEAD" 2>/dev/null || echo "")
# Extract unique languages from TWO sources:
# 1. Root-level files (un.py, un.go, etc.)
# 2. Client directory files (clients/python/*, clients/go/*, etc.)
CHANGED_LANGS=$(
{
# Root-level implementations
echo "$CHANGED_FILES" | grep -E '^un\.' | sed 's/un\.\([^.]*\).*/\1/'
# Client directory implementations
echo "$CHANGED_FILES" | grep -E '^clients/([^/]+)/' | sed 's|^clients/\([^/]*\)/.*|\1|'
} | sort -u || echo ""
)
# Map file extensions to language names (for root-level un.* files)
declare -A LANG_MAP=(
[py]="python"
[js]="javascript"
[ts]="typescript"
[go]="go"
[rb]="ruby"
[php]="php"
[pl]="perl"
[lua]="lua"
[sh]="bash"
[rs]="rust"
[java]="java"
[cs]="csharp"
[cpp]="cpp"
[c]="c"
[hs]="haskell"
[kt]="kotlin"
[ex]="elixir"
[erl]="erlang"
[cr]="crystal"
[dart]="dart"
[nim]="nim"
[jl]="julia"
[r]="r"
[groovy]="groovy"
[clj]="clojure"
[fs]="fsharp"
[ml]="ocaml"
[m]="objc"
[d]="d"
[v]="vlang"
[zig]="zig"
[f90]="fortran"
[cob]="cobol"
[scm]="scheme"
[lisp]="lisp"
[tcl]="tcl"
[awk]="awk"
[pro]="prolog"
[forth]="forth"
[ps1]="powershell"
[raku]="raku"
)
# Map directory names from clients/ to language names (clients/ already has language names)
declare -A DIR_MAP=(
[python]="python"
[javascript]="javascript"
[typescript]="typescript"
[go]="go"
[ruby]="ruby"
[php]="php"
[perl]="perl"
[lua]="lua"
[bash]="bash"
[rust]="rust"
[java]="java"
[csharp]="csharp"
[cpp]="cpp"
[c]="c"
[haskell]="haskell"
[kotlin]="kotlin"
[elixir]="elixir"
[erlang]="erlang"
[crystal]="crystal"
[dart]="dart"
[nim]="nim"
[julia]="julia"
[r]="r"
[groovy]="groovy"
[clojure]="clojure"
[fsharp]="fsharp"
[ocaml]="ocaml"
[objc]="objc"
[d]="d"
[vlang]="vlang"
[zig]="zig"
[fortran]="fortran"
[cobol]="cobol"
[scheme]="scheme"
[lisp]="lisp"
[tcl]="tcl"
[awk]="awk"
[prolog]="prolog"
[forth]="forth"
[powershell]="powershell"
[raku]="raku"
)
# Also check for changes in test files, scripts, or core infra
if echo "$CHANGED_FILES" | grep -qE '^(tests/|scripts/|\.gitlab-ci\.yml|clients/\{.*\}/)'; then
# If tests, scripts, or multi-language client templates changed, test ALL SDKs
echo '{"changed_langs": ["all"], "reason": "Core infrastructure changed", "test_all": true}'
exit 0
fi
# Convert file extensions and directory names to language names
LANGS_JSON="["
FIRST=true
for ITEM in $CHANGED_LANGS; do
# Try directory map first (for clients/python/, etc.)
LANG="${DIR_MAP[$ITEM]}"
# Fallback to extension map (for un.py, etc.)
LANG="${LANG:-${LANG_MAP[$ITEM]}}"
# Fallback to item as-is if not in any map
LANG="${LANG:-$ITEM}"
if [ "$FIRST" = true ]; then
LANGS_JSON="$LANGS_JSON\"$LANG\""
FIRST=false
else
LANGS_JSON="$LANGS_JSON,\"$LANG\""
fi
done
LANGS_JSON="$LANGS_JSON]"
# If no changes detected, test nothing (skip tests)
if [ "$LANGS_JSON" = "[]" ]; then
echo '{"changed_langs": [], "reason": "No SDK files changed", "test_all": false}'
exit 0
fi
echo "{\"changed_langs\": $LANGS_JSON, \"test_all\": false}"