name: CI
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
quality:
name: Format, lint, and test (stable Linux)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt
- uses: Swatinem/rust-cache@v2
- name: Verify generated parser is current
run: cargo run --locked --package open-cypher-xtask -- grammar verify
- name: Verify pinned openCypher snapshot
run: cargo run --locked --package open-cypher-xtask -- spec verify
- name: Check formatting
run: cargo fmt --all -- --check
- name: Check fuzz-target formatting
run: cargo fmt --manifest-path fuzz/Cargo.toml -- --check
- name: Check locked fuzz workspace
run: cargo check --manifest-path fuzz/Cargo.toml --bins --locked
- name: Lint all targets and features
run: cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
- name: Test workspace with default features
run: cargo test --workspace --locked
- name: Test workspace and all features
run: cargo test --workspace --all-features --locked
- name: Build documentation
env:
RUSTDOCFLAGS: -D warnings
run: cargo doc --workspace --all-features --no-deps --locked
package:
name: Verify packaged crate
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Package and test exact archive contents
shell: bash
run: |
set -euo pipefail
scratch="$(mktemp -d)"
package_target="$scratch/package-target"
cargo package --package open-cypher --all-features --locked \
--target-dir "$package_target"
shopt -s nullglob
archives=("$package_target"/package/open-cypher-*.crate)
if (( ${#archives[@]} != 1 )); then
printf 'expected one .crate archive, found %d\n' \
"${#archives[@]}" >&2
exit 1
fi
mkdir "$scratch/extracted"
tar -xzf "${archives[0]}" -C "$scratch/extracted"
roots=("$scratch"/extracted/open-cypher-*)
if (( ${#roots[@]} != 1 )) || [[ ! -d "${roots[0]}" ]]; then
printf 'expected one extracted package root, found %d\n' \
"${#roots[@]}" >&2
exit 1
fi
CARGO_TARGET_DIR="$scratch/test-target" \
cargo check --manifest-path "${roots[0]}/Cargo.toml" \
--all-targets --all-features --locked
CARGO_TARGET_DIR="$scratch/test-target" \
cargo test --manifest-path "${roots[0]}/Cargo.toml" \
--all-features --locked
compatibility:
name: Test (${{ matrix.name }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- name: MSRV 1.88 / Linux
os: ubuntu-latest
toolchain: "1.88"
- name: stable / macOS
os: macos-latest
toolchain: stable
- name: stable / Windows
os: windows-latest
toolchain: stable
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.toolchain }}
- uses: Swatinem/rust-cache@v2
- run: cargo test --workspace --all-features --locked
- name: Check independent fuzz workspace on MSRV
if: matrix.toolchain == '1.88'
run: cargo check --manifest-path fuzz/Cargo.toml --bins --locked
conformance:
name: openCypher 2024.3 syntax projection
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Verify deterministic TCK projection
run: cargo run --locked --package open-cypher-xtask -- tck verify
- name: Check projected syntax expectations
run: cargo run --locked --package open-cypher-xtask -- tck check
- name: Enforce production and conformance closure
run: cargo run --locked --package open-cypher-xtask -- spec release-check
- name: Write machine-readable report
if: always()
run: cargo run --locked --package open-cypher-xtask -- tck report
- name: Upload conformance report
if: always()
uses: actions/upload-artifact@v7
with:
name: tck-syntax-report-${{ github.sha }}
path: target/tck-syntax-report.json
if-no-files-found: error
retention-days: 14
coverage:
name: Coverage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview
- uses: taiki-e/install-action@v2
with:
tool: cargo-llvm-cov
- uses: Swatinem/rust-cache@v2
- name: Enforce handwritten-source line coverage
run: >-
cargo llvm-cov
--package open-cypher
--all-features
--locked
--ignore-filename-regex '(/target/|/tests/|/benches/|/fuzz/|/src/generated/)'
--fail-under-lines 85
fuzz-smoke:
name: Fuzz smoke (${{ matrix.target }})
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
target: [lex_str, parse_strict, parse_recovering, parse_generated_valid, parse_tck_mutations]
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@nightly
- uses: taiki-e/install-action@v2
with:
tool: cargo-fuzz@0.13.2
- uses: Swatinem/rust-cache@v2
with:
workspaces: fuzz -> fuzz/target
- name: Build fuzz target
run: >-
cargo +nightly fuzz build
--target x86_64-unknown-linux-gnu
${{ matrix.target }}
- name: Replay seed and regression corpus
env:
FUZZ_TARGET: ${{ matrix.target }}
run: |
set -euo pipefail
corpora=("fuzz/corpus/$FUZZ_TARGET")
if [[ "$FUZZ_TARGET" == "parse_strict" ]]; then
corpora+=("tests/fixtures/regressions/parse_strict")
fi
cargo +nightly fuzz run \
--target x86_64-unknown-linux-gnu \
"$FUZZ_TARGET" "${corpora[@]}" -- \
-dict=fuzz/cypher.dict \
-runs=0 \
-max_len=65536 \
-timeout=5 \
-rss_limit_mb=2048
benchmark-build:
name: Build benchmarks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo bench --workspace --all-features --no-run --locked