Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(306)

Delta Between Two Patch Sets: misc/dashboard/builder/main.go

Issue 7326053: code review 7326053: misc/dashboard/builder: various cleanups (Closed)
Left Patch Set: diff -r e93de8482d59 https://code.google.com/p/go Created 12 years ago
Right Patch Set: diff -r a74b58b21d3f https://code.google.com/p/go Created 12 years ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | misc/dashboard/builder/vcs.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2011 The Go Authors. All rights reserved. 1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package main 5 package main
6 6
7 import ( 7 import (
8 "bytes" 8 "bytes"
9 "flag" 9 "flag"
10 "fmt" 10 "fmt"
(...skipping 22 matching lines...) Expand all
33 var extraEnv = []string{ 33 var extraEnv = []string{
34 "CC", 34 "CC",
35 "GOARM", 35 "GOARM",
36 "GOHOSTARCH", 36 "GOHOSTARCH",
37 "GOHOSTOS", 37 "GOHOSTOS",
38 "PATH", 38 "PATH",
39 "TMPDIR", 39 "TMPDIR",
40 } 40 }
41 41
42 type Builder struct { 42 type Builder struct {
43 goroot *Repo
43 name string 44 name string
44 goos, goarch string 45 goos, goarch string
45 key string 46 key string
46 } 47 }
47 48
48 var ( 49 var (
49 buildroot = flag.String("buildroot", defaultBuildRoot(), "Directory under which to build") 50 buildroot = flag.String("buildroot", defaultBuildRoot(), "Directory under which to build")
50 dashboard = flag.String("dashboard", "build.golang.org", "Go Dashbo ard Host") 51 dashboard = flag.String("dashboard", "build.golang.org", "Go Dashbo ard Host")
51 buildRelease = flag.Bool("release", false, "Build and upload binary re lease archives") 52 buildRelease = flag.Bool("release", false, "Build and upload binary re lease archives")
52 buildRevision = flag.String("rev", "", "Build specified revision and ex it") 53 buildRevision = flag.String("rev", "", "Build specified revision and ex it")
53 buildCmd = flag.String("cmd", filepath.Join(".", allCmd), "Build c ommand (specify relative to go/src/)") 54 buildCmd = flag.String("cmd", filepath.Join(".", allCmd), "Build c ommand (specify relative to go/src/)")
54 failAll = flag.Bool("fail", false, "fail all builds") 55 failAll = flag.Bool("fail", false, "fail all builds")
55 parallel = flag.Bool("parallel", false, "Build multiple targets in parallel") 56 parallel = flag.Bool("parallel", false, "Build multiple targets in parallel")
56 buildTimeout = flag.Duration("buildTimeout", 60*time.Minute, "Maximum time to wait for builds and tests") 57 buildTimeout = flag.Duration("buildTimeout", 60*time.Minute, "Maximum time to wait for builds and tests")
57 cmdTimeout = flag.Duration("cmdTimeout", 5*time.Minute, "Maximum tim e to wait for an external command") 58 cmdTimeout = flag.Duration("cmdTimeout", 5*time.Minute, "Maximum tim e to wait for an external command")
58 commitInterval = flag.Duration("commitInterval", 1*time.Minute, "Time to wait between polling for new commits (0 disables commit poller)") 59 commitInterval = flag.Duration("commitInterval", 1*time.Minute, "Time to wait between polling for new commits (0 disables commit poller)")
59 verbose = flag.Bool("v", false, "verbose") 60 verbose = flag.Bool("v", false, "verbose")
60 ) 61 )
61 62
62 var ( 63 var (
63 binaryTagRe = regexp.MustCompile(`^(release\.r|weekly\.)[0-9\-.]+`) 64 binaryTagRe = regexp.MustCompile(`^(release\.r|weekly\.)[0-9\-.]+`)
64 releaseRe = regexp.MustCompile(`^release\.r[0-9\-.]+`) 65 releaseRe = regexp.MustCompile(`^release\.r[0-9\-.]+`)
65 allCmd = "all" + suffix 66 allCmd = "all" + suffix
66 cleanCmd = "clean" + suffix 67 cleanCmd = "clean" + suffix
67 suffix = defaultSuffix() 68 suffix = defaultSuffix()
68
69 goroot *Repo
70 ) 69 )
71 70
72 func main() { 71 func main() {
73 flag.Usage = func() { 72 flag.Usage = func() {
74 fmt.Fprintf(os.Stderr, "usage: %s goos-goarch...\n", os.Args[0]) 73 fmt.Fprintf(os.Stderr, "usage: %s goos-goarch...\n", os.Args[0])
75 flag.PrintDefaults() 74 flag.PrintDefaults()
76 os.Exit(2) 75 os.Exit(2)
77 } 76 }
78 flag.Parse() 77 flag.Parse()
79 if len(flag.Args()) == 0 { 78 if len(flag.Args()) == 0 {
80 flag.Usage() 79 flag.Usage()
81 } 80 }
82 » goroot = &Repo{ 81 » goroot := &Repo{
83 Path: filepath.Join(*buildroot, "goroot"), 82 Path: filepath.Join(*buildroot, "goroot"),
84 } 83 }
85 84
86 // set up work environment, use existing enviroment if possible 85 // set up work environment, use existing enviroment if possible
87 if goroot.Exists() { 86 if goroot.Exists() {
88 log.Print("Found old workspace, will use it") 87 log.Print("Found old workspace, will use it")
89 } else { 88 } else {
90 if err := os.RemoveAll(*buildroot); err != nil { 89 if err := os.RemoveAll(*buildroot); err != nil {
91 log.Fatalf("Error removing build root (%s): %s", *buildr oot, err) 90 log.Fatalf("Error removing build root (%s): %s", *buildr oot, err)
92 } 91 }
93 if err := os.Mkdir(*buildroot, mkdirPerm); err != nil { 92 if err := os.Mkdir(*buildroot, mkdirPerm); err != nil {
94 log.Fatalf("Error making build root (%s): %s", *buildroo t, err) 93 log.Fatalf("Error making build root (%s): %s", *buildroo t, err)
95 } 94 }
96 var err error 95 var err error
97 goroot, err = RemoteRepo(hgUrl).Clone(goroot.Path, "tip") 96 goroot, err = RemoteRepo(hgUrl).Clone(goroot.Path, "tip")
98 if err != nil { 97 if err != nil {
99 log.Fatal("Error cloning repository:", err) 98 log.Fatal("Error cloning repository:", err)
100 } 99 }
101 } 100 }
102 101
103 // set up builders 102 // set up builders
104 builders := make([]*Builder, len(flag.Args())) 103 builders := make([]*Builder, len(flag.Args()))
105 » for i, builder := range flag.Args() { 104 » for i, name := range flag.Args() {
106 » » b, err := NewBuilder(builder) 105 » » b, err := NewBuilder(goroot, name)
107 if err != nil { 106 if err != nil {
108 log.Fatal(err) 107 log.Fatal(err)
109 } 108 }
110 builders[i] = b 109 builders[i] = b
111 } 110 }
112 111
113 if *failAll { 112 if *failAll {
114 failMode(builders) 113 failMode(builders)
115 return 114 return
116 } 115 }
117 116
118 // if specified, build revision and return 117 // if specified, build revision and return
119 if *buildRevision != "" { 118 if *buildRevision != "" {
120 hash, err := goroot.FullHash(*buildRevision) 119 hash, err := goroot.FullHash(*buildRevision)
121 if err != nil { 120 if err != nil {
122 log.Fatal("Error finding revision: ", err) 121 log.Fatal("Error finding revision: ", err)
123 } 122 }
124 for _, b := range builders { 123 for _, b := range builders {
125 if err := b.buildHash(hash); err != nil { 124 if err := b.buildHash(hash); err != nil {
126 log.Println(err) 125 log.Println(err)
127 } 126 }
128 } 127 }
129 return 128 return
130 } 129 }
131 130
132 // Start commit watcher 131 // Start commit watcher
133 » go commitWatcher() 132 » go commitWatcher(goroot)
134 133
135 // go continuous build mode 134 // go continuous build mode
136 // check for new commits and build them 135 // check for new commits and build them
137 for { 136 for {
138 built := false 137 built := false
139 t := time.Now() 138 t := time.Now()
140 if *parallel { 139 if *parallel {
141 done := make(chan bool) 140 done := make(chan bool)
142 for _, b := range builders { 141 for _, b := range builders {
143 go func(b *Builder) { 142 go func(b *Builder) {
(...skipping 28 matching lines...) Expand all
172 for _, b := range builders { 171 for _, b := range builders {
173 built = b.failBuild() || built 172 built = b.failBuild() || built
174 } 173 }
175 // stop if there was nothing to fail 174 // stop if there was nothing to fail
176 if !built { 175 if !built {
177 break 176 break
178 } 177 }
179 } 178 }
180 } 179 }
181 180
182 func NewBuilder(builder string) (*Builder, error) { 181 func NewBuilder(goroot *Repo, name string) (*Builder, error) {
183 » b := &Builder{name: builder} 182 » b := &Builder{
183 » » goroot: goroot,
184 » » name: name,
185 » }
184 186
185 // get goos/goarch from builder string 187 // get goos/goarch from builder string
186 » s := strings.SplitN(builder, "-", 3) 188 » s := strings.SplitN(b.name, "-", 3)
187 if len(s) >= 2 { 189 if len(s) >= 2 {
188 b.goos, b.goarch = s[0], s[1] 190 b.goos, b.goarch = s[0], s[1]
189 } else { 191 } else {
190 » » return nil, fmt.Errorf("unsupported builder form: %s", builder) 192 » » return nil, fmt.Errorf("unsupported builder form: %s", name)
191 } 193 }
192 194
193 // read keys from keyfile 195 // read keys from keyfile
194 fn := "" 196 fn := ""
195 if runtime.GOOS == "windows" { 197 if runtime.GOOS == "windows" {
196 fn = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") 198 fn = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
197 } else { 199 } else {
198 fn = os.Getenv("HOME") 200 fn = os.Getenv("HOME")
199 } 201 }
200 fn = filepath.Join(fn, ".gobuildkey") 202 fn = filepath.Join(fn, ".gobuildkey")
(...skipping 14 matching lines...) Expand all
215 func (b *Builder) build() bool { 217 func (b *Builder) build() bool {
216 hash, err := b.todo("build-go-commit", "", "") 218 hash, err := b.todo("build-go-commit", "", "")
217 if err != nil { 219 if err != nil {
218 log.Println(err) 220 log.Println(err)
219 return false 221 return false
220 } 222 }
221 if hash == "" { 223 if hash == "" {
222 return false 224 return false
223 } 225 }
224 226
225 » // Look for hash locally before running hg pull. 227 » if err := b.buildHash(hash); err != nil {
226 » log.Println("looking for hash", hash)
227 » if _, err := goroot.FullHash(hash[:12]); err != nil {
228 » » // Don't have hash, so run hg pull.
229 » » log.Printf("Repo: %v does not have hash %s, pulling", goroot, ha sh)
230 » » if err := goroot.Pull(); err != nil {
231 » » » log.Println("hg pull failed:", err)
232 » » » return false
233 » » }
234 » }
235
236 » err = b.buildHash(hash)
237 » if err != nil {
238 log.Println(err) 228 log.Println(err)
239 } 229 }
240 return true 230 return true
241 } 231 }
242 232
243 func (b *Builder) buildHash(hash string) error { 233 func (b *Builder) buildHash(hash string) error {
244 log.Println(b.name, "building", hash) 234 log.Println(b.name, "building", hash)
245 235
246 // create place in which to do work 236 // create place in which to do work
247 workpath := filepath.Join(*buildroot, b.name+"-"+hash[:12]) 237 workpath := filepath.Join(*buildroot, b.name+"-"+hash[:12])
248 if err := os.Mkdir(workpath, mkdirPerm); err != nil { 238 if err := os.Mkdir(workpath, mkdirPerm); err != nil {
249 return err 239 return err
250 } 240 }
251 defer os.RemoveAll(workpath) 241 defer os.RemoveAll(workpath)
252 242
253 // pull before cloning to ensure we have the revision 243 // pull before cloning to ensure we have the revision
254 » if err := goroot.Pull(); err != nil { 244 » if err := b.goroot.Pull(); err != nil {
255 return err 245 return err
256 } 246 }
257 247
258 // clone repo at specified revision 248 // clone repo at specified revision
259 » if _, err := goroot.Clone(filepath.Join(workpath, "go"), hash); err != n il { 249 » if _, err := b.goroot.Clone(filepath.Join(workpath, "go"), hash); err != nil {
260 return err 250 return err
261 } 251 }
262 252
263 srcDir := filepath.Join(workpath, "go", "src") 253 srcDir := filepath.Join(workpath, "go", "src")
264 254
265 // build 255 // build
266 var buildlog bytes.Buffer 256 var buildlog bytes.Buffer
267 logfile := filepath.Join(workpath, "build.log") 257 logfile := filepath.Join(workpath, "build.log")
268 f, err := os.Create(logfile) 258 f, err := os.Create(logfile)
269 if err != nil { 259 if err != nil {
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 s, err := os.Stat(name) 451 s, err := os.Stat(name)
462 return err == nil && s.IsDir() 452 return err == nil && s.IsDir()
463 } 453 }
464 454
465 func isFile(name string) bool { 455 func isFile(name string) bool {
466 s, err := os.Stat(name) 456 s, err := os.Stat(name)
467 return err == nil && !s.IsDir() 457 return err == nil && !s.IsDir()
468 } 458 }
469 459
470 // commitWatcher polls hg for new commits and tells the dashboard about them. 460 // commitWatcher polls hg for new commits and tells the dashboard about them.
471 func commitWatcher() { 461 func commitWatcher(goroot *Repo) {
472 if *commitInterval == 0 { 462 if *commitInterval == 0 {
473 log.Printf("commitInterval is %s, disabling commitWatcher", *com mitInterval) 463 log.Printf("commitInterval is %s, disabling commitWatcher", *com mitInterval)
474 return 464 return
475 } 465 }
476 // Create builder just to get master key. 466 // Create builder just to get master key.
477 » b, err := NewBuilder("mercurial-commit") 467 » b, err := NewBuilder(goroot, "mercurial-commit")
478 if err != nil { 468 if err != nil {
479 log.Fatal(err) 469 log.Fatal(err)
480 } 470 }
481 key := b.key 471 key := b.key
482 472
483 for { 473 for {
484 if *verbose { 474 if *verbose {
485 log.Printf("poll...") 475 log.Printf("poll...")
486 } 476 }
487 // Main Go repository. 477 // Main Go repository.
488 » » commitPoll(key, "") 478 » » commitPoll(goroot, "", key)
489 // Go sub-repositories. 479 // Go sub-repositories.
490 for _, pkg := range dashboardPackages("subrepo") { 480 for _, pkg := range dashboardPackages("subrepo") {
491 » » » commitPoll(key, pkg) 481 » » » pkgroot := &Repo{
482 » » » » Path: filepath.Join(*buildroot, pkg),
483 » » » }
484 » » » commitPoll(pkgroot, pkg, key)
492 } 485 }
493 if *verbose { 486 if *verbose {
494 log.Printf("sleep...") 487 log.Printf("sleep...")
495 } 488 }
496 time.Sleep(*commitInterval) 489 time.Sleep(*commitInterval)
497 } 490 }
498 } 491 }
499 492
493 // logByHash is a cache of all Mercurial revisions we know about,
494 // indexed by full hash.
495 var logByHash = map[string]*HgLog{}
496
500 // commitPoll pulls any new revisions from the hg server 497 // commitPoll pulls any new revisions from the hg server
501 // and tells the server about them. 498 // and tells the server about them.
502 func commitPoll(key, pkg string) { 499 func commitPoll(repo *Repo, pkg, key string) {
503 » pkgRoot := goroot 500 » if !repo.Exists() {
504 501 » » var err error
505 » if pkg != "" { 502 » » repo, err = RemoteRepo(repoURL(pkg)).Clone(repo.Path, "tip")
506 » » pkgRoot = &Repo{ 503 » » if err != nil {
507 » » » Path: filepath.Join(*buildroot, pkg), 504 » » » log.Printf("%s: hg clone failed: %v", pkg, err)
508 » » } 505 » » » if err := os.RemoveAll(repo.Path); err != nil {
509 » » if !pkgRoot.Exists() { 506 » » » » log.Printf("%s: %v", pkg, err)
510 » » » var err error
511 » » » pkgRoot, err = RemoteRepo(repoURL(pkg)).Clone(pkgRoot.Pa th, "tip")
512 » » » if err != nil {
513 » » » » log.Printf("%s: hg clone failed: %v", pkg, err)
514 » » » » if err := os.RemoveAll(pkgRoot.Path); err != nil {
515 » » » » » log.Printf("%s: %v", pkg, err)
516 » » » » }
517 » » » » return
518 } 507 }
519 } 508 }
520 }
521
522 if err := pkgRoot.Pull(); err != nil {
523 log.Printf("hg pull: %v", err)
524 return 509 return
525 } 510 }
526 511
527 » logs, err := pkgRoot.Log() 512 » logs, err := repo.Log() // repo.Log calls repo.Pull internally
528 if err != nil { 513 if err != nil {
529 log.Printf("hg log: %v", err) 514 log.Printf("hg log: %v", err)
530 return 515 return
531 } 516 }
532 517
533 // Pass 1. Fill in parents and add new log entries to logsByHash. 518 // Pass 1. Fill in parents and add new log entries to logsByHash.
534 // Empty parent means take parent from next log entry. 519 // Empty parent means take parent from next log entry.
535 // Non-empty parent has form 1234:hashhashhash; we want full hash. 520 // Non-empty parent has form 1234:hashhashhash; we want full hash.
536 for i := range logs { 521 for i := range logs {
537 l := &logs[i] 522 l := &logs[i]
538 if l.Parent == "" && i+1 < len(logs) { 523 if l.Parent == "" && i+1 < len(logs) {
539 l.Parent = logs[i+1].Hash 524 l.Parent = logs[i+1].Hash
540 } else if l.Parent != "" { 525 } else if l.Parent != "" {
541 » » » l.Parent, _ = pkgRoot.FullHash(l.Parent) 526 » » » l.Parent, _ = repo.FullHash(l.Parent)
542 } 527 }
543 if *verbose { 528 if *verbose {
544 log.Printf("hg log %s: %s < %s\n", pkg, l.Hash, l.Parent ) 529 log.Printf("hg log %s: %s < %s\n", pkg, l.Hash, l.Parent )
545 } 530 }
546 if logByHash[l.Hash] == nil { 531 if logByHash[l.Hash] == nil {
547 // Make copy to avoid pinning entire slice when only one entry is new. 532 // Make copy to avoid pinning entire slice when only one entry is new.
548 t := *l 533 t := *l
549 logByHash[t.Hash] = &t 534 logByHash[t.Hash] = &t
550 } 535 }
551 } 536 }
552 537
553 » for i := range logs { 538 » for _, l := range logs {
554 » » l := &logs[i]
555 addCommit(pkg, l.Hash, key) 539 addCommit(pkg, l.Hash, key)
556 } 540 }
557 } 541 }
558 542
559 // addCommit adds the commit with the named hash to the dashboard. 543 // addCommit adds the commit with the named hash to the dashboard.
560 // key is the secret key for authentication to the dashboard. 544 // key is the secret key for authentication to the dashboard.
561 // It avoids duplicate effort. 545 // It avoids duplicate effort.
562 func addCommit(pkg, hash, key string) bool { 546 func addCommit(pkg, hash, key string) bool {
563 l := logByHash[hash] 547 l := logByHash[hash]
564 if l == nil { 548 if l == nil {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 return v, true 619 return v, true
636 } 620 }
637 keq := k + "=" 621 keq := k + "="
638 for _, kv := range os.Environ() { 622 for _, kv := range os.Environ() {
639 if kv == keq { 623 if kv == keq {
640 return "", true 624 return "", true
641 } 625 }
642 } 626 }
643 return "", false 627 return "", false
644 } 628 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b