# Upgrade Go Dependencies Every Week

Yes. Each week a Rush agent bumps your Go modules, runs go test ./... with your build tags, reverts what breaks and opens one tested pull request.

[Run this on Rush](https://cloud.getrush.ai/run/upgrade-dependencies-weekly/go/), in a Project that has your repository.

## What the agent does

In a Go service like navidrome/navidrome, go.mod declares go 1.27 and about 140 requirements, including github.com/mattn/go-sqlite3 v1.14.52, github.com/Masterminds/squirrel v1.5.4, github.com/onsi/ginkgo/v2 v2.33.0 and github.com/onsi/gomega v1.44.0. It also has a replace directive that points go.senan.xyz/taglib at a fork, github.com/deluan/go-taglib, at a pseudo-version, and a tool block that brings in the ginkgo CLI. The agent runs go list -m -u all to see what has a newer version, skips the replaced module (its version comes from the fork, not the upstream release), and treats the tool dependencies like any other.

The tests need build tags. The Makefile sets GO_BUILD_TAGS=netgo,sqlite_fts5, and the CI job in .github/workflows/pipeline.yml runs go test -shuffle=on -tags netgo,sqlite_fts5 -race over every package except /plugins. go-sqlite3 is cgo, so the sandbox needs a C compiler, and sqlite_fts5 enables full-text search in it. Plain go test ./... without the tags builds a different binary. The agent uses the same tags and the race detector, and also runs the separate module in plugins/cmd/ndpgen, which has its own go.mod and its own go test.

It upgrades one direct dependency at a time with go get <module>@latest, then go mod tidy, and runs the suite. Modules that are released together, such as ginkgo and gomega, or the golang.org/x packages, are moved as a set. Major versions in Go change the import path (a /v2 or /v3 suffix), so a major is a code change across every importing file; the agent only does it when asked, and otherwise moves to the latest version within the current major.

Any module whose upgrade fails the build, go vet or a Ginkgo spec is reverted in go.mod and go.sum, and the failing package and spec name are kept for the pull request. The agent finishes with go mod verify.

## Start it with one API call

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

```json
{
  "agent": "codex",
  "input": "Upgrade this project's Go module dependencies to the latest version within their current major, one direct dependency at a time with go get and go mod tidy. Leave modules covered by a replace directive alone. After each bump run go test -shuffle=on -race -tags netgo,sqlite_fts5 on every package except /plugins, and go test in plugins/cmd/ndpgen. Revert any bump that fails and record the failing package and test. Finish with go mod verify. Open one pull request listing each bump with its old and new version and each skipped upgrade with the error that blocked it.",
  "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

The pull request changes go.mod and go.sum, and plugins/cmd/ndpgen/go.mod and go.sum if that module's dependencies moved. Its description lists every module with its old and new version, notes the replaced module it did not touch, and lists each skipped upgrade with the package and test that failed. The repository's pipeline runs the Go tests on Linux and Windows, the JS tests and the lint on the pull request.

A reviewer checks indirect upgrades that go mod tidy pulled in, reads the changelog for anything that moved a minor version on a security-sensitive path (the HTTP stack, JWT, crypto), and compares the test command in the transcript with what CI ran.

## Run it on every Monday morning

Dependabot here already opens gomod pull requests weekly, up to 10 at a time, each built and tested on its own. Sending this request every Monday instead gives one pull request where every bump has been tested together with the others.

Put a webhook URL on the API key; when the turn ends Rush posts run.completed to it, and the handler can link the pull request in chat or close the week's open Dependabot pull requests it supersedes.

## Why run it on Rush?

A Go upgrade looks simple until cgo and build tags are involved: go-sqlite3 needs a C toolchain, and the tests only build the right binary with netgo and sqlite_fts5 set. In a Rush sandbox the agent sets that toolchain up from scratch, runs the race-enabled suite after each bump, and keeps every go command with its output in the transcript.

One pull request per module means ten red-or-green pull requests to read every week. One run that tests the bumps together and explains the failures is less to review. If you maintain several Go services, each can get its own run in parallel.

## Frequently asked questions

### Will it move a module to a new major version?

Not by default. In Go a major changes the import path, so it touches every file that imports the module. Ask for a specific major in the request and the agent does that rewrite as its own change.

### What happens to replace directives?

The agent leaves replaced modules alone, since their version comes from the replacement. It lists them in the pull request so you know they were not checked.

### Does it use my build tags?

Yes, when you name them or when the Makefile and CI show them. Here that is netgo and sqlite_fts5, and running without them would test a different build.

### Does it update the go directive or the toolchain?

No. The go line in go.mod stays as it is unless a dependency requires a newer Go, in which case the agent says so instead of raising it silently.
