blob: 7f6a12b720df790707fbb2eeebbb9d77a2284e6a [file] [log] [blame]
package autoroll
import (
"fmt"
"regexp"
"strings"
)
import (
"skia.googlesource.com/buildbot.git/go/gitinfo"
"skia.googlesource.com/buildbot.git/go/rietveld"
)
const (
RIETVELD_URL string = "http://codereview.chromium.org"
AUTO_ROLL_AUTHOR string = "skia-deps-roller@chromium.org"
STATUS_IDLE string = "Idle"
STATUS_ACTIVE string = "Active"
STATUS_STOPPED string = "Stopped"
)
// CurrentRoll returns a rietveld.Issue corresponding to the current roll, or
// nil if no roll is in progress.
func CurrentRoll() (*rietveld.Issue, error) {
open := true
inProgress, err := rietveld.New(RIETVELD_URL).Search(
rietveld.SearchOwner(AUTO_ROLL_AUTHOR),
rietveld.SearchOpen(open),
)
if err != nil {
return nil, fmt.Errorf("Unable to obtain current roll: %v", err)
}
if len(inProgress) == 0 {
return nil, nil
}
return inProgress[0], nil
}
// rollRevision returns the commit hash to which the given Issue rolls.
func rollRevision(roll *rietveld.Issue, skiaRepo *gitinfo.GitInfo) (string, error) {
re := regexp.MustCompile("Roll .* [0-9a-f]+:([0-9a-f]+)")
badFmtMsg := fmt.Errorf("DEPS roll CL subject line doesn't match expected format (%d)", roll.Issue)
match := re.FindAllStringSubmatch(roll.Subject, -1)
if match == nil {
return "", badFmtMsg
}
if len(match) != 1 {
return "", badFmtMsg
}
if len(match[0]) != 2 {
return "", badFmtMsg
}
rev, err := skiaRepo.FullHash(match[0][1])
if err != nil {
return "", fmt.Errorf("Could not find revision %s: %v", match[0][1], err)
}
return rev, nil
}
// LastRollRevision returns the commit hash for the last-completed roll.
func LastRollRevision(skiaRepo, chromiumRepo *gitinfo.GitInfo) (string, error) {
deps, err := chromiumRepo.GetFile("DEPS", "origin/master")
if err != nil {
return "", err
}
re := regexp.MustCompile("'skia_revision': '([0-9a-f]+)',")
match := re.FindAllStringSubmatch(deps, -1)
err = fmt.Errorf("Failed to parse the skia_revision from the DEPS file: \n%s", deps)
if match == nil {
return "", err
}
if len(match) != 1 {
return "", err
}
if len(match[0]) != 2 {
return "", err
}
return match[0][1], nil
}
// AutoRollStatus is a summary of the current status of the DEPS roller.
type AutoRollStatus struct {
LastRollRevision string
CurrentRollRevision string
CurrentRoll *rietveld.Issue
Head string
Status string
}
// CurrentStatus returns an up-to-date AutoRollStatus object.
func CurrentStatus(skiaRepo, chromiumRepo *gitinfo.GitInfo) (*AutoRollStatus, error) {
currentRoll, err := CurrentRoll()
if err != nil {
return nil, fmt.Errorf("Could not obtain current AutoRoll status: %v", err)
}
currentRollRev := "None"
status := STATUS_IDLE
if currentRoll != nil {
currentRollRev, err = rollRevision(currentRoll, skiaRepo)
if err != nil {
return nil, err
}
status = STATUS_ACTIVE
for _, m := range currentRoll.Messages {
if strings.Contains(m.Text, "STOP") {
status = STATUS_STOPPED
break
}
}
}
head, err := skiaRepo.FullHash("origin/master")
if err != nil {
return nil, fmt.Errorf("Unable to determine current AutoRoll status: %v", err)
}
lastRev, err := LastRollRevision(skiaRepo, chromiumRepo)
return &AutoRollStatus{
LastRollRevision: lastRev,
CurrentRollRevision: currentRollRev,
CurrentRoll: currentRoll,
Head: head,
Status: status,
}, nil
}