What the agent does
In a solution like dotnet/eShop, versions do not live in the project files. Directory.Packages.props sets ManagePackageVersionsCentrally and CentralPackageTransitivePinningEnabled to true and holds 71 PackageVersion entries, grouped by comments: Aspire.Hosting.* and Aspire.* client packages at 13.6.0 (three of them on 13.6.0-preview.1.26479.8), Asp.Versioning.* at 10.2.x, the Microsoft.AspNetCore.* and Microsoft.EntityFrameworkCore.* packages at 10.0.12, Npgsql.EntityFrameworkCore.PostgreSQL 10.0.3, Microsoft.Extensions.Http.Resilience and ServiceDiscovery at 10.10.0, and test packages such as MSTest 4.0.2, xunit.v3.mtp-v2 3.2.2 and NSubstitute 5.3.0. The agent edits only that file and keeps each comment group moving together, because packages released as a train (all of Aspire, all of ASP.NET at one patch) should not be split.
global.json pins the SDK to 10.0.302 with rollForward latestFeature, names Microsoft.Testing.Platform as the test runner and MSTest.Sdk 4.0.2 as an MSBuild SDK, and test projects such as tests/Catalog.FunctionalTests use Sdk="Aspire.AppHost.Sdk/13.6.0" in the csproj itself. Those SDK versions are not in Directory.Packages.props, so the agent bumps them in the same commit as the matching packages, or the build mixes two Aspire versions. nuget.config clears every source except nuget.org, so the agent resolves versions from there alone, with dotnet list package --outdated.
Directory.Build.props sets TreatWarningsAsErrors to true, so a new obsolete-API warning from an upgraded package fails the build, not just a test. The agent builds with dotnet build eShop.Web.slnf and runs dotnet test --solution eShop.Web.slnf, the two commands in .github/workflows/pr-validation.yml. The unit test projects (Basket.UnitTests, Ordering.UnitTests and others) run as is; the functional test projects start Postgres, Redis and RabbitMQ through Aspire fixtures such as CatalogApiFixture.cs, so they need a container runtime, and the agent reports plainly which suites ran.
Each group that breaks the build or the tests is reverted, and the agent records the error code (a CS0618 obsolete warning, a failing test name) with the first lines of output. Preview packages stay on preview only when the stable release does not exist yet.
Start it with one API call
POST https://api.prix.dev/o/{org}/sessions with this body:
{
"agent": "codex",
"input": "Upgrade the NuGet packages in Directory.Packages.props to their latest stable releases, keeping each commented group (Aspire, Asp.Versioning, ASP.NET, EF, runtime, dotnet/extensions) on one version train. When you bump Aspire, also bump the Aspire.AppHost.Sdk version in the test csproj files. Run dotnet build eShop.Web.slnf and dotnet test --solution eShop.Web.slnf after each group; warnings are errors here. Revert any group that fails and record the error. Say which test projects could not run and why. Open one pull request listing each bump with old and new version and each skipped upgrade with the error that blocked it.",
"resources": [
{
"url": "https://github.com/your-org/your-app"
}
]
}- 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.
- 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.
- 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
The pull request changes Directory.Packages.props and, when Aspire moves, the Sdk attribute in the test csproj files. Its description is a table of package, old version and new version, grouped as the props file groups them, followed by the groups left out with the compiler error or failing test that blocked each. A short note lists which test projects ran in the sandbox and which did not. pr-validation.yml runs on the pull request with the same build and test commands.
A reviewer checks the release notes for any group that crossed a minor version, confirms the functional tests pass in CI if they could not run in the sandbox, and looks for any code change the agent made to clear a new obsolete warning.
Run it on every Monday morning
Patch releases for ASP.NET Core, EF Core and the runtime packages ship together on a monthly train, and Aspire releases on its own schedule. A weekly job that sends this request picks each one up while the change is small. Point it at the repository in resources and send it from any scheduler you already run.
Give the API key a webhook URL and Rush sends run.completed or run.failed when the turn ends; the handler can post the pull request to your team channel.
The use case this job follows, with its automation and trigger: Upgrade dependencies weekly.
Why run it on Rush?
Upgrading a centrally managed .NET solution is mostly waiting: a restore, a full build with warnings as errors, and a test run for each group, then a revert and another round when one fails. In a Rush sandbox that loop runs on the SDK global.json names, and every dotnet command with its output is in the session transcript, so the reviewer can see exactly which test failed for a skipped group.
A bot that opens one pull request per package splits trains that must move together, and each of those fails on its own. One tested pull request per week is easier to review, and every service in a larger estate can get its own run at the same time.
Frequently asked questions
Does it understand central package management?
Yes. With ManagePackageVersionsCentrally on, versions live in Directory.Packages.props, and the agent edits that file instead of adding Version attributes to each csproj.
Will it upgrade the .NET SDK in global.json?
Not unless you ask. The request is about NuGet packages; changing the SDK or the target framework is a bigger change worth its own run.
What about tests that need Docker?
eShop's functional tests start Postgres, Redis and RabbitMQ through Aspire. If the sandbox cannot start them, the agent says so in the pull request, and your CI runs them on the pull request as usual.
Will it move to preview packages?
Only where the current version is already a preview with no stable release. Otherwise it keeps to stable releases.