blob: abef8faa48eb66c48b18fa3de6802176ddcece5b [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"
"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
}