From ad81dada8dc6549c3300341ff8004cee0308901f Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 30 Aug 2026 14:20:19 +0100 Subject: [PATCH] ci: add Nix CI shell and PR nightly checks --- .github/workflows/ci-nightly.yml | 46 +++++----------- .github/workflows/ci.yml | 43 ++++----------- .github/workflows/clippy-fmt.yml | 24 ++++++-- README.md | 10 ++++ flake.nix | 94 ++++++++++++++++++++++++++++---- justfile | 49 ++++++++++++++++- 6 files changed, 187 insertions(+), 79 deletions(-) diff --git a/.github/workflows/ci-nightly.yml b/.github/workflows/ci-nightly.yml index da33a042f..a404721d2 100644 --- a/.github/workflows/ci-nightly.yml +++ b/.github/workflows/ci-nightly.yml @@ -1,6 +1,9 @@ name: CI (nightly) on: + # Temporary: validate nightly CI on pull requests during the Nix migration. + pull_request: + types: [opened, synchronize, reopened] schedule: [cron: "40 1 * * *"] workflow_dispatch: @@ -27,49 +30,30 @@ jobs: with: toolchain: ${{ matrix.version }} - - name: Install system packages - run: | - sudo apt-get update - sudo apt-get -y install sqlite3 - sudo apt-get -y install libpq-dev - sudo apt-get -y install redis-server + - name: Install Nix + uses: nixbuild/nix-quick-install-action@9f63be77f412a248c9d9a65a4c82cf066cdf8f0c # v35 - - name: Install DB CLI tools - run: | - cargo install --force sqlx-cli --no-default-features --features=sqlite,rustls - cargo install --force diesel_cli --no-default-features --features=sqlite,postgres + - name: Enter Nix devshell + uses: nicknovitski/nix-develop@9be7cfb4b10451d3390a75dc18ad0465bed4932a # v1.2.1 + with: + arguments: .#ci - name: Create Test DBs - env: - DATABASE_URL: sqlite://./todo.db - run: | - sqlx database create - chmod a+rwx ./todo.db - sqlx migrate run --source=./basics/todo/migrations + run: just init-db - name: Start Redis - run: | - if ! redis-cli ping; then - redis-server --daemonize yes - fi - redis-cli ping + run: just start-redis - name: cargo check - run: cargo check --workspace --bins --examples --tests + run: just cargo-check timeout-minutes: 30 - name: cargo test - run: cargo test --workspace --all-features --no-fail-fast --exclude=db-diesel -- --nocapture + run: just test timeout-minutes: 30 - name: cargo test (diesel) - env: - DATABASE_URL: test.db - run: | - cd databases/diesel - diesel migration run - chmod a+rwx test.db - cargo test -p=db-diesel --no-fail-fast -- --nocapture + run: just test-diesel timeout-minutes: 10 - name: Install cargo-ci-cache-clean @@ -78,4 +62,4 @@ jobs: tool: cargo-ci-cache-clean - name: CI cache clean - run: cargo-ci-cache-clean + run: just ci-cache-clean diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8824d48be..1fe20ca47 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,49 +31,30 @@ jobs: with: toolchain: ${{ matrix.version }} - - name: Install system packages - run: | - sudo apt-get update - sudo apt-get -y install sqlite3 - sudo apt-get -y install libpq-dev - sudo apt-get -y install redis-server + - name: Install Nix + uses: nixbuild/nix-quick-install-action@9f63be77f412a248c9d9a65a4c82cf066cdf8f0c # v35 - - name: Install DB CLI tools - run: | - cargo install --force sqlx-cli --no-default-features --features=sqlite,rustls - cargo install --force diesel_cli --no-default-features --features=sqlite,postgres + - name: Enter Nix devshell + uses: nicknovitski/nix-develop@9be7cfb4b10451d3390a75dc18ad0465bed4932a # v1.2.1 + with: + arguments: .#ci - name: Create Test DBs - env: - DATABASE_URL: sqlite://./todo.db - run: | - sqlx database create - chmod a+rwx ./todo.db - sqlx migrate run --source=./basics/todo/migrations + run: just init-db - name: Start Redis - run: | - if ! redis-cli ping; then - redis-server --daemonize yes - fi - redis-cli ping + run: just start-redis - name: cargo check - run: cargo check --workspace --bins --examples --tests + run: just cargo-check timeout-minutes: 30 - name: cargo test - run: cargo test --workspace --all-features --no-fail-fast --exclude=db-diesel -- --nocapture + run: just test timeout-minutes: 30 - name: cargo test (diesel) - env: - DATABASE_URL: test.db - run: | - cd databases/diesel - diesel migration run - chmod a+rwx test.db - cargo test -p=db-diesel --no-fail-fast -- --nocapture + run: just test-diesel timeout-minutes: 10 - name: Install cargo-ci-cache-clean @@ -82,4 +63,4 @@ jobs: tool: cargo-ci-cache-clean - name: CI cache clean - run: cargo-ci-cache-clean + run: just ci-cache-clean diff --git a/.github/workflows/clippy-fmt.yml b/.github/workflows/clippy-fmt.yml index eabea8489..f665c18b2 100644 --- a/.github/workflows/clippy-fmt.yml +++ b/.github/workflows/clippy-fmt.yml @@ -34,14 +34,22 @@ jobs: with: persist-credentials: false - - name: Install Rust + - name: Install Rust (stable) uses: actions-rust-lang/setup-rust-toolchain@166cdcfd11aee3cb47222f9ddb555ce30ddb9659 # v1.17.0 with: toolchain: stable components: rustfmt + - name: Install Nix + uses: nixbuild/nix-quick-install-action@9f63be77f412a248c9d9a65a4c82cf066cdf8f0c # v35 + + - name: Enter Nix devshell + uses: nicknovitski/nix-develop@9be7cfb4b10451d3390a75dc18ad0465bed4932a # v1.2.1 + with: + arguments: .#ci + - name: rustfmt - uses: actions-rust-lang/rustfmt@4066006ec54a31931b9b1fddfd38f2fdf2d27143 # v1.1.2 + run: just fmt-check clippy: name: clippy check @@ -58,12 +66,20 @@ jobs: with: persist-credentials: false - - name: Install Rust + - name: Install Rust (stable) uses: actions-rust-lang/setup-rust-toolchain@166cdcfd11aee3cb47222f9ddb555ce30ddb9659 # v1.17.0 with: toolchain: stable components: clippy + - name: Install Nix + uses: nixbuild/nix-quick-install-action@9f63be77f412a248c9d9a65a4c82cf066cdf8f0c # v35 + + - name: Enter Nix devshell + uses: nicknovitski/nix-develop@9be7cfb4b10451d3390a75dc18ad0465bed4932a # v1.2.1 + with: + arguments: .#ci + - name: clippy timeout-minutes: 30 - run: cargo clippy --workspace --all-features --tests -- -D warnings + run: just clippy diff --git a/README.md b/README.md index 593bd56b9..74886aed3 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,16 @@ > Curated examples using the Actix ecosystem. +## Development + +Enter the full local development shell with `nix develop`. It provides native libraries, database tools, and project tooling used by the examples. Rust must be available in the host environment. + +The lighter CI shell is available with `nix develop .#ci`. It provides the database and service packages used by CI, without the extra local development tooling. CI selects its Rust toolchain separately. + +Initialize the SQLite databases used by the examples with `just init-db` from the repository root. The same operation is also available as `nix run .#init-db` for use outside a development shell. + +Run the local CI build and test sequence with `just ci` inside the default development shell. + [![CI status](https://github.com/actix/examples/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/examples/actions) diff --git a/flake.nix b/flake.nix index cdfb04e5f..fda7daedf 100644 --- a/flake.nix +++ b/flake.nix @@ -7,19 +7,89 @@ outputs = inputs@{ flake-parts, ... }: flake-parts.lib.mkFlake { inherit inputs; } { systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; - perSystem = { pkgs, config, inputs', system, lib, ... }: { - formatter = pkgs.nixpkgs-fmt; - - devShells.default = pkgs.mkShell { - packages = [ - config.formatter - pkgs.nodePackages.prettier - pkgs.taplo - pkgs.just - ] ++ lib.optional pkgs.stdenv.isDarwin [ - pkgs.pkgsBuildHost.libiconv + perSystem = { pkgs, config, lib, ... }: + let + runtimeLibraryPath = lib.makeLibraryPath [ + pkgs.openssl + pkgs.sqlite + pkgs.libpq + pkgs.zlib ]; + + rustRuntimeShellHook = lib.optionalString pkgs.stdenv.isLinux '' + export RUSTFLAGS="''${RUSTFLAGS:-} -C link-arg=-Wl,-rpath,${runtimeLibraryPath}" + ''; + + initDb = pkgs.writeShellApplication { + name = "init-db"; + runtimeInputs = [ + pkgs.coreutils + pkgs.sqlx-cli + pkgs.diesel-cli + ]; + text = '' + set -euo pipefail + + if [ ! -d "$PWD/basics/todo/migrations" ] || [ ! -d "$PWD/databases/diesel/migrations" ]; then + echo "init-db must be run from the repository root" >&2 + exit 1 + fi + + DATABASE_URL="sqlite://./todo.db" sqlx database create + chmod a+rwx ./todo.db + DATABASE_URL="sqlite://./todo.db" sqlx migrate run --source=./basics/todo/migrations + + ( + cd databases/diesel + DATABASE_URL=test.db diesel migration run + chmod a+rwx ./test.db + ) + ''; + }; + in + { + formatter = pkgs.nixpkgs-fmt; + + devShells.default = pkgs.mkShell { + packages = [ + config.formatter + pkgs.nodePackages.prettier + pkgs.taplo + pkgs.fd + pkgs.just + pkgs.pkg-config + pkgs.openssl + pkgs.sqlite + pkgs.libpq + pkgs.redis + pkgs.sqlx-cli + pkgs.diesel-cli + ] ++ lib.optional pkgs.stdenv.isDarwin [ + pkgs.pkgsBuildHost.libiconv + ]; + shellHook = rustRuntimeShellHook; + }; + + devShells.ci = pkgs.mkShell { + packages = [ + pkgs.just + pkgs.pkg-config + pkgs.openssl + pkgs.sqlite + pkgs.libpq + pkgs.redis + pkgs.sqlx-cli + pkgs.diesel-cli + ] ++ lib.optional pkgs.stdenv.isDarwin [ + pkgs.pkgsBuildHost.libiconv + ]; + shellHook = rustRuntimeShellHook; + }; + + apps.init-db = { + type = "app"; + program = lib.getExe initDb; + }; }; - }; }; } diff --git a/justfile b/justfile index 436116862..2cf7a3d57 100644 --- a/justfile +++ b/justfile @@ -8,6 +8,11 @@ fmt: fd --hidden --extension=toml --exec-batch taplo format cargo +nightly fmt +# Check Rust formatting. +[group("lint")] +fmt-check: + cargo fmt --all -- --check + # Check project. [group("lint")] check: && clippy @@ -18,4 +23,46 @@ check: && clippy # Run Clippy over workspace. [group("lint")] clippy: - cargo clippy --workspace --all-targets --all-features + cargo clippy --workspace --all-targets --all-features -- -D warnings + +# Initialize the test databases. +init-db: + nix run .#init-db + +# Start Redis for integration tests. +start-redis: + #!/usr/bin/env bash + set -euo pipefail + + if ! redis-cli ping; then + redis-server --daemonize yes + fi + redis-cli ping + +# Check that all workspace targets compile. +cargo-check: + cargo check --workspace --bins --examples --tests + +# Test the workspace except for the Diesel example. +test: + cargo test --workspace --all-features --no-fail-fast --exclude=db-diesel -- --nocapture + +# Test the Diesel example. +test-diesel: + #!/usr/bin/env bash + set -euo pipefail + + cd databases/diesel + DATABASE_URL=test.db cargo test -p=db-diesel --no-fail-fast -- --nocapture + +# Run the build and test sequence locally. +ci: + just init-db + just start-redis + just cargo-check + just test + just test-diesel + +# Clean Cargo artifacts before uploading the CI cache. +ci-cache-clean: + cargo-ci-cache-clean