| // Copyright 2011 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package main |
| |
| import ( |
| "bytes" |
| "fmt" |
| "http" |
| "json" |
| "log" |
| "os" |
| "strconv" |
| "url" |
| ) |
| |
| type param map[string]string |
| |
| // dash runs the given method and command on the dashboard. |
| // If args is not nil, it is the query or post parameters. |
| // If resp is not nil, dash unmarshals the body as JSON into resp. |
| func dash(meth, cmd string, resp interface{}, args param) os.Error { |
| var r *http.Response |
| var err os.Error |
| if *verbose { |
| log.Println("dash", cmd, args) |
| } |
| cmd = "http://" + *dashboard + "/" + cmd |
| vals := make(url.Values) |
| for k, v := range args { |
| vals.Add(k, v) |
| } |
| switch meth { |
| case "GET": |
| if q := vals.Encode(); q != "" { |
| cmd += "?" + q |
| } |
| r, err = http.Get(cmd) |
| case "POST": |
| r, err = http.PostForm(cmd, vals) |
| default: |
| return fmt.Errorf("unknown method %q", meth) |
| } |
| if err != nil { |
| return err |
| } |
| defer r.Body.Close() |
| var buf bytes.Buffer |
| buf.ReadFrom(r.Body) |
| if resp != nil { |
| if err = json.Unmarshal(buf.Bytes(), resp); err != nil { |
| log.Printf("json unmarshal %#q: %s\n", buf.Bytes(), err) |
| return err |
| } |
| } |
| return nil |
| } |
| |
| func dashStatus(meth, cmd string, args param) os.Error { |
| var resp struct { |
| Status string |
| Error string |
| } |
| err := dash(meth, cmd, &resp, args) |
| if err != nil { |
| return err |
| } |
| if resp.Status != "OK" { |
| return os.NewError("/build: " + resp.Error) |
| } |
| return nil |
| } |
| |
| // todo returns the next hash to build. |
| func (b *Builder) todo() (rev string, err os.Error) { |
| var resp []struct { |
| Hash string |
| } |
| if err = dash("GET", "todo", &resp, param{"builder": b.name}); err != nil { |
| return |
| } |
| if len(resp) > 0 { |
| rev = resp[0].Hash |
| } |
| return |
| } |
| |
| // recordResult sends build results to the dashboard |
| func (b *Builder) recordResult(buildLog string, hash string) os.Error { |
| return dash("POST", "build", nil, param{ |
| "builder": b.name, |
| "key": b.key, |
| "node": hash, |
| "log": buildLog, |
| }) |
| } |
| |
| // packages fetches a list of package paths from the dashboard |
| func packages() (pkgs []string, err os.Error) { |
| var resp struct { |
| Packages []struct { |
| Path string |
| } |
| } |
| err = dash("GET", "package", &resp, param{"fmt": "json"}) |
| if err != nil { |
| return |
| } |
| for _, p := range resp.Packages { |
| pkgs = append(pkgs, p.Path) |
| } |
| return |
| } |
| |
| // updatePackage sends package build results and info dashboard |
| func (b *Builder) updatePackage(pkg string, ok bool, buildLog, info string) os.Error { |
| return dash("POST", "package", nil, param{ |
| "builder": b.name, |
| "key": b.key, |
| "path": pkg, |
| "ok": strconv.Btoa(ok), |
| "log": buildLog, |
| "info": info, |
| }) |
| } |
| |
| // postCommit informs the dashboard of a new commit |
| func postCommit(key string, l *HgLog) os.Error { |
| return dashStatus("POST", "commit", param{ |
| "key": key, |
| "node": l.Hash, |
| "date": l.Date, |
| "user": l.Author, |
| "parent": l.Parent, |
| "desc": l.Desc, |
| }) |
| } |
| |
| // dashboardCommit returns true if the dashboard knows about hash. |
| func dashboardCommit(hash string) bool { |
| err := dashStatus("GET", "commit", param{"node": hash}) |
| if err != nil { |
| log.Printf("check %s: %s", hash, err) |
| return false |
| } |
| return true |
| } |