fix(sql): validate table qualifiers in single-table scope (SQLR-14) #287
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Continuous integration — runs on every pull request + every push to | |
| # main. Blocks PR merge when anything fails (once branch protection is | |
| # configured on the GitHub side — see docs/release-plan.md Phase 6c). | |
| # | |
| # Jobs: | |
| # - rust-build-and-test {ubuntu, macos, windows} cargo build + test | |
| # - rust-lint ubuntu fmt + clippy + doc | |
| # - python-sdk {ubuntu, macos, windows} maturin develop + pytest | |
| # - nodejs-sdk {ubuntu, macos, windows} napi build + node --test | |
| # - go-sdk {ubuntu, macos} cgo against libsqlrite_c + go test | |
| # - wasm-build ubuntu wasm-pack build + size report | |
| # - desktop-build ubuntu npm ci + cargo build -p sqlrite-desktop | |
| # - journal-build ubuntu npm ci + cargo build -p sqlrite-journal (SQLR-41 example) | |
| # | |
| # All jobs use caching so a warm PR run takes 2–3 minutes on ubuntu. | |
| # Go CI skips Windows for Phase 6b — Go's cgo on Windows needs a mingw | |
| # setup that we haven't wired into the Go sidecar; deferred follow-up. | |
| name: CI | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| # Cancel previous CI runs on the same branch when a new push arrives. | |
| # Saves compute + shortens PR feedback loops. | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| env: | |
| # Suppress the "incremental compilation is not recommended for CI" | |
| # advice line-noise across every Rust job. We don't want incremental | |
| # on CI anyway (every run is from scratch). | |
| CARGO_INCREMENTAL: '0' | |
| # Colored cargo output survives into the GitHub Actions log view. | |
| CARGO_TERM_COLOR: always | |
| # Note: we intentionally do NOT set `RUSTFLAGS: '-D warnings'` at | |
| # the workflow level. The codebase has ~24 pre-existing clippy | |
| # warnings (mostly cosmetic — overindented docstrings, `Vec::new() | |
| # + push` patterns, etc.) that will get cleaned up incrementally. | |
| # Once the count is zero, we'll tighten by adding `-D warnings` | |
| # here. Hard clippy errors (deny-by-default lints like | |
| # `approx_constant`) still fail CI without this flag — that's the | |
| # backstop for real correctness issues. | |
| jobs: | |
| # --------------------------------------------------------------------------- | |
| # Rust: build + test the whole workspace (minus the desktop crate — | |
| # it needs a frontend build, handled in its own job). | |
| rust-build-and-test: | |
| name: rust (${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| defaults: | |
| run: | |
| # Bash on every OS — Windows uses Git Bash (preinstalled on | |
| # `windows-latest`). Without this, Windows defaults to pwsh, | |
| # which doesn't understand bash's backslash line-continuation | |
| # in multi-line `run:` blocks. | |
| shell: bash | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| # Bucket by OS + job — separate caches so a Linux miss | |
| # doesn't steal macOS's target dir and vice versa. | |
| shared-key: rust-build-and-test | |
| # Exclusions explained: | |
| # | |
| # - `sqlrite-desktop` needs the Svelte frontend built first | |
| # (handled in the `desktop-build` job). | |
| # | |
| # - `sqlrite-python` + `sqlrite-nodejs` are PyO3/napi-rs | |
| # extension-module cdylibs. Their `extension-module` feature | |
| # tells the Rust toolchain not to link libpython / libnode at | |
| # compile time, so `--all-targets` fails on macOS when it | |
| # tries to build the auto-generated test binary for their | |
| # rlib targets (unresolved Python/Node symbols). The per-SDK | |
| # `python-sdk` + `nodejs-sdk` jobs below exercise these | |
| # crates through their native tooling (maturin / napi-rs). | |
| # | |
| # - `sqlrite-benchmarks` is the SQLR-4 / SQLR-16 bench harness. | |
| # Excluded from CI for two reasons: criterion benches are | |
| # noisy on shared GitHub runners (the published numbers come | |
| # from a pinned local host per Q1), and the bundled rusqlite | |
| # build pulls in a heavy C toolchain that we don't want to | |
| # pay on every PR. Run locally with `make bench`. | |
| - name: cargo build | |
| run: | | |
| cargo build --workspace \ | |
| --exclude sqlrite-desktop \ | |
| --exclude sqlrite-journal \ | |
| --exclude sqlrite-python \ | |
| --exclude sqlrite-nodejs \ | |
| --exclude sqlrite-benchmarks \ | |
| --all-targets | |
| - name: cargo test | |
| run: | | |
| cargo test --workspace \ | |
| --exclude sqlrite-desktop \ | |
| --exclude sqlrite-journal \ | |
| --exclude sqlrite-python \ | |
| --exclude sqlrite-nodejs \ | |
| --exclude sqlrite-benchmarks | |
| # --------------------------------------------------------------------------- | |
| # Rust: lint — fmt + clippy + doc. One cell (ubuntu) because these | |
| # are platform-independent checks. Runs in parallel with the matrix | |
| # build/test job above. | |
| rust-lint: | |
| name: rust lint | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust + components | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: rustfmt, clippy | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: rust-lint | |
| - name: cargo fmt | |
| run: cargo fmt --all -- --check | |
| - name: cargo clippy | |
| # No `-D warnings` for now — see the top-level env comment. | |
| # Deny-by-default lints (the ones that surface real bugs, | |
| # e.g. `approx_constant`) still fail without the flag. | |
| # Exclude the extension-module SDK cdylibs for the same | |
| # reason as `rust-build-and-test` — their test binaries | |
| # can't link standalone. | |
| run: | | |
| cargo clippy --workspace \ | |
| --exclude sqlrite-desktop \ | |
| --exclude sqlrite-journal \ | |
| --exclude sqlrite-python \ | |
| --exclude sqlrite-nodejs \ | |
| --exclude sqlrite-benchmarks \ | |
| --all-targets | |
| - name: cargo doc | |
| # `--no-deps` skips deps docs (they build on docs.rs, not here). | |
| # Not warnings-as-errors yet — same rationale as clippy above. | |
| run: | | |
| cargo doc --workspace \ | |
| --exclude sqlrite-desktop \ | |
| --exclude sqlrite-journal \ | |
| --exclude sqlrite-python \ | |
| --exclude sqlrite-nodejs \ | |
| --exclude sqlrite-benchmarks \ | |
| --no-deps | |
| # --------------------------------------------------------------------------- | |
| # Python SDK: build the PyO3 extension, install into a venv, run pytest. | |
| python-sdk: | |
| name: python-sdk (${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| defaults: | |
| run: | |
| # Bash on every runner (Windows' git bash is available via | |
| # `shell: bash`) so the same commands work everywhere — no | |
| # PowerShell / cmd fork. | |
| shell: bash | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| cache: pip | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: python-sdk-${{ matrix.os }} | |
| # maturin develop needs a virtualenv or conda env to install | |
| # into. We create one per job + export VIRTUAL_ENV so every | |
| # subsequent step sees it. Cross-platform: Windows venvs have | |
| # `Scripts/` instead of `bin/`, so we pick the right path. | |
| - name: Create venv | |
| run: | | |
| python -m venv .venv | |
| if [ -d .venv/bin ]; then | |
| echo "VIRTUAL_ENV=$PWD/.venv" >> "$GITHUB_ENV" | |
| echo "$PWD/.venv/bin" >> "$GITHUB_PATH" | |
| else | |
| echo "VIRTUAL_ENV=$PWD/.venv" >> "$GITHUB_ENV" | |
| echo "$PWD/.venv/Scripts" >> "$GITHUB_PATH" | |
| fi | |
| - name: Install maturin + pytest | |
| run: pip install maturin pytest | |
| - name: maturin develop | |
| working-directory: sdk/python | |
| run: maturin develop | |
| - name: pytest | |
| working-directory: sdk/python | |
| run: python -m pytest tests/ | |
| # --------------------------------------------------------------------------- | |
| # Node.js SDK: napi-rs build produces a .node binary. `npm test` | |
| # exercises the node:test suite against it. | |
| nodejs-sdk: | |
| name: nodejs-sdk (${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| defaults: | |
| run: | |
| shell: bash | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| cache-dependency-path: sdk/nodejs/package-lock.json | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: nodejs-sdk-${{ matrix.os }} | |
| - name: npm ci | |
| working-directory: sdk/nodejs | |
| run: npm ci | |
| - name: npm run build | |
| working-directory: sdk/nodejs | |
| run: npm run build | |
| - name: npm test | |
| working-directory: sdk/nodejs | |
| run: npm test | |
| # --------------------------------------------------------------------------- | |
| # Go SDK: cgo-linked against libsqlrite_c. We build the FFI crate in | |
| # release mode first so the .so / .dylib is available for go test. | |
| # | |
| # Skips Windows for Phase 6b — Go's cgo on Windows needs a mingw | |
| # toolchain that isn't preinstalled on `windows-latest` runners; a | |
| # follow-up task in the roadmap adds it. | |
| go-sdk: | |
| name: go-sdk (${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.21' | |
| cache-dependency-path: sdk/go/go.mod | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: go-sdk-${{ matrix.os }} | |
| - name: Build libsqlrite_c | |
| # The Go driver's `#cgo LDFLAGS` references target/release. | |
| run: cargo build --release -p sqlrite-ffi | |
| - name: go test ./... | |
| working-directory: sdk/go | |
| run: go test -v ./... | |
| # --------------------------------------------------------------------------- | |
| # Go edge/IoT collector example (SQLR-43). Builds + tests the example | |
| # app against the in-repo libsqlrite_c, so an engine/SDK API change | |
| # that breaks the example is caught here. Same {ubuntu, macos} matrix | |
| # and cgo wiring as the go-sdk job. | |
| go-collector: | |
| name: go-collector (${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.21' | |
| cache-dependency-path: examples/go-collector/go.mod | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: go-collector-${{ matrix.os }} | |
| - name: Build libsqlrite_c | |
| # The Go driver's `#cgo LDFLAGS` references target/release. | |
| run: cargo build --release -p sqlrite-ffi | |
| - name: go vet ./... | |
| working-directory: examples/go-collector | |
| run: go vet ./... | |
| - name: go test ./... | |
| working-directory: examples/go-collector | |
| run: go test -v ./... | |
| # --------------------------------------------------------------------------- | |
| # WASM: only the build + size check (no tests — the WASM module's | |
| # behavior is covered by the other SDKs' test suites; WASM just | |
| # re-targets the same engine). One cell because WASM is a | |
| # cross-compilation target, not a host OS. | |
| wasm-build: | |
| name: wasm-build | |
| runs-on: ubuntu-latest | |
| # Pinned binaryen version — see docs/release-plan.md | |
| # ("Pinned binaryen / wasm-opt") for the bump procedure. Older | |
| # binaryen rejects rustc's multi-table WASM output with | |
| # "Only 1 table definition allowed in MVP", which the runner | |
| # image's cache state used to surface non-deterministically | |
| # (SQLR-58). Pinning keeps wasm-opt out of "whatever's cached" | |
| # territory. | |
| env: | |
| BINARYEN_VERSION: version_122 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: wasm32-unknown-unknown | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| # sdk/wasm is its own workspace (see Cargo.toml comment); | |
| # key it separately so it doesn't blow the main cache. | |
| workspaces: sdk/wasm | |
| shared-key: wasm-build | |
| - name: Install pinned binaryen (wasm-opt) | |
| # MUST run before wasm-pack: wasm-pack picks up wasm-opt from | |
| # PATH if present, otherwise downloads whatever binaryen its | |
| # own internal cache happens to have. Pinning + prepending | |
| # to PATH forces a deterministic version across runner images. | |
| run: | | |
| set -euo pipefail | |
| curl -fsSL "https://github.com/WebAssembly/binaryen/releases/download/${BINARYEN_VERSION}/binaryen-${BINARYEN_VERSION}-x86_64-linux.tar.gz" \ | |
| -o "$RUNNER_TEMP/binaryen.tar.gz" | |
| tar -xzf "$RUNNER_TEMP/binaryen.tar.gz" -C "$RUNNER_TEMP" | |
| echo "$RUNNER_TEMP/binaryen-${BINARYEN_VERSION}/bin" >> "$GITHUB_PATH" | |
| "$RUNNER_TEMP/binaryen-${BINARYEN_VERSION}/bin/wasm-opt" --version | |
| - name: Install wasm-pack | |
| uses: jetli/wasm-pack-action@v0.4.0 | |
| - name: wasm-pack build --target web --release | |
| working-directory: sdk/wasm | |
| run: | | |
| # Sanity-check that the pinned wasm-opt is what wasm-pack sees. | |
| which wasm-opt | |
| wasm-opt --version | |
| wasm-pack build --target web --release | |
| - name: Report .wasm size | |
| # Surfaces size regressions in PR logs. Not a hard limit yet; | |
| # if/when we set a budget, convert to a failing check. | |
| working-directory: sdk/wasm | |
| run: | | |
| size=$(stat -c '%s' pkg/sqlrite_wasm_bg.wasm 2>/dev/null || stat -f '%z' pkg/sqlrite_wasm_bg.wasm) | |
| echo "::notice title=WASM bundle size::sqlrite_wasm_bg.wasm = $size bytes ($(( size / 1024 )) KiB)" | |
| # --------------------------------------------------------------------------- | |
| # Desktop: Tauri's Rust side + the Svelte frontend. Needs Node to | |
| # build the frontend first because Tauri's build.rs looks for the | |
| # compiled assets in `desktop/dist/`. | |
| # | |
| # One cell (ubuntu) for CI speed — release builds are tested in the | |
| # Phase 6e desktop-release workflow's build matrix on all three OSes. | |
| # Here we just need to prove the Rust side compiles. | |
| desktop-build: | |
| name: desktop-build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| cache-dependency-path: desktop/package-lock.json | |
| - uses: dtolnay/rust-toolchain@stable | |
| # Tauri needs Linux webkit + friends before cargo build runs. | |
| - name: Install Tauri Linux deps | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| libwebkit2gtk-4.1-dev \ | |
| libayatana-appindicator3-dev \ | |
| librsvg2-dev \ | |
| patchelf | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: desktop-build | |
| - name: npm ci | |
| working-directory: desktop | |
| run: npm ci | |
| - name: Build frontend | |
| working-directory: desktop | |
| run: npm run build | |
| - name: Build Rust side | |
| run: cargo build -p sqlrite-desktop | |
| # --------------------------------------------------------------------------- | |
| # Journal example (SQLR-41): Tauri 2 + Svelte 5 daily-notes app under | |
| # `examples/desktop-journal/`. Same shape as `desktop-build` — frontend | |
| # first, then `cargo build -p sqlrite-journal`. Excluded from the | |
| # default workspace commands for the same reasons (Svelte build is a | |
| # prerequisite that the main rust-build-and-test job can't satisfy). | |
| journal-build: | |
| name: journal-build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| cache-dependency-path: examples/desktop-journal/package-lock.json | |
| - uses: dtolnay/rust-toolchain@stable | |
| - name: Install Tauri Linux deps | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| libwebkit2gtk-4.1-dev \ | |
| libayatana-appindicator3-dev \ | |
| librsvg2-dev \ | |
| patchelf | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: journal-build | |
| - name: npm install | |
| working-directory: examples/desktop-journal | |
| # `npm ci` would be ideal, but the example doesn't ship a | |
| # lockfile in version control (it's listed in .gitignore so | |
| # downstream forkers don't have to fight a node-version-pinned | |
| # lockfile). `npm install` is acceptable for an example app; | |
| # the engine API surface is what we're really exercising. | |
| run: npm install | |
| - name: Build frontend | |
| working-directory: examples/desktop-journal | |
| run: npm run build | |
| - name: Build Rust side (with ask) | |
| run: cargo build -p sqlrite-journal --all-targets | |
| - name: Build Rust side (no ask) | |
| run: cargo build -p sqlrite-journal --no-default-features --all-targets | |
| - name: Run journal unit tests | |
| run: cargo test -p sqlrite-journal |