#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" REPORT_DIR="$ROOT_DIR/reports" ERROR_REPORT="$REPORT_DIR/errors.md" FILES_CHECKED=0 WARNINGS=0 ERRORS=0 DETAILS=() EXCLUDES=( ".git" ".forgejo" "node_modules" "vendor" "Library" "Temp" "Logs" "obj" "bin" ) mkdir -p "$REPORT_DIR" escape_md() { printf '%s' "$1" | sed 's/|/\\|/g' } have_tool() { command -v "$1" >/dev/null 2>&1 } add_warning() { local message="$1" WARNINGS=$((WARNINGS + 1)) DETAILS+=("- Warning: $(escape_md "$message")") } add_error() { local message="$1" ERRORS=$((ERRORS + 1)) DETAILS+=("- Error: $(escape_md "$message")") } add_ok() { local message="$1" DETAILS+=("- OK: $(escape_md "$message")") } relative_path() { local path="$1" path="${path#"$ROOT_DIR"/}" printf '%s' "$path" } join_by() { local delimiter="$1" shift || true local first=1 local item for item in "$@"; do if [[ $first -eq 1 ]]; then printf '%s' "$item" first=0 else printf '%s%s' "$delimiter" "$item" fi done } collect_files() { local find_args=("$ROOT_DIR") local exclude if ((${#EXCLUDES[@]} > 0)); then find_args+=("(") for exclude in "${EXCLUDES[@]}"; do find_args+=(-name "$exclude" -o) done unset 'find_args[${#find_args[@]}-1]' find_args+=(")" -prune -o) fi find_args+=(-type f -print0) find "${find_args[@]}" } run_check() { local label="$1" local file="$2" shift 2 FILES_CHECKED=$((FILES_CHECKED + 1)) if "$@" >/tmp/runlevel-validate.out 2>/tmp/runlevel-validate.err; then add_ok "$label passed: $(relative_path "$file")" else local stdout stderr combined stdout="$(tr '\n' ' ' 0 || ${#csproj_files[@]} > 0)); then if have_tool dotnet; then if ((${#sln_files[@]} > 0)); then for file in "${sln_files[@]}"; do run_check "dotnet build" "$file" dotnet build "$file" --nologo --verbosity minimal done else for file in "${csproj_files[@]}"; do run_check "dotnet build" "$file" dotnet build "$file" --nologo --verbosity minimal done fi else add_warning "dotnet not installed; skipping C# validation." fi fi if [[ -f "$cmake_file" ]]; then if have_tool cmake; then FILES_CHECKED=$((FILES_CHECKED + 1)) tmp_dir="$(mktemp -d)" if cmake -S "$ROOT_DIR" -B "$tmp_dir" >/tmp/runlevel-validate.out 2>/tmp/runlevel-validate.err; then add_ok "cmake configure passed: CMakeLists.txt" else local stdout stderr combined stdout="$(tr '\n' ' ' "$ERROR_REPORT" rm -f /tmp/runlevel-validate.out /tmp/runlevel-validate.err if ((ERRORS > 0)); then exit 1 fi exit 0