# Review Pull Requests on an Actix Web API

Yes. An agent checks out the pull request, runs cargo clippy with -D warnings and cargo test in its sandbox, and posts one review on extractors and shared state.

[Run this on Rush](https://cloud.getrush.ai/run/review-pull-requests/actix/), in a Project that has your repository.

## What the agent does

The agent reads the workspace before the diff, because in actix/examples a change to one crate is built under rules set at the root. `Cargo.toml` is a workspace with `resolver = "3"`, seventy-four members from `auth/casbin` to `websockets/echo`, `edition = "2024"` and `rust-version = "1.98"` in `[workspace.package]`, and a `[workspace.dependencies]` table that pins `actix-web` at `4.11`, `actix` at `0.13`, `actix-session` at `0.11`, `actix-ws` at `0.4`, `awc` at `3.7`, `tokio` at `1.24.2` and the rest, so a member `Cargo.toml` says `actix-web.workspace = true` rather than a version. `databases/sqlite` is excluded from the workspace. `examples-common` is a member that the TLS and tracing examples share. A pull request that adds a version to a member crate, or a crate without adding it to `members`, is a finding before any code is read.

Then it runs what CI runs. `.github/workflows/clippy-fmt.yml` runs `zizmor` over the workflows, a `rustfmt` check, and `cargo clippy --workspace --all-features --tests -- -D warnings`, so a single warning fails the pull request. `ci.yml` installs `sqlite3`, `libpq-dev` and `redis-server`, installs `sqlx-cli` and `diesel_cli`, creates `todo.db` with `sqlx database create` and `sqlx migrate run --source=./basics/todo/migrations`, starts Redis, then runs `cargo check --workspace --bins --examples --tests` and `cargo test --workspace --all-features --no-fail-fast --exclude=db-diesel -- --nocapture`, with the Diesel example tested separately after `diesel migration run`. `rustfmt.toml` sets `group_imports = "StdExternalCrate"`, `imports_granularity = "Crate"` and `use_field_init_shorthand`, which `justfile` applies with `cargo +nightly fmt`. The agent runs clippy with the same flags across the workspace, `cargo fmt --check` with the nightly toolchain, and `cargo test` in the touched example, with the SQLite and Redis setup from `ci.yml` when the example needs it.

The tests are concentrated in a few examples, which tells the agent where proof is available. Ten files carry `#[actix_web::test]`, among them `json/json`, `basics/hello-world`, `basics/nested-routing`, `forms/form`, `databases/diesel`, `databases/diesel-async`, `databases/mongodb`, `templating/yarte`, `guards` and `auth/redis-session`. `json/json/src/main.rs` is the model: `test::init_service(App::new().service(...))`, a `TestRequest::post().uri("/").set_json(MyObj { ... })`, `app.call(req)`, then `to_bytes(resp.into_body())` compared with the exact JSON string. An example that gets new behaviour without a test in that shape gets a finding that names the file, and the agent writes the case in the sandbox to confirm the behaviour before posting it.

The diff is read with the three questions the prompt names. Extractors: `json/json` shows `web::Json<MyObj>` with `JsonConfig::default().limit(4096)` set on the app and a tighter `limit(1024)` on one resource, and `index_manual` taking `web::Bytes` and calling `serde_json::from_slice`; a new handler that takes `web::Json` without a limit where the app sets none, or that unwraps a `Result` extractor, is a finding. Shared state: `basics/state/src/main.rs` explains the three kinds, `Data<Mutex<usize>>` and `Data<AtomicUsize>` created outside the `HttpServer::new` closure and cloned in, and a `Cell<u32>` created inside the closure so each worker thread gets its own; a diff that builds a `Data` inside the closure and expects it to be shared, or holds a `Mutex` guard across an `.await`, gets a finding with the line. Blocking inside async handlers: `basics/todo` uses `sqlx` with `runtime-tokio`, while a `std::fs::read`, a synchronous `reqwest::blocking` call or a `std::thread::sleep` inside a handler stalls the worker; the fix the review names is `web::block` or the async client. One GitHub review is posted per run, quoting clippy, fmt and the example's tests, separating blocking issues from suggestions, with file and line on every finding. The agent pushes nothing.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "Review this pull request on an Actix Web examples workspace. Check it out, run cargo clippy --workspace --all-features --tests -- -D warnings and cargo +nightly fmt --check, then cargo test -p <crate> for each example the diff touches, setting up todo.db with sqlx-cli or starting redis-server first as .github/workflows/ci.yml does when the example needs them. Read the diff with the example's main.rs, its Cargo.toml, the root Cargo.toml workspace table and any #[cfg(test)] module. Look for member crates that pin a version instead of using workspace = true or are missing from members, web::Json or web::Form extractors without a payload limit where the app sets none, Result extractors unwrapped in handlers, Data built inside the HttpServer closure that the code treats as shared, Mutex guards held across .await, blocking file, network or sleep calls in async handlers, and new behaviour with no #[actix_web::test] case. Confirm a finding with a short test in the sandbox where you can, but do not add it to the branch. Post one GitHub review that quotes the clippy, fmt and test results, separates blocking issues from suggestions, and cites file and line for every finding. Do not push commits.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app/pull/42"
    }
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

