diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 58c3fe2ab01..2f9ba8e95c6 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -33,6 +33,24 @@ jobs: echo "has_firmware=$(echo "$FILES" | grep -qE '^(omi|omiGlass)/.*\.(c|cpp|cc|cxx|h|hpp)$' && echo true || echo false)" >> $GITHUB_OUTPUT echo "has_frontend=$(echo "$FILES" | grep -q '^web/frontend/' && echo true || echo false)" >> $GITHUB_OUTPUT echo "has_personas=$(echo "$FILES" | grep -q '^web/personas-open-source/' && echo true || echo false)" >> $GITHUB_OUTPUT + # Also run the Rust check when this workflow changes so CI PRs dogfood + # the new guard instead of only validating YAML syntax. + echo "has_desktop_rust=$(echo "$FILES" | grep -qE '^desktop/macos/Backend-Rust/|^\.github/workflows/lint\.yml$' && echo true || echo false)" >> $GITHUB_OUTPUT + + # -- Universal source hygiene -- + - name: Check merge conflict markers + run: | + failed=0 + while IFS= read -r file; do + if [ -f "$file" ] && grep -I -nE '^(<<<<<<<|>>>>>>>)' "$file"; then + failed=1 + fi + done < /tmp/changed-files.txt + + if [ "$failed" -eq 1 ]; then + echo "FAIL: unresolved merge conflict markers found in changed files" + exit 1 + fi # -- Dart -- - name: Setup Flutter @@ -103,6 +121,29 @@ jobs: echo "$FILES" | xargs clang-format --dry-run --Werror fi + # -- Desktop Rust backend -- + - name: Cache desktop Rust backend build + if: steps.changed.outputs.has_desktop_rust == 'true' + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + desktop/macos/Backend-Rust/target + key: ${{ runner.os }}-desktop-rust-${{ hashFiles('desktop/macos/Backend-Rust/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-desktop-rust- + + - name: Check desktop Rust backend + if: steps.changed.outputs.has_desktop_rust == 'true' + run: | + FILES=$(grep -E '^desktop/macos/Backend-Rust/.*\.rs$' /tmp/changed-files.txt || true) + if [ -n "$FILES" ]; then + echo "$FILES" | xargs rustfmt --edition 2021 --check + fi + cd desktop/macos/Backend-Rust + cargo check --locked + # -- Frontend -- - name: Setup Node.js if: steps.changed.outputs.has_frontend == 'true' || steps.changed.outputs.has_personas == 'true' diff --git a/scripts/pre-commit b/scripts/pre-commit index fc7011f1c00..eaef5dfdcd1 100755 --- a/scripts/pre-commit +++ b/scripts/pre-commit @@ -1,5 +1,25 @@ #!/bin/sh +# Universal source hygiene: fail fast on unresolved merge conflict markers. +STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM) + +if [ -n "$STAGED_FILES" ]; then + conflict_found=0 + while IFS= read -r file; do + [ -n "$file" ] || continue + if git grep --cached -n -I -E '^(<<<<<<<|>>>>>>>)' -- "$file"; then + conflict_found=1 + fi + done <&2 + exit 1 + fi +fi + # Dart formatting for app/ STAGED_DART_FILES=$(git diff --cached --name-only --diff-filter=ACM "app/**.dart" | grep -v -e '\.gen\.dart$' -e '\.g\.dart$') @@ -79,4 +99,34 @@ if [ -n "$STAGED_C_FILES" ]; then echo "$STAGED_C_FILES" | xargs git add fi +# Rust formatting/checking for desktop backend. +STAGED_DESKTOP_RUST_INPUTS=$(git diff --cached --name-only --diff-filter=ACM | grep -E '^desktop/macos/Backend-Rust/' || true) +STAGED_DESKTOP_RUST_FILES=$(printf '%s\n' "$STAGED_DESKTOP_RUST_INPUTS" | grep -E '\.rs$' || true) + +if [ -n "$STAGED_DESKTOP_RUST_INPUTS" ]; then + echo "Checking desktop Rust backend..." + if ! command -v cargo >/dev/null 2>&1; then + echo "cargo is not installed. Please install Rust/Cargo first" >&2 + exit 1 + fi + if [ -n "$STAGED_DESKTOP_RUST_FILES" ]; then + while IFS= read -r file; do + [ -n "$file" ] || continue + if ! rustfmt --edition 2021 "$file"; then + echo "rustfmt failed for $file" >&2 + exit 1 + fi + git add "$file" + done <