From 07612fdcfce773fb98ccbdf3b6305f4fea18147ee04404b2e4e9ca767ead3c73 Mon Sep 17 00:00:00 2001 From: Adam Majer Date: Mon, 19 Aug 2024 13:54:44 +0200 Subject: [PATCH] . --- bots-common/obs_utils.go | 30 ++++++++++++++++++--- obs-staging-bot/main.go | 58 +++++++++++++++++++++++++++++++--------- 2 files changed, 71 insertions(+), 17 deletions(-) diff --git a/bots-common/obs_utils.go b/bots-common/obs_utils.go index 90fd60e..ca0fca6 100644 --- a/bots-common/obs_utils.go +++ b/bots-common/obs_utils.go @@ -42,9 +42,12 @@ type RepositoryPathMeta struct { } type RepositoryMeta struct { - Name string `xml:"name,attr"` - Archs []string `xml:"arch"` - Paths []RepositoryPathMeta `xml:"path"` + Name string `xml:"name,attr"` + BuildTrigger string `xml:"rebuild,attr"` + BlockMode string `xml:"block"` + LinkedBuild string `xml:"linkedbuild"` + Archs []string `xml:"arch"` + Paths []RepositoryPathMeta `xml:"path"` } type Flags struct { @@ -77,7 +80,6 @@ func parseProjectMeta(data []byte) (*ProjectMeta, error) { } func (c *ObsClient) GetProjectMeta(project string) (*ProjectMeta, error) { - req, err := http.NewRequest("GET", c.baseUrl.JoinPath("source", project, "_meta").String(), nil) if err != nil { return nil, err @@ -129,8 +131,24 @@ func ObsSafeProjectName(prjname string) string { return prjname } +var ValidBlockModes []string +var ValidPrjLinkModes []string +var ValidTriggerModes []string + func (c *ObsClient) SetProjectMeta(meta *ProjectMeta) error { + for _, repo := range meta.Repositories { + if len(repo.BlockMode) > 0 && !slices.Contains(ValidBlockModes, repo.BlockMode) { + return fmt.Errorf("Invalid repository block mode: '%s'", repo.BlockMode) + } + if len(repo.BuildTrigger) > 0 && !slices.Contains(ValidTriggerModes, repo.BuildTrigger) { + return fmt.Errorf("Invalid repository trigger mode: '%s'", repo.BuildTrigger) + } + if len(repo.LinkedBuild) > 0 && !slices.Contains(ValidPrjLinkModes, repo.LinkedBuild) { + return fmt.Errorf("Invalid linked project rebuild mode: '%s'", repo.LinkedBuild) + } + } + req, err := http.NewRequest("PUT", c.baseUrl.JoinPath("source", meta.Name, "_meta").String(), nil) if err != nil { return err @@ -278,6 +296,10 @@ type ObsBuildStatusDetail struct { } func init() { + ValidTriggerModes = []string{"transitive", "direct", "local"} + ValidBlockModes = []string{"all", "local", "never"} + ValidPrjLinkModes = []string{"off", "localdep", "alldirect", "all"} + ObsBuildStatusDetails = make(map[string]ObsBuildStatusDetail) ObsRepoStatusDetails = make(map[string]ObsBuildStatusDetail) diff --git a/obs-staging-bot/main.go b/obs-staging-bot/main.go index 18f81bb..5c6001d 100644 --- a/obs-staging-bot/main.go +++ b/obs-staging-bot/main.go @@ -136,7 +136,7 @@ func processBuildStatus(h *common.RequestHandler, project, refProject *common.Bu for i := 0; i < len(project.Result); i++ { h.Log("searching for %s/%s", project.Result[i].Repository, project.Result[i].Arch) j := 0 - found: + found: for ; j < len(refProject.Result); j++ { if project.Result[i].Repository != refProject.Result[j].Repository || project.Result[i].Arch != refProject.Result[j].Arch { @@ -209,11 +209,12 @@ func processRepoBuildStatus(h *common.RequestHandler, results, ref []common.Pack return BuildStatusSummarySuccess } -func startBuild(h *common.RequestHandler, pr *models.PullRequest, obsClient *common.ObsClient) error { +func generateObsPrjMeta(h *common.RequestHandler, pr *models.PullRequest, obsClient *common.ObsClient) (*common.ProjectMeta, error) { + h.Log("repo content fetching ...") err := fetchPrGit(h, pr) if err != nil { h.LogError("Cannot fetch PR git: %s", pr.URL) - return err + return nil, err } // find modified submodules and new submodules -- build them @@ -227,27 +228,25 @@ func startBuild(h *common.RequestHandler, pr *models.PullRequest, obsClient *com modifiedOrNew = append(modifiedOrNew, pkg) } } - - h.Log("repo content fetching ...") buildPrj := string(bytes.TrimSpace(h.GitCatFile(dir, pr.Head.Sha, "project.build"))) if len(buildPrj) < 1 { _, err := h.AddReviewComment(pr, common.ReviewStateRequestChanges, "Cannot find reference project") if err != nil { h.LogPlainError(err) - return h.Error + return nil, h.Error } - return fmt.Errorf("Cannot find reference project for %s PR#%d", pr.Base.Name, pr.Index) + return nil, fmt.Errorf("Cannot find reference project for %s PR#%d", pr.Base.Name, pr.Index) } if h.HasError() { h.LogPlainError(h.Error) - return h.Error + return nil, h.Error } meta, err := obsClient.GetProjectMeta(buildPrj) if err != nil { h.Log("error fetching project meta for %s: %v", buildPrj, err) - return err + return nil, err } // generate new project with paths pointinig back to original repos @@ -267,7 +266,7 @@ func startBuild(h *common.RequestHandler, pr *models.PullRequest, obsClient *com for _, pkg := range modifiedOrNew { urlPkg = append(urlPkg, "onlybuild="+url.QueryEscape(pkg)) } - meta.ScmSync = pr.Head.Repo.CloneURL + "?" + strings.Join(urlPkg, "&") + "#" + pr.Head.Name + meta.ScmSync = pr.Head.Repo.CloneURL + "?" + strings.Join(urlPkg, "&") + "#" + pr.Head.Sha meta.Title = fmt.Sprintf("PR#%d to %s", pr.Index, pr.Base.Name) meta.PublicFlags = common.Flags{Contents: ""} @@ -278,8 +277,41 @@ func startBuild(h *common.RequestHandler, pr *models.PullRequest, obsClient *com Repository: r.Name, }} } - h.Log("%#v", meta) + return meta, nil +} + +func startOrUpdateBuild(h *common.RequestHandler, pr *models.PullRequest, obsClient *common.ObsClient) error { + h.Log("fetching OBS project Meta") + obsPrProject := getObsProjectAssociatedWithPr(obsClient.HomeProject, pr) + meta, err := obsClient.GetProjectMeta(obsPrProject) + if err != nil { + h.Log("error fetching project meta for %s: %v", obsPrProject, err) + return err + } + + if meta != nil { + path, err := url.Parse(meta.ScmSync) + if err != nil { + h.Log("Cannot parse SCMSYNC url: '%s' .. regenerating build", meta.ScmSync) + meta = nil + } else { + if path.Fragment == pr.Head.Sha { + // build in progress + return nil + } + // build needs update + h.Log("Detected Head update... regenerating build...") + meta = nil + } + } + if meta == nil { + // new build + meta, err = generateObsPrjMeta(h, pr, obsClient) + if err != nil { + return err + } + } err = obsClient.SetProjectMeta(meta) if err != nil { @@ -360,7 +392,7 @@ func processPullNotification(h *common.RequestHandler, thread *models.Notificati // create build project, if doesn't exist, and add it to pending requests case common.ReviewStateUnknown, common.ReviewStateRequestReview: - if err := startBuild(h, pr, obsClient); err != nil { + if err := startOrUpdateBuild(h, pr, obsClient); err != nil { return } @@ -410,7 +442,7 @@ func processPullNotification(h *common.RequestHandler, thread *models.Notificati if errors.Is(err, common.ObsProjectNotFound{Project: obsProject}) { // recreate missing project h.LogError("missing OBS project ... recreating '%s': %v", obsProject, err) - startBuild(h, pr, obsClient) + startOrUpdateBuild(h, pr, obsClient) return }