From 4a1856a2161b0763ef17e7a8c76fe11c0b7ebc5d975bbcf90a7218a106f4b229 Mon Sep 17 00:00:00 2001 From: Adam Majer Date: Thu, 18 Jul 2024 23:36:41 +0200 Subject: [PATCH] . --- bots-common/gitea_utils.go | 62 ++++++++++++++++++++++++++- obs-staging-bot/main.go | 83 +++++++++++++++++++++++++++++++------ obs-staging-bot/rabbitmq.go | 6 --- 3 files changed, 130 insertions(+), 21 deletions(-) diff --git a/bots-common/gitea_utils.go b/bots-common/gitea_utils.go index b43a5ec..efb4fb9 100644 --- a/bots-common/gitea_utils.go +++ b/bots-common/gitea_utils.go @@ -28,6 +28,64 @@ func (h *RequestHandler) allocateGiteaTransport() (*transport.Runtime, *apiclien return r, apiclient.New(r, nil) } +const ( + // from Gitea + // ReviewStateApproved pr is approved + ReviewStateApproved models.ReviewStateType = "APPROVED" + // ReviewStatePending pr state is pending + ReviewStatePending models.ReviewStateType = "PENDING" + // ReviewStateComment is a comment review + ReviewStateComment models.ReviewStateType = "COMMENT" + // ReviewStateRequestChanges changes for pr are requested + ReviewStateRequestChanges models.ReviewStateType = "REQUEST_CHANGES" + // ReviewStateRequestReview review is requested from user + ReviewStateRequestReview models.ReviewStateType = "REQUEST_REVIEW" + // ReviewStateUnknown state of pr is unknown + ReviewStateUnknown models.ReviewStateType = "" +) + + +func (h *RequestHandler) GetPullRequestAndReviews(org, project string, num int64) (*models.PullRequest, []*models.PullReview, error) { + if h.HasError() { + return nil, nil, h.Error + } + + transport, client := h.allocateGiteaTransport() + pr, err := client.Repository.RepoGetPullRequest( + repository.NewRepoGetPullRequestParams(). + WithDefaults(). + WithOwner(org). + WithRepo(project). + WithIndex(num), + transport.DefaultAuthentication, + ) + + if err != nil { + h.Error = err; + h.LogPlainError(err) + return nil, nil, err + } + + limit := int64(1000) + reviews, err := client.Repository.RepoListPullReviews( + repository.NewRepoListPullReviewsParams(). + WithDefaults(). + WithOwner(org). + WithRepo(project). + WithIndex(num). + WithLimit(&limit), + transport.DefaultAuthentication, + ) + + if err != nil { + h.Error = err + h.LogPlainError(err) + return nil, nil, err + } + + return pr.Payload, reviews.Payload, nil +} + func (h *RequestHandler) GetNotifications(since *time.Time) ([]*models.NotificationThread, error){ if h.HasError() { return nil, h.Error @@ -59,7 +117,7 @@ func (h *RequestHandler) GetNotifications(since *time.Time) ([]*models.Notificat return list.Payload, nil } -func (h *RequestHandler) SetNotificationRead(notificationId int) error { +func (h *RequestHandler) SetNotificationRead(notificationId int64) error { if h.HasError() { return h.Error } @@ -68,7 +126,7 @@ func (h *RequestHandler) SetNotificationRead(notificationId int) error { list, err := client.Notification.NotifyReadThread( notification.NewNotifyReadThreadParams(). WithDefaults(). - WithID(string(id)), + WithID(fmt.Sprint(id)), transport.DefaultAuthentication, ) diff --git a/obs-staging-bot/main.go b/obs-staging-bot/main.go index 7048780..c325977 100644 --- a/obs-staging-bot/main.go +++ b/obs-staging-bot/main.go @@ -1,28 +1,81 @@ package main import ( + "log" "os" + "regexp" + "strconv" "src.opensuse.org/autogits/common" + "src.opensuse.org/autogits/common/gitea-generated/models" ) const ( - GitAuthor = "GiteaBot - Obs Staging" + GitAuthor = "GiteaBot - Obs Staging" ObsBuildBot = "/obsbuild" ) var GiteaToken string - var runId uint - +var runId uint +func failOnError(err error, msg string) { + if err != nil { + log.Panicf("%s: %s", err, msg) + } +} func allocateRequestHandler() *common.RequestHandler { - return &common.RequestHandler { + return &common.RequestHandler{ Logger: common.CreateStdoutLogger(os.Stdout, os.Stdout), } } -func PollWorkNotifications() { +func processPullNotification(h *common.RequestHandler, notification *models.NotificationSubject) { + rx := regexp.MustCompile(`^https://src\.(?:open)?suse\.org/api/v\d+/repos/(?[a-zA-Z0-9]+)/(?[_a-zA-Z0-9]+)/issues/(?[0-9]+)$`) + match := rx.FindStringSubmatch(notification.URL) + if match == nil { + 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]) + + org := match[1] + repo := match[2] + id, _ := strconv.ParseInt(match[3], 10, 64) + + pr, reviews, err := h.GetPullRequestAndReviews(org, repo, id) + if err != nil { + return + } + + for _, reviewer := range pr.RequestedReviewers { + h.Log(reviewer.UserName) + } + + for _, review := range reviews { + h.Log("state: %s, body: %s, id:%d\n", string(review.State), review.Body, review.ID) + + if *review.User.LoginName != "autogits_obs_staging_bot" { + continue + } + + switch review.State { + case common.ReviewStateUnknown, common.ReviewStateRequestReview: + // start review + case common.ReviewStatePending: + // waiting for build results + case common.ReviewStateApproved: + // done, mark notification as read + case common.ReviewStateRequestChanges: + // build failures, mark notification as read + } + } +} + +func pollWorkNotifications() { h := allocateRequestHandler() data, err := h.GetNotifications(nil) @@ -33,9 +86,13 @@ func PollWorkNotifications() { if data != nil { for _, notification := range data { - h.Log("[+] id: %d", notification.ID) - h.Log(" title: %s", notification.Subject.Title) - h.Log(" subj: %#v", notification.Subject) + + switch notification.Subject.Type { + case "Pull": + processPullNotification(h, notification.Subject) + default: + h.SetNotificationRead(notification.ID) + } } } } @@ -46,13 +103,13 @@ func main() { defs.Url = ObsBuildBot defs.GitAuthor = GitAuthor - common.RequireGiteaSecretToken() - common.RequireObsSecretToken() + failOnError(common.RequireGiteaSecretToken(), "Cannot find GITEA_TOKEN") + failOnError(common.RequireObsSecretToken(), "Cannot find OBS_USER and OBS_PASSWORD") -// go ProcessingObsMessages("rabbit.opensuse.org", "opensuse", "opensuse", "") + // go ProcessingObsMessages("rabbit.opensuse.org", "opensuse", "opensuse", "") - PollWorkNotifications() + pollWorkNotifications() - stuck := make(chan int) + stuck := make(chan int) <-stuck } diff --git a/obs-staging-bot/rabbitmq.go b/obs-staging-bot/rabbitmq.go index 9a8a681..777f82a 100644 --- a/obs-staging-bot/rabbitmq.go +++ b/obs-staging-bot/rabbitmq.go @@ -17,12 +17,6 @@ type BuildNotification struct { Starttime, Endtime, Readytime string } -func failOnError(err error, msg string) { - if err != nil { - log.Panicf("%s: %s", err, msg) - } -} - func processObsMessage(msg *rabbitmq.Delivery) { key := strings.SplitN(msg.RoutingKey, ".", 4) if len(key) != 4 || len(key[3]) < 7 || key[3][:6] != "build_" {