all: clean up obsolete +build lines and io/ioutil uses [generated]

The module go directive is at 1.20, so modernize it a bit by
applying changes generated by the script below with go1.21.1.

[git-generate]
go fix ./...
gofmt -r 'ioutil.Discard -> io.Discard' -w .
gofmt -r 'ioutil.NopCloser -> io.NopCloser' -w .
gofmt -r 'ioutil.ReadAll -> io.ReadAll' -w .
gofmt -r '"ioutil.ReadAll: %v" -> "io.ReadAll: %v"' -w .
gofmt -r 'ioutil.ReadDir -> os.ReadDir' -w .
gofmt -r 'ioutil.ReadFile -> os.ReadFile' -w .
gofmt -r 'ioutil.TempDir -> os.MkdirTemp' -w .
gofmt -r 'ioutil.TempFile -> os.CreateTemp' -w .
gofmt -r 'ioutil.WriteFile -> os.WriteFile' -w .
goimports -w .

Change-Id: I145b27756e7c6101e992747ee822e7237df4cb91
Reviewed-on: https://go-review.googlesource.com/c/build/+/527016
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
diff --git a/autocertcache/autocertcache.go b/autocertcache/autocertcache.go
index 2cbce70..1e2881b 100644
--- a/autocertcache/autocertcache.go
+++ b/autocertcache/autocertcache.go
@@ -8,7 +8,7 @@
 
 import (
 	"context"
-	"io/ioutil"
+	"io"
 
 	"cloud.google.com/go/storage"
 	"golang.org/x/crypto/acme/autocert"
@@ -40,7 +40,7 @@
 		return nil, err
 	}
 	defer rd.Close()
-	return ioutil.ReadAll(rd)
+	return io.ReadAll(rd)
 }
 
 func (c *gcsAutocertCache) Put(ctx context.Context, key string, data []byte) error {
diff --git a/buildlet/buildlet.go b/buildlet/buildlet.go
index e9589cd..9065d09 100644
--- a/buildlet/buildlet.go
+++ b/buildlet/buildlet.go
@@ -8,7 +8,7 @@
 	"context"
 	"crypto/tls"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"log"
 	"net/http"
 	"time"
@@ -139,7 +139,7 @@
 	if err != nil {
 		return fmt.Errorf("error probe buildlet %s: %w", buildletURL, err)
 	}
-	ioutil.ReadAll(res.Body)
+	io.ReadAll(res.Body)
 	res.Body.Close()
 	if res.StatusCode != http.StatusOK {
 		return fmt.Errorf("buildlet returned HTTP status code %d for %s", res.StatusCode, buildletURL)
diff --git a/buildlet/buildletclient.go b/buildlet/buildletclient.go
index 8c75a7c..4e6a394 100644
--- a/buildlet/buildletclient.go
+++ b/buildlet/buildletclient.go
@@ -11,7 +11,6 @@
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net"
 	"net/http"
@@ -279,7 +278,7 @@
 		return nil, err
 	}
 	if res.StatusCode != http.StatusSwitchingProtocols {
-		slurp, _ := ioutil.ReadAll(io.LimitReader(res.Body, 4<<10))
+		slurp, _ := io.ReadAll(io.LimitReader(res.Body, 4<<10))
 		res.Body.Close()
 		return nil, fmt.Errorf("wanted 101 Switching Protocols; unexpected response: %v, %q", res.Status, slurp)
 	}
@@ -397,7 +396,7 @@
 	}
 	defer res.Body.Close()
 	if res.StatusCode != http.StatusOK {
-		slurp, _ := ioutil.ReadAll(io.LimitReader(res.Body, 4<<10))
+		slurp, _ := io.ReadAll(io.LimitReader(res.Body, 4<<10))
 		return fmt.Errorf("%v; body: %s", res.Status, slurp)
 	}
 	return nil
@@ -459,7 +458,7 @@
 		return nil, err
 	}
 	if res.StatusCode != http.StatusOK {
-		slurp, _ := ioutil.ReadAll(io.LimitReader(res.Body, 4<<10))
+		slurp, _ := io.ReadAll(io.LimitReader(res.Body, 4<<10))
 		res.Body.Close()
 		return nil, fmt.Errorf("%v; body: %s", res.Status, slurp)
 	}
@@ -574,7 +573,7 @@
 	}
 	defer res.Body.Close()
 	if res.StatusCode != http.StatusOK {
-		slurp, _ := ioutil.ReadAll(io.LimitReader(res.Body, 4<<10))
+		slurp, _ := io.ReadAll(io.LimitReader(res.Body, 4<<10))
 		return nil, fmt.Errorf("buildlet: HTTP status %v: %s", res.Status, slurp)
 	}
 	condRun(opts.OnStartExec)
@@ -587,7 +586,7 @@
 		// Stream the output:
 		out := opts.Output
 		if out == nil {
-			out = ioutil.Discard
+			out = io.Discard
 		}
 		if _, err := io.Copy(out, res.Body); err != nil {
 			resc <- errs{execErr: fmt.Errorf("error copying response: %w", err)}
@@ -673,7 +672,7 @@
 	if resp.StatusCode != http.StatusOK {
 		return Status{}, errors.New(resp.Status)
 	}
-	b, err := ioutil.ReadAll(resp.Body)
+	b, err := io.ReadAll(resp.Body)
 	resp.Body.Close()
 	if err != nil {
 		return Status{}, err
@@ -699,7 +698,7 @@
 	if resp.StatusCode != http.StatusOK {
 		return "", errors.New(resp.Status)
 	}
-	b, err := ioutil.ReadAll(resp.Body)
+	b, err := io.ReadAll(resp.Body)
 	resp.Body.Close()
 	if err != nil {
 		return "", err
@@ -792,7 +791,7 @@
 	}
 	defer resp.Body.Close()
 	if resp.StatusCode != http.StatusOK {
-		slurp, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<10))
+		slurp, _ := io.ReadAll(io.LimitReader(resp.Body, 1<<10))
 		return fmt.Errorf("%s: %s", resp.Status, slurp)
 	}
 	sc := bufio.NewScanner(resp.Body)
@@ -853,7 +852,7 @@
 		return nil, fmt.Errorf("reading /connect-ssh response: %v", err)
 	}
 	if res.StatusCode != http.StatusSwitchingProtocols {
-		slurp, _ := ioutil.ReadAll(res.Body)
+		slurp, _ := io.ReadAll(res.Body)
 		conn.Close()
 		return nil, fmt.Errorf("unexpected /connect-ssh response: %v, %s", res.Status, slurp)
 	}
diff --git a/buildlet/remote.go b/buildlet/remote.go
index 4e97e87..cef9933 100644
--- a/buildlet/remote.go
+++ b/buildlet/remote.go
@@ -11,7 +11,7 @@
 	"errors"
 	"flag"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"log"
 	"net/http"
 	"net/url"
@@ -112,7 +112,7 @@
 	}
 	defer res.Body.Close()
 	if res.StatusCode != 200 {
-		slurp, _ := ioutil.ReadAll(res.Body)
+		slurp, _ := io.ReadAll(res.Body)
 		return nil, fmt.Errorf("%s: %s", res.Status, slurp)
 	}
 
@@ -185,7 +185,7 @@
 	}
 	defer res.Body.Close()
 	if res.StatusCode != 200 {
-		slurp, _ := ioutil.ReadAll(res.Body)
+		slurp, _ := io.ReadAll(res.Body)
 		return nil, fmt.Errorf("%s: %s", res.Status, slurp)
 	}
 	var ret []RemoteBuildlet
@@ -256,7 +256,7 @@
 	}
 	keyDir := configDir()
 	userPath := filepath.Join(keyDir, "user-"+gomoteUserFlag+".user")
-	b, err := ioutil.ReadFile(userPath)
+	b, err := os.ReadFile(userPath)
 	if err == nil {
 		gomoteUserFlag = string(bytes.TrimSpace(b))
 	}
@@ -265,7 +265,7 @@
 		baseFile = "staging-" + baseFile
 	}
 	tokenFile := filepath.Join(keyDir, baseFile)
