Skip to content

Commit 8be4277

Browse files
heschigopherbot
authored andcommitted
internal/task: tidy gopls while tagging tools
gopls has a replace directive that uses the local tools version, which means that they have to be updated together. This is currently a one-off, so rather than trying to figure it out automatically tools is hardcoded. I'm not proud of it. But at least there's a test! (?) For golang/go#48523. Change-Id: If59e669ba3ede08967b72ba3bb36b2c66e1a03a7 Reviewed-on: https://go-review.googlesource.com/c/build/+/443857 TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> Run-TryBot: Heschi Kreinick <[email protected]> Auto-Submit: Heschi Kreinick <[email protected]>
1 parent 4237ab0 commit 8be4277

File tree

2 files changed

+99
-43
lines changed

2 files changed

+99
-43
lines changed

Diff for: internal/task/tagx.go

+87-40
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package task
22

33
import (
4-
"bytes"
4+
"archive/tar"
5+
"compress/gzip"
56
"context"
67
"encoding/json"
78
"errors"
89
"fmt"
10+
"io"
911
"net/http"
1012
"net/url"
13+
"path"
1114
"reflect"
1215
"regexp"
1316
"strconv"
@@ -47,6 +50,7 @@ type TagRepo struct {
4750
Name string // Gerrit project name, e.g. "tools".
4851
ModPath string // Module path, e.g. "golang.org/x/tools".
4952
Deps []string // Dependency module paths.
53+
Compat string // The version to pass to go mod tidy -compat for this repository.
5054
Version string // After a tagging decision has been made, the version dependencies should upgrade to.
5155
}
5256

@@ -127,6 +131,14 @@ func (x *TagXReposTasks) readRepo(ctx *wf.TaskContext, project string) (*TagRepo
127131
ModPath: mf.Module.Mod.Path,
128132
}
129133

134+
compatRe := regexp.MustCompile(`tagx:compat\s+([\d.]+)`)
135+
if mf.Go != nil {
136+
for _, c := range mf.Go.Syntax.Comments.Suffix {
137+
if matches := compatRe.FindStringSubmatch(c.Token); matches != nil {
138+
result.Compat = matches[1]
139+
}
140+
}
141+
}
130142
require:
131143
for _, req := range mf.Require {
132144
if !isX(req.Mod.Path) {
@@ -266,88 +278,126 @@ func (x *TagXReposTasks) planRepo(wd *wf.Definition, repo TagRepo, updated map[s
266278
return tagged, true
267279
}
268280

269-
type UpdatedModSum struct {
270-
Mod, Sum string
271-
}
272-
273-
func (x *TagXReposTasks) UpdateGoMod(ctx *wf.TaskContext, repo TagRepo, deps []TagRepo, branch string) (UpdatedModSum, error) {
281+
func (x *TagXReposTasks) UpdateGoMod(ctx *wf.TaskContext, repo TagRepo, deps []TagRepo, branch string) (files map[string]string, _ error) {
274282
commit, err := x.Gerrit.ReadBranchHead(ctx, repo.Name, branch)
275283
if err != nil {
276-
return UpdatedModSum{}, err
284+
return nil, err
277285
}
278286

279287
binaries, err := x.LatestGoBinaries(ctx)
280288
if err != nil {
281-
return UpdatedModSum{}, err
289+
return nil, err
282290
}
283291
bc, err := x.CreateBuildlet(ctx, "linux-amd64-longtest") // longtest to allow network access. A little yucky.
284292
if err != nil {
285-
return UpdatedModSum{}, err
293+
return nil, err
286294
}
287295
defer bc.Close()
288296

289297
if err := bc.PutTarFromURL(ctx, binaries, ""); err != nil {
290-
return UpdatedModSum{}, err
298+
return nil, err
291299
}
292300
tarURL := fmt.Sprintf("%s/%s/+archive/%s.tar.gz", x.GerritURL, repo.Name, commit)
293301
if err := bc.PutTarFromURL(ctx, tarURL, "repo"); err != nil {
294-
return UpdatedModSum{}, err
302+
return nil, err
295303
}
296304

297305
writer := &LogWriter{Logger: ctx}
298306
go writer.Run(ctx)
299307

300-
args := []string{"get"}
308+
// Update the root module to the selected versions.
309+
getCmd := []string{"get"}
301310
for _, dep := range deps {
302-
args = append(args, dep.ModPath+"@"+dep.Version)
311+
getCmd = append(getCmd, dep.ModPath+"@"+dep.Version)
303312
}
304313
remoteErr, execErr := bc.Exec(ctx, "go/bin/go", buildlet.ExecOpts{
305314
Dir: "repo",
306-
Args: args,
315+
Args: getCmd,
307316
Output: writer,
308317
})
309318
if execErr != nil {
310-
return UpdatedModSum{}, execErr
319+
return nil, execErr
311320
}
312321
if remoteErr != nil {
313-
return UpdatedModSum{}, fmt.Errorf("Command failed: %v", remoteErr)
322+
return nil, fmt.Errorf("Command failed: %v", remoteErr)
314323
}
315324

316-
remoteErr, execErr = bc.Exec(ctx, "go/bin/go", buildlet.ExecOpts{
317-
Dir: "repo",
318-
Args: []string{"mod", "tidy"},
319-
Output: writer,
320-
})
321-
if execErr != nil {
322-
return UpdatedModSum{}, execErr
325+
// Tidy the root module. For tools, also tidy gopls so that its replaced
326+
// version still works.
327+
dirs := []string{""}
328+
if repo.Name == "tools" {
329+
dirs = append(dirs, "gopls")
323330
}
324-
if remoteErr != nil {
325-
return UpdatedModSum{}, fmt.Errorf("Command failed: %v", remoteErr)
331+
var fetchCmd []string
332+
for _, dir := range dirs {
333+
var tidyFlags []string
334+
if repo.Compat != "" {
335+
tidyFlags = append(tidyFlags, "-compat", repo.Compat)
336+
}
337+
remoteErr, execErr = bc.Exec(ctx, "go/bin/go", buildlet.ExecOpts{
338+
Dir: path.Join("repo", dir),
339+
Args: append([]string{"mod", "tidy"}, tidyFlags...),
340+
Output: writer,
341+
})
342+
if execErr != nil {
343+
return nil, execErr
344+
}
345+
if remoteErr != nil {
346+
return nil, fmt.Errorf("Command failed: %v", remoteErr)
347+
}
348+
349+
repoDir, fetchDir := path.Join("repo", dir), path.Join("fetch", dir)
350+
fetchCmd = append(fetchCmd, fmt.Sprintf("mkdir -p %[2]v && cp %[1]v/go.mod %[2]v && touch %[1]v/go.sum && cp %[1]v/go.sum %[2]v", repoDir, fetchDir))
326351
}
327352

328353
remoteErr, execErr = bc.Exec(ctx, "bash", buildlet.ExecOpts{
329354
Dir: ".",
330-
Args: []string{"-c", "mkdir fetchgomod && cp repo/go.mod fetchgomod && touch repo/go.sum && mkdir fetchgosum && cp repo/go.sum fetchgosum"},
355+
Args: []string{"-c", strings.Join(fetchCmd, " && ")},
331356
Output: writer,
332357
SystemLevel: true,
333358
})
334359
if execErr != nil {
335-
return UpdatedModSum{}, execErr
360+
return nil, execErr
336361
}
337362
if remoteErr != nil {
338-
return UpdatedModSum{}, fmt.Errorf("Command failed: %v", remoteErr)
363+
return nil, fmt.Errorf("Command failed: %v", remoteErr)
339364
}
340365

341-
mod := &bytes.Buffer{}
342-
if err := fetchFile(ctx, bc, mod, "fetchgomod"); err != nil {
343-
return UpdatedModSum{}, err
366+
tgz, err := bc.GetTar(ctx, "fetch")
367+
if err != nil {
368+
return nil, err
344369
}
345-
sum := &bytes.Buffer{}
346-
if err := fetchFile(ctx, bc, sum, "fetchgosum"); err != nil {
347-
return UpdatedModSum{}, err
370+
defer tgz.Close()
371+
return tgzToMap(tgz)
372+
}
373+
374+
func tgzToMap(r io.Reader) (map[string]string, error) {
375+
gzr, err := gzip.NewReader(r)
376+
if err != nil {
377+
return nil, err
348378
}
379+
defer gzr.Close()
349380

350-
return UpdatedModSum{mod.String(), sum.String()}, nil
381+
result := map[string]string{}
382+
tr := tar.NewReader(gzr)
383+
for {
384+
h, err := tr.Next()
385+
if err == io.EOF {
386+
break
387+
}
388+
if err != nil {
389+
return nil, err
390+
}
391+
if h.Typeflag != tar.TypeReg {
392+
continue
393+
}
394+
b, err := io.ReadAll(tr)
395+
if err != nil {
396+
return nil, err
397+
}
398+
result[h.Name] = string(b)
399+
}
400+
return result, nil
351401
}
352402

353403
func LatestGoBinaries(ctx context.Context) (string, error) {
@@ -374,7 +424,7 @@ func LatestGoBinaries(ctx context.Context) (string, error) {
374424
return "", fmt.Errorf("no linux-amd64??")
375425
}
376426

377-
func (x *TagXReposTasks) MailGoMod(ctx *wf.TaskContext, repo string, gomod UpdatedModSum) (string, error) {
427+
func (x *TagXReposTasks) MailGoMod(ctx *wf.TaskContext, repo string, files map[string]string) (string, error) {
378428
const subject = `go.mod: update golang.org/x dependencies
379429
380430
Update golang.org/x dependencies to their latest tagged versions.
@@ -386,10 +436,7 @@ will be tagged with its next minor version.
386436
Project: repo,
387437
Branch: "master",
388438
Subject: subject,
389-
}, nil, map[string]string{
390-
"go.mod": gomod.Mod,
391-
"go.sum": gomod.Sum,
392-
})
439+
}, nil, files)
393440
}
394441

395442
func (x *TagXReposTasks) AwaitGoMod(ctx *wf.TaskContext, changeID, repo, branch string) (string, error) {

Diff for: internal/task/tagx_test.go

+12-3
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ case "$1" in
325325
;;
326326
"mod")
327327
ls go.mod go.sum >/dev/null
328-
echo "tidied!" >> go.mod
328+
echo "tidied! $*" >> go.mod
329329
;;
330330
*)
331331
echo unexpected command $@
@@ -369,8 +369,10 @@ func TestTagXRepos(t *testing.T) {
369369
mod.Tag("v1.0.0", mod1)
370370
tools := NewFakeRepo(t, "tools")
371371
tools1 := tools.Commit(map[string]string{
372-
"go.mod": "module golang.org/x/tools\nrequire golang.org/x/mod v1.0.0\nrequire golang.org/x/sys v0.1.0\n",
373-
"go.sum": "\n",
372+
"go.mod": "module golang.org/x/tools\nrequire golang.org/x/mod v1.0.0\ngo 1.18 // tagx:compat 1.16\nrequire golang.org/x/sys v0.1.0\n",
373+
"go.sum": "\n",
374+
"gopls/go.mod": "module golang.org/x/tools/gopls\nrequire golang.org/x/mod v1.0.0\n",
375+
"gopls/go.sum": "\n",
374376
})
375377
tools.Tag("v1.1.5", tools1)
376378
fakeGerrit := NewFakeGerrit(t, goRepo, sys, mod, tools)
@@ -467,6 +469,13 @@ func TestTagXRepos(t *testing.T) {
467469
if !strings.Contains(string(goMod), "tidied!") {
468470
t.Error("tools go.mod should be tidied")
469471
}
472+
goplsMod, err := fakeGerrit.ReadFile(ctx, "tools", tag.Revision, "gopls/go.mod")
473+
if err != nil {
474+
t.Fatal(err)
475+
}
476+
if !strings.Contains(string(goplsMod), "tidied!") || !strings.Contains(string(goplsMod), "1.16") || strings.Contains(string(goplsMod), "upgraded") {
477+
t.Error("gopls go.mod should be tidied with -compat 1.16, but not upgraded")
478+
}
470479
}
471480

472481
type verboseListener struct {

0 commit comments

Comments
 (0)