chore(scripts): add lint-infra, typecheck-all, test-all cross-repo scripts
This commit is contained in:
parent
f8c0da5c2a
commit
409144a2ef
11
AGENTS.md
11
AGENTS.md
@ -344,6 +344,17 @@ npx tsx scripts/encrypt-migrate.ts --product chronomind # Live encrypt
|
||||
./scripts/prep-consumer.sh /path/to/consumer-dir # pack + rewrite
|
||||
./scripts/prep-consumer.sh /path/to/consumer-dir --restore # undo
|
||||
|
||||
# ── Infrastructure lint (Dockerfiles + Helm charts) ─
|
||||
./scripts/lint-infra.sh # Lint all 25 Dockerfiles + any Helm charts
|
||||
./scripts/lint-infra.sh --docker # Dockerfiles only
|
||||
./scripts/lint-infra.sh --helm # Helm charts only
|
||||
./scripts/lint-infra.sh path/to/Dockerfile # Explicit path(s)
|
||||
# Requires: brew install hadolint helm
|
||||
|
||||
# ── Cross-repo typecheck + test ──────────────────────
|
||||
./scripts/typecheck-all.sh # pnpm typecheck across all 11 repos
|
||||
./scripts/test-all.sh # pnpm test --run across all 11 repos
|
||||
|
||||
# ── Health check all services ──────────────────────
|
||||
pnpm --filter @lysnrai/monitoring check
|
||||
```
|
||||
|
||||
21
README.md
21
README.md
@ -159,6 +159,27 @@ Each consumer repo has a convenience wrapper: `scripts/docker-prep.sh` (or `scri
|
||||
|
||||
> **Dashboards inside this repo** (`dashboards/admin-web`, `dashboards/tracker-web`) use `workspace:*` refs and do NOT need this workflow — pnpm resolves them automatically.
|
||||
|
||||
## Infrastructure Lint
|
||||
|
||||
Validates all 25 Dockerfiles across the 11 ByteLyst repos using [hadolint](https://github.com/hadolint/hadolint), and any Helm charts using `helm lint` + `helm template`.
|
||||
|
||||
```bash
|
||||
# Prerequisites
|
||||
brew install hadolint helm
|
||||
|
||||
# Lint everything
|
||||
./scripts/lint-infra.sh
|
||||
|
||||
# Dockerfiles only / Helm charts only
|
||||
./scripts/lint-infra.sh --docker
|
||||
./scripts/lint-infra.sh --helm
|
||||
|
||||
# Explicit paths
|
||||
./scripts/lint-infra.sh path/to/Dockerfile path/to/chart-dir
|
||||
```
|
||||
|
||||
Suppressed rules (false positives for this codebase): `DL3045`, `DL3018`, `DL3008`, `DL3059`, `SC2155`.
|
||||
|
||||
## Design Tokens
|
||||
|
||||
Generate platform-specific token files from the canonical JSON:
|
||||
|
||||
348
scripts/lint-infra.sh
Executable file
348
scripts/lint-infra.sh
Executable file
@ -0,0 +1,348 @@
|
||||
#!/usr/bin/env bash
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
# lint-infra.sh — Infrastructure validation for the ByteLyst ecosystem
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
# Validates all Dockerfiles (hadolint) and Helm charts (helm lint + template)
|
||||
# across the 11 ByteLyst repos.
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/lint-infra.sh # Lint everything (Dockerfiles + Helm charts)
|
||||
# ./scripts/lint-infra.sh --docker # Dockerfiles only
|
||||
# ./scripts/lint-infra.sh --helm # Helm charts only
|
||||
# ./scripts/lint-infra.sh --fix # Show suggested fixes alongside errors
|
||||
# ./scripts/lint-infra.sh path/to/Dockerfile [path/to/Chart-dir] ...
|
||||
#
|
||||
# Prerequisites:
|
||||
# brew install hadolint helm
|
||||
#
|
||||
# Exit codes:
|
||||
# 0 All checks passed
|
||||
# 1 One or more checks failed
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
set -euo pipefail
|
||||
|
||||
# ── Colors ─────────────────────────────────────────────────────────────
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'; BOLD='\033[1m'; DIM='\033[2m'; NC='\033[0m'
|
||||
|
||||
# ── Globals ────────────────────────────────────────────────────────────
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
WORKSPACE_ROOT="$(cd "$REPO_ROOT/.." && pwd)"
|
||||
|
||||
LINT_DOCKER=true
|
||||
LINT_HELM=true
|
||||
SHOW_FIX=false
|
||||
EXPLICIT_PATHS=()
|
||||
|
||||
PASS=0
|
||||
FAIL=0
|
||||
SKIP=0
|
||||
FAILURES=()
|
||||
|
||||
# ── Known Hadolint false-positive suppressions ─────────────────────────
|
||||
# DL3045: COPY to relative path — all our Dockerfiles set WORKDIR first
|
||||
# DL3018: Pin versions in apk add — we use node:22-alpine base images
|
||||
# DL3008: Pin versions in apt-get — impractical for Python sidecar base images
|
||||
# DL3059: Multiple consecutive RUN — intentional for layer caching
|
||||
# SC2155: Declare and assign separately — false positive for BuildKit secret mount pattern
|
||||
# (export VAR="$(cat /run/secrets/...)" is the canonical Docker secret idiom)
|
||||
HADOLINT_IGNORE="DL3045,DL3018,DL3008,DL3059,SC2155"
|
||||
|
||||
# ── ByteLyst ecosystem repos (relative to workspace root) ─────────────
|
||||
ECOSYSTEM_REPOS=(
|
||||
learning_ai_common_plat
|
||||
learning_voice_ai_agent
|
||||
learning_multimodal_memory_agents
|
||||
learning_ai_clock
|
||||
learning_ai_jarvis_jr
|
||||
learning_ai_fastgap
|
||||
learning_ai_peakpulse
|
||||
learning_ai_flowmonk
|
||||
learning_ai_notes
|
||||
learning_ai_trails
|
||||
learning_ai_local_memory_gpt
|
||||
)
|
||||
|
||||
# ── Helpers ────────────────────────────────────────────────────────────
|
||||
log() { echo -e "${CYAN}[lint-infra]${NC} $*"; }
|
||||
ok() { echo -e " ${GREEN}✓${NC} $*"; PASS=$((PASS + 1)); }
|
||||
fail() { echo -e " ${RED}✗${NC} $*"; FAIL=$((FAIL + 1)); FAILURES+=("$1"); }
|
||||
skip() { echo -e " ${DIM}⊘ $*${NC}"; SKIP=$((SKIP + 1)); }
|
||||
warn() { echo -e " ${YELLOW}⚠${NC} $*"; }
|
||||
|
||||
usage() {
|
||||
echo "Usage: $(basename "$0") [OPTIONS] [PATH ...]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --docker Lint Dockerfiles only"
|
||||
echo " --helm Lint Helm charts only"
|
||||
echo " --fix Show suggested fixes alongside errors"
|
||||
echo " -h, --help Show this help"
|
||||
echo ""
|
||||
echo "If PATHs are given, only those files/dirs are checked."
|
||||
echo "Otherwise, auto-discovers across all 11 ByteLyst repos."
|
||||
echo ""
|
||||
echo "Prerequisites: brew install hadolint helm"
|
||||
}
|
||||
|
||||
# Check if a tool is available, print install instructions if not
|
||||
require_tool() {
|
||||
local tool="$1" install_cmd="$2"
|
||||
if ! command -v "$tool" &>/dev/null; then
|
||||
echo -e "${RED}Error:${NC} '${tool}' is not installed."
|
||||
echo -e " Install: ${BOLD}${install_cmd}${NC}"
|
||||
echo ""
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# Return a short relative path for display
|
||||
short_path() {
|
||||
local full="$1"
|
||||
# Try to make path relative to workspace root
|
||||
if [[ "$full" == "$WORKSPACE_ROOT"/* ]]; then
|
||||
echo "${full#$WORKSPACE_ROOT/}"
|
||||
else
|
||||
echo "$full"
|
||||
fi
|
||||
}
|
||||
|
||||
# ── Auto-discovery ─────────────────────────────────────────────────────
|
||||
discover_dockerfiles() {
|
||||
local files=()
|
||||
for repo in "${ECOSYSTEM_REPOS[@]}"; do
|
||||
local repo_dir="${WORKSPACE_ROOT}/${repo}"
|
||||
[ -d "$repo_dir" ] || continue
|
||||
while IFS= read -r -d '' f; do
|
||||
files+=("$f")
|
||||
done < <(find "$repo_dir" -maxdepth 4 -name 'Dockerfile*' \
|
||||
-not -path '*/node_modules/*' \
|
||||
-not -path '*/.git/*' \
|
||||
-not -path '*/_deferred*' \
|
||||
-print0 2>/dev/null | sort -z)
|
||||
done
|
||||
echo "${files[@]}"
|
||||
}
|
||||
|
||||
discover_helm_charts() {
|
||||
local dirs=()
|
||||
for repo in "${ECOSYSTEM_REPOS[@]}"; do
|
||||
local repo_dir="${WORKSPACE_ROOT}/${repo}"
|
||||
[ -d "$repo_dir" ] || continue
|
||||
while IFS= read -r -d '' f; do
|
||||
dirs+=("$(dirname "$f")")
|
||||
done < <(find "$repo_dir" -maxdepth 4 -name 'Chart.yaml' \
|
||||
-not -path '*/node_modules/*' \
|
||||
-not -path '*/.git/*' \
|
||||
-print0 2>/dev/null | sort -z)
|
||||
done
|
||||
echo "${dirs[@]+"${dirs[@]}"}"
|
||||
}
|
||||
|
||||
# ── Lint functions ─────────────────────────────────────────────────────
|
||||
|
||||
lint_dockerfile() {
|
||||
local file="$1"
|
||||
local display
|
||||
display=$(short_path "$file")
|
||||
|
||||
if [ ! -f "$file" ]; then
|
||||
skip "${display} (not found)"
|
||||
return
|
||||
fi
|
||||
|
||||
local output exit_code=0
|
||||
# Build hadolint args
|
||||
local hadolint_args=(--no-color)
|
||||
IFS=',' read -ra ignore_rules <<< "$HADOLINT_IGNORE"
|
||||
for rule in "${ignore_rules[@]}"; do
|
||||
hadolint_args+=(--ignore "$rule")
|
||||
done
|
||||
|
||||
output=$(hadolint "${hadolint_args[@]}" "$file" 2>&1) || exit_code=$?
|
||||
|
||||
if [ $exit_code -eq 0 ]; then
|
||||
ok "${display}"
|
||||
else
|
||||
fail "${display}"
|
||||
# Print each warning/error indented
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" == *"error"* ]]; then
|
||||
echo -e " ${RED}${line}${NC}"
|
||||
elif [[ "$line" == *"warning"* ]]; then
|
||||
echo -e " ${YELLOW}${line}${NC}"
|
||||
else
|
||||
echo -e " ${DIM}${line}${NC}"
|
||||
fi
|
||||
done <<< "$output"
|
||||
|
||||
if $SHOW_FIX; then
|
||||
echo -e " ${CYAN}Fix: review hadolint wiki — https://github.com/hadolint/hadolint/wiki${NC}"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
lint_helm_chart() {
|
||||
local chart_dir="$1"
|
||||
local display
|
||||
display=$(short_path "$chart_dir")
|
||||
|
||||
if [ ! -f "${chart_dir}/Chart.yaml" ]; then
|
||||
skip "${display} (no Chart.yaml)"
|
||||
return
|
||||
fi
|
||||
|
||||
local output exit_code
|
||||
|
||||
# 1. helm lint (syntax + structure)
|
||||
output=$(helm lint "$chart_dir" 2>&1) || exit_code=$?
|
||||
if [ "${exit_code:-0}" -ne 0 ]; then
|
||||
fail "${display} (helm lint)"
|
||||
echo "$output" | while IFS= read -r line; do
|
||||
echo -e " ${DIM}${line}${NC}"
|
||||
done
|
||||
return
|
||||
fi
|
||||
|
||||
# 2. helm template (renders without errors)
|
||||
output=$(helm template test-release "$chart_dir" 2>&1) || exit_code=$?
|
||||
if [ "${exit_code:-0}" -ne 0 ]; then
|
||||
fail "${display} (helm template)"
|
||||
echo "$output" | tail -10 | while IFS= read -r line; do
|
||||
echo -e " ${DIM}${line}${NC}"
|
||||
done
|
||||
return
|
||||
fi
|
||||
|
||||
ok "${display}"
|
||||
}
|
||||
|
||||
# ── Parse CLI ──────────────────────────────────────────────────────────
|
||||
parse_args() {
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--docker)
|
||||
LINT_DOCKER=true; LINT_HELM=false ;;
|
||||
--helm)
|
||||
LINT_DOCKER=false; LINT_HELM=true ;;
|
||||
--fix)
|
||||
SHOW_FIX=true ;;
|
||||
-h|--help)
|
||||
usage; exit 0 ;;
|
||||
-*)
|
||||
echo "Unknown option: $1"; usage; exit 1 ;;
|
||||
*)
|
||||
EXPLICIT_PATHS+=("$1") ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
# ── Main ───────────────────────────────────────────────────────────────
|
||||
main() {
|
||||
parse_args "$@"
|
||||
|
||||
echo ""
|
||||
echo -e "${BOLD}╔═══════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BOLD}║ ByteLyst Infrastructure Lint ║${NC}"
|
||||
echo -e "${BOLD}╚═══════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
|
||||
# ── Tool checks ────────────────────────────────────────────────────
|
||||
local missing=false
|
||||
if $LINT_DOCKER; then
|
||||
require_tool hadolint "brew install hadolint" || missing=true
|
||||
fi
|
||||
if $LINT_HELM; then
|
||||
require_tool helm "brew install helm" || missing=true
|
||||
fi
|
||||
if $missing; then
|
||||
echo -e "${RED}Missing required tools. Install them and re-run.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ── Explicit paths mode ────────────────────────────────────────────
|
||||
if [ ${#EXPLICIT_PATHS[@]} -gt 0 ]; then
|
||||
log "Linting ${#EXPLICIT_PATHS[@]} explicit path(s)..."
|
||||
echo ""
|
||||
for p in "${EXPLICIT_PATHS[@]}"; do
|
||||
if [[ "$(basename "$p")" == Dockerfile* ]]; then
|
||||
lint_dockerfile "$p"
|
||||
elif [ -f "${p}/Chart.yaml" ]; then
|
||||
lint_helm_chart "$p"
|
||||
else
|
||||
warn "Unknown target: $p (expected Dockerfile* or dir with Chart.yaml)"
|
||||
fi
|
||||
done
|
||||
else
|
||||
# ── Auto-discover mode ─────────────────────────────────────────
|
||||
if $LINT_DOCKER; then
|
||||
log "Discovering Dockerfiles across ${#ECOSYSTEM_REPOS[@]} repos..."
|
||||
echo ""
|
||||
|
||||
local dockerfiles
|
||||
IFS=' ' read -ra dockerfiles <<< "$(discover_dockerfiles)"
|
||||
|
||||
if [ ${#dockerfiles[@]} -eq 0 ]; then
|
||||
warn "No Dockerfiles found."
|
||||
else
|
||||
log "Found ${#dockerfiles[@]} Dockerfile(s)"
|
||||
echo ""
|
||||
for df in "${dockerfiles[@]}"; do
|
||||
lint_dockerfile "$df"
|
||||
done
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if $LINT_HELM; then
|
||||
log "Discovering Helm charts across ${#ECOSYSTEM_REPOS[@]} repos..."
|
||||
echo ""
|
||||
|
||||
local charts
|
||||
IFS=' ' read -ra charts <<< "$(discover_helm_charts)"
|
||||
|
||||
if [ ${#charts[@]} -eq 0 ] || [ -z "${charts[0]:-}" ]; then
|
||||
log "No Helm charts found (none in this workspace)."
|
||||
else
|
||||
log "Found ${#charts[@]} Helm chart(s)"
|
||||
echo ""
|
||||
for chart in "${charts[@]}"; do
|
||||
lint_helm_chart "$chart"
|
||||
done
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── Summary ──────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo -e "${BOLD}═══ Summary ═══${NC}"
|
||||
echo -e " ${GREEN}Passed:${NC} ${PASS}"
|
||||
echo -e " ${RED}Failed:${NC} ${FAIL}"
|
||||
if [ $SKIP -gt 0 ]; then
|
||||
echo -e " ${DIM}Skipped: ${SKIP}${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
if [ $FAIL -gt 0 ]; then
|
||||
echo -e "${RED}${BOLD}FAILED${NC} — ${FAIL} issue(s) found:"
|
||||
for f in "${FAILURES[@]}"; do
|
||||
echo -e " ${RED}✗${NC} ${f}"
|
||||
done
|
||||
echo ""
|
||||
echo -e "${DIM}Suppressed rules: ${HADOLINT_IGNORE}${NC}"
|
||||
echo -e "${DIM}To see fix suggestions, re-run with --fix${NC}"
|
||||
exit 1
|
||||
else
|
||||
echo -e "${GREEN}${BOLD}ALL PASSED${NC} — ${PASS} check(s) clean."
|
||||
if [ $SKIP -gt 0 ]; then
|
||||
echo -e "${DIM}(${SKIP} skipped)${NC}"
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
95
scripts/test-all.sh
Executable file
95
scripts/test-all.sh
Executable file
@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env bash
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
# test-all.sh — Run Vitest across all ByteLyst repos
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
set -euo pipefail
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; CYAN='\033[0;36m'
|
||||
BOLD='\033[1m'; DIM='\033[2m'; NC='\033[0m'
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
WORKSPACE_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
PASS=0
|
||||
FAIL=0
|
||||
SKIP=0
|
||||
FAILURES=()
|
||||
|
||||
REPOS=(
|
||||
learning_ai_common_plat
|
||||
learning_voice_ai_agent
|
||||
learning_multimodal_memory_agents
|
||||
learning_ai_clock
|
||||
learning_ai_jarvis_jr
|
||||
learning_ai_fastgap
|
||||
learning_ai_peakpulse
|
||||
learning_ai_flowmonk
|
||||
learning_ai_notes
|
||||
learning_ai_trails
|
||||
learning_ai_local_memory_gpt
|
||||
)
|
||||
|
||||
SUBS=(backend web user-dashboard-web mindlyst-native/web)
|
||||
|
||||
echo ""
|
||||
echo -e "${BOLD}╔═══════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BOLD}║ ByteLyst Cross-Repo Test Runner ║${NC}"
|
||||
echo -e "${BOLD}╚═══════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
|
||||
for repo in "${REPOS[@]}"; do
|
||||
repo_dir="${WORKSPACE_ROOT}/${repo}"
|
||||
[ -d "$repo_dir" ] || continue
|
||||
|
||||
for sub in "${SUBS[@]}"; do
|
||||
pkg="${repo_dir}/${sub}/package.json"
|
||||
[ -f "$pkg" ] || continue
|
||||
|
||||
has_test=$(jq -r '.scripts.test // empty' "$pkg" 2>/dev/null)
|
||||
[ -n "$has_test" ] || continue
|
||||
|
||||
# Check if there are actually test files
|
||||
test_count=$(find "${repo_dir}/${sub}/src" -name '*.test.ts' -o -name '*.test.tsx' 2>/dev/null | head -1)
|
||||
if [ -z "$test_count" ]; then
|
||||
SKIP=$((SKIP + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
label="${repo}/${sub}"
|
||||
echo -ne " ${CYAN}▶${NC} ${label}..."
|
||||
|
||||
if (cd "${repo_dir}/${sub}" && pnpm run test --run 2>&1) > /tmp/test-output-$$.txt 2>&1; then
|
||||
# Extract test count from vitest output
|
||||
summary=$(grep -E 'Tests\s+[0-9]' /tmp/test-output-$$.txt 2>/dev/null | tail -1 || echo "")
|
||||
echo -e "\r ${GREEN}✓${NC} ${label} ${DIM}${summary}${NC}"
|
||||
PASS=$((PASS + 1))
|
||||
else
|
||||
echo -e "\r ${RED}✗${NC} ${label}"
|
||||
grep -E 'FAIL|Error|failed' /tmp/test-output-$$.txt 2>/dev/null | tail -5 | while IFS= read -r line; do echo " ${line}"; done
|
||||
FAIL=$((FAIL + 1))
|
||||
FAILURES+=("$label")
|
||||
fi
|
||||
rm -f /tmp/test-output-$$.txt
|
||||
done
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo -e "${BOLD}═══ Summary ═══${NC}"
|
||||
echo -e " ${GREEN}Passed:${NC} ${PASS}"
|
||||
echo -e " ${RED}Failed:${NC} ${FAIL}"
|
||||
if [ $SKIP -gt 0 ]; then
|
||||
echo -e " ${DIM}Skipped: ${SKIP} (no test files)${NC}"
|
||||
fi
|
||||
|
||||
if [ $FAIL -gt 0 ]; then
|
||||
echo ""
|
||||
echo -e "${RED}${BOLD}FAILED${NC} — ${FAIL} test suite(s) failed:"
|
||||
for f in "${FAILURES[@]}"; do
|
||||
echo -e " ${RED}✗${NC} ${f}"
|
||||
done
|
||||
exit 1
|
||||
else
|
||||
echo ""
|
||||
echo -e "${GREEN}${BOLD}ALL PASSED${NC} — ${PASS} suite(s) green."
|
||||
exit 0
|
||||
fi
|
||||
83
scripts/typecheck-all.sh
Executable file
83
scripts/typecheck-all.sh
Executable file
@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env bash
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
# typecheck-all.sh — Run TypeScript typecheck across all ByteLyst repos
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
set -euo pipefail
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; CYAN='\033[0;36m'
|
||||
BOLD='\033[1m'; DIM='\033[2m'; NC='\033[0m'
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
WORKSPACE_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
PASS=0
|
||||
FAIL=0
|
||||
FAILURES=()
|
||||
|
||||
REPOS=(
|
||||
learning_ai_common_plat
|
||||
learning_voice_ai_agent
|
||||
learning_multimodal_memory_agents
|
||||
learning_ai_clock
|
||||
learning_ai_jarvis_jr
|
||||
learning_ai_fastgap
|
||||
learning_ai_peakpulse
|
||||
learning_ai_flowmonk
|
||||
learning_ai_notes
|
||||
learning_ai_trails
|
||||
learning_ai_local_memory_gpt
|
||||
)
|
||||
|
||||
# Subdirectories that may have their own typecheck script
|
||||
SUBS=(backend web user-dashboard-web mindlyst-native/web)
|
||||
|
||||
echo ""
|
||||
echo -e "${BOLD}╔═══════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BOLD}║ ByteLyst Cross-Repo Typecheck ║${NC}"
|
||||
echo -e "${BOLD}╚═══════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
|
||||
for repo in "${REPOS[@]}"; do
|
||||
repo_dir="${WORKSPACE_ROOT}/${repo}"
|
||||
[ -d "$repo_dir" ] || continue
|
||||
|
||||
for sub in "${SUBS[@]}"; do
|
||||
pkg="${repo_dir}/${sub}/package.json"
|
||||
[ -f "$pkg" ] || continue
|
||||
|
||||
has_tc=$(jq -r '.scripts.typecheck // empty' "$pkg" 2>/dev/null)
|
||||
[ -n "$has_tc" ] || continue
|
||||
|
||||
label="${repo}/${sub}"
|
||||
echo -ne " ${CYAN}▶${NC} ${label}..."
|
||||
|
||||
if (cd "${repo_dir}/${sub}" && pnpm run typecheck 2>&1) > /tmp/tc-output-$$.txt 2>&1; then
|
||||
echo -e "\r ${GREEN}✓${NC} ${label}"
|
||||
PASS=$((PASS + 1))
|
||||
else
|
||||
echo -e "\r ${RED}✗${NC} ${label}"
|
||||
tail -5 /tmp/tc-output-$$.txt | while IFS= read -r line; do echo " ${line}"; done
|
||||
FAIL=$((FAIL + 1))
|
||||
FAILURES+=("$label")
|
||||
fi
|
||||
rm -f /tmp/tc-output-$$.txt
|
||||
done
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo -e "${BOLD}═══ Summary ═══${NC}"
|
||||
echo -e " ${GREEN}Passed:${NC} ${PASS}"
|
||||
echo -e " ${RED}Failed:${NC} ${FAIL}"
|
||||
|
||||
if [ $FAIL -gt 0 ]; then
|
||||
echo ""
|
||||
echo -e "${RED}${BOLD}FAILED${NC} — ${FAIL} typecheck(s) failed:"
|
||||
for f in "${FAILURES[@]}"; do
|
||||
echo -e " ${RED}✗${NC} ${f}"
|
||||
done
|
||||
exit 1
|
||||
else
|
||||
echo ""
|
||||
echo -e "${GREEN}${BOLD}ALL PASSED${NC} — ${PASS} typecheck(s) clean."
|
||||
exit 0
|
||||
fi
|
||||
Loading…
Reference in New Issue
Block a user