This commit is contained in:
Adam Majer 2024-10-01 17:21:28 +02:00
parent 881cba862f
commit 6ecc4ecb3a

View File

@ -27,6 +27,7 @@ import (
"os"
"path"
"regexp"
"runtime/debug"
"slices"
"strconv"
"strings"
@ -53,14 +54,14 @@ func failOnError(err error, msg string) {
}
}
func fetchPrGit(h *common.RequestHandler, pr *models.PullRequest) error {
func fetchPrGit(git *common.GitHandler, pr *models.PullRequest) error {
// clone PR head and base and return path
if h.HasError() {
return h.Error
}
if _, err := os.Stat(path.Join(h.GitPath, pr.Head.Sha)); os.IsNotExist(err) {
h.GitExec("", "clone", "--depth", "1", pr.Head.Repo.CloneURL, pr.Head.Sha)
h.GitExec(pr.Head.Sha, "fetch", "--depth", "1", "origin", pr.Head.Sha, pr.Base.Sha)
git.GitExec("", "clone", "--depth", "1", pr.Head.Repo.CloneURL, pr.Head.Sha)
git.GitExec(pr.Head.Sha, "fetch", "--depth", "1", "origin", pr.Head.Sha, pr.Base.Sha)
} else if err != nil {
h.Error = err
}
@ -130,7 +131,7 @@ func processBuildStatus(h *common.RequestHandler, project, refProject *common.Bu
repoRes := &project.Result[i]
repoResStatus, ok := common.ObsRepoStatusDetails[repoRes.Code]
if !ok {
h.LogError("cannot find code: %s", repoRes.Code)
log.Println("cannot find code:", repoRes.Code)
return BuildStatusSummaryUnknown
}
if !repoResStatus.Finished {
@ -140,9 +141,8 @@ func processBuildStatus(h *common.RequestHandler, project, refProject *common.Bu
for _, pkg := range repoRes.Status {
pkgStatus, ok := common.ObsBuildStatusDetails[pkg.Code]
if !ok {
h.LogError("Unknown package build status: %s for %s", pkg.Code, pkg.Package)
h.LogError("Details: %s", pkg.Details)
return BuildStatusSummaryUnknown
log.Println("Unknown package build status: %s", pkg.Code, "for", pkg.Package)
log.Println("Details:", pkg.Details)
}
if pkgStatus.Success {
@ -159,9 +159,9 @@ func processBuildStatus(h *common.RequestHandler, project, refProject *common.Bu
slices.SortFunc(refProject.Result, BuildResultSorter)
h.Log("comparing results %d vs. ref %d", len(project.Result), len(refProject.Result))
log.Printf("comparing results %d vs. ref %d\n", len(project.Result), len(refProject.Result))
for i := 0; i < len(project.Result); i++ {
h.Log("searching for %s/%s", project.Result[i].Repository, project.Result[i].Arch)
log.Println("searching for", project.Result[i].Repository, "/", project.Result[i].Arch)
j := 0
found:
for ; j < len(refProject.Result); j++ {
@ -170,7 +170,7 @@ func processBuildStatus(h *common.RequestHandler, project, refProject *common.Bu
continue
}
h.Log("found match for %s/%s @ %d", project.Result[i].Repository, project.Result[i].Arch, j)
log.Printf("found match for %s/%s @ %d\n", project.Result[i].Repository, project.Result[i].Arch, j)
res := processRepoBuildStatus(h, project.Result[i].Status, refProject.Result[j].Status)
switch res {
case BuildStatusSummarySuccess:
@ -180,9 +180,9 @@ func processBuildStatus(h *common.RequestHandler, project, refProject *common.Bu
}
}
h.Log("%d", j)
log.Println(j)
if j >= len(refProject.Result) {
h.LogError("Cannot find results... %#v \n %#v\n", project.Result[i], refProject.Result)
log.Printf("Cannot find results... %#v \n %#v\n", project.Result[i], refProject.Result)
return BuildStatusSummaryUnknown
}
}
@ -202,7 +202,7 @@ func processRepoBuildStatus(h *common.RequestHandler, results, ref []common.Pack
for i := 0; i < len(results); i++ {
res, ok := common.ObsBuildStatusDetails[results[i].Code]
if !ok {
h.LogError("unknown package result code: %s for package %s", results[i].Code, results[i].Package)
log.Printf("unknown package result code: %s for package %s\n", results[i].Code, results[i].Package)
return BuildStatusSummaryUnknown
}
@ -218,12 +218,12 @@ func processRepoBuildStatus(h *common.RequestHandler, results, ref []common.Pack
if j < len(results) && results[i].Package == ref[j].Package {
refRes, ok := common.ObsBuildStatusDetails[ref[j].Code]
if !ok {
h.LogError("unknown package result code: %s for package %s", ref[j].Code, ref[j].Package)
log.Printf("unknown package result code: %s for package %s\n", ref[j].Code, ref[j].Package)
return BuildStatusSummaryUnknown
}
if !refRes.Finished {
h.LogError("not finished building in reference project?!")
log.Println("not finished building in reference project?!")
}
if refRes.Success {
@ -236,18 +236,24 @@ func processRepoBuildStatus(h *common.RequestHandler, results, ref []common.Pack
return BuildStatusSummarySuccess
}
func generateObsPrjMeta(h *common.RequestHandler, pr *models.PullRequest, obsClient *common.ObsClient) (*common.ProjectMeta, error) {
h.Log("repo content fetching ...")
err := fetchPrGit(h, pr)
func generateObsPrjMeta(git *common.GitHandler, gitea *common.GiteaTransport, pr *models.PullRequest, obsClient *common.ObsClient) (*common.ProjectMeta, error) {
log.Println("repo content fetching ...")
err := fetchPrGit(git, pr)
if err != nil {
h.LogError("Cannot fetch PR git: %s", pr.URL)
log.Println("Cannot fetch PR git:", pr.URL)
return nil, err
}
// find modified submodules and new submodules -- build them
dir := pr.Head.Sha
headSubmodules := h.GitSubmoduleList(dir, pr.Head.Sha)
baseSubmodules := h.GitSubmoduleList(dir, pr.Base.Sha)
headSubmodules, err := git.GitSubmoduleList(dir, pr.Head.Sha)
if err != nil {
return nil, err
}
baseSubmodules, err := git.GitSubmoduleList(dir, pr.Base.Sha)
if err != nil {
return nil, err
}
modifiedOrNew := make([]string, 0, 16)
for pkg, headOid := range headSubmodules {
@ -255,24 +261,24 @@ func generateObsPrjMeta(h *common.RequestHandler, pr *models.PullRequest, obsCli
modifiedOrNew = append(modifiedOrNew, pkg)
}
}
buildPrj := string(bytes.TrimSpace(h.GitCatFile(dir, pr.Head.Sha, "project.build")))
prjBuild, err := git.GitCatFile(dir, pr.Head.Sha, "project.build")
if err != nil {
return nil, err
}
buildPrj := string(bytes.TrimSpace(prjBuild))
if len(buildPrj) < 1 {
_, err := h.AddReviewComment(pr, common.ReviewStateRequestChanges, "Cannot find reference project")
_, err := gitea.AddReviewComment(pr, common.ReviewStateRequestChanges, "Cannot find reference project")
if err != nil {
h.LogPlainError(err)
return nil, h.Error
log.Println(err)
return nil, err
}
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 nil, h.Error
}
meta, err := obsClient.GetProjectMeta(buildPrj)
if err != nil {
h.Log("error fetching project meta for %s: %v", buildPrj, err)
log.Println("error fetching project meta for", buildPrj, ". Err:", err)
return nil, err
}
@ -304,23 +310,23 @@ func generateObsPrjMeta(h *common.RequestHandler, pr *models.PullRequest, obsCli
Repository: r.Name,
}}
}
h.Log("%#v", meta)
log.Println(meta)
return meta, nil
}
func startOrUpdateBuild(h *common.RequestHandler, pr *models.PullRequest, obsClient *common.ObsClient) error {
h.Log("fetching OBS project Meta")
func startOrUpdateBuild(git *common.GitHandler, gitea *common.GiteaTransport, pr *models.PullRequest, obsClient *common.ObsClient) error {
log.Println("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)
log.Println("error fetching project meta for", 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)
log.Println("Cannot parse SCMSYNC url: '", meta.ScmSync, "' .. regenerating build")
meta = nil
} else {
if path.Fragment == pr.Head.Sha {
@ -328,13 +334,13 @@ func startOrUpdateBuild(h *common.RequestHandler, pr *models.PullRequest, obsCli
return nil
}
// build needs update
h.Log("Detected Head update... regenerating build...")
log.Println("Detected Head update... regenerating build...")
meta = nil
}
}
if meta == nil {
// new build
meta, err = generateObsPrjMeta(h, pr, obsClient)
meta, err = generateObsPrjMeta(git, gitea, pr, obsClient)
if err != nil {
return err
}
@ -342,15 +348,27 @@ func startOrUpdateBuild(h *common.RequestHandler, pr *models.PullRequest, obsCli
err = obsClient.SetProjectMeta(meta)
if err != nil {
h.Error = err
h.LogError("cannot create meta project: %#v", err)
return h.Error
log.Println("cannot create meta project:", err)
return err
}
return nil
}
func processPullNotification(h *common.RequestHandler, thread *models.NotificationThread) {
func processPullNotification(gitea *common.GiteaTransport, thread *models.NotificationThread) {
defer func() {
err := recover()
if err != nil {
log.Println(err)
log.Println(string(debug.Stack()))
}
}()
git, err := common.CreateGitHandler(GitAuthor, "noaddress@suse.de", BotName)
if err != nil {
log.Panicln(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)
@ -358,24 +376,24 @@ func processPullNotification(h *common.RequestHandler, thread *models.Notificati
log.Panicf("Unexpected format of notification: %s", notification.URL)
}
h.Log("processing")
h.Log("project: %s", match[2])
h.Log("org: %s", match[1])
h.Log("number: %s", match[3])
log.Println("processing")
log.Println("project:", match[2])
log.Println("org: ", match[1])
log.Println("number: ", match[3])
org := match[1]
repo := match[2]
id, _ := strconv.ParseInt(match[3], 10, 64)
pr, reviews, err := h.GetPullRequestAndReviews(org, repo, id)
pr, reviews, err := gitea.GetPullRequestAndReviews(org, repo, id)
if err != nil {
h.LogError("No PR associated with review: %s. Error: %v", notification.URL, err)
log.Println("No PR associated with review:", notification.URL, "Error:", err)
return
}
obsClient, err := common.NewObsClient("api.opensuse.org")
if err != nil {
h.LogPlainError(err)
log.Println(err)
return
}
@ -388,8 +406,8 @@ func processPullNotification(h *common.RequestHandler, thread *models.Notificati
}
if !reviewRequested {
h.Log("Review not requested in notification. Setting to status 'read'")
h.SetNotificationRead(thread.ID)
log.Println("Review not requested in notification. Setting to status 'read'")
gitea.SetNotificationRead(thread.ID)
return
}
@ -407,37 +425,37 @@ func processPullNotification(h *common.RequestHandler, thread *models.Notificati
for idx := len(reviews) - 1; idx >= 0; idx-- {
review := reviews[idx]
h.Log("state: %s, body: %s, id:%d\n", string(review.State), review.Body, review.ID)
log.Printf("state: %s, body: %s, id:%d\n", string(review.State), review.Body, review.ID)
if review.User.UserName != "autogits_obs_staging_bot" {
if review.User.UserName != Username {
continue
}
h.Log("processing state...")
log.Println("processing state...")
switch review.State {
// create build project, if doesn't exist, and add it to pending requests
case common.ReviewStateUnknown, common.ReviewStateRequestReview:
if err := startOrUpdateBuild(h, pr, obsClient); err != nil {
if err := startOrUpdateBuild(git, pr, obsClient); err != nil {
return
}
msg := "Build is started in https://build.opensuse.org/project/show/" +
getObsProjectAssociatedWithPr(obsClient.HomeProject, pr)
h.AddReviewComment(pr, common.ReviewStatePending, msg)
gitea.AddReviewComment(pr, common.ReviewStatePending, msg)
case common.ReviewStatePending:
err := fetchPrGit(h, pr)
err := fetchPrGit(git, pr)
if err != nil {
h.LogError("Cannot fetch PR git: %s", pr.URL)
log.Println("Cannot fetch PR git:", pr.URL)
return
}
// find modified submodules and new submodules -- build them
dir := pr.Head.Sha
headSubmodules := h.GitSubmoduleList(dir, pr.Head.Sha)
baseSubmodules := h.GitSubmoduleList(dir, pr.Base.Sha)
headSubmodules := git.GitSubmoduleList(dir, pr.Head.Sha)
baseSubmodules := git.GitSubmoduleList(dir, pr.Base.Sha)
modifiedOrNew := make([]string, 0, 16)
for pkg, headOid := range headSubmodules {
@ -446,13 +464,13 @@ func processPullNotification(h *common.RequestHandler, thread *models.Notificati
}
}
h.Log("repo content fetching ...")
log.Println("repo content fetching ...")
refPrj := string(bytes.TrimSpace(h.GitCatFile(dir, pr.Head.Sha, "project.build")))
if len(refPrj) < 1 {
_, err := h.AddReviewComment(pr, common.ReviewStateRequestChanges, "Cannot find reference project")
_, err := gitea.AddReviewComment(pr, common.ReviewStateRequestChanges, "Cannot find reference project")
if err != nil {
h.LogPlainError(err)
log.Println(err)
return
}
h.LogError("Cannot find reference project for %s PR#%d", pr.Base.Name, pr.Index)