From 17a0750b66fc0451418ace1e20cd116f3a8529e2 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 13 Nov 2025 23:59:54 +0000 Subject: [PATCH] feat: Add comprehensive GitHub Actions CI workflow for PR testing This commit adds a comprehensive CI/CD pipeline that runs on all pull requests and pushes to main/master branches. ## Workflow Features ### Rust Checks (Multi-OS) - Runs on Ubuntu and macOS - Checks Rust code formatting with `cargo fmt --check` - Runs Clippy linter (warnings displayed but not enforced) - Runs all Rust unit tests with `cargo test` - Uses caching for faster builds ### Elixir Tests (Matrix Testing) - Tests on multiple Elixir versions (1.17.0, 1.18.0) - Tests on multiple OTP versions (26.2, 27.0) - Tests on Ubuntu and macOS - Checks Elixir code formatting with `mix format --check-formatted` - Compiles with warnings as errors - Runs full Elixir test suite - Uses caching for Mix and Cargo dependencies ### Integration Tests - Runs comprehensive integration tests with `mix test --trace` - Ensures full project compilation works - Only runs after Rust and Elixir checks pass ### Final Gate Check - Ensures all jobs passed before merging - Provides clear status for PR reviews ## Benefits 1. **Prevents Breaking Changes**: Catches issues before they reach main 2. **Multi-Platform Testing**: Ensures code works on Linux and macOS 3. **Version Compatibility**: Tests against multiple Elixir/OTP versions 4. **Fast Feedback**: Caching makes subsequent runs much faster 5. **Clear Status**: Easy-to-read job summaries in PR checks ## Usage The workflow runs automatically on every PR. You can also: - View workflow runs in the "Actions" tab on GitHub - Re-run failed jobs from the Actions tab - See detailed logs for each step This provides a solid foundation for maintaining code quality as the project grows and accepts contributions. --- .github/workflows/ci.yml | 173 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..c633e346 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,173 @@ +name: CI + +on: + pull_request: + branches: ["*"] + push: + branches: ["main", "master"] + +env: + CARGO_TERM_COLOR: always + MIX_ENV: test + +jobs: + rust-checks: + name: Rust Checks + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + rust: [stable] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: ${{ matrix.rust }} + components: rustfmt, clippy + + - name: Cache Rust dependencies + uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + native/libsqlex/target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo- + + - name: Check Rust formatting + run: cargo fmt --check --manifest-path native/libsqlex/Cargo.toml + + - name: Run Clippy + run: cargo clippy --manifest-path native/libsqlex/Cargo.toml --all-targets --all-features + # Note: Currently not treating warnings as errors due to await_holding_lock warnings + # These should be addressed in a future PR by using async-aware Mutex types + + - name: Run Rust tests + run: cargo test --manifest-path native/libsqlex/Cargo.toml --all-features + + elixir-tests: + name: Elixir ${{ matrix.elixir }} / OTP ${{ matrix.otp }} / ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + elixir: ['1.18.0', '1.17.0'] + otp: ['27.0', '26.2'] + exclude: + # OTP 27 requires Elixir 1.17+ + - elixir: '1.16.0' + otp: '27.0' + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + + - name: Cache Rust dependencies + uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + native/libsqlex/target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo- + + - name: Set up Elixir + uses: erlef/setup-beam@v1 + with: + elixir-version: ${{ matrix.elixir }} + otp-version: ${{ matrix.otp }} + + - name: Cache Mix dependencies + uses: actions/cache@v4 + with: + path: | + deps + _build + key: ${{ runner.os }}-mix-${{ matrix.elixir }}-${{ matrix.otp }}-${{ hashFiles('**/mix.lock') }} + restore-keys: | + ${{ runner.os }}-mix-${{ matrix.elixir }}-${{ matrix.otp }}- + + - name: Install Mix dependencies + run: mix deps.get + + - name: Check Elixir formatting + run: mix format --check-formatted + + - name: Compile (warnings as errors) + run: mix compile --warnings-as-errors + + - name: Run Elixir tests + run: mix test + + integration-test: + name: Integration Tests + runs-on: ubuntu-latest + needs: [rust-checks, elixir-tests] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Rust + uses: dtolnay/rust-toolchain@stable + + - name: Set up Elixir + uses: erlef/setup-beam@v1 + with: + elixir-version: '1.18.0' + otp-version: '27.0' + + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: | + deps + _build + ~/.cargo + native/libsqlex/target/ + key: ${{ runner.os }}-integration-${{ hashFiles('**/mix.lock', '**/Cargo.lock') }} + + - name: Install dependencies + run: mix deps.get + + - name: Compile project + run: mix compile + + - name: Run full test suite + run: mix test --trace + + all-checks-pass: + name: All Checks Pass + runs-on: ubuntu-latest + needs: [rust-checks, elixir-tests, integration-test] + if: always() + + steps: + - name: Check if all jobs passed + run: | + if [ "${{ needs.rust-checks.result }}" != "success" ] || \ + [ "${{ needs.elixir-tests.result }}" != "success" ] || \ + [ "${{ needs.integration-test.result }}" != "success" ]; then + echo "One or more checks failed" + exit 1 + fi + echo "All checks passed successfully!"