Skip to content

Commit d781efd

Browse files
author
Dung Le
committed
internal/relui: extend VersionTasks feature to automate goimports stdlib regeneration
Add a new task in addSingleReleaseWorkflow that creates the stdlib regeneration CL for each Go release using func CreateUpdateStdlibIndexCL in VersionTasks. CreateUpdateStdlibIndexCL fetches the latest go binaries, downloads the latest version of tools repo, and submit a CL whose diff is created by regenerating stdlib with `go generate ./internal/imports`. For golang/go#54377. Change-Id: I3d95a88def984dd677d49f38587bed298b3aeaea Reviewed-on: https://go-review.googlesource.com/c/build/+/442157 Reviewed-by: Heschi Kreinick <[email protected]> Run-TryBot: Dylan Le <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 24869eb commit d781efd

File tree

5 files changed

+146
-13
lines changed

5 files changed

+146
-13
lines changed

cmd/relui/main.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,6 @@ func main() {
113113
gerritClient := &task.RealGerritClient{
114114
Client: gerrit.NewClient("https://go-review.googlesource.com", gerrit.OAuth2Auth(creds.TokenSource)),
115115
}
116-
versionTasks := &task.VersionTasks{
117-
Gerrit: gerritClient,
118-
GoProject: "go",
119-
}
120116
commTasks := task.CommunicationTasks{
121117
AnnounceMailTasks: task.AnnounceMailTasks{
122118
SendMail: task.NewSendGridMailClient(*sendgridAPIKey).SendMail,
@@ -196,6 +192,11 @@ func main() {
196192
RepoName: "go",
197193
ApproveAction: relui.ApproveActionDep(dbPool),
198194
}
195+
versionTasks := &task.VersionTasks{
196+
Gerrit: gerritClient,
197+
GoProject: "go",
198+
CreateBuildlet: coordinator.CreateBuildlet,
199+
}
199200
if err := relui.RegisterReleaseWorkflows(ctx, dh, buildTasks, milestoneTasks, versionTasks, commTasks); err != nil {
200201
log.Fatalf("RegisterReleaseWorkflows: %v", err)
201202
}

internal/relui/buildrelease_test.go

+46-3
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,31 @@ func TestSecurity(t *testing.T) {
5656
})
5757
}
5858

59+
const fakeGo = `#!/bin/bash -eu
60+
61+
case "$1" in
62+
"get")
63+
ls go.mod go.sum >/dev/null
64+
for i in "${@:2}"; do
65+
echo -e "// pretend we've upgraded to $i" >> go.mod
66+
echo "$i h1:asdasd" | tr '@' ' ' >> go.sum
67+
done
68+
;;
69+
"mod")
70+
ls go.mod go.sum >/dev/null
71+
echo "tidied!" >> go.mod
72+
;;
73+
"generate")
74+
mkdir -p internal/imports
75+
cd internal/imports && echo "package imports" >> zstdlib.go
76+
;;
77+
*)
78+
echo unexpected command $@
79+
exit 1
80+
;;
81+
esac
82+
`
83+
5984
type releaseTestDeps struct {
6085
ctx context.Context
6186
cancel context.CancelFunc
@@ -142,12 +167,30 @@ esac
142167
base := goRepo.Commit(goFiles)
143168
goRepo.Tag("go1.17", base)
144169
dlRepo := task.NewFakeRepo(t, "dl")
145-
fakeGerrit := task.NewFakeGerrit(t, goRepo, dlRepo)
170+
toolsRepo := task.NewFakeRepo(t, "tools")
171+
toolsRepo1 := toolsRepo.Commit(map[string]string{
172+
"go.mod": "module golang.org/x/tools\n",
173+
"go.sum": "\n",
174+
"internal/imports/mkstdlib.go": "package imports\nconst C=1",
175+
})
176+
toolsRepo.Tag("master", toolsRepo1)
177+
fakeGerrit := task.NewFakeGerrit(t, goRepo, dlRepo, toolsRepo)
146178

147179
gerrit := &reviewerCheckGerrit{FakeGerrit: fakeGerrit}
180+
goServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
181+
task.ServeTarball("dl/go1.19.linux-amd64.tar.gz", map[string]string{
182+
"go/bin/go": fakeGo,
183+
}, w, r)
184+
}))
185+
t.Cleanup(goServer.Close)
148186
versionTasks := &task.VersionTasks{
149-
Gerrit: gerrit,
150-
GoProject: "go",
187+
Gerrit: gerrit,
188+
GerritURL: fakeGerrit.GerritURL(),
189+
GoProject: "go",
190+
CreateBuildlet: fakeBuildlets.CreateBuildlet,
191+
LatestGoBinaries: func(context.Context) (string, error) {
192+
return goServer.URL + "/dl/go1.19.linux-amd64.tar.gz", nil
193+
},
151194
}
152195
milestoneTasks := &task.MilestoneTasks{
153196
Client: &fakeGitHub{},

internal/relui/workflows.go

+3
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,9 @@ func addSingleReleaseWorkflow(
392392
uploaded := wf.Action1(wd, "Upload artifacts to CDN", build.uploadArtifacts, signedAndTestedArtifacts, wf.After(tagged))
393393
pushed := wf.Action3(wd, "Push issues", milestone.PushIssues, milestones, nextVersion, kindVal, wf.After(tagged))
394394
versionPublished = wf.Task2(wd, "Publish to website", build.publishArtifacts, nextVersion, signedAndTestedArtifacts, wf.After(uploaded, pushed))
395+
if kind == task.KindMajor {
396+
wf.Task3(wd, fmt.Sprintf("Mail update stdlib index CL for 1.%d", major), version.CreateUpdateStdlibIndexCL, wf.Const("master"), coordinators, versionPublished)
397+
}
395398
wf.Output(wd, "Released version", versionPublished)
396399
return versionPublished
397400
}

internal/task/fakes.go

+31-4
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,24 @@ func (repo *FakeRepo) Tag(tag, commit string) {
363363
repo.tags[tag] = commit
364364
}
365365

366+
// GetRepoContent returns the content of repo based on the value of commit:
367+
// - commit is "master": return content of the most recent revision
368+
// - commit is tag: return content of the repo associating with the commit that the tag maps to
369+
// - commit is neither "master" or tag: return content of the repo associated with that commit
370+
func (repo *FakeRepo) GetRepoContent(commit string) (map[string]string, error) {
371+
rev := commit
372+
if commit == "master" {
373+
l := len(repo.history)
374+
if l == 0 {
375+
return nil, fmt.Errorf("repo %v history is empty", repo.name)
376+
}
377+
rev = repo.history[l-1]
378+
} else if val, ok := repo.tags[commit]; ok {
379+
rev = val
380+
}
381+
return repo.content[rev], nil
382+
}
383+
366384
var _ GerritClient = (*FakeGerrit)(nil)
367385

368386
func (g *FakeGerrit) ListProjects(ctx context.Context) ([]string, error) {
@@ -394,11 +412,15 @@ func (g *FakeGerrit) ReadFile(ctx context.Context, project string, commit string
394412
if err != nil {
395413
return nil, err
396414
}
397-
content := repo.content[commit][file]
398-
if content == "" {
415+
repoContent, err := repo.GetRepoContent(commit)
416+
if err != nil {
417+
return nil, err
418+
}
419+
fileContent := repoContent[file]
420+
if fileContent == "" {
399421
return nil, fmt.Errorf("commit/file not found %v at %v: %w", file, commit, gerrit.ErrResourceNotExist)
400422
}
401-
return []byte(content), nil
423+
return []byte(fileContent), nil
402424
}
403425

404426
func (g *FakeGerrit) ListTags(ctx context.Context, project string) ([]string, error) {
@@ -475,5 +497,10 @@ func (g *FakeGerrit) serveHTTP(w http.ResponseWriter, r *http.Request) {
475497
return
476498
}
477499
rev := strings.TrimSuffix(parts[3], ".tar.gz")
478-
ServeTarball("", repo.content[rev], w, r)
500+
repoContent, err := repo.GetRepoContent(rev)
501+
if err != nil {
502+
w.WriteHeader(http.StatusInternalServerError)
503+
return
504+
}
505+
ServeTarball("", repoContent, w, r)
479506
}

internal/task/version.go

+61-2
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,19 @@ import (
66
"strings"
77
"time"
88

9+
"golang.org/x/build/buildlet"
910
"golang.org/x/build/gerrit"
1011
"golang.org/x/build/internal/workflow"
1112
"golang.org/x/net/context"
1213
)
1314

1415
// VersionTasks contains tasks related to versioning the release.
1516
type VersionTasks struct {
16-
Gerrit GerritClient
17-
GoProject string
17+
Gerrit GerritClient
18+
GerritURL string
19+
GoProject string
20+
CreateBuildlet func(context.Context, string) (buildlet.RemoteClient, error)
21+
LatestGoBinaries func(context.Context) (string, error)
1822
}
1923

2024
func (t *VersionTasks) GetCurrentMajor(ctx context.Context) (int, error) {
@@ -138,3 +142,58 @@ func (t *VersionTasks) ReadBranchHead(ctx *workflow.TaskContext, branch string)
138142
func (t *VersionTasks) TagRelease(ctx *workflow.TaskContext, version, commit string) error {
139143
return t.Gerrit.Tag(ctx, t.GoProject, version, commit)
140144
}
145+
146+
func (t *VersionTasks) CreateUpdateStdlibIndexCL(ctx *workflow.TaskContext, branch string, reviewers []string, version string) (string, error) {
147+
var files = make(map[string]string) // Map key is relative path, and map value is file content.
148+
149+
binaries, err := t.LatestGoBinaries(ctx)
150+
if err != nil {
151+
return "", err
152+
}
153+
bc, err := t.CreateBuildlet(ctx, "linux-amd64-longtest")
154+
if err != nil {
155+
return "", err
156+
}
157+
defer bc.Close()
158+
if err := bc.PutTarFromURL(ctx, binaries, ""); err != nil {
159+
return "", err
160+
}
161+
toolsTarURL := fmt.Sprintf("%s/%s/+archive/%s.tar.gz", t.GerritURL, "tools", "master")
162+
if err := bc.PutTarFromURL(ctx, toolsTarURL, "tools"); err != nil {
163+
return "", err
164+
}
165+
writer := &LogWriter{Logger: ctx}
166+
go writer.Run(ctx)
167+
remoteErr, execErr := bc.Exec(ctx, "go/bin/go", buildlet.ExecOpts{
168+
Dir: "tools",
169+
Args: []string{"generate", "./internal/imports"},
170+
Output: writer,
171+
})
172+
if execErr != nil {
173+
return "", fmt.Errorf("Exec failed: %v", execErr)
174+
}
175+
if remoteErr != nil {
176+
return "", fmt.Errorf("Command failed: %v", remoteErr)
177+
}
178+
tgz, err := bc.GetTar(context.Background(), "tools/internal/imports")
179+
if err != nil {
180+
return "", err
181+
}
182+
defer tgz.Close()
183+
tools, err := tgzToMap(tgz)
184+
if err != nil {
185+
return "", err
186+
}
187+
files["internal/imports/zstdlib.go"] = tools["zstdlib.go"]
188+
189+
major, err := t.GetCurrentMajor(ctx)
190+
if err != nil {
191+
return "", err
192+
}
193+
changeInput := gerrit.ChangeInput{
194+
Project: "tools",
195+
Subject: fmt.Sprintf("internal/imports: update stdlib index for %v", major),
196+
Branch: "master",
197+
}
198+
return t.Gerrit.CreateAutoSubmitChange(ctx, changeInput, reviewers, files)
199+
}

0 commit comments

Comments
 (0)