diff --git a/.envrc b/.envrc new file mode 100755 index 00000000..3550a30f --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore index 1a2971ca..ba180f3f 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ sqlpage/sqlpage.db tests_uploads/ /test-results/ /playwright-report/ +/result +.direnv/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 43487637..ce81efe0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,6 +48,22 @@ or depend on having one already installed on the system where it is running (dyn Windows comes with ODBC pre-installed; SQLPage cannot statically link to the unixODBC driver manager on windows. +### (Optional) Nix Dev Shell + +If you have [Nix](https://nixos.org/download/) with flakes enabled, `nix develop` drops you into a dev shell with everything needed to build and test SQLPage. + +If you use [direnv](https://direnv.net/), `direnv allow` is a one time command to auto assume the shell when you enter the dir. + +| Command | What it runs | +| --- | --- | +| `nix fmt` | rustfmt, Biome, and nixfmt | +| `nix flake check` | the formats all files | +| `nix run .#lint-rust` | `cargo fmt --check` and `cargo clippy` | +| `nix run .#test-rust` | the Rust test suites | +| `nix run .#test-browser` | the Playwright suites | +| `nix run .#test-examples` | the Hurl suite | +| `nix build .#odbc-drivers` | builds an `odbcinst.ini`; point `ODBCSYSINI` at it to run the ODBC tests | + ## Code Style and Linting ### Rust diff --git a/flake.lock b/flake.lock new file mode 100755 index 00000000..1cdfb70f --- /dev/null +++ b/flake.lock @@ -0,0 +1,48 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1790046670, + "narHash": "sha256-MYiI+CzL0tuWgRPjGsKCDHqYs2T3OzMlMQWOYWG0qso=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "6774f7bc253789b113a4f39285dc0fa100abeacc", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1790149037, + "narHash": "sha256-01WcSplVEmQt13QUZLfWez27JO+2lyYWX+yTitvkF3g=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "fb058ecf6d14837ea152a3d5225ce7f88ee5cde1", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..def67e21 --- /dev/null +++ b/flake.nix @@ -0,0 +1,251 @@ +{ + description = "Optional development environment for SQLPage"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + # Ships the official rustup binaries, so the toolchain in this shell is + # the same build CI and the release use, down to the bundled LLVM. + rust-overlay.url = "github:oxalica/rust-overlay"; + rust-overlay.inputs.nixpkgs.follows = "nixpkgs"; + }; + + outputs = + { + self, + nixpkgs, + rust-overlay, + }: + let + inherit (nixpkgs) lib; + + systems = [ + "aarch64-darwin" + "aarch64-linux" + "x86_64-linux" + ]; + + # Oracle governs its own client library by licence, so nixpkgs marks it + # unfree. Naming it here keeps every other package in this flake free. + unfreePackages = [ "oracle-instantclient" ]; + + forEachSystem = + build: + lib.genAttrs systems ( + system: + build ( + import nixpkgs { + inherit system; + config.allowUnfreePredicate = package: builtins.elem (lib.getName package) unfreePackages; + overlays = [ rust-overlay.overlays.default ]; + } + ) + ); + + cargoEdition = (lib.importTOML ./Cargo.toml).package.edition; + + lockedPlaywrightVersion = + (lib.importJSON ./package-lock.json).packages."node_modules/playwright-core".version; + + formatterFor = + pkgs: + pkgs.treefmt.withConfig { + runtimeInputs = [ + pkgs.biome + pkgs.nixfmt + pkgs.rustfmt + ]; + settings = { + on-unmatched = "info"; + formatter = { + nixfmt = { + command = "nixfmt"; + includes = [ "*.nix" ]; + }; + rustfmt = { + command = "rustfmt"; + options = [ + "--edition" + cargoEdition + ]; + includes = [ "*.rs" ]; + }; + biome = { + command = "biome"; + options = [ + "format" + "--write" + "--no-errors-on-unmatched" + ]; + includes = [ + "*.css" + "*.js" + "*.json" + "*.jsonc" + "*.mjs" + "*.ts" + ]; + }; + }; + }; + }; + + rustToolchainFor = pkgs: pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; + + # odbc-sys links against a driver manager, and the C sources vendored by + # aws-lc-sys, libsqlite3-sys and zstd-sys need a compiler. Nothing here + # reaches for OpenSSL: SQLPage speaks TLS through rustls. + cargoRuntime = pkgs: [ + (rustToolchainFor pkgs) + pkgs.stdenv.cc + pkgs.unixodbc + ]; + # The database matrix runs prebuilt test binaries that link the unixODBC + # driver manager statically. It still reads ODBCSYSINI at run time and + # dlopens whatever absolute path this file names, so pointing that one + # variable at the store replaces every driver install step. + odbcDriversFor = + pkgs: + pkgs.runCommand "sqlpage-odbc-drivers" { } '' + mkdir -p "$out" + oracleDriver=(${lib.getLib pkgs.oracle-instantclient}/lib/libsqora.so.*) + cat > "$out/odbcinst.ini" <