What comes back is a review on the pull request. Its summary quotes `cargo clippy` with `-D warnings`, the `rustfmt` check, and `cargo test` for each touched example with its pass and fail counts, plus the SQLite or Redis setup it needed. Findings follow with file and line in the example's `src/`, marked blocking or suggestion, and a state finding says which of the three patterns in `basics/state` the code should have used.

The transcript keeps the crate downloads, every command with its output, the `todo.db` migration when it ran, and the `#[actix_web::test]` cases the agent wrote to confirm a finding, so when the review says a handler blocks the worker, the test that timed out is in the record.

Before merging, a reviewer runs clippy and the touched example's tests on the branch, opens each cited line, and decides which suggestions to keep. A clippy warning, a guard held across `.await` or a blocking call in a handler is blocking by default; a request to add a test to an example that never had one is a suggestion.

## Run it on every pull request opened

Create an automation in the Project with a `github` trigger on `pull_request.opened` and `pull_request.synchronize`, `branch_patterns` set to `main`, and this prompt. Each fire adds the pull request after the prompt, so every pull request and every push to it gets its own sandbox, its own `target/` directory and its own review. Set `read_only` so the runs comment and never push.

The review is the result on the pull request; the run is listed in the Project. `max_runs_per_hour`, 1 to 30, bounds a dependency-update morning, since `.github/dependabot.yml` runs weekly Cargo updates behind a three-day cooldown and groups them; a fire past the cap is skipped as `rate_limited` and the pull request is reviewed on its next push.

## Why run it on Rush?

An Actix review that stops at the diff misses what clippy with `-D warnings` catches across seventy-four crates, what a `Mutex` guard across an `.await` does under load, and whether the example's test still passes once `todo.db` has been migrated and Redis is up. Doing that locally means a full workspace build and the service setup from `ci.yml`. On Rush the agent does it in its own sandbox and keeps every command and its output, so the review of an extractor or a state change rests on a compiled, tested branch rather than a reading.

One sandbox per pull request keeps reviews parallel when several examples change at once, each with its own `target/` and its own SQLite file, and nothing is pushed to the author's branch. The reviewer gets findings with the clippy and test output attached and the author gets the same verdict CI would give, with the fix named in the terms `basics/state` and `json/json` already use.

## Frequently asked questions

### Does it build every crate in the workspace?

Clippy and `cargo check` run across the workspace as `clippy-fmt.yml` and `ci.yml` do, since a workspace dependency change affects every member. `cargo test` runs for the touched examples only, with `--all-features` to match CI.

### Which examples need a service to test?

`basics/todo` needs `todo.db` created and migrated with `sqlx-cli`, `databases/diesel` needs `diesel migration run` and is excluded from the workspace test run, `auth/redis-session` and `cache/redis` need `redis-server`, and `databases/mongodb` has a test marked `#[ignore]` that needs a MongoDB instance. The agent sets up what `ci.yml` sets up and says in the review which tests it could not run.

### Why does the fmt check need nightly?

`rustfmt.toml` uses `group_imports`, `imports_granularity` and `use_field_init_shorthand`, and the first two are nightly-only options, which is why `justfile` runs `cargo +nightly fmt`. The sandbox installs the nightly toolchain for the check only; the build and tests use stable, as the README asks.

### What does it do with a new example?

It checks the crate is in the root `members` list, uses `workspace = true` for shared dependencies, has a `README.md` with run instructions, and compiles under clippy's `-D warnings`. CI's `cargo check --workspace --bins --examples --tests` will fail on an unlisted crate's dependency drift, so the review treats that as blocking.
