name: CI
on:
pull_request:
branches: [main]
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install Rust
uses: dtolnay/rust-toolchain@nightly
with:
components: rustfmt, clippy
- name: Cache Rust dependencies
uses: Swatinem/rust-cache@v2
with:
shared-key: nightly
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Check formatting
run: cargo fmt --all -- --check
- name: Run clippy
run: cargo clippy --workspace --all-targets --all-features -- -D warnings
test-matrix:
name: Test Matrix
runs-on: ubuntu-latest
needs: lint
outputs:
sqlite: ${{ steps.matrix.outputs.sqlite }}
pg: ${{ steps.matrix.outputs.pg }}
steps:
- uses: actions/checkout@v6
- name: Install just
uses: taiki-e/install-action@just
- name: Generate matrices
id: matrix
run: |
echo "sqlite=$(just test::sqlite-matrix-json)" >> $GITHUB_OUTPUT
echo "pg=$(just test::pg-matrix-json)" >> $GITHUB_OUTPUT
test-sqlite:
name: "test::sqlite (${{ matrix.features }})"
runs-on: ubuntu-latest
needs: test-matrix
strategy:
fail-fast: false
matrix:
features: ${{ fromJson(needs.test-matrix.outputs.sqlite) }}
steps:
- uses: actions/checkout@v6
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Install just
uses: taiki-e/install-action@just
- name: Cache Rust dependencies
uses: Swatinem/rust-cache@v2
with:
shared-key: stable
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Run tests
run: just test::sqlite "${{ matrix.features }}"
- name: Run example
if: contains(matrix.features, 'uuid') && startsWith(matrix.features, 'rusqlite')
run: cargo run --example rusqlite --features "rusqlite,uuid,serde"
test-pg:
name: "test::pg (${{ matrix.features }})"
runs-on: ubuntu-latest
needs: test-matrix
strategy:
fail-fast: false
matrix:
features: ${{ fromJson(needs.test-matrix.outputs.pg) }}
steps:
- uses: actions/checkout@v6
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Install just
uses: taiki-e/install-action@just
- name: Cache Rust dependencies
uses: Swatinem/rust-cache@v2
with:
shared-key: stable
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Run tests
run: just test::pg "${{ matrix.features }}"
test-turso:
name: Test (Turso - Experimental)
runs-on: ubuntu-latest
needs: lint
continue-on-error: true
steps:
- uses: actions/checkout@v6
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache Rust dependencies
uses: Swatinem/rust-cache@v2
with:
shared-key: stable
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Run tests
id: test
run: |
mkdir -p test-output
cargo test --workspace --features "turso,uuid,serde" 2>&1 | tee test-output/output.txt || true
if grep -q "FAILED" test-output/output.txt; then
echo "has_failures=true" >> $GITHUB_OUTPUT
echo "::warning::Turso tests failed (expected - turso is experimental)"
else
echo "has_failures=false" >> $GITHUB_OUTPUT
echo "::notice::Turso tests passed"
fi
- name: Extract failure reports
id: extract
if: steps.test.outputs.has_failures == 'true'
run: |
python3 -c "
import sys
text = open('test-output/output.txt').read()
reports = []
in_report = False
buffer = []
prev_line = ''
box_chars = set('╔═╗║╚╝├─┤│')
for line in text.splitlines(True):
if 'TEST FAILURE REPORT' in line:
in_report = True
buffer = []
if any(c in box_chars for c in prev_line):
buffer.append(prev_line)
buffer.append(line)
elif in_report:
if line.strip() == '' or any(c in box_chars for c in line):
buffer.append(line)
else:
reports.append(''.join(buffer))
buffer = []
in_report = False
prev_line = line
if buffer:
reports.append(''.join(buffer))
if reports:
with open('test-output/failure-reports.txt', 'w') as f:
for i, report in enumerate(reports):
if i > 0:
f.write('\n' + '=' * 80 + '\n\n')
f.write(report)
print(f'Extracted {len(reports)} failure report(s)')
else:
print('No structured failure reports found in output')
"
# Set output based on whether the file was created
if [ -f test-output/failure-reports.txt ]; then
echo "has_reports=true" >> $GITHUB_OUTPUT
fi
- name: Upload failure reports
if: steps.extract.outputs.has_reports == 'true'
uses: actions/upload-artifact@v7
with:
name: turso-failure-reports
path: test-output/failure-reports.txt
retention-days: 7
docs:
name: Documentation
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v6
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache Rust dependencies
uses: Swatinem/rust-cache@v2
with:
shared-key: stable
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Check documentation
run: cargo doc --workspace --all-features --no-deps
build-matrix:
name: Build (${{ matrix.rust }})
runs-on: ubuntu-latest
needs: lint
strategy:
matrix:
rust: [stable, nightly]
steps:
- uses: actions/checkout@v6
- name: Install Rust ${{ matrix.rust }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
- name: Cache Rust dependencies
uses: Swatinem/rust-cache@v2
with:
shared-key: ${{ matrix.rust }}
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Build
run: cargo build --workspace --all-features
msrv:
name: MSRV Check
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v6
- name: Get Rust version
id: rust-version
run: |
RUST_VERSION=$(grep '^rust-version = ' Cargo.toml | sed 's/rust-version = "\(.*\)"/\1/')
echo "version=$RUST_VERSION" >> $GITHUB_OUTPUT
- name: Install Rust (MSRV)
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ steps.rust-version.outputs.version }}
- name: Cache Rust dependencies
uses: Swatinem/rust-cache@v2
with:
shared-key: msrv
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Check MSRV
run: cargo check --workspace --all-targets --all-features