Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions .git-hooks/pre-commit-fast
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/bin/bash
# Fast pre-commit hook: Only check what matters for your code changes
# Non-blocking: Warns but doesn't prevent commits

set -e

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

echo "🚀 ColdVox Pre-Commit Checks (fast & non-blocking)"
echo ""

# Track failures
FAILED=0

# Function to run a check
run_check() {
local name="$1"
local cmd="$2"

echo -n " ⏳ $name... "
if eval "$cmd" &>/dev/null; then
echo -e "${GREEN}✓${NC}"
else
echo -e "${RED}✗${NC}"
FAILED=$((FAILED + 1))
echo " Command: $cmd"
fi
}

# === FAST CHECKS (< 5 seconds total) ===

# 1. Check formatting (instant)
run_check "Formatting" "cargo fmt --all --check"

# 2. Clippy on changed files only (fast)
run_check "Clippy" "cargo clippy --all-targets --locked -- -D warnings"

# 3. Type check (fast with cache)
run_check "Type check" "cargo check --workspace --all-targets --locked"

# 4. Build (usually cached, fast)
run_check "Build" "cargo build --workspace --locked"

# 5. Fast unit tests only (skip integration/e2e)
echo -n " ⏳ Unit tests... "
if cargo nextest run --workspace --locked --lib &>/dev/null; then
echo -e "${GREEN}✓${NC}"
else
# Fallback to regular cargo test if nextest not installed
if cargo test --workspace --locked --lib &>/dev/null; then
echo -e "${GREEN}✓${NC} (via cargo test)"
else
echo -e "${RED}✗${NC}"
FAILED=$((FAILED + 1))
fi
fi

echo ""

# === RESULTS ===

if [[ $FAILED -eq 0 ]]; then
echo -e "${GREEN}✅ All checks passed!${NC}"
exit 0
else
echo -e "${YELLOW}⚠️ $FAILED check(s) failed${NC}"
echo ""
echo "This won't block your commit, but you should fix these issues."
echo "Run the individual commands above to see details."
echo ""
echo "To skip these checks: git commit --no-verify"

# NON-BLOCKING: Don't exit 1
exit 0
fi
94 changes: 94 additions & 0 deletions .github/actions/setup-coldvox/action-refactored.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
name: Setup ColdVox Dependencies
description: Install system deps, libvosk, and Rust toolchain
inputs:
skip-toolchain:
description: Skip Rust toolchain setup (for jobs with custom toolchain)
required: false
default: "false"
verify-text-injection:
description: Verify text injection tools (only needed for text_injection_tests)
required: false
default: "false"

runs:
using: composite
steps:
# Core dependencies - fail fast if these are missing
- name: Verify core build dependencies
shell: bash
run: |
set -euo pipefail
echo "--- Verifying Core Build Dependencies ---"

# Only essentials for Rust compilation
required_commands="gcc g++ make pkg-config"

failed=0
for cmd in $required_commands; do
if ! command -v "$cmd" &> /dev/null; then
echo "::error::Required build tool '$cmd' not found. Install build-essential."
failed=1
fi
done

# Check for pkg-config dependencies needed for compilation
required_pkgs="alsa"
for pkg in $required_pkgs; do
if ! pkg-config --exists "$pkg"; then
echo "::error::Required library '$pkg' not found. Install libalsa-devel."
failed=1
fi
done

if [[ $failed -ne 0 ]]; then
echo "::error::Core build dependencies missing. Cannot compile."
exit 1
fi

echo "✅ Core build dependencies verified"

# Text injection dependencies - warn but don't fail
- name: Check text injection dependencies
if: inputs.verify-text-injection == 'true'
shell: bash
run: |
set -euo pipefail
echo "--- Checking Text Injection Dependencies ---"

# Tools needed for text_injection_tests job
text_injection_tools="xdotool Xvfb openbox dbus-launch wl-paste xclip ydotool xprop wmctrl"

missing=0
for cmd in $text_injection_tools; do
if ! command -v "$cmd" &> /dev/null; then
echo "::warning::Text injection tool '$cmd' not found. Some tests may be skipped."
missing=1
fi
done

# Check for X11/accessibility libraries
text_injection_pkgs="gtk+-3.0 at-spi-2.0 xtst"
for pkg in $text_injection_pkgs; do
if ! pkg-config --exists "$pkg"; then
echo "::warning::Text injection library '$pkg' not found. Some tests may be skipped."
missing=1
fi
done

if [[ $missing -ne 0 ]]; then
echo "⚠️ Some text injection dependencies missing. Tests will adapt."
else
echo "✅ All text injection dependencies available"
fi

- name: Setup Rust toolchain
if: inputs.skip-toolchain != 'true'
uses: dtolnay/rust-toolchain@v1
with:
toolchain: stable
components: rustfmt, clippy

- name: Cache Cargo
uses: Swatinem/rust-cache@v2
with:
key: "nobara-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}"
43 changes: 12 additions & 31 deletions .github/actions/setup-coldvox/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,22 @@ inputs:
runs:
using: composite
steps:
- name: Verify provisioned system dependencies
- name: Confirm runner provisioning expectations
shell: bash
run: |
set -euo pipefail
echo "--- Verifying Provisioned System Dependencies ---"
echo "--- Runner Provisioning Assumptions ---"
cat <<'INFO'
The ColdVox runner action now assumes the self-hosted runner is pre-provisioned
with the desktop automation and multimedia dependencies documented in
docs/dev/runnerAgent/RunnerAgent.md. Direct command/library verification has
been removed to avoid failing fast on partially provisioned systems; downstream
tests will surface any missing tools in a more actionable context.

