All jobs

Upgrade Axum and Cargo Dependencies

Yes. An agent upgrades an Axum API's Cargo dependencies in groups, ports the code across Axum and SQLx breaking releases, and opens one pull request.

Run this on RushIn a Project that has your repository.

What the agent does

The agent reads Cargo.toml and Cargo.lock to see how far behind the project is and what moves together. In launchbadge/realworld-axum-sqlx the manifest asks for axum 0.3.4, sqlx 0.5 with runtime-tokio-native-tls, postgres, uuid and time, tokio 1.14, tower 0.4 and tower-http 0.2 with trace, clap at 3.0.0-beta.5, time 0.2, uuid 0.8, argon2 0.3, jwt 0.15 with hmac 0.11 and sha2 0.9, rand 0.8, itertools 0.10, thiserror 1, anyhow, async-trait, dotenv, env_logger 0.9 and log. The lock has not moved since the code was written: sqlx resolves to 0.5.9, time to 0.2.27, uuid to 0.8.2. There are no tests under tests/ and no .sqlx offline data, and the handlers use sqlx::query! and query_as! throughout, so even cargo build needs a DATABASE_URL pointing at a Postgres with the four files in migrations/ applied.

Then it reads what a build proves here. .github/workflows/rust.yml starts a postgres service, installs sqlx-cli, runs sqlx db setup, then cargo build --verbose and cargo test --verbose, and finally starts the server with cargo run and runs the RealWorld Postman collection from a pinned fork against port 8080. .env.sample names the two settings config.rs reads through clap, DATABASE_URL and HMAC_KEY, plus RUST_LOG. The agent does the same in its sandbox: starts Postgres, writes .env, runs sqlx db setup so the macros can check every query at compile time, and keeps the Postman run as the integration check since there is no unit suite to lean on.

The groups are decided by where the code breaks. Axum and Tower move together, and the port is in src/http/mod.rs and src/http/extractor.rs: AddExtensionLayer becomes Extension as a layer, axum::Server::bind becomes a TcpListener with axum::serve, the #[async_trait] impl FromRequest for AuthUser and MaybeAuthUser become FromRequestParts without the macro, and route paths such as /api/articles/:slug in src/http/articles/mod.rs take the newer brace syntax. SQLx moves on its own, with the runtime feature split into runtime-tokio and tls-native-tls, and Timestamptz in src/http/types.rs rechecked as a sqlx::Type over OffsetDateTime. The time major changes types.rs, where Format::Rfc3339 and lazy_format give way to the well-known format description, and extractor.rs, which builds a two-week Duration. clap from the beta to a release changes the attributes on Config in src/config.rs and needs the derive and env features. hmac, sha2 and jwt move together because extractor.rs signs and verifies with all three and NewMac was renamed. argon2, uuid, rand, itertools, thiserror and env_logger are each a small group, and dotenv is swapped for its maintained fork only if the prompt allows a crate change.

After each group the agent runs cargo build, cargo clippy, cargo test and the Postman collection against a running server, all against the same Postgres. A group that passes is a commit with the port in it; a group that fails, for example a jwt release that changes how claims deserialize, is reverted with the compiler output kept. The pull request lists each bump with old and new versions, the source files each port touched, the skips with their reason, and the four check results.

Start it with one API call

POST https://api.prix.dev/o/{org}/sessions with this body:

{
  "agent": "claude",
  "input": "Upgrade this Axum API's Cargo dependencies in groups: axum with tower and tower-http, then sqlx, then time, then clap, then hmac, sha2 and jwt together, then each remaining crate on its own. Start Postgres in the sandbox, write .env from .env.sample, install sqlx-cli and run sqlx db setup so the query macros compile. Axum and SQLx have had breaking releases since this code was written; port the code to them in the same commit as the bump, touching only the files the compiler points at. After each group run cargo build, cargo clippy, cargo test, and the RealWorld Postman collection against cargo run on port 8080. Keep a group only if everything passes; otherwise revert it and record the error. Open one pull request with one commit per group, one line per bump with old and new versions, the files each port touched, and every upgrade left out with the reason.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
  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 pull request on a new branch that changes Cargo.toml and Cargo.lock in one commit per group that passed, each commit carrying the port that group needed: src/http/mod.rs and src/http/extractor.rs for Axum, src/http/types.rs for time and SQLx, src/config.rs for clap, and the route strings in src/http/articles/mod.rs and its siblings. Migrations are untouched.

The description is one line per bump with old and new versions, the files each port touched, a list of upgrades left out with the compiler error or failing Postman request that excluded them, and the result lines of cargo build, cargo clippy, cargo test and the collection run. The trajectory keeps the full output for every group, including the reverted ones, and the server log from each collection run.

Before merging, a reviewer reads the extractor.rs port closely, since it is the token verification path, checks that the Timestamptz serialization still produces RFC 3339 strings, and confirms the Postman run exercised login and article creation, because there is no unit test covering either.

Run it on every Monday morning

Create an automation in the Project with this prompt and a schedule trigger (cron 0 9 * * 1 in your timezone). After the first run catches the project up, each week's run opens one pull request with that week's bumps, or none when nothing moved. Because each group is its own commit, dropping a bump before merge is a revert of one commit.

To have the link reach your server, start the weekly run from your own scheduler instead, with POST /o/{org}/sessions and an API key that has a webhook URL: Rush then POSTs run.completed with the session_url when the turn ends, and a handler on your side can post the pull request link where the API's maintainers read. A run that ends with no safe group opens no pull request and says why in its result.

The use case this job follows, with its automation and trigger: Upgrade dependencies weekly.

Why run it on Rush?

An Axum API that has not moved in a few releases cannot be upgraded by a bot: every bump is also a port, the query macros need a live database to compile, and the only integration check is a Postman collection against a running server. On Rush the agent has Postgres, sqlx-cli and the server in its own sandbox, does one group at a time, keeps the groups that pass and the compiler output for the ones that do not, so the pull request that reaches you is already green.

The record shows every build, every clippy run and every collection run, which is the evidence a reviewer needs when the code that changed is the authentication extractor. The same request runs against every Axum service you maintain at once.

Frequently asked questions

There are no tests. What stops a bad port?

The compiler, clippy, and the RealWorld Postman collection the repository's own CI runs against a live server. The sqlx::query! macros also check every query against the database at compile time. A behavior the collection does not cover is named in the description as unverified.

Why does cargo build need Postgres?

Because the handlers use SQLx's checked macros and the repository has no .sqlx offline data. The macros connect to DATABASE_URL during compilation and fail without the schema, so the agent runs sqlx db setup before the first build. It can also generate offline data with cargo sqlx prepare if you ask for it in the prompt.

Will it change the route syntax?

Yes, as part of the Axum group, since newer releases use braces for path parameters where this code has colons. The change is in the router strings only, named in the description, and the Postman run confirms the routes still answer.

Does it replace the dotenv crate?

Only if the prompt allows a crate swap; by default it bumps what is there and notes that dotenv has a maintained fork. The one-line change in main.rs is easy to review if you ask for it.

Can it do only part of the catch-up?

Yes. Name the groups to take, for example Axum and SQLx only, and the rest stays at its locked version with a line in the pull request saying so. The next weekly run picks up from there.