blob: 4546f855a4f3872662b8b5f84911e1d146475d6e [file] [log] [blame]
// 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"
)
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
switch meth {
case "GET":
if args != nil {
m := make(map[string][]string)
for k, v := range args {
m[k] = []string{v}
}
cmd += "?" + http.EncodeQuery(m)
}
r, err = http.Get(cmd)
case "POST":
r, err = http.PostForm(cmd, args)
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 to the dashboard
func (b *Builder) updatePackage(pkg string, state bool, buildLog, info string, hash string) os.Error {
return dash("POST", "package", nil, param{
"builder": b.name,
"key": b.key,
"path": pkg,
"state": strconv.Btoa(state),
"log": buildLog,
"info": info,
"go_rev": hash[:12],
})
}
// 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
}