# List of essential commands the runner MUST have
# This replaces the sudo dnf/apt install commands
required_commands="xdotool wget unzip gcc g++ make Xvfb openbox dbus-launch wl-paste xclip ydotool xprop wmctrl pkg-config pulseaudio"

failed=0
echo "Checking for required commands..."
for cmd in $required_commands; do
if ! command -v "$cmd" &> /dev/null; then
echo "::error::Required command '$cmd' not found on runner. Please provision the runner with this dependency."
failed=1
fi
done

# Check for pkg-config dependencies (for -devel packages)
required_pkgs="alsa gtk+-3.0 at-spi-2.0 xtst"
echo "Checking for required libraries via pkg-config..."
for pkg in $required_pkgs; do
if ! pkg-config --exists "$pkg"; then
echo "::error::Required library '$pkg' not found by pkg-config. Please install the corresponding -devel package on the runner."
failed=1
fi
done

if [[ $failed -ne 0 ]]; then
echo "::error::One or more system dependencies are missing. Please provision the runner correctly."
exit 1
fi

echo "--- All system dependencies are correctly provisioned. ---"
If you encounter missing dependency errors during later workflow steps, refer to
docs/dev/runnerAgent/RunnerAgent.md#interactive-dependency-management for the
recommended package list.
INFO

- name: Setup Rust toolchain
if: inputs.skip-toolchain != 'true'
Expand Down
157 changes: 157 additions & 0 deletions .github/workflows/ci-minimal.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
name: CI (Minimal)

on:
push:
branches: [main, "release/*", "feature/*", "feat/*", "fix/*"]
pull_request:
branches: [main]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

env:
RUSTFLAGS: "-D warnings"
CARGO_TERM_COLOR: always

jobs:
# Fast compilation check on MSRV and stable
check:
name: Check (${{ matrix.rust }})
runs-on: [self-hosted, Linux, X64, fedora, nobara]
strategy:
matrix:
rust: [stable, "1.75"] # MSRV
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@v1
with:
toolchain: ${{ matrix.rust }}
- uses: Swatinem/rust-cache@v2

- name: Type check
run: cargo check --workspace --all-targets --locked

- name: Build
run: cargo build --workspace --locked

# Linting and formatting (stable only)
lint:
name: Lint & Format
runs-on: [self-hosted, Linux, X64, fedora, nobara]
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2

- name: Check formatting
run: cargo fmt --all -- --check

- name: Clippy
run: cargo clippy --all-targets --locked -- -D warnings

- name: Build docs
run: cargo doc --workspace --no-deps --locked

# Unit and integration tests (not E2E)
test:
name: Test
runs-on: [self-hosted, Linux, X64, fedora, nobara]
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2

# Core build dependencies only (no X11/text injection stuff)
- name: Verify core deps
run: |
set -euo pipefail
for cmd in gcc g++ make pkg-config; do
command -v $cmd || { echo "Missing: $cmd"; exit 1; }
done
pkg-config --exists alsa || { echo "Missing: libalsa-dev"; exit 1; }

- name: Run tests
run: |
# Use nextest if available, otherwise fallback
if command -v cargo-nextest &>/dev/null; then
cargo nextest run --workspace --locked
else
cargo test --workspace --locked
fi

# Optional: Text injection tests (only if tools available)
text-injection:
name: Text Injection (Optional)
runs-on: [self-hosted, Linux, X64, fedora, nobara]
continue-on-error: true # Don't fail CI if this fails
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2

- name: Check if tools available
id: check_tools
run: |
has_tools=true
for tool in xdotool Xvfb openbox; do
if ! command -v $tool &>/dev/null; then
echo "Missing: $tool"
has_tools=false
fi
done
echo "available=$has_tools" >> $GITHUB_OUTPUT

- name: Run text injection tests
if: steps.check_tools.outputs.available == 'true'
env:
DISPLAY: :99
run: |
# Start headless X server
Xvfb :99 -screen 0 1024x768x24 &
sleep 2
openbox &
sleep 1

cargo test -p coldvox-text-injection --locked

- name: Skip text injection tests
if: steps.check_tools.outputs.available != 'true'
run: echo "⚠️ Skipping - X11 tools not available"

# Optional: Vosk E2E tests (only if model available)
vosk-e2e:
name: Vosk E2E (Optional)
runs-on: [self-hosted, Linux, X64, fedora, nobara]
continue-on-error: true # Don't fail CI if this fails
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2

- name: Check if Vosk model available
id: check_model
run: |
MODEL_PATH="${VOSK_MODEL_PATH:-models/vosk-model-small-en-us-0.15}"
if [[ -d "$MODEL_PATH/graph" ]]; then
echo "available=true" >> $GITHUB_OUTPUT
echo "path=$MODEL_PATH" >> $GITHUB_OUTPUT
else
echo "available=false" >> $GITHUB_OUTPUT
fi

- name: Run Vosk E2E test
if: steps.check_model.outputs.available == 'true'
env:
VOSK_MODEL_PATH: ${{ steps.check_model.outputs.path }}
run: cargo test -p coldvox-app --features vosk test_end_to_end_wav_pipeline -- --nocapture

- name: Skip Vosk E2E
if: steps.check_model.outputs.available != 'true'
run: echo "⚠️ Skipping - Vosk model not available"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,6 @@ docs/config.md
docs/install.md
docs/reference.md
docs/usage.md

# Vendor directory (symlinks to runner cache)
vendor/
Loading
Loading