# Fix a Failing CI Build in a .NET Project

Yes. When a .NET solution's Actions run fails, an agent reads the log, reruns the pinned SDK's build and dotnet test, fixes the cause and opens a pull request.

[Run this on Rush](https://cloud.getrush.ai/run/fix-failing-ci/dotnet/), in a Project that has your repository.

## What the agent does

The agent reads the failed job before it opens a single source file. From the `workflow_run` payload after the prompt it runs `gh run view <run id> --log-failed` and finds the step that failed. In a solution like dotnet/eShop, `.github/workflows/pr-validation.yml` has two steps that matter: `dotnet build eShop.Web.slnf` and `dotnet test --solution eShop.Web.slnf --no-build --no-progress --output detailed`. A build failure comes with a `CSxxxx` or `NUxxxx` code and a file and line; `Directory.Build.props` sets `TreatWarningsAsErrors` to true, so a new warning anywhere in the filter's 17 projects breaks the build. A test failure names the test project and method, and the `--output detailed` flag means the assertion message is already in the log. The agent quotes the exact block it will fix.

Then it matches the toolchain. `global.json` pins SDK `10.0.302` with `rollForward: latestFeature`, selects `Microsoft.Testing.Platform` as the test runner and `MSTest.Sdk` 4.0.2, and `Directory.Packages.props` pins every package version centrally with transitive pinning on. The agent installs that SDK, runs `dotnet build eShop.Web.slnf`, and for a test failure runs the single project first: `dotnet test tests/Ordering.UnitTests --no-build`, where `Ordering.UnitTests.csproj` uses the MSTest SDK with NSubstitute and the tests in `Domain/OrderAggregateTest.cs`, `Domain/BuyerAggregateTest.cs` and `Application/NewOrderCommandHandlerTest.cs` run with no external services. `tests/Directory.Build.props` turns on the Microsoft Testing Platform runner for the xUnit projects too, which is why the `--solution` form of `dotnet test` is the one the workflow uses.

Functional test projects are a different case. `Catalog.FunctionalTests`, `Ordering.FunctionalTests`, `Basket.FunctionalTests` and `Webhooks.FunctionalTests` build an Aspire distributed application in their fixtures: `CatalogApiFixture` adds a Postgres resource with the `ankane/pgvector` image, and `OrderingApiFixture` adds two Postgres resources plus the `Identity.API` project. `tests/README.md` says these need Docker running. The agent starts a container runtime in its sandbox before it reruns them, and when the log shows a container pull or port error rather than an assertion it says so instead of changing code.

With the failure reproduced it fixes the cause: the warning the build promoted to an error, the handler or aggregate the failing test exercises, or a central package version in `Directory.Packages.props` that no longer resolves. It does not add `<NoWarn>` entries, `[Ignore]` attributes or `Skip` reasons. Before pushing it runs the full `dotnet build eShop.Web.slnf` and `dotnet test --solution eShop.Web.slnf --no-build` again, and when the change touches `src/WebApp` it also runs the Playwright journeys from `playwright.config.ts` (`npm ci`, `npx playwright install chromium`, `npm run test:e2e`), which start the AppHost on port 5045 the way `playwright.yml` does.

## Start it with one API call

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

```json
{
  "agent": "claude",
  "input": "The GitHub Actions run on this branch failed; the workflow_run event is at the end of this prompt. Read the failed job's log with gh run view <run id> --log-failed, name the step that failed, and quote the compiler error or the failing test and its assertion message. Install the SDK that global.json pins, run dotnet build eShop.Web.slnf, and for a test failure run that one test project with dotnet test --no-build first; start a container runtime before rerunning a functional test project whose fixture builds an Aspire application. Fix the cause in the code or the central package versions. Do not add NoWarn entries, Ignore attributes or Skip reasons, and do not loosen an assertion; if a test is wrong, change it and say why. Rerun dotnet build and dotnet test --solution eShop.Web.slnf --no-build until both pass, and open a pull request against the failing branch that quotes the error it fixed.\n\nEvent: <workflow_run payload>",
  "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

A pull request against the failing branch with the fix in the project the log named and the step, error code or test method and quoted message in the description. For a build break it shows the compiler line before and after; for a test it shows the single-project `dotnet test` output failing and then passing; for a functional test it says whether the fixture's containers started in the sandbox. Every command is listed, and the session transcript keeps each with its output.

`eShop Pull Request Validation` and the Playwright workflow run again on the pull request. If the log shows no code cause, such as a NuGet restore timeout or a Docker pull that failed on the runner, the agent opens nothing and explains what it reran and what it saw.

A reviewer checks that the fix removed the warning rather than suppressing it, that a changed test still asserts the business rule in the aggregate or handler, and that a package version change in `Directory.Packages.props` kept the versions that the comments say move together, such as the Aspire and ASP.NET groups.

## Run it on every failed .NET workflow run

Create an automation in the Project with this prompt and a `github` trigger on `workflow_run.failure`. Only runs caused by an owner, member or collaborator fire it, and runs from forks never do, so the trigger acts on your team's branches and not on every external contribution. The event is placed after the prompt as untrusted text.

Or subscribe your own server to the repository's `workflow_run` webhook and, on `conclusion: failure`, send this request with the event in `input` and `https://github.com/<owner>/<repo>/tree/<head_branch>` as the resource. Keep the `workflow_run.id` with the `execution_id` you get back so a redelivery does not start a second run, and use the `run.completed` webhook to post the pull request link on the commit.

## Why run it on Rush?

A failing .NET build in a 17-project solution with warnings as errors, central package management and Aspire-backed functional tests is slow to reproduce on a laptop: the exact SDK, a container runtime, and a full restore before the first useful error. The agent does that once in its own sandbox and runs the same `dotnet build` and `dotnet test --solution` the workflow runs.

The pull request arrives with the quoted log, the failing and passing output of the same command and the validation workflow rerunning on the branch, so review is about the fix and not about trust. Several red branches get separate sandboxes at the same time, and a person still approves each merge.

## Frequently asked questions

### Can it run the functional tests that need Docker?

Yes. The fixtures build an Aspire application with Postgres containers, and the sandbox can run a container runtime, so the agent starts one before `dotnet test` on those projects. When a container cannot start for a sandbox reason it says so in the pull request rather than guessing at the code.

### Will it silence a warning with NoWarn to get the build green?

No. `Directory.Build.props` already lists the four NuGet audit warnings that are deliberately suppressed, and the prompt forbids adding more. The fix has to remove the warning at its source, and the diff shows any change to that file.

### Which SDK does it use?

The one `global.json` pins, `10.0.302` with `rollForward: latestFeature`, which is what `actions/setup-dotnet` picks up in the workflow. Using a different SDK could hide or invent analyzer warnings, so the agent matches it exactly.

### Does it run the MAUI client tests?

No. `pr-validation.yml` ignores `src/ClientApp` and `tests/ClientApp.UnitTests`, and the MAUI workflow is separate. The agent works on the projects in `eShop.Web.slnf`, which is what the failing job built.

### What if the failure is in the Playwright workflow instead?

The same flow applies: it reads the failed spec from the log, starts the AppHost with `dotnet run --project src/eShop.AppHost/eShop.AppHost.csproj` as `playwright.config.ts` does, runs that spec against `http://localhost:5045`, and fixes the page or the spec with the reason in the pull request.
