mirror of
https://github.com/tailscale/tailscale.git
synced 2026-09-14 23:11:39 -04:00
Promote the toolchain from Go 1.26.6 to Go 1.27.0, matching what go.toolchain.next.rev has been testing. Besides the toolchain files themselves (updated by pull-toolchain.sh), this bumps the go.mod go directive, the Dockerfile golang base image, and the README, and regenerates the depaware.txt files and the gzip assets in tempfork/spf13/cobra and util/eventbus, whose bytes change with Go 1.27's rewritten compress/flate. Also bump golangci-lint to v2.13.1, the first release line built with Go 1.27; the prebuilt v2.10.1 binary refuses to target a Go version newer than the one it was built with. Also bump golang.org/x/net to v0.58.0 (plus the sibling x/ module upgrades it requires) to pick up upstream commit 8d10596d2624 (http2: avoid deadlocks in wrapped ClientConn state callback), which we hit during Go 1.27 rc testing. Also add docs/go-bump-checklist.md for next time. Updates #20220 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com> Change-Id: Ia3e4c9effafbc91227eed39efb52f1fba1b8d89c
4.9 KiB
4.9 KiB
Go major version bump checklist
Things to update every six months when we move to a new Go major version (e.g. Go 1.NN to Go 1.MM). See the git history of this file and past bump commits (e.g. "go.toolchain.branch: switch to Go 1.26", "go.toolchain.branch: switch to Go 1.27") for worked examples.
Prerequisites
- The
tailscale/gofork has atailscale.goX.YYbranch with our patches rebased onto the new release, and its CI has published a toolchain tarball for that rev. - During the rc period, test the new version via the "next"
toolchain first: update
go.toolchain.next.branchand runTS_GO_NEXT=1 ./pull-toolchain.sh, then let the optionalgo-nextCI jobs find breakage before release day.
Toolchain switch
- Update
go.toolchain.branchto the newtailscale.goX.YYbranch name. - Run
./pull-toolchain.sh. This updates:go.toolchain.rev(andgo.toolchain.next.revif it fell behind)go.toolchain.version- the
godirective ingo.mod flakehashes.json(Nix SRI hashes, viatool/updateflakes)
Version strings elsewhere
Dockerfile:FROM golang:1.NN-alpinein the build stage.README.md: "We always require the latest Go release, currently Go 1.NN"..github/workflows/: grep for hardcoded Go versions. As of Go 1.27 the workflows usego-version-file: go.modand need no changes, but rc-period pins (e.g.actions/setup-gowith an explicit rc version) must be reverted if any were added.
Regenerate derived files
make updatedepsto regenerate alldepaware.txtfiles. The new stdlib usually reshuffles internal dependencies.- Regenerate gzip assets if
compress/flateoutput changed (it did in Go 1.27; thego generatesteps embed compressed bytes and CI checks they are reproducible with the current toolchain):tempfork/spf13/cobra:go generate ./...util/eventbus:go generate ./...Use the new toolchain (./tool/go) onPATHwhen running these.
Things that may need attention
- Lint tools: check that staticcheck and golangci-lint releases
support the new Go version, and bump them in
go.mod/.github/workflows/golangci-lint.ymlif needed (Go 1.26 needed a staticcheck bump). The golangci-lint version pinned in the workflow must be a release built with the new Go version or it fails with "the Go language version (go1.NN) used to build golangci-lint is lower than the targeted Go version"; golangci-lint usually ships such a release within days of the Go release (v2.13.0 for Go 1.27). Verify withgolangci-lint versionand a localgolangci-lint runagainst the repo config before pushing. go.mod/go.sum: run./tool/go mod tidyand eyeball the diff; a new Go version can reorganize the file format or module graph pruning.- New-version breakage in our code or vendored deps: build and
test everything (
./tool/go build ./... && ./tool/go test ./...), including GOOS=darwin,windows,etc. cross-builds, before relying on CI. - The corp repo, Android, iOS, and other downstream repos have their own bumps; this checklist covers only this repo.
Behavior changes that have bitten us
Categories of Go release fallout seen in past bumps (mostly in corp, but the categories generalize); grep for them before blaming the code:
- gofmt output can change; run
gofmt -lacross the tree (and corp) with the new toolchain and reformat (Go 1.27 reformatted two corp files). - encoding/json error strings and UnmarshalTypeError.Field can change. Tests asserting exact error text break, and so can third-party libraries: Go 1.27 reports the full path to the offending value ("errors.deletes.0") where earlier versions reported just the top-level field, which broke dnsimple-go's error-recovery gate (their PR #271).
- Error identity from canceled streaming HTTP requests can change: Go 1.27's http2 surfaces the underlying "use of closed network connection" where Go 1.26 returned the context error. Prefer normalizing to ctx.Err() at the source (see sendMapRequest in control/controlclient) over teaching each test the new string.
- json.Decoder over a reader that gains data after reporting EOF is not guaranteed to see the later writes; Go 1.27 stopped re-polling. Interleaved write-then-decode test helpers should read complete lines instead (corp tslogtest).
- The race detector's cost profile can shift: Go 1.27's race mode made a reflection-heavy corp test several times slower, turning a slow-but-passing 70s test into a 10 minute timeout. Watch race job durations, not just pass/fail.
After the switch
- Send the branch through full CI and fix what falls out; amend this checklist with anything new you discover.
- Once the release is proven, consider a follow-up "use Go 1.NN things" cleanup commit (gofix modernizers, new stdlib APIs), kept separate from the mechanical bump.