Skip to content

Commit 5c85681

Browse files
heschigopherbot
authored andcommitted
internal/relui,internal/task: move useful structs to task
For whatever reason I've decided to write the tagging workflow in the task package, so I need the test helpers here. I also need the website structs to find the latest Go release later. For golang/go#48523. Change-Id: I92a1430bd27f0aa90c9fccefa12fb057e7e7f864 Reviewed-on: https://go-review.googlesource.com/c/build/+/425090 Reviewed-by: Dmitri Shuralyov <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> Run-TryBot: Heschi Kreinick <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Auto-Submit: Heschi Kreinick <[email protected]>
1 parent 58cf979 commit 5c85681

File tree

5 files changed

+117
-119
lines changed

5 files changed

+117
-119
lines changed

Diff for: cmd/relui/main.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ func main() {
175175
ScratchURL: *scratchFilesBase,
176176
ServingURL: *servingFilesBase,
177177
DownloadURL: *edgeCacheURL,
178-
PublishFile: func(f *relui.WebsiteFile) error {
178+
PublishFile: func(f *task.WebsiteFile) error {
179179
return publishFile(*websiteUploadURL, userPassAuth, f)
180180
},
181181
ApproveAction: relui.ApproveActionDep(dbPool),
@@ -228,7 +228,7 @@ func key(masterKey, principal string) string {
228228
return fmt.Sprintf("%x", h.Sum(nil))
229229
}
230230

231-
func publishFile(uploadURL string, auth buildlet.UserPass, f *relui.WebsiteFile) error {
231+
func publishFile(uploadURL string, auth buildlet.UserPass, f *task.WebsiteFile) error {
232232
req, err := json.Marshal(f)
233233
if err != nil {
234234
return err

Diff for: internal/relui/buildrelease_test.go

+15-15
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ type releaseTestDeps struct {
6666
versionTasks *task.VersionTasks
6767
buildTasks *BuildReleaseTasks
6868
milestoneTasks *task.MilestoneTasks
69-
publishedFiles map[string]*WebsiteFile
69+
publishedFiles map[string]*task.WebsiteFile
7070
outputListener func(taskName string, output interface{})
7171
}
7272

@@ -115,8 +115,8 @@ func newReleaseTestDeps(t *testing.T, wantVersion string) *releaseTestDeps {
115115

116116
// Set up the fake website to publish to.
117117
var filesMu sync.Mutex
118-
files := map[string]*WebsiteFile{}
119-
publishFile := func(f *WebsiteFile) error {
118+
files := map[string]*task.WebsiteFile{}
119+
publishFile := func(f *task.WebsiteFile) error {
120120
filesMu.Lock()
121121
defer filesMu.Unlock()
122122
files[strings.TrimPrefix(f.Filename, wantVersion+".")] = f
@@ -197,20 +197,20 @@ func testRelease(t *testing.T, wantVersion string, kind task.ReleaseKind) {
197197
}
198198

199199
dlURL, files := deps.buildTasks.DownloadURL, deps.publishedFiles
200-
checkTGZ(t, dlURL, files, "src.tar.gz", &WebsiteFile{
200+
checkTGZ(t, dlURL, files, "src.tar.gz", &task.WebsiteFile{
201201
OS: "",
202202
Arch: "",
203203
Kind: "source",
204204
}, map[string]string{
205205
"go/VERSION": wantVersion,
206206
"go/src/make.bash": makeScript,
207207
})
208-
checkContents(t, dlURL, files, "windows-amd64.msi", &WebsiteFile{
208+
checkContents(t, dlURL, files, "windows-amd64.msi", &task.WebsiteFile{
209209
OS: "windows",
210210
Arch: "amd64",
211211
Kind: "installer",
212212
}, "I'm an MSI!\n")
213-
checkTGZ(t, dlURL, files, "linux-amd64.tar.gz", &WebsiteFile{
213+
checkTGZ(t, dlURL, files, "linux-amd64.tar.gz", &task.WebsiteFile{
214214
OS: "linux",
215215
Arch: "amd64",
216216
Kind: "archive",
@@ -219,23 +219,23 @@ func testRelease(t *testing.T, wantVersion string, kind task.ReleaseKind) {
219219
"go/tool/something_orother/compile": "",
220220
"go/pkg/something_orother/race.a": "",
221221
})
222-
checkZip(t, dlURL, files, "windows-arm64.zip", &WebsiteFile{
222+
checkZip(t, dlURL, files, "windows-arm64.zip", &task.WebsiteFile{
223223
OS: "windows",
224224
Arch: "arm64",
225225
Kind: "archive",
226226
}, map[string]string{
227227
"go/VERSION": wantVersion,
228228
"go/tool/something_orother/compile": "",
229229
})
230-
checkTGZ(t, dlURL, files, "linux-armv6l.tar.gz", &WebsiteFile{
230+
checkTGZ(t, dlURL, files, "linux-armv6l.tar.gz", &task.WebsiteFile{
231231
OS: "linux",
232232
Arch: "armv6l",
233233
Kind: "archive",
234234
}, map[string]string{
235235
"go/VERSION": wantVersion,
236236
"go/tool/something_orother/compile": "",
237237
})
238-
checkContents(t, dlURL, files, "darwin-amd64.pkg", &WebsiteFile{
238+
checkContents(t, dlURL, files, "darwin-amd64.pkg", &task.WebsiteFile{
239239
OS: "darwin",
240240
Arch: "amd64",
241241
Kind: "installer",
@@ -312,7 +312,7 @@ func testSecurity(t *testing.T, mergeFixes bool) {
312312
runToFailure(t, deps.ctx, w, "Check branch state matches source archive", &verboseListener{t, deps.outputListener})
313313
return
314314
}
315-
checkTGZ(t, deps.buildTasks.DownloadURL, deps.publishedFiles, "src.tar.gz", &WebsiteFile{
315+
checkTGZ(t, deps.buildTasks.DownloadURL, deps.publishedFiles, "src.tar.gz", &task.WebsiteFile{
316316
OS: "",
317317
Arch: "",
318318
Kind: "source",
@@ -465,13 +465,13 @@ func serveTarball(pathMatch string, files map[string]string, w http.ResponseWrit
465465
}
466466
}
467467

468-
func checkFile(t *testing.T, dlURL string, files map[string]*WebsiteFile, filename string, meta *WebsiteFile, check func(*testing.T, []byte)) {
468+
func checkFile(t *testing.T, dlURL string, files map[string]*task.WebsiteFile, filename string, meta *task.WebsiteFile, check func(*testing.T, []byte)) {
469469
t.Run(filename, func(t *testing.T) {
470470
f, ok := files[filename]
471471
if !ok {
472472
t.Fatalf("file %q not published", filename)
473473
}
474-
if diff := cmp.Diff(meta, f, cmpopts.IgnoreFields(WebsiteFile{}, "Filename", "Version", "ChecksumSHA256", "Size")); diff != "" {
474+
if diff := cmp.Diff(meta, f, cmpopts.IgnoreFields(task.WebsiteFile{}, "Filename", "Version", "ChecksumSHA256", "Size")); diff != "" {
475475
t.Errorf("file metadata mismatch (-want +got):\n%v", diff)
476476
}
477477
resp, err := http.Get(dlURL + "/" + f.Filename)
@@ -486,15 +486,15 @@ func checkFile(t *testing.T, dlURL string, files map[string]*WebsiteFile, filena
486486
})
487487
}
488488

489-
func checkContents(t *testing.T, dlURL string, files map[string]*WebsiteFile, filename string, meta *WebsiteFile, contents string) {
489+
func checkContents(t *testing.T, dlURL string, files map[string]*task.WebsiteFile, filename string, meta *task.WebsiteFile, contents string) {
490490
checkFile(t, dlURL, files, filename, meta, func(t *testing.T, b []byte) {
491491
if got, want := string(b), contents; got != want {
492492
t.Errorf("%v contains %q, want %q", filename, got, want)
493493
}
494494
})
495495
}
496496

497-
func checkTGZ(t *testing.T, dlURL string, files map[string]*WebsiteFile, filename string, meta *WebsiteFile, contents map[string]string) {
497+
func checkTGZ(t *testing.T, dlURL string, files map[string]*task.WebsiteFile, filename string, meta *task.WebsiteFile, contents map[string]string) {
498498
checkFile(t, dlURL, files, filename, meta, func(t *testing.T, b []byte) {
499499
gzr, err := gzip.NewReader(bytes.NewReader(b))
500500
if err != nil {
@@ -528,7 +528,7 @@ func checkTGZ(t *testing.T, dlURL string, files map[string]*WebsiteFile, filenam
528528
})
529529
}
530530

531-
func checkZip(t *testing.T, dlURL string, files map[string]*WebsiteFile, filename string, meta *WebsiteFile, contents map[string]string) {
531+
func checkZip(t *testing.T, dlURL string, files map[string]*task.WebsiteFile, filename string, meta *task.WebsiteFile, contents map[string]string) {
532532
checkFile(t, dlURL, files, filename, meta, func(t *testing.T, b []byte) {
533533
zr, err := zip.NewReader(bytes.NewReader(b), int64(len(b)))
534534
if err != nil {

Diff for: internal/relui/workflows.go

+4-72
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ type BuildReleaseTasks struct {
550550
GCSClient *storage.Client
551551
ScratchURL, ServingURL string
552552
DownloadURL string
553-
PublishFile func(*WebsiteFile) error
553+
PublishFile func(*task.WebsiteFile) error
554554
CreateBuildlet func(context.Context, string) (buildlet.RemoteClient, error)
555555
ApproveAction func(*wf.TaskContext) error
556556
}
@@ -705,8 +705,8 @@ func (b *BuildReleaseTasks) runBuildStep(
705705
return artifact{}, err
706706
}
707707
defer client.Close()
708-
w := &logWriter{logger: ctx}
709-
go w.run(ctx)
708+
w := &task.LogWriter{Logger: ctx}
709+
go w.Run(ctx)
710710
step = &task.BuildletStep{
711711
Target: target,
712712
Buildlet: client,
@@ -812,62 +812,6 @@ func (w *sizeWriter) Write(p []byte) (n int, err error) {
812812
return len(p), nil
813813
}
814814

815-
type logWriter struct {
816-
flushTicker *time.Ticker
817-
818-
mu sync.Mutex
819-
buf []byte
820-
logger wf.Logger
821-
}
822-
823-
func (w *logWriter) Write(b []byte) (int, error) {
824-
w.mu.Lock()
825-
defer w.mu.Unlock()
826-
827-
w.buf = append(w.buf, b...)
828-
if len(w.buf) > 1<<20 {
829-
w.flushLocked(false)
830-
w.flushTicker.Reset(10 * time.Second)
831-
}
832-
return len(b), nil
833-
}
834-
835-
func (w *logWriter) flush(force bool) {
836-
w.mu.Lock()
837-
defer w.mu.Unlock()
838-
w.flushLocked(force)
839-
}
840-
841-
func (w *logWriter) flushLocked(force bool) {
842-
if len(w.buf) == 0 {
843-
return
844-
}
845-
log, rest := w.buf, []byte(nil)
846-
if !force {
847-
nl := bytes.LastIndexByte(w.buf, '\n')
848-
if nl == -1 {
849-
return
850-
}
851-
log, rest = w.buf[:nl], w.buf[nl+1:]
852-
}
853-
w.logger.Printf("\n%s", string(log))
854-
w.buf = append([]byte(nil), rest...) // don't leak
855-
}
856-
857-
func (w *logWriter) run(ctx context.Context) {
858-
w.flushTicker = time.NewTicker(10 * time.Second)
859-
defer w.flushTicker.Stop()
860-
for {
861-
select {
862-
case <-w.flushTicker.C:
863-
w.flush(false)
864-
case <-ctx.Done():
865-
w.flush(true)
866-
return
867-
}
868-
}
869-
}
870-
871815
func (tasks *BuildReleaseTasks) startSigningCommand(ctx *wf.TaskContext, version string) (string, error) {
872816
args := fmt.Sprintf("--relui_staging=%q", tasks.ScratchURL+"/"+signingStagingDir(ctx, version))
873817
ctx.Printf("run signer with " + args)
@@ -1099,7 +1043,7 @@ func uploadArtifact(scratchFS, servingFS fs.FS, a artifact) error {
10991043
// The version string uses the same format as Go tags. For example, "go1.19rc1".
11001044
func (tasks *BuildReleaseTasks) publishArtifacts(ctx *wf.TaskContext, version string, artifacts []artifact) (publishedVersion string, _ error) {
11011045
for _, a := range artifacts {
1102-
f := &WebsiteFile{
1046+
f := &task.WebsiteFile{
11031047
Filename: a.Filename,
11041048
Version: version,
11051049
ChecksumSHA256: a.SHA256,
@@ -1127,15 +1071,3 @@ func (tasks *BuildReleaseTasks) publishArtifacts(ctx *wf.TaskContext, version st
11271071
ctx.Printf("Published %v artifacts for %v", len(artifacts), version)
11281072
return version, nil
11291073
}
1130-
1131-
// WebsiteFile represents a file on the go.dev downloads page.
1132-
// It should be kept in sync with the download code in x/website/internal/dl.
1133-
type WebsiteFile struct {
1134-
Filename string `json:"filename"`
1135-
OS string `json:"os"`
1136-
Arch string `json:"arch"`
1137-
Version string `json:"version"`
1138-
ChecksumSHA256 string `json:"sha256"`
1139-
Size int64 `json:"size"`
1140-
Kind string `json:"kind"` // "archive", "installer", "source"
1141-
}

Diff for: internal/task/task.go

+91-2
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@
66
package task
77

88
import (
9+
"bytes"
10+
"context"
11+
"sync"
912
"time"
1013

11-
"golang.org/x/build/internal/workflow"
14+
wf "golang.org/x/build/internal/workflow"
1215
)
1316

1417
// CommunicationTasks combines communication tasks together.
@@ -22,7 +25,7 @@ var AwaitDivisor int = 1
2225
// AwaitCondition calls the condition function every period until it returns
2326
// true to indicate success, or an error. If the condition succeeds,
2427
// AwaitCondition returns its result.
25-
func AwaitCondition[T any](ctx *workflow.TaskContext, period time.Duration, condition func() (T, bool, error)) (T, error) {
28+
func AwaitCondition[T any](ctx *wf.TaskContext, period time.Duration, condition func() (T, bool, error)) (T, error) {
2629
pollTimer := time.NewTicker(period / time.Duration(AwaitDivisor))
2730
defer pollTimer.Stop()
2831
for {
@@ -39,3 +42,89 @@ func AwaitCondition[T any](ctx *workflow.TaskContext, period time.Duration, cond
3942
}
4043
}
4144
}
45+
46+
// LogWriter is an io.Writer that writes to a workflow task's log, flushing
47+
// its buffer periodically to avoid too many writes.
48+
type LogWriter struct {
49+
Logger wf.Logger
50+
51+
flushTicker *time.Ticker
52+
53+
mu sync.Mutex
54+
buf []byte
55+
}
56+
57+
func (w *LogWriter) Write(b []byte) (int, error) {
58+
w.mu.Lock()
59+
defer w.mu.Unlock()
60+
61+
w.buf = append(w.buf, b...)
62+
if len(w.buf) > 1<<20 {
63+
w.flushLocked(false)
64+
w.flushTicker.Reset(10 * time.Second)
65+
}
66+
return len(b), nil
67+
}
68+
69+
func (w *LogWriter) flush(force bool) {
70+
w.mu.Lock()
71+
defer w.mu.Unlock()
72+
w.flushLocked(force)
73+
}
74+
75+
func (w *LogWriter) flushLocked(force bool) {
76+
if len(w.buf) == 0 {
77+
return
78+
}
79+
log, rest := w.buf, []byte(nil)
80+
if !force {
81+
nl := bytes.LastIndexByte(w.buf, '\n')
82+
if nl == -1 {
83+
return
84+
}
85+
log, rest = w.buf[:nl], w.buf[nl+1:]
86+
}
87+
w.Logger.Printf("\n%s", string(log))
88+
w.buf = append([]byte(nil), rest...) // don't leak
89+
}
90+
91+
func (w *LogWriter) Run(ctx context.Context) {
92+
w.flushTicker = time.NewTicker(10 * time.Second)
93+
defer w.flushTicker.Stop()
94+
for {
95+
select {
96+
case <-w.flushTicker.C:
97+
w.flush(false)
98+
case <-ctx.Done():
99+
w.flush(true)
100+
return
101+
}
102+
}
103+
}
104+
105+
// WebsiteFile represents a file on the go.dev downloads page.
106+
// It should be kept in sync with the download code in x/website/internal/dl.
107+
type WebsiteFile struct {
108+
Filename string `json:"filename"`
109+
OS string `json:"os"`
110+
Arch string `json:"arch"`
111+
Version string `json:"version"`
112+
ChecksumSHA256 string `json:"sha256"`
113+
Size int64 `json:"size"`
114+
Kind string `json:"kind"` // "archive", "installer", "source"
115+
}
116+
117+
func (f WebsiteFile) GOARCH() string {
118+
if f.OS == "linux" && f.Arch == "armv6l" {
119+
return "arm"
120+
}
121+
return f.Arch
122+
}
123+
124+
type WebsiteRelease struct {
125+
Version string `json:"version"`
126+
Stable bool `json:"stable"`
127+
Files []WebsiteFile `json:"files"`
128+
Visible bool `json:"-"` // show files on page load
129+
SplitPortTable bool `json:"-"` // whether files should be split by primary/other ports.
130+
}

0 commit comments

Comments
 (0)