-	slurp, err := ioutil.ReadFile(tokenFile)
+	slurp, err := os.ReadFile(tokenFile)
 	if os.IsNotExist(err) {
 		return "", fmt.Errorf("Missing file %s for user %q. Change --user or obtain a token and place it there.",
 			tokenFile, gomoteUserFlag)
diff --git a/cmd/buildlet/buildlet.go b/cmd/buildlet/buildlet.go
index c9d5a70..b18e317 100644
--- a/cmd/buildlet/buildlet.go
+++ b/cmd/buildlet/buildlet.go
@@ -25,7 +25,6 @@
 	"fmt"
 	"io"
 	"io/fs"
-	"io/ioutil"
 	"log"
 	"net"
 	"net/http"
@@ -412,7 +411,7 @@
 	v := os.Getenv(envKey)
 	// Respect curl-style '@' prefix to mean the rest is a filename.
 	if strings.HasPrefix(v, "@") {
-		slurp, err := ioutil.ReadFile(v[1:])
+		slurp, err := os.ReadFile(v[1:])
 		if err != nil {
 			log.Fatalf("Error reading file for GCEMETA_%v: %v", key, err)
 		}
@@ -1613,7 +1612,7 @@
 
 func numProcs() int {
 	n := 0
-	fis, _ := ioutil.ReadDir("/proc")
+	fis, _ := os.ReadDir("/proc")
 	for _, fi := range fis {
 		if _, err := strconv.Atoi(fi.Name()); err == nil {
 			n++
@@ -1810,7 +1809,7 @@
 		return err
 	}
 	authFile := filepath.Join(sshDir, "authorized_keys")
-	exist, err := ioutil.ReadFile(authFile)
+	exist, err := os.ReadFile(authFile)
 	if err != nil && !os.IsNotExist(err) {
 		return err
 	}
diff --git a/cmd/buildlet/buildlet_rlimit.go b/cmd/buildlet/buildlet_rlimit.go
index 0afaa93..0e2048e 100644
--- a/cmd/buildlet/buildlet_rlimit.go
+++ b/cmd/buildlet/buildlet_rlimit.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build netbsd || openbsd
-// +build netbsd openbsd
 
 package main
 
diff --git a/cmd/buildlet/buildlet_unix.go b/cmd/buildlet/buildlet_unix.go
index 36769d3..e34182e 100644
--- a/cmd/buildlet/buildlet_unix.go
+++ b/cmd/buildlet/buildlet_unix.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux
-// +build linux
 
 // (We only care about Linux on GKE for now)
 
diff --git a/cmd/buildlet/reverse.go b/cmd/buildlet/reverse.go
index 2b56a10..19b71f0 100644
--- a/cmd/buildlet/reverse.go
+++ b/cmd/buildlet/reverse.go
@@ -13,7 +13,6 @@
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net"
 	"net/http"
@@ -37,7 +36,7 @@
 	if v := os.Getenv("GO_BUILD_KEY_PATH"); v != "" {
 		keyPath = v
 	}
-	key, err := ioutil.ReadFile(keyPath)
+	key, err := os.ReadFile(keyPath)
 	if ok, _ := strconv.ParseBool(os.Getenv("GO_BUILD_KEY_DELETE_AFTER_READ")); ok {
 		os.Remove(keyPath)
 	}
diff --git a/cmd/buildlet/reverse_test.go b/cmd/buildlet/reverse_test.go
index 5a89f06..456c96d 100644
--- a/cmd/buildlet/reverse_test.go
+++ b/cmd/buildlet/reverse_test.go
@@ -4,7 +4,6 @@
 
 // Same requirements as internal/coordinator/pool/reverse.go.
 //go:build linux || darwin
-// +build linux darwin
 
 package main
 
diff --git a/cmd/buildlet/testssh/testssh.go b/cmd/buildlet/testssh/testssh.go
index 7a75760..9b24e79 100644
--- a/cmd/buildlet/testssh/testssh.go
+++ b/cmd/buildlet/testssh/testssh.go
@@ -12,7 +12,6 @@
 	"flag"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net"
 	"os"
@@ -129,7 +128,7 @@
 			log.Fatalf("ssh-keygen: %v, %s", err, out)
 		}
 	}
-	slurp, err := ioutil.ReadFile(pubKeyPath)
+	slurp, err := os.ReadFile(pubKeyPath)
 	if err != nil {
 		log.Fatal(err)
 	}
diff --git a/cmd/coordinator/builders.go b/cmd/coordinator/builders.go
index 520ef04..16f6dfd 100644
--- a/cmd/coordinator/builders.go
+++ b/cmd/coordinator/builders.go
@@ -3,8 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16 && (linux || darwin)
-// +build go1.16
-// +build linux darwin
 
 package main
 
diff --git a/cmd/coordinator/builders_test.go b/cmd/coordinator/builders_test.go
index 6e51117..03ca12e 100644
--- a/cmd/coordinator/builders_test.go
+++ b/cmd/coordinator/builders_test.go
@@ -3,8 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16 && (linux || darwin)
-// +build go1.16
-// +build linux darwin
 
 package main
 
diff --git a/cmd/coordinator/buildstatus.go b/cmd/coordinator/buildstatus.go
index aeb84c2..8cb1d82 100644
--- a/cmd/coordinator/buildstatus.go
+++ b/cmd/coordinator/buildstatus.go
@@ -3,8 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16 && (linux || darwin)
-// +build go1.16
-// +build linux darwin
 
 package main
 
diff --git a/cmd/coordinator/buildstatus_test.go b/cmd/coordinator/buildstatus_test.go
index d4a7cfc..814a34a 100644
--- a/cmd/coordinator/buildstatus_test.go
+++ b/cmd/coordinator/buildstatus_test.go
@@ -3,8 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16 && (linux || darwin)
-// +build go1.16
-// +build linux darwin
 
 package main
 
diff --git a/cmd/coordinator/coordinator.go b/cmd/coordinator/coordinator.go
index 847b17e..5c1865f 100644
--- a/cmd/coordinator/coordinator.go
+++ b/cmd/coordinator/coordinator.go
@@ -3,8 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16 && (linux || darwin)
-// +build go1.16
-// +build linux darwin
 
 // The coordinator runs the majority of the Go build system.
 //
@@ -27,7 +25,6 @@
 	"fmt"
 	"html"
 	"io"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"net/url"
@@ -2013,7 +2010,7 @@
 			io.Closer
 		}{
 			os.Stderr,
-			ioutil.NopCloser(nil),
+			io.NopCloser(nil),
 		}, "devmode://build-log/" + objName
 	}
 	if pool.NewGCEConfiguration().StorageClient() == nil {
diff --git a/cmd/coordinator/coordinator_test.go b/cmd/coordinator/coordinator_test.go
index 038ac42..9d58133 100644
--- a/cmd/coordinator/coordinator_test.go
+++ b/cmd/coordinator/coordinator_test.go
@@ -3,14 +3,12 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16 && (linux || darwin)
-// +build go1.16
-// +build linux darwin
 
 package main
 
 import (
 	"bytes"
-	"io/ioutil"
+	"io"
 	"log"
 	"net/http"
 	"net/http/httptest"
@@ -138,9 +136,9 @@
 				t.Errorf("response status code: got %d; want %d", got, want)
 			}
 			defer resp.Body.Close()
-			b, err := ioutil.ReadAll(resp.Body)
+			b, err := io.ReadAll(resp.Body)
 			if err != nil {
-				t.Fatalf("ioutil.ReadAll: %v", err)
+				t.Fatalf("io.ReadAll: %v", err)
 			}
 			if got, want := string(b), tc.body; got != want {
 				t.Errorf("body: got\n%v\nwant\n%v", got, want)
diff --git a/cmd/coordinator/dash.go b/cmd/coordinator/dash.go
index f82dd41..7d5f336 100644
--- a/cmd/coordinator/dash.go
+++ b/cmd/coordinator/dash.go
@@ -3,8 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16 && (linux || darwin)
-// +build go1.16
-// +build linux darwin
 
 // Code interacting with build.golang.org ("the dashboard").
 
@@ -19,10 +17,10 @@
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"net/url"
+	"os"
 	"strings"
 	"sync"
 	"time"
@@ -163,7 +161,7 @@
 
 func loadKey(sc *secret.Client) {
 	if *masterKeyFile != "" {
-		b, err := ioutil.ReadFile(*masterKeyFile)
+		b, err := os.ReadFile(*masterKeyFile)
 		if err != nil {
 			log.Fatal(err)
 		}
diff --git a/cmd/coordinator/debug.go b/cmd/coordinator/debug.go
index 1113991..1b00f10 100644
--- a/cmd/coordinator/debug.go
+++ b/cmd/coordinator/debug.go
@@ -3,8 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16 && (linux || darwin)
-// +build go1.16
-// +build linux darwin
 
 package main
 
diff --git a/cmd/coordinator/internal/dashboard/datastore.go b/cmd/coordinator/internal/dashboard/datastore.go
index ac43d15..d4c2dd6 100644
--- a/cmd/coordinator/internal/dashboard/datastore.go
+++ b/cmd/coordinator/internal/dashboard/datastore.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package dashboard
 
diff --git a/cmd/coordinator/internal/dashboard/datastore_test.go b/cmd/coordinator/internal/dashboard/datastore_test.go
index 802252b..6ac23a2 100644
--- a/cmd/coordinator/internal/dashboard/datastore_test.go
+++ b/cmd/coordinator/internal/dashboard/datastore_test.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package dashboard
 
diff --git a/cmd/coordinator/internal/dashboard/handler.go b/cmd/coordinator/internal/dashboard/handler.go
index ca37f9d..0e29f31 100644
--- a/cmd/coordinator/internal/dashboard/handler.go
+++ b/cmd/coordinator/internal/dashboard/handler.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 // Package dashboard contains the implementation of the build dashboard for the Coordinator.
 package dashboard
diff --git a/cmd/coordinator/internal/dashboard/handler_test.go b/cmd/coordinator/internal/dashboard/handler_test.go
index bfde2a3..971d475 100644
--- a/cmd/coordinator/internal/dashboard/handler_test.go
+++ b/cmd/coordinator/internal/dashboard/handler_test.go
@@ -3,13 +3,12 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux
-// +build linux
 
 package dashboard
 
 import (
 	"context"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"net/http/httptest"
 	"testing"
@@ -54,7 +53,7 @@
 	dh.ServeHTTP(w, req)
 	resp := w.Result()
 	defer resp.Body.Close()
-	ioutil.ReadAll(resp.Body)
+	io.ReadAll(resp.Body)
 
 	if resp.StatusCode != http.StatusOK {
 		t.Errorf("resp.StatusCode = %d, wanted %d", resp.StatusCode, http.StatusOK)
diff --git a/cmd/coordinator/internal/legacydash/build.go b/cmd/coordinator/internal/legacydash/build.go
index 76bbd36..f199bf3 100644
--- a/cmd/coordinator/internal/legacydash/build.go
+++ b/cmd/coordinator/internal/legacydash/build.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16
-// +build go1.16
 
 package legacydash
 
@@ -14,7 +13,6 @@
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"math/rand"
 	pathpkg "path"
 	"strings"
@@ -444,7 +442,7 @@
 	if err != nil {
 		return nil, fmt.Errorf("reading log data: %v", err)
 	}
-	b, err := ioutil.ReadAll(d)
+	b, err := io.ReadAll(d)
 	if err != nil {
 		return nil, fmt.Errorf("reading log data: %v", err)
 	}
diff --git a/cmd/coordinator/internal/legacydash/dash.go b/cmd/coordinator/internal/legacydash/dash.go
index c4e9a01..f1478c3 100644
--- a/cmd/coordinator/internal/legacydash/dash.go
+++ b/cmd/coordinator/internal/legacydash/dash.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16
-// +build go1.16
 
 // Package legacydash holds the serving code for the build dashboard
 // (build.golang.org) and its remaining HTTP API endpoints.
diff --git a/cmd/coordinator/internal/legacydash/handler.go b/cmd/coordinator/internal/legacydash/handler.go
index b6c9a2b..84ff6a1 100644
--- a/cmd/coordinator/internal/legacydash/handler.go
+++ b/cmd/coordinator/internal/legacydash/handler.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16
-// +build go1.16
 
 package legacydash
 
diff --git a/cmd/coordinator/internal/legacydash/ui.go b/cmd/coordinator/internal/legacydash/ui.go
index ba9c3bd..9b4abd6 100644
--- a/cmd/coordinator/internal/legacydash/ui.go
+++ b/cmd/coordinator/internal/legacydash/ui.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16
-// +build go1.16
 
 package legacydash
 
diff --git a/cmd/coordinator/internal/legacydash/ui_test.go b/cmd/coordinator/internal/legacydash/ui_test.go
index 4b76c54..c9e7256 100644
--- a/cmd/coordinator/internal/legacydash/ui_test.go
+++ b/cmd/coordinator/internal/legacydash/ui_test.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16
-// +build go1.16
 
 package legacydash
 
diff --git a/cmd/coordinator/metrics.go b/cmd/coordinator/metrics.go
index d3a1a26..2b5ceec 100644
--- a/cmd/coordinator/metrics.go
+++ b/cmd/coordinator/metrics.go
@@ -3,8 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16 && (linux || darwin)
-// +build go1.16
-// +build linux darwin
 
 package main
 
diff --git a/cmd/coordinator/modproxy.go b/cmd/coordinator/modproxy.go
index 28a8b0b..88f0530 100644
--- a/cmd/coordinator/modproxy.go
+++ b/cmd/coordinator/modproxy.go
@@ -3,8 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16 && (linux || darwin)
-// +build go1.16
-// +build linux darwin
 
 package main
 
diff --git a/cmd/coordinator/modproxy_test.go b/cmd/coordinator/modproxy_test.go
index 6110fd4..e05640b 100644
--- a/cmd/coordinator/modproxy_test.go
+++ b/cmd/coordinator/modproxy_test.go
@@ -3,8 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16 && (linux || darwin)
-// +build go1.16
-// +build linux darwin
 
 package main
 
diff --git a/cmd/coordinator/protos/coordinator.pb.go b/cmd/coordinator/protos/coordinator.pb.go
index 29f99e2..d90b759 100644
--- a/cmd/coordinator/protos/coordinator.pb.go
+++ b/cmd/coordinator/protos/coordinator.pb.go
@@ -6,11 +6,12 @@
 import (
 	context "context"
 	fmt "fmt"
+	math "math"
+
 	proto "github.com/golang/protobuf/proto"
 	grpc "google.golang.org/grpc"
 	codes "google.golang.org/grpc/codes"
 	status "google.golang.org/grpc/status"
-	math "math"
 )
 
 // Reference imports to suppress errors if they are not otherwise used.
diff --git a/cmd/coordinator/queues.go b/cmd/coordinator/queues.go
index 4e44eab..850f462 100644
--- a/cmd/coordinator/queues.go
+++ b/cmd/coordinator/queues.go
@@ -3,8 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16 && (linux || darwin)
-// +build go1.16
-// +build linux darwin
 
 package main
 
diff --git a/cmd/coordinator/queues_test.go b/cmd/coordinator/queues_test.go
index 076ad94..72d32e2 100644
--- a/cmd/coordinator/queues_test.go
+++ b/cmd/coordinator/queues_test.go
@@ -3,8 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16 && (linux || darwin)
-// +build go1.16
-// +build linux darwin
 
 package main
 
diff --git a/cmd/coordinator/results.go b/cmd/coordinator/results.go
index 5512089..66a77d7 100644
--- a/cmd/coordinator/results.go
+++ b/cmd/coordinator/results.go
@@ -3,8 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16 && (linux || darwin)
-// +build go1.16
-// +build linux darwin
 
 // Code related to the Build Results API.
 
@@ -13,7 +11,7 @@
 import (
 	"context"
 	"encoding/json"
-	"io/ioutil"
+	"io"
 	"log"
 	"net/http"
 	"net/url"
@@ -77,7 +75,7 @@
 		log.Printf("gRPCServer.ClearResults: error performing wipe for %q/%q: %v", builder, hash, err)
 		return grpcstatus.Error(codes.Internal, codes.Internal.String())
 	}
-	body, err := ioutil.ReadAll(resp.Body)
+	body, err := io.ReadAll(resp.Body)
 	resp.Body.Close()
 	if err != nil {
 		log.Printf("gRPCServer.ClearResults: error reading response body for %q/%q: %v", builder, hash, err)
diff --git a/cmd/coordinator/results_test.go b/cmd/coordinator/results_test.go
index 372d5bf..2a2ea95 100644
--- a/cmd/coordinator/results_test.go
+++ b/cmd/coordinator/results_test.go
@@ -3,8 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16 && (linux || darwin)
-// +build go1.16
-// +build linux darwin
 
 package main
 
diff --git a/cmd/coordinator/status.go b/cmd/coordinator/status.go
index f52a09a..c81b5a2 100644
--- a/cmd/coordinator/status.go
+++ b/cmd/coordinator/status.go
@@ -3,8 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16 && (linux || darwin)
-// +build go1.16
-// +build linux darwin
 
 package main
 
diff --git a/cmd/coordinator/status_test.go b/cmd/coordinator/status_test.go
index ee46e0a..4ccd665 100644
--- a/cmd/coordinator/status_test.go
+++ b/cmd/coordinator/status_test.go
@@ -3,8 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16 && (linux || darwin)
-// +build go1.16
-// +build linux darwin
 
 package main
 
diff --git a/cmd/coordinator/trybot_dev.go b/cmd/coordinator/trybot_dev.go
index e3a20db..86e1dc6 100644
--- a/cmd/coordinator/trybot_dev.go
+++ b/cmd/coordinator/trybot_dev.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package main
 
diff --git a/cmd/docker2boot/docker2boot.go b/cmd/docker2boot/docker2boot.go
index 72e133a..a819475 100644
--- a/cmd/docker2boot/docker2boot.go
+++ b/cmd/docker2boot/docker2boot.go
@@ -10,7 +10,6 @@
 	"flag"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"os"
@@ -62,7 +61,7 @@
 
 	checkDeps()
 
-	mntDir, err := ioutil.TempDir("", "docker2boot")
+	mntDir, err := os.MkdirTemp("", "docker2boot")
 	if err != nil {
 		failf("Failed to create mount temp dir: %v", err)
 	}
@@ -152,7 +151,7 @@
 	writeFile(filepath.Join(mntDir, "etc", "resolv.conf"), "nameserver 8.8.8.8\n")
 
 	// Append the source image id & docker version to /etc/issue.
-	issue, err := ioutil.ReadFile("/etc/issue")
+	issue, err := os.ReadFile("/etc/issue")
 	if err != nil && !os.IsNotExist(err) {
 		failf("Failed to read /etc/issue: %v", err)
 	}
@@ -252,7 +251,7 @@
 }
 
 func slurpFile(file string) string {
-	v, err := ioutil.ReadFile(file)
+	v, err := os.ReadFile(file)
 	if err != nil {
 		failf("Failed to read %s: %v", file, err)
 	}
@@ -260,7 +259,7 @@
 }
 
 func writeFile(file, contents string) {
-	if err := ioutil.WriteFile(file, []byte(contents), 0644); err != nil {
+	if err := os.WriteFile(file, []byte(contents), 0644); err != nil {
 		failf("writeFile %s: %v", file, err)
 	}
 }
diff --git a/cmd/genbuilderkey/genbuilderkey.go b/cmd/genbuilderkey/genbuilderkey.go
index 8d7d710..ef2fb07 100644
--- a/cmd/genbuilderkey/genbuilderkey.go
+++ b/cmd/genbuilderkey/genbuilderkey.go
@@ -14,7 +14,6 @@
 	"flag"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"os"
 	"path/filepath"
@@ -57,7 +56,7 @@
 	if err == nil {
 		return []byte(strings.TrimSpace(v))
 	}
-	key, err := ioutil.ReadFile(filepath.Join(os.Getenv("HOME"), "keys/gobuilder-master.key"))
+	key, err := os.ReadFile(filepath.Join(os.Getenv("HOME"), "keys/gobuilder-master.key"))
 	if err == nil {
 		return bytes.TrimSpace(key)
 	}
diff --git a/cmd/gerritbot/gerritbot.go b/cmd/gerritbot/gerritbot.go
index 730ab68..eb5b401 100644
--- a/cmd/gerritbot/gerritbot.go
+++ b/cmd/gerritbot/gerritbot.go
@@ -12,7 +12,6 @@
 	"crypto/sha1"
 	"flag"
 	"fmt"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"net/url"
@@ -110,7 +109,7 @@
 	if err != nil {
 		return fmt.Errorf("secret.Retrieve(ctx, %q): %q, %w", secret.NameGerritbotGitCookies, cookies, err)
 	}
-	return ioutil.WriteFile(*gitcookiesFile, []byte(cookies), 0600)
+	return os.WriteFile(*gitcookiesFile, []byte(cookies), 0600)
 }
 
 func githubClient(sc *secret.Client) (*github.Client, error) {
@@ -144,7 +143,7 @@
 			return token, nil
 		}
 	}
-	slurp, err := ioutil.ReadFile(*githubTokenFile)
+	slurp, err := os.ReadFile(*githubTokenFile)
 	if err != nil {
 		return "", err
 	}
@@ -176,7 +175,7 @@
 		}
 	}
 	if len(slurp) == 0 {
-		slurpBytes, err := ioutil.ReadFile(*gerritTokenFile)
+		slurpBytes, err := os.ReadFile(*gerritTokenFile)
 		if err != nil {
 			return "", "", err
 		}
diff --git a/cmd/gitmirror/gitmirror.go b/cmd/gitmirror/gitmirror.go
index ad0978b..715d2f0 100644
--- a/cmd/gitmirror/gitmirror.go
+++ b/cmd/gitmirror/gitmirror.go
@@ -14,7 +14,6 @@
 	"errors"
 	"flag"
 	"fmt"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"os"
@@ -68,7 +67,7 @@
 	if err != nil {
 		log.Fatalf("creating cache dir: %v", err)
 	}
-	credsDir, err := ioutil.TempDir("", "gitmirror-credentials")
+	credsDir, err := os.MkdirTemp("", "gitmirror-credentials")
 	if err != nil {
 		log.Fatalf("creating credentials dir: %v", err)
 	}
@@ -136,7 +135,7 @@
 			return fmt.Errorf("reading github key from secret manager: %v", err)
 		}
 		privKeyPath := filepath.Join(home, secret.NameGitHubSSHKey)
-		if err := ioutil.WriteFile(privKeyPath, []byte(privKey+"\n"), 0600); err != nil {
+		if err := os.WriteFile(privKeyPath, []byte(privKey+"\n"), 0600); err != nil {
 			return err
 		}
 		fmt.Fprintf(sshConfig, "Host github.com\n  IdentityFile %v\n", privKeyPath)
@@ -147,10 +146,10 @@
 		fmt.Fprintf(gitConfig, "[credential \"https://source.developers.google.com\"]\n  helper=gcloud.sh\n")
 	}
 
-	if err := ioutil.WriteFile(filepath.Join(home, ".gitconfig"), gitConfig.Bytes(), 0600); err != nil {
+	if err := os.WriteFile(filepath.Join(home, ".gitconfig"), gitConfig.Bytes(), 0600); err != nil {
 		return err
 	}
-	if err := ioutil.WriteFile(sshConfigPath, sshConfig.Bytes(), 0600); err != nil {
+	if err := os.WriteFile(sshConfigPath, sshConfig.Bytes(), 0600); err != nil {
 		return err
 	}
 
@@ -159,7 +158,7 @@
 
 func retrieveSecret(ctx context.Context, name string) (string, error) {
 	if *flagSecretsDir != "" {
-		secret, err := ioutil.ReadFile(filepath.Join(*flagSecretsDir, name))
+		secret, err := os.ReadFile(filepath.Join(*flagSecretsDir, name))
 		return string(secret), err
 	}
 	sc := secret.MustNewClient()
@@ -169,7 +168,7 @@
 
 func createCacheDir() (string, error) {
 	if *flagCacheDir == "" {
-		dir, err := ioutil.TempDir("", "gitmirror")
+		dir, err := os.MkdirTemp("", "gitmirror")
 		if err != nil {
 			log.Fatal(err)
 		}
@@ -467,7 +466,7 @@
 	remote := "URL: " + url + "\n" +
 		"Push: +refs/heads/*:refs/heads/*\n" +
 		"Push: +refs/tags/*:refs/tags/*\n"
-	return ioutil.WriteFile(filepath.Join(r.root, "remotes", name), []byte(remote), 0777)
+	return os.WriteFile(filepath.Join(r.root, "remotes", name), []byte(remote), 0777)
 }
 
 // loop continuously runs "git fetch" in the repo, checks for new
diff --git a/cmd/gitmirror/gitmirror_test.go b/cmd/gitmirror/gitmirror_test.go
index 17a8efa..de105ca 100644
--- a/cmd/gitmirror/gitmirror_test.go
+++ b/cmd/gitmirror/gitmirror_test.go
@@ -6,7 +6,7 @@
 
 import (
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"net/http/httptest"
 	"os"
@@ -195,7 +195,7 @@
 
 func (tm *testMirror) commit(content string) {
 	tm.t.Helper()
-	if err := ioutil.WriteFile(filepath.Join(tm.gerrit, "README"), []byte(content), 0777); err != nil {
+	if err := os.WriteFile(filepath.Join(tm.gerrit, "README"), []byte(content), 0777); err != nil {
 		tm.t.Fatal(err)
 	}
 	tm.git(tm.gerrit, "add", ".")
@@ -219,7 +219,7 @@
 	if err != nil {
 		tm.t.Fatal(err)
 	}
-	body, err := ioutil.ReadAll(resp.Body)
+	body, err := io.ReadAll(resp.Body)
 	resp.Body.Close()
 	if err != nil {
 		tm.t.Fatal(err)
diff --git a/cmd/gomote/ssh.go b/cmd/gomote/ssh.go
index 85487f8..cb49f93 100644
--- a/cmd/gomote/ssh.go
+++ b/cmd/gomote/ssh.go
@@ -9,7 +9,6 @@
 	"errors"
 	"flag"
 	"fmt"
-	"io/ioutil"
 	"log"
 	"os"
 	"os/exec"
@@ -102,7 +101,7 @@
 	if err := os.MkdirAll(tmpDir, 0700); err != nil {
 		return "", fmt.Errorf("unable to create temp directory for certficates: %w", err)
 	}
-	tf, err := ioutil.TempFile(tmpDir, "id_ed25519-*-cert.pub")
+	tf, err := os.CreateTemp(tmpDir, "id_ed25519-*-cert.pub")
 	if err != nil {
 		return "", err
 	}
diff --git a/cmd/gopherbot/gopherbot.go b/cmd/gopherbot/gopherbot.go
index c292e9e..4a2e68c 100644
--- a/cmd/gopherbot/gopherbot.go
+++ b/cmd/gopherbot/gopherbot.go
@@ -15,7 +15,6 @@
 	"errors"
 	"flag"
 	"fmt"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"os"
@@ -123,7 +122,7 @@
 			return token, nil
 		}
 	}
-	slurp, err := ioutil.ReadFile(*githubTokenFile)
+	slurp, err := os.ReadFile(*githubTokenFile)
 	if err != nil {
 		return "", err
 	}
@@ -147,7 +146,7 @@
 	}
 
 	var slurpBytes []byte
-	slurpBytes, err = ioutil.ReadFile(*gerritTokenFile)
+	slurpBytes, err = os.ReadFile(*gerritTokenFile)
 	if err != nil {
 		return "", "", err
 	}
diff --git a/cmd/greplogs/main.go b/cmd/greplogs/main.go
index bf9cad9..edbddd4 100644
--- a/cmd/greplogs/main.go
+++ b/cmd/greplogs/main.go
@@ -19,7 +19,6 @@
 import (
 	"flag"
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"regexp"
@@ -141,7 +140,7 @@
 	var stripDir string
 	if *flagDashboard {
 		revDir := filepath.Join(xdgCacheDir(), "fetchlogs", "rev")
-		fis, err := ioutil.ReadDir(revDir)
+		fis, err := os.ReadDir(revDir)
 		if err != nil {
 			fmt.Fprintf(os.Stderr, "%s: %s\n", revDir, err)
 			os.Exit(1)
@@ -235,7 +234,7 @@
 	}
 
 	// TODO: Use streaming if possible.
-	data, err := ioutil.ReadFile(path)
+	data, err := os.ReadFile(path)
 	if err != nil {
 		return false, err
 	}
diff --git a/cmd/pubsubhelper/github.go b/cmd/pubsubhelper/github.go
index d2144da..66c467a 100644
--- a/cmd/pubsubhelper/github.go
+++ b/cmd/pubsubhelper/github.go
@@ -12,7 +12,7 @@
 	"encoding/json"
 	"fmt"
 	"hash"
-	"io/ioutil"
+	"io"
 	"log"
 	"net/http"
 	"strings"
@@ -96,7 +96,7 @@
 		return nil, err
 	}
 
-	body, err = ioutil.ReadAll(http.MaxBytesReader(w, r.Body, 5<<20))
+	body, err = io.ReadAll(http.MaxBytesReader(w, r.Body, 5<<20))
 	if err != nil {
 		return nil, err
 	}
diff --git a/cmd/racebuild/racebuild.go b/cmd/racebuild/racebuild.go
index 499f8b7..728459e 100644
--- a/cmd/racebuild/racebuild.go
+++ b/cmd/racebuild/racebuild.go
@@ -16,7 +16,6 @@
 	"flag"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"os"
 	"os/exec"
@@ -491,7 +490,7 @@
 	}
 
 	// Execute the script.
-	script, err := ioutil.TempFile("", "racebuild")
+	script, err := os.CreateTemp("", "racebuild")
 	if err != nil {
 		return fmt.Errorf("failed to create temp file: %v", err)
 	}
@@ -572,7 +571,7 @@
 	defer readmeMu.Unlock()
 
 	readmeFile := filepath.Join(*flagGoroot, "src", "runtime", "race", "README")
-	readme, err := ioutil.ReadFile(readmeFile)
+	readme, err := os.ReadFile(readmeFile)
 	if err != nil {
 		log.Fatalf("bad -goroot? %v", err)
 	}
@@ -597,7 +596,7 @@
 		readme = append(append(readme, []byte(updatedLine)...), '\n')
 	}
 
-	return ioutil.WriteFile(readmeFile, readme, 0640)
+	return os.WriteFile(readmeFile, readme, 0640)
 }
 
 func (p *Platform) Gomote(ctx context.Context, args ...string) ([]byte, error) {
diff --git a/cmd/relui/main.go b/cmd/relui/main.go
index 2051571..4db3bcb 100644
--- a/cmd/relui/main.go
+++ b/cmd/relui/main.go
@@ -14,7 +14,6 @@
 	"flag"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"math/rand"
 	"net/http"
@@ -319,7 +318,7 @@
 	}
 	defer resp.Body.Close()
 	if resp.StatusCode != http.StatusOK {
-		b, _ := ioutil.ReadAll(resp.Body)
+		b, _ := io.ReadAll(resp.Body)
 		return fmt.Errorf("upload failed to %q: %v\n%s", uploadURL, resp.Status, b)
 	}
 	return nil
diff --git a/cmd/retrybuilds/retrybuilds.go b/cmd/retrybuilds/retrybuilds.go
index e6e632a..12d6f7f 100644
--- a/cmd/retrybuilds/retrybuilds.go
+++ b/cmd/retrybuilds/retrybuilds.go
@@ -24,7 +24,7 @@
 	"encoding/json"
 	"flag"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"log"
 	"net/http"
 	"net/url"
@@ -147,7 +147,7 @@
 			if err != nil {
 				log.Fatalf("Error fetching %s: %v", f.LogURL, err)
 			}
-			failLog, err := ioutil.ReadAll(res.Body)
+			failLog, err := io.ReadAll(res.Body)
 			res.Body.Close()
 			if err != nil {
 				log.Fatalf("Error reading %s: %v", f.LogURL, err)
@@ -290,7 +290,7 @@
 		if err != nil {
 			log.Fatal(err)
 		}
-		body, err := ioutil.ReadAll(res.Body)
+		body, err := io.ReadAll(res.Body)
 		res.Body.Close()
 		if err != nil {
 			log.Fatal(err)
@@ -327,7 +327,7 @@
 	if *keyFile == "" {
 		log.Fatalf("No --key specified for builder %s", builder)
 	}
-	slurp, err := ioutil.ReadFile(*keyFile)
+	slurp, err := os.ReadFile(*keyFile)
 	if err != nil {
 		log.Fatalf("Error reading builder key %s: %v", builder, err)
 	}
@@ -337,7 +337,7 @@
 func builderKeyFromMaster(builder string) (key string, ok bool) {
 	masterKey, err := getMasterKeyFromSecretManager()
 	if err != nil {
-		slurp, err := ioutil.ReadFile(*masterKeyFile)
+		slurp, err := os.ReadFile(*masterKeyFile)
 		if err != nil {
 			return "", false
 		}
@@ -380,7 +380,7 @@
 	if err != nil {
 		log.Fatal(err)
 	}
-	slurp, err := ioutil.ReadAll(res.Body)
+	slurp, err := io.ReadAll(res.Body)
 	res.Body.Close()
 	if err != nil {
 		log.Fatal(err)
diff --git a/cmd/rundockerbuildlet/rundockerbuildlet.go b/cmd/rundockerbuildlet/rundockerbuildlet.go
index dcc4517..05a3a94 100644
--- a/cmd/rundockerbuildlet/rundockerbuildlet.go
+++ b/cmd/rundockerbuildlet/rundockerbuildlet.go
@@ -14,7 +14,6 @@
 	"encoding/json"
 	"flag"
 	"fmt"
-	"io/ioutil"
 	"log"
 	"os"
 	"os/exec"
@@ -105,7 +104,7 @@
 }
 
 func getBuildKey() []byte {
-	key, err := ioutil.ReadFile(*keyFile)
+	key, err := os.ReadFile(*keyFile)
 	if err != nil {
 		log.Fatalf("error reading build key from --key=%s: %v", *keyFile, err)
 	}
@@ -187,7 +186,7 @@
 		if err := os.MkdirAll(filepath.Dir(keyFile), 0700); err != nil {
 			return err
 		}
-		if err := ioutil.WriteFile(keyFile, buildKey, 0600); err != nil {
+		if err := os.WriteFile(keyFile, buildKey, 0600); err != nil {
 			return err
 		}
 		cmd := exec.Command("docker", "run",
diff --git a/cmd/runqemubuildlet/darwin.go b/cmd/runqemubuildlet/darwin.go
index 18ba7d5..bf6aff4 100644
--- a/cmd/runqemubuildlet/darwin.go
+++ b/cmd/runqemubuildlet/darwin.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16
-// +build go1.16
 
 package main
 
diff --git a/cmd/runqemubuildlet/heartbeat.go b/cmd/runqemubuildlet/heartbeat.go
index 8aed2d8..a5be6da 100644
--- a/cmd/runqemubuildlet/heartbeat.go
+++ b/cmd/runqemubuildlet/heartbeat.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16
-// +build go1.16
 
 package main
 
diff --git a/cmd/runqemubuildlet/heartbeat_test.go b/cmd/runqemubuildlet/heartbeat_test.go
index c69bc04..6481ba7 100644
--- a/cmd/runqemubuildlet/heartbeat_test.go
+++ b/cmd/runqemubuildlet/heartbeat_test.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16
-// +build go1.16
 
 package main
 
diff --git a/cmd/runqemubuildlet/main.go b/cmd/runqemubuildlet/main.go
index f254958..f250a23 100644
--- a/cmd/runqemubuildlet/main.go
+++ b/cmd/runqemubuildlet/main.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16
-// +build go1.16
 
 // Binary runqemubuildlet runs a single VM-based buildlet in a loop.
 package main
diff --git a/cmd/runqemubuildlet/windows.go b/cmd/runqemubuildlet/windows.go
index 0ee88eb..7f877b2 100644
--- a/cmd/runqemubuildlet/windows.go
+++ b/cmd/runqemubuildlet/windows.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16
-// +build go1.16
 
 package main
 
diff --git a/gerrit/auth.go b/gerrit/auth.go
index 7afad05..16bc97f 100644
--- a/gerrit/auth.go
+++ b/gerrit/auth.go
@@ -9,7 +9,6 @@
 	"crypto/md5"
 	"encoding/hex"
 	"fmt"
-	"io/ioutil"
 	"net/http"
 	"net/http/cookiejar"
 	"net/url"
@@ -102,7 +101,7 @@
 	// got so long that old versions of curl couldn't handle them.
 	host := url.Host
 	netrc := netrcPath()
-	data, _ := ioutil.ReadFile(netrc)
+	data, _ := os.ReadFile(netrc)
 	for _, line := range strings.Split(string(data), "\n") {
 		if i := strings.Index(line, "#"); i >= 0 {
 			line = line[:i]
@@ -125,7 +124,7 @@
 }
 
 func (a *gitCookieFileAuth) loadCookieFileOnce() {
-	data, err := ioutil.ReadFile(a.file)
+	data, err := os.ReadFile(a.file)
 	if err != nil {
 		a.err = fmt.Errorf("Error loading cookie file: %v", err)
 		return
diff --git a/gerrit/demo.go b/gerrit/demo.go
index 328d89a..a2c73e7 100644
--- a/gerrit/demo.go
+++ b/gerrit/demo.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build ignore
-// +build ignore
 
 // The demo command shows and tests usage of the gerrit package.
 package main
@@ -11,7 +10,6 @@
 import (
 	"context"
 	"encoding/json"
-	"io/ioutil"
 	"log"
 	"os"
 	"path/filepath"
@@ -22,7 +20,7 @@
 )
 
 func main() {
-	gobotPass, err := ioutil.ReadFile(filepath.Join(os.Getenv("HOME"), "keys", "gobot-golang-org.cookie"))
+	gobotPass, err := os.ReadFile(filepath.Join(os.Getenv("HOME"), "keys", "gobot-golang-org.cookie"))
 	if err != nil {
 		log.Fatal(err)
 	}
diff --git a/influx/main.go b/influx/main.go
index 14712a9..f676843 100644
--- a/influx/main.go
+++ b/influx/main.go
@@ -25,7 +25,7 @@
 
 	"cloud.google.com/go/compute/metadata"
 	secretmanager "cloud.google.com/go/secretmanager/apiv1"
-	"github.com/influxdata/influxdb-client-go/v2"
+	influxdb2 "github.com/influxdata/influxdb-client-go/v2"
 	"github.com/influxdata/influxdb-client-go/v2/domain"
 	"golang.org/x/build/internal/https"
 	"golang.org/x/build/internal/influx"
diff --git a/internal/coordinator/pool/ec2.go b/internal/coordinator/pool/ec2.go
index 0c57a56..cb6e546 100644
--- a/internal/coordinator/pool/ec2.go
+++ b/internal/coordinator/pool/ec2.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package pool
 
diff --git a/internal/coordinator/pool/ec2_test.go b/internal/coordinator/pool/ec2_test.go
index 35065c0..313687c 100644
--- a/internal/coordinator/pool/ec2_test.go
+++ b/internal/coordinator/pool/ec2_test.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package pool
 
diff --git a/internal/coordinator/pool/gce.go b/internal/coordinator/pool/gce.go
index 2f3c8fd..edd266c 100644
--- a/internal/coordinator/pool/gce.go
+++ b/internal/coordinator/pool/gce.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 // Code interacting with Google Compute Engine (GCE) and
 // a GCE implementation of the BuildletPool interface.
diff --git a/internal/coordinator/pool/ledger.go b/internal/coordinator/pool/ledger.go
index 1bb6511..02e8c5c 100644
--- a/internal/coordinator/pool/ledger.go
+++ b/internal/coordinator/pool/ledger.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package pool
 
diff --git a/internal/coordinator/pool/ledger_test.go b/internal/coordinator/pool/ledger_test.go
index 4c33cf4..714b6b1 100644
--- a/internal/coordinator/pool/ledger_test.go
+++ b/internal/coordinator/pool/ledger_test.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package pool
 
diff --git a/internal/coordinator/pool/log.go b/internal/coordinator/pool/log.go
index 707a790..1b0b7f7 100644
--- a/internal/coordinator/pool/log.go
+++ b/internal/coordinator/pool/log.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package pool
 
diff --git a/internal/coordinator/pool/pool.go b/internal/coordinator/pool/pool.go
index 9be58d1..f545b71 100644
--- a/internal/coordinator/pool/pool.go
+++ b/internal/coordinator/pool/pool.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package pool
 
diff --git a/internal/coordinator/pool/pool_test.go b/internal/coordinator/pool/pool_test.go
index 7bceb61..baedd81 100644
--- a/internal/coordinator/pool/pool_test.go
+++ b/internal/coordinator/pool/pool_test.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package pool
 
diff --git a/internal/coordinator/pool/reverse.go b/internal/coordinator/pool/reverse.go
index be54b35..a8b46f6 100644
--- a/internal/coordinator/pool/reverse.go
+++ b/internal/coordinator/pool/reverse.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package pool
 
diff --git a/internal/coordinator/remote/ssh.go b/internal/coordinator/remote/ssh.go
index 9d90318..79cac1f 100644
--- a/internal/coordinator/remote/ssh.go
+++ b/internal/coordinator/remote/ssh.go
@@ -3,8 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16 && (linux || darwin)
-// +build go1.16
-// +build linux darwin
 
 package remote
 
@@ -19,7 +17,6 @@
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net"
 	"os"
@@ -330,7 +327,7 @@
 // WriteSSHPrivateKeyToTempFile writes a key to a temporary file on the local file system. It also
 // sets the permissions on the file to what is expected by OpenSSH implementations of SSH.
 func WriteSSHPrivateKeyToTempFile(key []byte) (path string, err error) {
-	tf, err := ioutil.TempFile("", "ssh-priv-key")
+	tf, err := os.CreateTemp("", "ssh-priv-key")
 	if err != nil {
 		return "", err
 	}
diff --git a/internal/coordinator/remote/ssh_test.go b/internal/coordinator/remote/ssh_test.go
index abd9a07..f404d07 100644
--- a/internal/coordinator/remote/ssh_test.go
+++ b/internal/coordinator/remote/ssh_test.go
@@ -3,8 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build go1.16 && (linux || darwin)
-// +build go1.16
-// +build linux darwin
 
 package remote
 
diff --git a/internal/coordinator/schedule/fake_schedule.go b/internal/coordinator/schedule/fake_schedule.go
index a21f017..4080277 100644
--- a/internal/coordinator/schedule/fake_schedule.go
+++ b/internal/coordinator/schedule/fake_schedule.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package schedule
 
diff --git a/internal/coordinator/schedule/schedule.go b/internal/coordinator/schedule/schedule.go
index c6e8bf7..79be100 100644
--- a/internal/coordinator/schedule/schedule.go
+++ b/internal/coordinator/schedule/schedule.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package schedule
 
diff --git a/internal/coordinator/schedule/schedule_test.go b/internal/coordinator/schedule/schedule_test.go
index 04718a9..4cb94e2 100644
--- a/internal/coordinator/schedule/schedule_test.go
+++ b/internal/coordinator/schedule/schedule_test.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package schedule
 
diff --git a/internal/coordinator/schedule/span.go b/internal/coordinator/schedule/span.go
index 6f18ec6..333f79f 100644
--- a/internal/coordinator/schedule/span.go
+++ b/internal/coordinator/schedule/span.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package schedule
 
diff --git a/internal/coordinator/schedule/span_test.go b/internal/coordinator/schedule/span_test.go
index 25fe443..3e75d7b 100644
--- a/internal/coordinator/schedule/span_test.go
+++ b/internal/coordinator/schedule/span_test.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package schedule
 
diff --git a/internal/gcsfs/gcsfs_test.go b/internal/gcsfs/gcsfs_test.go
index 6eac0bf..de5f1c0 100644
--- a/internal/gcsfs/gcsfs_test.go
+++ b/internal/gcsfs/gcsfs_test.go
@@ -8,7 +8,6 @@
 	"context"
 	"flag"
 	"io/fs"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"testing"
@@ -82,7 +81,7 @@
 	if err := f.Close(); err != nil {
 		t.Fatal(err)
 	}
-	b, err := ioutil.ReadFile(filepath.Join(temp, "fsystest.txt"))
+	b, err := os.ReadFile(filepath.Join(temp, "fsystest.txt"))
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/internal/gitauth/gitauth.go b/internal/gitauth/gitauth.go
index 314cc24..fabed0b 100644
--- a/internal/gitauth/gitauth.go
+++ b/internal/gitauth/gitauth.go
@@ -10,7 +10,6 @@
 	"bytes"
 	"context"
 	"fmt"
-	"io/ioutil"
 	"log"
 	"os"
 	"os/exec"
@@ -49,7 +48,7 @@
 	var buf bytes.Buffer
 	fmt.Fprintf(&buf, "go.googlesource.com\tFALSE\t/\tTRUE\t2147483647\to\tgit-gobot.gmail.com=%s\n", slurp)
 	fmt.Fprintf(&buf, "go-review.googlesource.com\tFALSE\t/\tTRUE\t2147483647\to\tgit-gobot.gmail.com=%s\n", slurp)
-	return ioutil.WriteFile(cookieFile, buf.Bytes(), 0644)
+	return os.WriteFile(cookieFile, buf.Bytes(), 0644)
 }
 
 func homeDir() string {
diff --git a/internal/gomote/gomote.go b/internal/gomote/gomote.go
index 6639208..a18fad2 100644
--- a/internal/gomote/gomote.go
+++ b/internal/gomote/gomote.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package gomote
 
diff --git a/internal/gomote/gomote_test.go b/internal/gomote/gomote_test.go
index 48fcaf9..f3969c9 100644
--- a/internal/gomote/gomote_test.go
+++ b/internal/gomote/gomote_test.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package gomote
 
diff --git a/internal/gomote/protos/gomote.pb.go b/internal/gomote/protos/gomote.pb.go
index af58770..4350cf7 100644
--- a/internal/gomote/protos/gomote.pb.go
+++ b/internal/gomote/protos/gomote.pb.go
@@ -11,10 +11,11 @@
 package protos
 
 import (
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	reflect "reflect"
 	sync "sync"
+
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 )
 
 const (
diff --git a/internal/gomote/protos/gomote_grpc.pb.go b/internal/gomote/protos/gomote_grpc.pb.go
index 6bc7690..884314d 100644
--- a/internal/gomote/protos/gomote_grpc.pb.go
+++ b/internal/gomote/protos/gomote_grpc.pb.go
@@ -8,6 +8,7 @@
 
 import (
 	context "context"
+
 	grpc "google.golang.org/grpc"
 	codes "google.golang.org/grpc/codes"
 	status "google.golang.org/grpc/status"
diff --git a/internal/gomote/swarming.go b/internal/gomote/swarming.go
index d26104a..2c94b7e 100644
--- a/internal/gomote/swarming.go
+++ b/internal/gomote/swarming.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package gomote
 
diff --git a/internal/gomote/swarming_test.go b/internal/gomote/swarming_test.go
index cf06cf4..97a80b5 100644
--- a/internal/gomote/swarming_test.go
+++ b/internal/gomote/swarming_test.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package gomote
 
diff --git a/internal/httpdl/httpdl_test.go b/internal/httpdl/httpdl_test.go
index ccaded8..086f7d4 100644
--- a/internal/httpdl/httpdl_test.go
+++ b/internal/httpdl/httpdl_test.go
@@ -5,7 +5,6 @@
 package httpdl
 
 import (
-	"io/ioutil"
 	"net/http"
 	"net/http/httptest"
 	"os"
@@ -26,7 +25,7 @@
 	}))
 	defer ts.Close()
 
-	tmpDir, err := ioutil.TempDir("", "dl")
+	tmpDir, err := os.MkdirTemp("", "dl")
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -70,7 +69,7 @@
 	}
 
 	// Also check re-download on size change.
-	ioutil.WriteFile(dstFile, []byte(someContent+someContent), 0644)
+	os.WriteFile(dstFile, []byte(someContent+someContent), 0644)
 	os.Chtimes(dstFile, someTime, someTime)
 	if err := Download(dstFile, ts.URL+"/foo.txt"); err != nil {
 		t.Fatal(err)
diff --git a/internal/releasetargets/releasetargets_test.go b/internal/releasetargets/releasetargets_test.go
index 87fdd4d..f0f4efc 100644
--- a/internal/releasetargets/releasetargets_test.go
+++ b/internal/releasetargets/releasetargets_test.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux || darwin
-// +build linux darwin
 
 package releasetargets
 
@@ -12,7 +11,7 @@
 	"flag"
 	"fmt"
 	"io"
-	"io/ioutil"
+	"os"
 	"sort"
 	"strings"
 	"testing"
@@ -29,13 +28,13 @@
 		printRelease(out, release, TargetsForGo1Point(release))
 	}
 	if *update {
-		if err := ioutil.WriteFile("releases.txt", out.Bytes(), 0); err != nil {
+		if err := os.WriteFile("releases.txt", out.Bytes(), 0); err != nil {
 			t.Fatalf("updating golden: %v", err)
 		}
 		return
 	}
 
-	golden, err := ioutil.ReadFile("releases.txt")
+	golden, err := os.ReadFile("releases.txt")
 	if err != nil {
 		t.Fatalf("reading golden: %v", err)
 	}
diff --git a/internal/relui/buildrelease_test.go b/internal/relui/buildrelease_test.go
index e834aef..700fc9e 100644
--- a/internal/relui/buildrelease_test.go
+++ b/internal/relui/buildrelease_test.go
@@ -14,7 +14,6 @@
 	"fmt"
 	"io"
 	"io/fs"
-	"io/ioutil"
 	"net/http"
 	"net/http/httptest"
 	"os"
@@ -676,7 +675,7 @@
 			if !ok {
 				continue
 			}
-			b, err := ioutil.ReadAll(tr)
+			b, err := io.ReadAll(tr)
 			if err != nil {
 				t.Fatal(err)
 			}
@@ -706,7 +705,7 @@
 			if err != nil {
 				t.Fatal(err)
 			}
-			b, err := ioutil.ReadAll(r)
+			b, err := io.ReadAll(r)
 			if err != nil {
 				t.Fatal(err)
 			}
diff --git a/internal/relui/protos/relui.pb.go b/internal/relui/protos/relui.pb.go
index 4075ebe..23d8f04 100644
--- a/internal/relui/protos/relui.pb.go
+++ b/internal/relui/protos/relui.pb.go
@@ -11,10 +11,11 @@
 package protos
 
 import (
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	reflect "reflect"
 	sync "sync"
+
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 )
 
 const (
diff --git a/internal/relui/protos/relui_grpc.pb.go b/internal/relui/protos/relui_grpc.pb.go
index 2312f5d..312c943 100644
--- a/internal/relui/protos/relui_grpc.pb.go
+++ b/internal/relui/protos/relui_grpc.pb.go
@@ -4,6 +4,7 @@
 
 import (
 	context "context"
+
 	grpc "google.golang.org/grpc"
 	codes "google.golang.org/grpc/codes"
 	status "google.golang.org/grpc/status"
diff --git a/internal/relui/web_test.go b/internal/relui/web_test.go
index 1f7b98a..03a04d0 100644
--- a/internal/relui/web_test.go
+++ b/internal/relui/web_test.go
@@ -11,7 +11,6 @@
 	"flag"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"net/http/httptest"
@@ -83,7 +82,7 @@
 			if resp.StatusCode != c.wantCode {
 				t.Errorf("rep.StatusCode = %d, wanted %d", resp.StatusCode, c.wantCode)
 			}
-			b, err := ioutil.ReadAll(resp.Body)
+			b, err := io.ReadAll(resp.Body)
 			if err != nil {
 				t.Errorf("resp.Body = _, %v, wanted no error", err)
 			}
diff --git a/internal/secret/gcp_secret_manager_test.go b/internal/secret/gcp_secret_manager_test.go
index 5cf66f7..0926141 100644
--- a/internal/secret/gcp_secret_manager_test.go
+++ b/internal/secret/gcp_secret_manager_test.go
@@ -8,7 +8,7 @@
 	"context"
 	"flag"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"reflect"
 	"testing"
 
@@ -167,7 +167,7 @@
 	for _, tt := range tests {
 		t.Run(tt.flagVal, func(t *testing.T) {
 			fs := flag.NewFlagSet("", flag.ContinueOnError)
-			fs.SetOutput(ioutil.Discard)
+			fs.SetOutput(io.Discard)
 			flagVal := r.Flag(fs, "testflag", "usage")
 			err := fs.Parse([]string{"--testflag", tt.flagVal})
 			if tt.wantErr {
@@ -214,7 +214,7 @@
 	for _, tt := range tests {
 		t.Run(tt.flagVal, func(t *testing.T) {
 			fs := flag.NewFlagSet("", flag.ContinueOnError)
-			fs.SetOutput(ioutil.Discard)
+			fs.SetOutput(io.Discard)
 			value := &jsonValue{}
 			r.JSONVarFlag(fs, value, "testflag", "usage")
 			err := fs.Parse([]string{"--testflag", tt.flagVal})
diff --git a/internal/sourcecache/source.go b/internal/sourcecache/source.go
index 3faae67..4641f01 100644
--- a/internal/sourcecache/source.go
+++ b/internal/sourcecache/source.go
@@ -13,7 +13,6 @@
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net"
 	"net/http"
@@ -145,11 +144,11 @@
 	}
 	defer res.Body.Close()
 	if res.StatusCode/100 != 2 {
-		slurp, _ := ioutil.ReadAll(io.LimitReader(res.Body, 4<<10))
+		slurp, _ := io.ReadAll(io.LimitReader(res.Body, 4<<10))
 		return source{}, fmt.Errorf("fetching %s/%s from %s: %v; body: %s", repo, rev, service, res.Status, slurp)
 	}
 	// See golang.org/issue/11224 for a discussion on tree filtering.
-	b, err := ioutil.ReadAll(io.LimitReader(res.Body, maxSize(repo)+1))
+	b, err := io.ReadAll(io.LimitReader(res.Body, maxSize(repo)+1))
 	if int64(len(b)) > maxSize(repo) && err == nil {
 		return source{TooBig: true}, nil
 	}
diff --git a/internal/task/fakes.go b/internal/task/fakes.go
index c12ec55..3fcfe65 100644
--- a/internal/task/fakes.go
+++ b/internal/task/fakes.go
@@ -13,7 +13,6 @@
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"net/http/httptest"
 	"net/url"
@@ -270,7 +269,7 @@
 	if err := zw.Close(); err != nil {
 		return nil, err
 	}
-	return ioutil.NopCloser(buf), nil
+	return io.NopCloser(buf), nil
 }
 
 func (b *fakeBuildlet) ListDir(ctx context.Context, dir string, opts buildlet.ListDirOpts, fn func(buildlet.DirEntry)) error {
diff --git a/kubernetes/client.go b/kubernetes/client.go
index 1b2eb36..e49403a 100644
--- a/kubernetes/client.go
+++ b/kubernetes/client.go
@@ -12,7 +12,6 @@
 	"encoding/json"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"net/url"
@@ -90,7 +89,7 @@
 	if err != nil {
 		return nil, fmt.Errorf("failed to make request: POST %q: %v", postURL, err)
 	}
-	body, err := ioutil.ReadAll(res.Body)
+	body, err := io.ReadAll(res.Body)
 	res.Body.Close()
 	if err != nil {
 		return nil, fmt.Errorf("failed to read request body for POST %q: %v", postURL, err)
@@ -142,7 +141,7 @@
 	}
 	defer res.Body.Close()
 	if res.StatusCode != http.StatusOK {
-		body, _ := ioutil.ReadAll(res.Body)
+		body, _ := io.ReadAll(res.Body)
 		return fmt.Errorf("%v %s: %v, %s", method, urlStr, res.Status, body)
 	}
 	if dst != nil {
@@ -223,7 +222,7 @@
 	if err != nil {
 		return fmt.Errorf("failed to make request: DELETE %q: %v", url, err)
 	}
-	body, err := ioutil.ReadAll(res.Body)
+	body, err := io.ReadAll(res.Body)
 	res.Body.Close()
 	if err != nil {
 		return fmt.Errorf("failed to read response body: DELETE %q: %v", url, err)
@@ -389,7 +388,7 @@
 		return nil, fmt.Errorf("failed to make request: GET %q: %v", getURL, err)
 	}
 
-	body, err := ioutil.ReadAll(res.Body)
+	body, err := io.ReadAll(res.Body)
 	res.Body.Close()
 	if err != nil {
 		return nil, fmt.Errorf("failed to read request body for GET %q: %v", getURL, err)
@@ -418,7 +417,7 @@
 	if err != nil {
 		return "", fmt.Errorf("failed to make request: GET %q: %v", url, err)
 	}
-	body, err := ioutil.ReadAll(res.Body)
+	body, err := io.ReadAll(res.Body)
 	res.Body.Close()
 	if err != nil {
 		return "", fmt.Errorf("failed to read response body: GET %q: %v", url, err)
diff --git a/maintner/github_test.go b/maintner/github_test.go
index a3039e3..417a1ad 100644
--- a/maintner/github_test.go
+++ b/maintner/github_test.go
@@ -8,9 +8,10 @@
 	"bytes"
 	"context"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"net/http/httptest"
+	"os"
 	"path/filepath"
 	"reflect"
 	"sort"
@@ -568,7 +569,7 @@
 }
 
 func TestParseMultipleGithubEvents(t *testing.T) {
-	content, err := ioutil.ReadFile(filepath.Join("testdata", "TestParseMultipleGithubEvents.json"))
+	content, err := os.ReadFile(filepath.Join("testdata", "TestParseMultipleGithubEvents.json"))
 	if err != nil {
 		t.Errorf("error while loading testdata: %s\n", err.Error())
 	}
@@ -626,13 +627,13 @@
 		c.testdata = "TestParseMultipleGithubEvents.json"
 	}
 	timesDoWasCalled++
-	content, _ := ioutil.ReadFile(filepath.Join("testdata", c.testdata))
+	content, _ := os.ReadFile(filepath.Join("testdata", c.testdata))
 	headers := make(http.Header, 0)
 	t := time.Now()
 	var b []byte
 	headers["Date"] = []string{string(t.AppendFormat(b, "Mon Jan _2 15:04:05 2006"))}
 	return &http.Response{
-		Body:       ioutil.NopCloser(bytes.NewReader(content)),
+		Body:       io.NopCloser(bytes.NewReader(content)),
 		Status:     c.status,
 		StatusCode: c.statusCode,
 		Header:     headers,
diff --git a/maintner/internal/robustio/robustio_flaky.go b/maintner/internal/robustio/robustio_flaky.go
index d5c2418..c56e36c 100644
--- a/maintner/internal/robustio/robustio_flaky.go
+++ b/maintner/internal/robustio/robustio_flaky.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build windows || darwin
-// +build windows darwin
 
 package robustio
 
diff --git a/maintner/internal/robustio/robustio_other.go b/maintner/internal/robustio/robustio_other.go
index 3a20cac..da9a46e 100644
--- a/maintner/internal/robustio/robustio_other.go
+++ b/maintner/internal/robustio/robustio_other.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build !windows && !darwin
-// +build !windows,!darwin
 
 package robustio
 
diff --git a/maintner/maintnerd/apipb/api.pb.go b/maintner/maintnerd/apipb/api.pb.go
index 8cf625d..563e45c 100644
--- a/maintner/maintnerd/apipb/api.pb.go
+++ b/maintner/maintnerd/apipb/api.pb.go
@@ -13,10 +13,11 @@
 package apipb
 
 import (
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	reflect "reflect"
 	sync "sync"
+
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 )
 
 const (
diff --git a/maintner/maintnerd/apipb/api_grpc.pb.go b/maintner/maintnerd/apipb/api_grpc.pb.go
index 38441e5..42e4d98 100644
--- a/maintner/maintnerd/apipb/api_grpc.pb.go
+++ b/maintner/maintnerd/apipb/api_grpc.pb.go
@@ -4,6 +4,7 @@
 
 import (
 	context "context"
+
 	grpc "google.golang.org/grpc"
 	codes "google.golang.org/grpc/codes"
 	status "google.golang.org/grpc/status"
diff --git a/maintner/maintnerd/maintnerd.go b/maintner/maintnerd/maintnerd.go
index 9c354b3..d73dcca 100644
--- a/maintner/maintnerd/maintnerd.go
+++ b/maintner/maintnerd/maintnerd.go
@@ -11,7 +11,6 @@
 	"flag"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"os"
@@ -327,7 +326,7 @@
 	}
 
 	tokenFile := filepath.Join(os.Getenv("HOME"), ".github-issue-token")
-	slurp, err := ioutil.ReadFile(tokenFile)
+	slurp, err := os.ReadFile(tokenFile)
 	if err != nil {
 		return "", err
 	}
@@ -391,11 +390,11 @@
 
 	for name := range want {
 		log.Printf("syncing %s from %s to %s", name, src, dst)
-		slurp, err := ioutil.ReadFile(filepath.Join(src, strings.TrimPrefix(name, "maintner-")))
+		slurp, err := os.ReadFile(filepath.Join(src, strings.TrimPrefix(name, "maintner-")))
 		if err != nil {
 			log.Fatal(err)
 		}
-		if err := ioutil.WriteFile(filepath.Join(dst, name), slurp, 0644); err != nil {
+		if err := os.WriteFile(filepath.Join(dst, name), slurp, 0644); err != nil {
 			log.Fatal(err)
 		}
 	}
diff --git a/maintner/maintpb/maintner.pb.go b/maintner/maintpb/maintner.pb.go
index 939d311..2085a52 100644
--- a/maintner/maintpb/maintner.pb.go
+++ b/maintner/maintpb/maintner.pb.go
@@ -35,10 +35,15 @@
 */
 package maintpb
 
-import proto "github.com/golang/protobuf/proto"
-import fmt "fmt"
-import math "math"
-import google_protobuf "github.com/golang/protobuf/ptypes/timestamp"
+import (
+	fmt "fmt"
+
+	proto "github.com/golang/protobuf/proto"
+
+	math "math"
+
+	google_protobuf "github.com/golang/protobuf/ptypes/timestamp"
+)
 
 // Reference imports to suppress errors if they are not otherwise used.
 var _ = proto.Marshal
diff --git a/maintner/netsource.go b/maintner/netsource.go
index fb6f0db..5d8d9f2 100644
--- a/maintner/netsource.go
+++ b/maintner/netsource.go
@@ -13,7 +13,6 @@
 	"fmt"
 	"io"
 	"io/fs"
-	"io/ioutil"
 	"log"
 	"net"
 	"net/http"
@@ -54,7 +53,7 @@
 // TailNetworkMutationSource returns if fn returns an error, if ctx expires,
 // or if it runs into a network error.
 func TailNetworkMutationSource(ctx context.Context, server string, fn func(MutationStreamEvent) error) error {
-	td, err := ioutil.TempDir("", "maintnertail")
+	td, err := os.MkdirTemp("", "maintnertail")
 	if err != nil {
 		return err
 	}
@@ -654,7 +653,7 @@
 	// then perhaps encoding the desired file size into the
 	// filename suffix (instead of just *.growing.mutlog) so
 	// concurrent readers know where to stop.
-	tf, err := ioutil.TempFile(ns.cacheDir, "tempseg")
+	tf, err := os.CreateTemp(ns.cacheDir, "tempseg")
 	if err != nil {
 		return fileSeg{}, nil, err
 	}
diff --git a/perfdata/app/appengine.go b/perfdata/app/appengine.go
index fb3c9d7..ebe4210 100644
--- a/perfdata/app/appengine.go
+++ b/perfdata/app/appengine.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build appengine
-// +build appengine
 
 package app
 
diff --git a/perfdata/app/local.go b/perfdata/app/local.go
index 56a0287..f168b15 100644
--- a/perfdata/app/local.go
+++ b/perfdata/app/local.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build !appengine
-// +build !appengine
 
 package app
 
diff --git a/perfdata/app/query_test.go b/perfdata/app/query_test.go
index 8733e38..175ae8b 100644
--- a/perfdata/app/query_test.go
+++ b/perfdata/app/query_test.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build cgo
-// +build cgo
 
 package app
 
diff --git a/perfdata/app/upload_test.go b/perfdata/app/upload_test.go
index ef6cc38..617355c 100644
--- a/perfdata/app/upload_test.go
+++ b/perfdata/app/upload_test.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build cgo
-// +build cgo
 
 package app
 
@@ -11,7 +10,6 @@
 	"encoding/json"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"mime/multipart"
 	"net/http"
 	"net/http/httptest"
@@ -83,7 +81,7 @@
 	if resp.StatusCode != 200 {
 		t.Fatalf("post /upload: %v", resp.Status)
 	}
-	body, err := ioutil.ReadAll(resp.Body)
+	body, err := io.ReadAll(resp.Body)
 	if err != nil {
 		t.Fatalf("reading /upload response: %v", err)
 	}
diff --git a/perfdata/client.go b/perfdata/client.go
index a74b0cc..f2cb111 100644
--- a/perfdata/client.go
+++ b/perfdata/client.go
@@ -10,7 +10,6 @@
 	"encoding/json"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"mime/multipart"
 	"net/http"
 	"net/url"
@@ -54,7 +53,7 @@
 	}
 	if resp.StatusCode != 200 {
 		defer resp.Body.Close()
-		body, err := ioutil.ReadAll(resp.Body)
+		body, err := io.ReadAll(resp.Body)
 		if err != nil {
 			return nil, err
 		}
@@ -95,7 +94,7 @@
 		return &UploadList{err: err}
 	}
 	if resp.StatusCode != 200 {
-		body, err := ioutil.ReadAll(resp.Body)
+		body, err := io.ReadAll(resp.Body)
 		if err != nil {
 			return &UploadList{err: err}
 		}
@@ -187,7 +186,7 @@
 		}
 		defer resp.Body.Close()
 		if resp.StatusCode != 200 {
-			body, _ := ioutil.ReadAll(resp.Body)
+			body, _ := io.ReadAll(resp.Body)
 			errCh <- fmt.Errorf("upload failed: %v\n%s", resp.Status, body)
 			return
 		}
diff --git a/perfdata/client_test.go b/perfdata/client_test.go
index 92b6afe..96aca6b 100644
--- a/perfdata/client_test.go
+++ b/perfdata/client_test.go
@@ -9,7 +9,6 @@
 	"context"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"net/http/httptest"
 	"reflect"
@@ -119,7 +118,7 @@
 			if have, want := p.FileName(), fmt.Sprintf("want%d.txt", i); have != want {
 				t.Errorf("file name = %q, want %q", have, want)
 			}
-			content, _ := ioutil.ReadAll(p)
+			content, _ := io.ReadAll(p)
 			if have, want := string(content), "content"; have != want {
 				t.Errorf("unexpected content %q, want %q", have, want)
 			}
@@ -177,7 +176,7 @@
 			if have, want := p.FileName(), fmt.Sprintf("want%d.txt", i); have != want {
 				t.Errorf("file name = %q, want %q", have, want)
 			}
-			content, _ := ioutil.ReadAll(p)
+			content, _ := io.ReadAll(p)
 			if have, want := string(content), "content"; have != want {
 				t.Errorf("unexpected content %q, want %q", have, want)
 			}
diff --git a/perfdata/db/db_test.go b/perfdata/db/db_test.go
index 6c13850..cb117f8 100644
--- a/perfdata/db/db_test.go
+++ b/perfdata/db/db_test.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build cgo
-// +build cgo
 
 package db_test
 
diff --git a/perfdata/db/dbtest/cloud.go b/perfdata/db/dbtest/cloud.go
index 553c0be..643ad5e 100644
--- a/perfdata/db/dbtest/cloud.go
+++ b/perfdata/db/dbtest/cloud.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build cloud && !plan9
-// +build cloud,!plan9
 
 package dbtest
 
diff --git a/perfdata/db/dbtest/dbtest.go b/perfdata/db/dbtest/dbtest.go
index dd00f52..c2e38a6 100644
--- a/perfdata/db/dbtest/dbtest.go
+++ b/perfdata/db/dbtest/dbtest.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build cgo
-// +build cgo
 
 package dbtest
 
diff --git a/perfdata/db/dbtest/nocloud.go b/perfdata/db/dbtest/nocloud.go
index 68dfb61..30e740d 100644
--- a/perfdata/db/dbtest/nocloud.go
+++ b/perfdata/db/dbtest/nocloud.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build !cloud && !plan9
-// +build !cloud,!plan9
 
 package dbtest
 
diff --git a/perfdata/db/sqlite3/sqlite3.go b/perfdata/db/sqlite3/sqlite3.go
index 550df96..ae62d46 100644
--- a/perfdata/db/sqlite3/sqlite3.go
+++ b/perfdata/db/sqlite3/sqlite3.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build cgo
-// +build cgo
 
 // Package sqlite3 provides the sqlite3 driver for
 // x/build/perfdata/db. It must be imported instead of go-sqlite3 to
diff --git a/perfdata/fs/local/local_test.go b/perfdata/fs/local/local_test.go
index 1225abd..12f772e 100644
--- a/perfdata/fs/local/local_test.go
+++ b/perfdata/fs/local/local_test.go
@@ -6,7 +6,6 @@
 
 import (
 	"context"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"testing"
@@ -17,7 +16,7 @@
 func TestNewWriter(t *testing.T) {
 	ctx := context.Background()
 
-	dir, err := ioutil.TempDir("", "local_test")
+	dir, err := os.MkdirTemp("", "local_test")
 	if err != nil {
 		t.Fatalf("TempDir = %v", err)
 	}
@@ -40,7 +39,7 @@
 		t.Fatalf("Close = %v", err)
 	}
 
-	have, err := ioutil.ReadFile(filepath.Join(dir, "dir/file"))
+	have, err := os.ReadFile(filepath.Join(dir, "dir/file"))
 	if err != nil {
 		t.Fatalf("ReadFile = %v", err)
 	}
diff --git a/perfdata/localperfdata/app.go b/perfdata/localperfdata/app.go
index 4ee768b..c060e78 100644
--- a/perfdata/localperfdata/app.go
+++ b/perfdata/localperfdata/app.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build cgo
-// +build cgo
 
 // Localperfdata runs an HTTP server for benchmark perfdata.
 //
diff --git a/tarutil/tarutil_test.go b/tarutil/tarutil_test.go
index b8e318e..3cc73fe 100644
--- a/tarutil/tarutil_test.go
+++ b/tarutil/tarutil_test.go
@@ -8,7 +8,6 @@
 	"archive/tar"
 	"compress/gzip"
 	"io"
-	"io/ioutil"
 	"os"
 	"path"
 	"strings"
@@ -66,7 +65,7 @@
 		switch h.Name {
 		case "symlink-file":
 		case "regular.txt":
-			all, err := ioutil.ReadAll(tr)
+			all, err := io.ReadAll(tr)
 			if err != nil {
 				t.Fatalf("Reading regular.txt: %v", err)
 			}
diff --git a/update-readmes.go b/update-readmes.go
index 033e9c5..0125394 100644
--- a/update-readmes.go
+++ b/update-readmes.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build ignore
-// +build ignore
 
 // The update-readmes.go tool creates or updates README.md files in
 // the golang.org/x/build tree. It only updates files if they are
@@ -19,7 +18,6 @@
 	"bytes"
 	"fmt"
 	"go/build"
-	"io/ioutil"
 	"log"
 	"os"
 	"path/filepath"
@@ -61,7 +59,7 @@
 			return nil
 		}
 		readmePath := filepath.Join(pkg.Dir, "README.md")
-		exist, err := ioutil.ReadFile(readmePath)
+		exist, err := os.ReadFile(readmePath)
 		if err != nil && !os.IsNotExist(err) {
 			// A real error.
 			return err
@@ -85,7 +83,7 @@
 		if bytes.Equal(exist, newContents) {
 			return nil
 		}
-		if err := ioutil.WriteFile(readmePath, newContents, 0644); err != nil {
+		if err := os.WriteFile(readmePath, newContents, 0644); err != nil {
 			return err
 		}
 		log.Printf("Wrote %s", readmePath)
diff --git a/vcs-test/vcweb/auth.go b/vcs-test/vcweb/auth.go
index 1f3fe69..a8d2198 100644
--- a/vcs-test/vcweb/auth.go
+++ b/vcs-test/vcweb/auth.go
@@ -3,14 +3,13 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux
-// +build linux
 
 package main
 
 import (
 	"encoding/json"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"log"
 	"net/http"
 	"os"
@@ -90,7 +89,7 @@
 		accessDir = pathpkg.Dir(accessDir)
 	}
 
-	data, err := ioutil.ReadAll(accessFile)
+	data, err := io.ReadAll(accessFile)
 	if err != nil {
 		http.Error(w, err.Error(), http.StatusInternalServerError)
 		return
diff --git a/vcs-test/vcweb/bzr.go b/vcs-test/vcweb/bzr.go
index d6cdf4f..224ef4e 100644
--- a/vcs-test/vcweb/bzr.go
+++ b/vcs-test/vcweb/bzr.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux
-// +build linux
 
 package main
 
diff --git a/vcs-test/vcweb/fossil.go b/vcs-test/vcweb/fossil.go
index 5fcbdcf..3baf4be 100644
--- a/vcs-test/vcweb/fossil.go
+++ b/vcs-test/vcweb/fossil.go
@@ -3,12 +3,10 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux
-// +build linux
 
 package main
 
 import (
-	"io/ioutil"
 	"net/http"
 	"net/http/cgi"
 	"os"
@@ -36,7 +34,7 @@
 		w.WriteHeader(404)
 	}
 	if _, err := os.Stat(db + ".cgi"); err != nil {
-		ioutil.WriteFile(db+".cgi", []byte("#!/usr/bin/fossil\nrepository: "+db+"\n"), 0777)
+		os.WriteFile(db+".cgi", []byte("#!/usr/bin/fossil\nrepository: "+db+"\n"), 0777)
 	}
 
 	h := &cgi.Handler{
diff --git a/vcs-test/vcweb/git.go b/vcs-test/vcweb/git.go
index 7fde62c..35df622 100644
--- a/vcs-test/vcweb/git.go
+++ b/vcs-test/vcweb/git.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux
-// +build linux
 
 package main
 
diff --git a/vcs-test/vcweb/hg.go b/vcs-test/vcweb/hg.go
index 80d78e9..c9ff849 100644
--- a/vcs-test/vcweb/hg.go
+++ b/vcs-test/vcweb/hg.go
@@ -3,12 +3,10 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux
-// +build linux
 
 package main
 
 import (
-	"io/ioutil"
 	"log"
 	"net/http"
 	"net/http/cgi"
@@ -38,10 +36,10 @@
 
 func hgHandler() http.Handler {
 	py := filepath.Join(*dir, "hgweb.py")
-	if err := ioutil.WriteFile(py, []byte(hgwebPy), 0777); err != nil {
+	if err := os.WriteFile(py, []byte(hgwebPy), 0777); err != nil {
 		log.Fatal(err)
 	}
-	if err := ioutil.WriteFile(filepath.Join(*dir, "hgweb.cfg"), []byte(strings.Replace(hgwebCfg, "DIR", *dir, -1)), 0777); err != nil {
+	if err := os.WriteFile(filepath.Join(*dir, "hgweb.cfg"), []byte(strings.Replace(hgwebCfg, "DIR", *dir, -1)), 0777); err != nil {
 		log.Fatal(err)
 	}
 	os.Mkdir(filepath.Join(*dir, "hg"), 0777)
diff --git a/vcs-test/vcweb/insecure.go b/vcs-test/vcweb/insecure.go
index 937a12f..3cf83b7 100644
--- a/vcs-test/vcweb/insecure.go
+++ b/vcs-test/vcweb/insecure.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux
-// +build linux
 
 package main
 
diff --git a/vcs-test/vcweb/load.go b/vcs-test/vcweb/load.go
index 6a760de..2420191 100644
--- a/vcs-test/vcweb/load.go
+++ b/vcs-test/vcweb/load.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux
-// +build linux
 
 package main
 
diff --git a/vcs-test/vcweb/main.go b/vcs-test/vcweb/main.go
index 9f7a9a6..2054a17 100644
--- a/vcs-test/vcweb/main.go
+++ b/vcs-test/vcweb/main.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux
-// +build linux
 
 package main
 
diff --git a/vcs-test/vcweb/svn.go b/vcs-test/vcweb/svn.go
index 1e95621..7d3601d 100644
--- a/vcs-test/vcweb/svn.go
+++ b/vcs-test/vcweb/svn.go
@@ -3,7 +3,6 @@
 // license that can be found in the LICENSE file.
 
 //go:build linux
-// +build linux
 
 package main