SHA256
1
0
forked from adamm/autogits

staging: refactor

This commit is contained in:
2025-04-28 19:44:32 +02:00
parent 248ec4d03c
commit 82b5b105b1
5 changed files with 224 additions and 179 deletions

View File

@@ -37,8 +37,14 @@ import (
//go:generate mockgen -source=obs_utils.go -destination=mock/obs_utils.go -typed
type BuildResultOptions struct {
BinaryList bool
OldState string
LastBuild bool
}
type ObsStatusFetcherWithState interface {
BuildStatusWithState(project string, oldstate string, packages ...string) (*BuildResultList, error)
BuildStatusWithState(project string, opts *BuildResultOptions, packages ...string) (*BuildResultList, error)
}
type ObsClient struct {
@@ -699,20 +705,28 @@ func (c *ObsClient) ProjectConfig(project string) (string, error) {
}
func (c *ObsClient) BuildStatus(project string, packages ...string) (*BuildResultList, error) {
return c.BuildStatusWithState(project, "", packages...)
return c.BuildStatusWithState(project, &BuildResultOptions{}, packages...)
}
func (c *ObsClient) BuildStatusWithState(project string, oldstate string, packages ...string) (*BuildResultList, error) {
func (c *ObsClient) LastBuildResults(project string, packages ...string) (*BuildResultList, error) {
return c.BuildStatusWithState(project, &BuildResultOptions{LastBuild: true}, packages...)
}
func (c *ObsClient) BuildStatusWithState(project string, opts *BuildResultOptions, packages ...string) (*BuildResultList, error) {
u := c.baseUrl.JoinPath("build", project, "_result")
query := u.Query()
query.Add("view", "status")
// query.Add("view", "binarylist")
if opts.BinaryList {
query.Add("view", "binarylist")
}
query.Add("multibuild", "1")
if len(oldstate) > 0 {
query.Add("oldstate", oldstate)
if len(opts.OldState) > 0 {
query.Add("oldstate", opts.OldState)
}
if opts.LastBuild {
query.Add("lastbuild", "1")
}
if len(packages) > 0 {
query.Add("lastbuild", "1")
for _, pkg := range packages {
query.Add("package", pkg)
}

View File

@@ -20,6 +20,7 @@ package main
import (
"encoding/xml"
"errors"
"flag"
"fmt"
"net/url"
@@ -47,10 +48,10 @@ const (
var GiteaToken string
var runId uint
func fetchPrGit(git common.Git, pr *models.PullRequest) error {
func FetchPrGit(git common.Git, pr *models.PullRequest) error {
// clone PR head and base and return path
cloneURL := pr.Head.Repo.CloneURL
if giteaUseSshClone {
if GiteaUseSshClone {
cloneURL = pr.Head.Repo.SSHURL
}
if _, err := os.Stat(path.Join(git.GetPath(), pr.Head.Sha)); os.IsNotExist(err) {
@@ -63,7 +64,7 @@ func fetchPrGit(git common.Git, pr *models.PullRequest) error {
return nil
}
func getObsProjectAssociatedWithPr(baseProject string, pr *models.PullRequest) string {
func GetObsProjectAssociatedWithPr(baseProject string, pr *models.PullRequest) string {
if pr.Base.Repo.Name == common.DefaultGitPrj {
// if default project git, we don't need it in project name to be unique
return fmt.Sprintf(
@@ -100,7 +101,7 @@ const (
BuildStatusSummaryUnknown = 4
)
func processBuildStatus(project, refProject *common.BuildResultList) BuildStatusSummary {
func ProcessBuildStatus(project, refProject *common.BuildResultList) BuildStatusSummary {
if _, finished := project.BuildResultSummary(); !finished {
return BuildStatusSummaryBuilding
}
@@ -171,7 +172,7 @@ func processBuildStatus(project, refProject *common.BuildResultList) BuildStatus
}
common.LogDebug(" found match for @ idx:", j)
res := processRepoBuildStatus(project.Result[i].Status, refProject.Result[j].Status)
res := ProcessRepoBuildStatus(project.Result[i].Status, refProject.Result[j].Status)
switch res {
case BuildStatusSummarySuccess:
break found
@@ -190,7 +191,7 @@ func processBuildStatus(project, refProject *common.BuildResultList) BuildStatus
return BuildStatusSummarySuccess
}
func processRepoBuildStatus(results, ref []common.PackageBuildStatus) BuildStatusSummary {
func ProcessRepoBuildStatus(results, ref []common.PackageBuildStatus) BuildStatusSummary {
PackageBuildStatusSorter := func(a, b common.PackageBuildStatus) int {
return strings.Compare(a.Package, b.Package)
}
@@ -237,9 +238,9 @@ func processRepoBuildStatus(results, ref []common.PackageBuildStatus) BuildStatu
return BuildStatusSummarySuccess
}
func generateObsPrjMeta(git common.Git, gitea common.Gitea, pr *models.PullRequest, obsClient *common.ObsClient, buildPrj string) (*common.ProjectMeta, error) {
func GenerateObsPrjMeta(git common.Git, gitea common.Gitea, pr *models.PullRequest, obsClient *common.ObsClient, buildPrj string) (*common.ProjectMeta, error) {
common.LogDebug("repo content fetching ...")
err := fetchPrGit(git, pr)
err := FetchPrGit(git, pr)
if err != nil {
common.LogError("Cannot fetch PR git:", pr.URL)
return nil, err
@@ -272,12 +273,12 @@ func generateObsPrjMeta(git common.Git, gitea common.Gitea, pr *models.PullReque
// generate new project with paths pointinig back to original repos
// disable publishing
meta.Name = getObsProjectAssociatedWithPr(buildPrj, pr)
meta.Name = GetObsProjectAssociatedWithPr(buildPrj, pr)
meta.Description = fmt.Sprintf(`Pull request build job PR#%d to branch %s of %s/%s`,
pr.Index, pr.Base.Name, pr.Base.Repo.Owner.UserName, pr.Base.Repo.Name)
meta.Url = fmt.Sprintf(
"%s/%s/%s/pulls/%d",
giteaUrl,
GiteaUrl,
url.PathEscape(pr.Base.Repo.Owner.UserName),
url.PathEscape(pr.Base.Repo.Name),
pr.Index,
@@ -308,7 +309,7 @@ func generateObsPrjMeta(git common.Git, gitea common.Gitea, pr *models.PullReque
// stagingProject:$buildProject
// ^- stagingProject:$buildProject:$subProjectName (based on templateProject)
func createQASubProject(git common.Git, gitea common.Gitea, pr *models.PullRequest, obsClient *common.ObsClient, buildProject, stagingProject, templateProject, subProjectName string) error {
func CreateQASubProject(git common.Git, gitea common.Gitea, pr *models.PullRequest, obsClient *common.ObsClient, buildProject, stagingProject, templateProject, subProjectName string) error {
common.LogDebug("Setup QA sub projects")
templateMeta, err := obsClient.GetProjectMeta(templateProject)
if err != nil {
@@ -333,17 +334,22 @@ func createQASubProject(git common.Git, gitea common.Gitea, pr *models.PullReque
}
}
err = obsClient.SetProjectMeta(templateMeta)
if err != nil {
common.LogError("cannot create project:", templateMeta.Name, err)
return err
if !IsDryRun {
err = obsClient.SetProjectMeta(templateMeta)
if err != nil {
common.LogError("cannot create project:", templateMeta.Name, err)
return err
}
} else {
common.LogDebug("Create project:", templateMeta.Name)
common.LogDebug(templateMeta)
}
return nil
}
func startOrUpdateBuild(git common.Git, gitea common.Gitea, pr *models.PullRequest, obsClient *common.ObsClient, baseProject string) (RequestModification, error) {
func StartOrUpdateBuild(git common.Git, gitea common.Gitea, pr *models.PullRequest, obsClient *common.ObsClient, baseProject string) (RequestModification, error) {
common.LogDebug("fetching OBS project Meta")
obsPrProject := getObsProjectAssociatedWithPr(baseProject, pr)
obsPrProject := GetObsProjectAssociatedWithPr(baseProject, pr)
meta, err := obsClient.GetProjectMeta(obsPrProject)
if err != nil {
common.LogError("error fetching project meta for", obsPrProject, ":", err)
@@ -368,15 +374,16 @@ func startOrUpdateBuild(git common.Git, gitea common.Gitea, pr *models.PullReque
var state RequestModification = RequestModificationSourceChanged
if meta == nil {
// new build
meta, err = generateObsPrjMeta(git, gitea, pr, obsClient, baseProject)
meta, err = GenerateObsPrjMeta(git, gitea, pr, obsClient, baseProject)
if err != nil {
return RequestModificationNoChange, err
}
state = RequestModificationProjectCreated
}
if dryRun {
if IsDryRun {
x, _ := xml.MarshalIndent(meta, "", " ")
common.LogDebug("Creating build project:")
common.LogDebug(" meta:", x)
} else {
err = obsClient.SetProjectMeta(meta)
@@ -389,7 +396,51 @@ func startOrUpdateBuild(git common.Git, gitea common.Gitea, pr *models.PullReque
return state, nil
}
func processPullNotification(gitea common.Gitea, thread *models.NotificationThread) {
func IsReviewerRequested(pr *models.PullRequest) bool {
for _, reviewer := range pr.RequestedReviewers {
if reviewer.UserName == Username {
return true
}
}
return false
}
var NonActionableReviewError = errors.New("Ignoring non-actionable review request. Marking as done.")
var NoReviewsFoundError = errors.New("No review requests found for the review user. Marking as done.")
func FetchOurLatestActionableReview(gitea common.Gitea, org, repo string, id int64) (*models.PullReview, error) {
reviews, err := gitea.GetPullRequestReviews(org, repo, id)
if err != nil {
return nil, err
}
slices.SortFunc(reviews, func(a, b *models.PullReview) int {
return time.Time(a.Submitted).Compare(time.Time(b.Submitted))
})
for idx := len(reviews) - 1; idx >= 0; idx-- {
review := reviews[idx]
if review.User != nil || review.User.UserName == Username {
if IsDryRun {
// for purposes of moving forward a no-op check
return review, nil
}
switch review.State {
default:
// non-actionable state, mark as done
common.LogInfo("Ignoring non-actionable review request. Marking as done.")
return nil, NonActionableReviewError
case common.ReviewStatePending, common.ReviewStateRequestReview:
return review, nil
}
}
}
return nil, NoReviewsFoundError
}
func ProcessPullNotification(gitea common.Gitea, thread *models.NotificationThread) {
defer func() {
err := recover()
if err != nil {
@@ -398,12 +449,6 @@ func processPullNotification(gitea common.Gitea, thread *models.NotificationThre
}
}()
dir, err := os.MkdirTemp(os.TempDir(), BotName)
common.PanicOnError(err)
defer os.RemoveAll(dir)
gh, err := common.AllocateGitWorkTree(dir, GitAuthor, "noaddress@suse.de")
common.PanicOnError(err)
rx := regexp.MustCompile(`^https://src\.(?:open)?suse\.(?:org|de)/api/v\d+/repos/(?<org>[-_a-zA-Z0-9]+)/(?<project>[-_a-zA-Z0-9]+)/issues/(?<num>[0-9]+)$`)
notification := thread.Subject
match := rx.FindStringSubmatch(notification.URL)
@@ -421,155 +466,135 @@ func processPullNotification(gitea common.Gitea, thread *models.NotificationThre
repo := match[2]
id, _ := strconv.ParseInt(match[3], 10, 64)
err := ProcessPullRequest(gitea, org, repo, id)
if !IsDryRun && err == nil {
gitea.SetNotificationRead(thread.ID)
} else if err != nil {
common.LogError(err)
}
}
func ProcessPullRequest(gitea common.Gitea, org, repo string, id int64) error {
dir, err := os.MkdirTemp(os.TempDir(), BotName)
common.PanicOnError(err)
defer os.RemoveAll(dir)
gh, err := common.AllocateGitWorkTree(dir, GitAuthor, "noaddress@suse.de")
common.PanicOnError(err)
git, err := gh.CreateGitHandler(org)
common.PanicOnError(err)
pr, err := gitea.GetPullRequest(org, repo, id)
if err != nil {
common.LogError("No PR associated with review:", notification.URL, "Error:", err)
return
common.LogError("No PR associated with review:", org, "/", repo, "#", id, "Error:", err)
return err
}
common.LogDebug("PR state:", pr.State)
if pr.State == "closed" {
// dismiss the review
common.LogInfo(" -- closed request, so nothing to review")
gitea.SetNotificationRead(thread.ID)
return
return nil
}
reviews, err := gitea.GetPullRequestReviews(org, repo, id)
obsClient, err := common.NewObsClient(ObsApiHost)
if err != nil {
common.LogInfo("No reviews associated with request:", notification.URL, "Error:", err)
return
}
obsClient, err := common.NewObsClient(obsApiHost)
if err != nil {
common.LogError(err)
return
return err
}
if len(BuildRoot) > 0 {
obsClient.HomeProject = BuildRoot
}
reviewRequested := false
for _, reviewer := range pr.RequestedReviewers {
if reviewer.UserName == Username {
reviewRequested = true
break
}
}
if !reviewRequested {
if !IsReviewerRequested(pr) && !IsDryRun {
common.LogError("Review not requested in notification. Setting to status 'read'")
gitea.SetNotificationRead(thread.ID)
return
return nil
}
newReviews := make([]*models.PullReview, 0, len(reviews))
for _, review := range reviews {
if review.User != nil && (review.User.UserName == Username) {
newReviews = append(newReviews, review)
}
}
reviews = newReviews
if review, err := FetchOurLatestActionableReview(gitea, org, repo, id); err == nil {
common.LogInfo("processing review", review.HTMLURL, "state", review.State)
slices.SortFunc(reviews, func(a, b *models.PullReview) int {
return time.Time(a.Submitted).Compare(time.Time(b.Submitted))
})
// find review request or review in progress...
for idx := len(reviews) - 1; idx >= 0; idx-- {
review := reviews[idx]
if review.User.UserName != Username {
continue
err = FetchPrGit(git, pr)
if err != nil {
common.LogError("Cannot fetch PR git:", pr.URL)
return err
}
common.LogInfo("processing review", idx, "state", review.State)
// find modified submodules and new submodules -- build them
dir := pr.Head.Sha
headSubmodules, err := git.GitSubmoduleList(dir, pr.Head.Sha)
common.PanicOnError(err)
baseSubmodules, err := git.GitSubmoduleList(dir, pr.Base.Sha)
common.PanicOnError(err)
switch review.State {
modifiedOrNew := make([]string, 0, 16)
for pkg, headOid := range headSubmodules {
if baseOid, exists := baseSubmodules[pkg]; !exists || baseOid != headOid {
modifiedOrNew = append(modifiedOrNew, pkg)
common.LogDebug(pkg, "modified:", baseOid, "->", headOid)
}
}
// create build project, if doesn't exist, and add it to pending requests
case common.ReviewStateUnknown:
// what to do?
case common.ReviewStatePending, common.ReviewStateRequestReview:
err = fetchPrGit(git, pr)
if err != nil {
common.LogError("Cannot fetch PR git:", pr.URL)
return
// we want the possibly pending modification here, in case stagings are added, etc.
// jobs of review team to deal with issues
common.LogDebug("QA configuration fetching ...")
buildProject := ""
QA := []common.QAConfig{}
if stagingConfig, err := common.ReadWorkflowConfig(gitea, fmt.Sprintf("%s/%s#%s", pr.Base.Repo.Owner.UserName, pr.Base.Repo.Name, pr.Head.Sha)); err == nil {
if len(stagingConfig.ObsBuildProject) > 1 {
buildProject = stagingConfig.ObsBuildProject
}
// find modified submodules and new submodules -- build them
dir := pr.Head.Sha
headSubmodules, err := git.GitSubmoduleList(dir, pr.Head.Sha)
common.PanicOnError(err)
baseSubmodules, err := git.GitSubmoduleList(dir, pr.Base.Sha)
common.PanicOnError(err)
QA = stagingConfig.QA
}
modifiedOrNew := make([]string, 0, 16)
for pkg, headOid := range headSubmodules {
if baseOid, exists := baseSubmodules[pkg]; !exists || baseOid != headOid {
modifiedOrNew = append(modifiedOrNew, pkg)
}
}
// we want the possibly pending modification here, in case stagings are added, etc.
// jobs of review team to deal with issues
common.LogDebug("QA configuration fetching ...")
buildProject := ""
QA := []common.QAConfig{}
if stagingConfig, err := common.ReadWorkflowConfig(gitea, fmt.Sprintf("%s/%s#%s", pr.Base.Repo.Owner.UserName, pr.Base.Repo.Name, pr.Head.Sha)); err == nil {
if len(stagingConfig.ObsBuildProject) > 1 {
buildProject = stagingConfig.ObsBuildProject
}
QA = stagingConfig.QA
}
if len(buildProject) < 1 {
if len(buildProject) < 1 {
if !IsDryRun {
_, err := gitea.AddReviewComment(pr, common.ReviewStateRequestChanges, "Cannot find reference project")
if err != nil {
common.LogError(err)
return
return err
}
common.LogError("Cannot find reference project for %s PR#%d\n", pr.Base.Name, pr.Index)
return
}
common.LogError("Cannot find reference project for %s PR#%d\n", pr.Base.Name, pr.Index)
return nil
}
stagingProject := getObsProjectAssociatedWithPr(buildProject, pr)
change, err := startOrUpdateBuild(git, gitea, pr, obsClient, buildProject)
if change != RequestModificationNoChange {
msg := "Changed source updated for build"
if change == RequestModificationProjectCreated {
msg = "Build is started in https://" + obsWebHost + "/project/show/" +
stagingProject
}
stagingProject := GetObsProjectAssociatedWithPr(buildProject, pr)
change, err := StartOrUpdateBuild(git, gitea, pr, obsClient, buildProject)
if change != RequestModificationNoChange {
msg := "Changed source updated for build"
if change == RequestModificationProjectCreated {
msg = "Build is started in https://" + ObsWebHost + "/project/show/" +
stagingProject
}
if !IsDryRun {
gitea.AddComment(pr, msg)
}
}
if change == RequestModificationProjectCreated {
for _, setup := range QA {
createQASubProject(git, gitea, pr, obsClient,
buildProject,
stagingProject,
setup.Origin,
setup.Name)
}
if change == RequestModificationProjectCreated {
for _, setup := range QA {
CreateQASubProject(git, gitea, pr, obsClient,
buildProject,
stagingProject,
setup.Origin,
setup.Name)
}
}
baseResult, err := obsClient.BuildStatus(buildProject, modifiedOrNew...)
if err != nil {
common.LogError("failed fetching ref project status for", buildProject, ":", err)
}
stagingResult, err := obsClient.BuildStatus(stagingProject)
if err != nil {
common.LogError("failed fetching ref project status for", stagingProject, ":", err)
}
buildStatus := processBuildStatus(stagingResult, baseResult)
baseResult, err := obsClient.LastBuildResults(buildProject, modifiedOrNew...)
if err != nil {
common.LogError("failed fetching ref project status for", buildProject, ":", err)
}
stagingResult, err := obsClient.BuildStatus(stagingProject)
if err != nil {
common.LogError("failed fetching ref project status for", stagingProject, ":", err)
}
buildStatus := ProcessBuildStatus(stagingResult, baseResult)
if !IsDryRun {
switch buildStatus {
case BuildStatusSummarySuccess:
_, err := gitea.AddReviewComment(pr, common.ReviewStateApproved, "Build successful")
@@ -582,29 +607,18 @@ func processPullNotification(gitea common.Gitea, thread *models.NotificationThre
common.LogError(err)
}
}
common.LogInfo("Build status waiting:", buildStatus)
// waiting for build results -- nothing to do
case common.ReviewStateApproved:
// done, mark notification as read
common.LogInfo("processing request for success build ...")
if !dryRun {
gitea.SetNotificationRead(thread.ID)
}
case common.ReviewStateRequestChanges:
// build failures, nothing to do here, mark notification as read
common.LogInfo("processing request for failed request changes...")
if !dryRun {
gitea.SetNotificationRead(thread.ID)
}
}
common.LogInfo("Build status:", buildStatus)
// waiting for build results -- nothing to do
break
} else if err == NonActionableReviewError || err == NoReviewsFoundError {
return nil
}
return nil
}
func pollWorkNotifications(giteaUrl string) {
func PollWorkNotifications(giteaUrl string) {
gitea := common.AllocateGiteaTransport(giteaUrl)
data, err := gitea.GetPullNotifications(nil)
@@ -618,12 +632,14 @@ func pollWorkNotifications(giteaUrl string) {
for _, notification := range data {
common.LogInfo(notification.ID, "--", notification.Subject)
if !ListPullNotificationsOnly && (ProcessIDOnly < 0 || ProcessIDOnly == notification.ID) {
if !ListPullNotificationsOnly {
switch notification.Subject.Type {
case "Pull":
processPullNotification(gitea, notification)
ProcessPullNotification(gitea, notification)
default:
gitea.SetNotificationRead(notification.ID)
if !IsDryRun {
gitea.SetNotificationRead(notification.ID)
}
}
}
}
@@ -631,13 +647,13 @@ func pollWorkNotifications(giteaUrl string) {
}
var ListPullNotificationsOnly bool
var ProcessIDOnly int64
var BuildRoot string
var giteaUrl string
var giteaUseSshClone bool
var obsApiHost string
var obsWebHost string
var dryRun bool
var GiteaUrl string
var GiteaUseSshClone bool
var ObsApiHost string
var ObsWebHost string
var IsDryRun bool
var ProcessPROnly string
func ObsWebHostFromApiHost(apihost string) string {
if len(apihost) > 4 && apihost[0:4] == "api." {
@@ -649,13 +665,13 @@ func ObsWebHostFromApiHost(apihost string) string {
func main() {
flag.BoolVar(&ListPullNotificationsOnly, "list-notifications-only", false, "Only lists notifications without acting on them")
flag.Int64Var(&ProcessIDOnly, "id", -1, "Process only the specific ID and ignore the rest. Use for debugging")
ProcessPROnly := flag.String("pr", "", "Process only specific PR and ignore the rest. Use for debugging")
flag.StringVar(&BuildRoot, "build-root", "", "Default build location for staging projects. Default is bot's home project")
flag.StringVar(&giteaUrl, "gitea-url", "https://src.opensuse.org", "Gitea instance")
flag.BoolVar(&giteaUseSshClone, "use-ssh-clone", false, "enforce cloning via ssh")
flag.StringVar(&obsApiHost, "obs", "api.opensuse.org", "API for OBS instance")
flag.StringVar(&obsWebHost, "obs-web", "", "Web OBS instance, if not derived from the obs config")
flag.BoolVar(&dryRun, "dry", false, "Dry-run, don't actually create any build projects or review changes")
flag.StringVar(&GiteaUrl, "gitea-url", "https://src.opensuse.org", "Gitea instance")
flag.BoolVar(&GiteaUseSshClone, "use-ssh-clone", false, "enforce cloning via ssh")
flag.StringVar(&ObsApiHost, "obs", "api.opensuse.org", "API for OBS instance")
flag.StringVar(&ObsWebHost, "obs-web", "", "Web OBS instance, if not derived from the obs config")
flag.BoolVar(&IsDryRun, "dry", false, "Dry-run, don't actually create any build projects or review changes")
debug := flag.Bool("debug", false, "One-shot run. Use for debugging")
flag.Parse()
@@ -664,15 +680,30 @@ func main() {
}
common.SetLoggingLevel(common.LogLevelInfo)
if len(obsWebHost) == 0 {
obsWebHost = ObsWebHostFromApiHost(obsApiHost)
if len(ObsWebHost) == 0 {
ObsWebHost = ObsWebHostFromApiHost(ObsApiHost)
}
common.PanicOnErrorWithMsg(common.RequireGiteaSecretToken(), "Cannot find GITEA_TOKEN")
common.PanicOnErrorWithMsg(common.RequireObsSecretToken(), "Cannot find OBS_USER and OBS_PASSWORD")
if len(*ProcessPROnly) > 0 {
rx := regexp.MustCompile("^(\\w+)/(\\w+)#(\\d+)$")
m := rx.FindStringSubmatch(*ProcessPROnly)
if m == nil {
common.LogError("Cannot find any PR matches in", *ProcessPROnly)
return
}
gitea := common.AllocateGiteaTransport(GiteaUrl)
id, _ := strconv.ParseInt(m[3], 10, 64)
ProcessPullRequest(gitea, m[1], m[2], id)
return
}
for {
pollWorkNotifications(giteaUrl)
PollWorkNotifications(GiteaUrl)
if *debug {
break
}

View File

@@ -86,7 +86,7 @@ func TestPRtoObsProjectMapping(t *testing.T) {
Index: n,
}
p := getObsProjectAssociatedWithPr("home:foo", &pr)
p := GetObsProjectAssociatedWithPr("home:foo", &pr)
if p != test.expectedProject {
t.Error("invalid project:", p, "Expected:", test.expectedProject)
}

View File

@@ -24,7 +24,6 @@ import (
"fmt"
"log"
"net/http"
"strings"
"src.opensuse.org/autogits/common"
)

View File

@@ -67,13 +67,14 @@ func WatchObsProject(obs common.ObsStatusFetcherWithState, ObsProject string) {
}
LogDebug("+ watching", ObsProject)
opts := common.BuildResultOptions{}
for {
state, err := obs.BuildStatusWithState(ObsProject, old_state)
state, err := obs.BuildStatusWithState(ObsProject, &opts)
if err != nil {
log.Println(" *** Error fetching build for", ObsProject, err)
time.Sleep(time.Minute)
} else {
old_state = state.State
opts.OldState = state.State
LogDebug(" --> update", ObsProject, " => ", old_state)
StatusUpdateCh <- StatusUpdateMsg{ObsProject: ObsProject, Result: state}
}