This commit is contained in:
Adam Majer 2024-08-30 17:05:57 +02:00
parent c380674a71
commit 629b10fbac
2 changed files with 70 additions and 91 deletions

View File

@ -3,7 +3,6 @@ package common
import ( import (
"fmt" "fmt"
"io" "io"
"log"
"os" "os"
"path/filepath" "path/filepath"
"slices" "slices"
@ -21,14 +20,6 @@ import (
const PrPattern = "PR: %s/%s#%d" const PrPattern = "PR: %s/%s#%d"
func (h *RequestHandler) allocateGiteaTransport() (*transport.Runtime, *apiclient.GiteaAPI) {
r := transport.New("src.opensuse.org", apiclient.DefaultBasePath, [](string){"https"})
r.DefaultAuthentication = transport.BearerToken(giteaToken)
// r.SetDebug(true)
return r, apiclient.New(r, nil)
}
const ( const (
// from Gitea // from Gitea
// ReviewStateApproved pr is approved // ReviewStateApproved pr is approved
@ -45,44 +36,56 @@ const (
ReviewStateUnknown models.ReviewStateType = "" ReviewStateUnknown models.ReviewStateType = ""
) )
func (h *RequestHandler) GetPullRequestAndReviews(org, project string, num int64) (*models.PullRequest, []*models.PullReview, error) { type GiteaTransport struct {
transport, client := h.allocateGiteaTransport() transport *transport.Runtime
pr, err := client.Repository.RepoGetPullRequest( client *apiclient.GiteaAPI
}
func AllocateGiteaTransport(host string) *GiteaTransport {
var r GiteaTransport
r.transport = transport.New(host, apiclient.DefaultBasePath, [](string){"https"})
r.transport.DefaultAuthentication = transport.BearerToken(giteaToken)
r.client = apiclient.New(r.transport, nil)
return &r
}
func (gitea *GiteaTransport) GetPullRequestAndReviews(org, project string, num int64) (*models.PullRequest, []*models.PullReview, error) {
pr, err := gitea.client.Repository.RepoGetPullRequest(
repository.NewRepoGetPullRequestParams(). repository.NewRepoGetPullRequestParams().
WithDefaults(). WithDefaults().
WithOwner(org). WithOwner(org).
WithRepo(project). WithRepo(project).
WithIndex(num), WithIndex(num),
transport.DefaultAuthentication, gitea.transport.DefaultAuthentication,
) )
if err != nil { if err != nil {
log.Println(err.Error())
return nil, nil, err return nil, nil, err
} }
limit := int64(1000) limit := int64(1000)
reviews, err := client.Repository.RepoListPullReviews( reviews, err := gitea.client.Repository.RepoListPullReviews(
repository.NewRepoListPullReviewsParams(). repository.NewRepoListPullReviewsParams().
WithDefaults(). WithDefaults().
WithOwner(org). WithOwner(org).
WithRepo(project). WithRepo(project).
WithIndex(num). WithIndex(num).
WithLimit(&limit), WithLimit(&limit),
transport.DefaultAuthentication, gitea.transport.DefaultAuthentication,
) )
if err != nil { if err != nil {
log.Println(err.Error())
return nil, nil, err return nil, nil, err
} }
return pr.Payload, reviews.Payload, nil return pr.Payload, reviews.Payload, nil
} }
func (h *RequestHandler) GetPullNotifications(since *time.Time) ([]*models.NotificationThread, error) { func (gitea *GiteaTransport) GetPullNotifications(since *time.Time) ([]*models.NotificationThread, error) {
bigLimit := int64(100000) bigLimit := int64(100000)
transport, client := h.allocateGiteaTransport()
params := notification.NewNotifyGetListParams(). params := notification.NewNotifyGetListParams().
WithDefaults(). WithDefaults().
@ -95,51 +98,38 @@ func (h *RequestHandler) GetPullNotifications(since *time.Time) ([]*models.Notif
params.SetSince(&s) params.SetSince(&s)
} }
list, err := client.Notification.NotifyGetList(params, transport.DefaultAuthentication) list, err := gitea.client.Notification.NotifyGetList(params, gitea.transport.DefaultAuthentication)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if !list.IsSuccess() {
return nil, fmt.Errorf("Cannot fetch notifications: %s", list.Error())
}
return list.Payload, nil return list.Payload, nil
} }
func (h *RequestHandler) SetNotificationRead(notificationId int64) error { func (gitea *GiteaTransport) SetNotificationRead(notificationId int64) error {
transport, client := h.allocateGiteaTransport() _, err := gitea.client.Notification.NotifyReadThread(
list, err := client.Notification.NotifyReadThread(
notification.NewNotifyReadThreadParams(). notification.NewNotifyReadThreadParams().
WithDefaults(). WithDefaults().
WithID(fmt.Sprint(notificationId)), WithID(fmt.Sprint(notificationId)),
transport.DefaultAuthentication, gitea.transport.DefaultAuthentication,
) )
if err != nil { if err != nil {
log.Printf("Error setting notification: %d: %v\n", notificationId, err) return fmt.Errorf("Error setting notification: %d. Err: %w", notificationId, err)
return err
}
if !list.IsSuccess() {
return fmt.Errorf("Cannot update notifications: %d", notificationId)
} }
return nil return nil
} }
func (h *RequestHandler) CreateRepositoryIfNotExist(org Organization, repoName string) (*models.Repository, error) { func (gitea *GiteaTransport) CreateRepositoryIfNotExist(git GitHandler, org Organization, repoName string) (*models.Repository, error) {
transport, client := h.allocateGiteaTransport() repo, err := gitea.client.Repository.RepoGet(
repo, err := client.Repository.RepoGet(
repository.NewRepoGetParams().WithDefaults().WithOwner(org.Username).WithRepo(repoName), repository.NewRepoGetParams().WithDefaults().WithOwner(org.Username).WithRepo(repoName),
transport.DefaultAuthentication) gitea.transport.DefaultAuthentication)
if err != nil { if err != nil {
switch err.(type) { switch err.(type) {
case *repository.RepoGetNotFound: case *repository.RepoGetNotFound:
h.StdLogger.Printf("repo '%s' does not exist. Trying to create it ....\n", repoName) repo, err := gitea.client.Organization.CreateOrgRepo(
repo, err := client.Organization.CreateOrgRepo(
organization.NewCreateOrgRepoParams().WithDefaults().WithBody( organization.NewCreateOrgRepoParams().WithDefaults().WithBody(
&models.CreateRepoOption{ &models.CreateRepoOption{
AutoInit: false, AutoInit: false,
@ -153,31 +143,28 @@ func (h *RequestHandler) CreateRepositoryIfNotExist(org Organization, repoName s
if err != nil { if err != nil {
switch err.(type) { switch err.(type) {
case *organization.CreateOrgRepoCreated: case *organization.CreateOrgRepoCreated:
h.StdLogger.Printf("repo '%s' created, with notification error?\n", repoName) // weird, but ok, repo created
default: default:
log.Printf("error creating repo '%s' under '%s': %s\n", repoName, org.Username, err.Error()) return nil, fmt.Errorf("error creating repo '%s' under '%s'. Err: %w", repoName, org.Username, err)
return nil, err
} }
} else {
h.StdLogger.Printf("repo '%s' created\n", repoName)
} }
// initialize repository // initialize repository
if err = os.Mkdir(filepath.Join(h.Git.GitPath, DefaultGitPrj), 0700); err != nil { if err = os.Mkdir(filepath.Join(git.GitPath, DefaultGitPrj), 0700); err != nil {
return nil, err return nil, err
} }
h.Git.GitExec(DefaultGitPrj, "init", "--object-format="+repo.Payload.ObjectFormatName) git.GitExec(DefaultGitPrj, "init", "--object-format="+repo.Payload.ObjectFormatName)
h.Git.GitExec(DefaultGitPrj, "checkout", "-b", repo.Payload.DefaultBranch) git.GitExec(DefaultGitPrj, "checkout", "-b", repo.Payload.DefaultBranch)
readmeFilename := filepath.Join(h.Git.GitPath, DefaultGitPrj, "README.md") readmeFilename := filepath.Join(git.GitPath, DefaultGitPrj, "README.md")
{ {
file, _ := os.Create(readmeFilename) file, _ := os.Create(readmeFilename)
defer file.Close() defer file.Close()
io.WriteString(file, ReadmeBoilerplate) io.WriteString(file, ReadmeBoilerplate)
} }
h.Git.GitExec(DefaultGitPrj, "add", "README.md") git.GitExec(DefaultGitPrj, "add", "README.md")
h.Git.GitExec(DefaultGitPrj, "commit", "-m", "Automatic devel project creation") git.GitExec(DefaultGitPrj, "commit", "-m", "Automatic devel project creation")
h.Git.GitExec(DefaultGitPrj, "remote", "add", "origin", repo.Payload.SSHURL) git.GitExec(DefaultGitPrj, "remote", "add", "origin", repo.Payload.SSHURL)
return repo.Payload, nil return repo.Payload, nil
default: default:
@ -188,9 +175,7 @@ func (h *RequestHandler) CreateRepositoryIfNotExist(org Organization, repoName s
return repo.Payload, nil return repo.Payload, nil
} }
func (h *RequestHandler) CreatePullRequest(repo *models.Repository, srcId, targetId, title, body string) (*models.PullRequest, error) { func (gitea *GiteaTransport) CreatePullRequest(repo *models.Repository, srcId, targetId, title, body string) (*models.PullRequest, error) {
transport, client := h.allocateGiteaTransport()
prOptions := models.CreatePullRequestOption{ prOptions := models.CreatePullRequestOption{
Base: repo.DefaultBranch, Base: repo.DefaultBranch,
Head: srcId, Head: srcId,
@ -198,14 +183,14 @@ func (h *RequestHandler) CreatePullRequest(repo *models.Repository, srcId, targe
Body: body, Body: body,
} }
pr, err := client.Repository.RepoCreatePullRequest( pr, err := gitea.client.Repository.RepoCreatePullRequest(
repository. repository.
NewRepoCreatePullRequestParams(). NewRepoCreatePullRequestParams().
WithDefaults(). WithDefaults().
WithOwner(repo.Owner.UserName). WithOwner(repo.Owner.UserName).
WithRepo(repo.Name). WithRepo(repo.Name).
WithBody(&prOptions), WithBody(&prOptions),
transport.DefaultAuthentication, gitea.transport.DefaultAuthentication,
) )
if err != nil { if err != nil {
@ -215,21 +200,19 @@ func (h *RequestHandler) CreatePullRequest(repo *models.Repository, srcId, targe
return pr.GetPayload(), nil return pr.GetPayload(), nil
} }
func (h *RequestHandler) RequestReviews(pr *models.PullRequest, reviewer string) ([]*models.PullReview, error) { func (gitea *GiteaTransport) RequestReviews(pr *models.PullRequest, reviewer string) ([]*models.PullReview, error) {
transport, client := h.allocateGiteaTransport()
reviewOptions := models.PullReviewRequestOptions{ reviewOptions := models.PullReviewRequestOptions{
Reviewers: []string{reviewer}, Reviewers: []string{reviewer},
} }
review, err := client.Repository.RepoCreatePullReviewRequests( review, err := gitea.client.Repository.RepoCreatePullReviewRequests(
repository. repository.
NewRepoCreatePullReviewRequestsParams(). NewRepoCreatePullReviewRequestsParams().
WithOwner(pr.Base.Repo.Owner.UserName). WithOwner(pr.Base.Repo.Owner.UserName).
WithRepo(pr.Base.Repo.Name). WithRepo(pr.Base.Repo.Name).
WithIndex(pr.Index). WithIndex(pr.Index).
WithBody(&reviewOptions), WithBody(&reviewOptions),
transport.DefaultAuthentication, gitea.transport.DefaultAuthentication,
) )
if err != nil { if err != nil {
@ -239,8 +222,7 @@ func (h *RequestHandler) RequestReviews(pr *models.PullRequest, reviewer string)
return review.GetPayload(), nil return review.GetPayload(), nil
} }
func (h *RequestHandler) IsReviewed(pr *models.PullRequest) (bool, error) { func (gitea *GiteaTransport) IsReviewed(pr *models.PullRequest) (bool, error) {
transport, client := h.allocateGiteaTransport()
// TODO: get review from project git // TODO: get review from project git
reviewers := pr.RequestedReviewers reviewers := pr.RequestedReviewers
var page, limit int64 var page, limit int64
@ -248,13 +230,13 @@ func (h *RequestHandler) IsReviewed(pr *models.PullRequest) (bool, error) {
page = 0 page = 0
limit = 20 limit = 20
for { for {
res, err := client.Repository.RepoListPullReviews( res, err := gitea.client.Repository.RepoListPullReviews(
repository.NewRepoListPullReviewsParams(). repository.NewRepoListPullReviewsParams().
WithOwner(pr.Base.Repo.Owner.UserName). WithOwner(pr.Base.Repo.Owner.UserName).
WithRepo(pr.Base.Repo.Name). WithRepo(pr.Base.Repo.Name).
WithPage(&page). WithPage(&page).
WithLimit(&limit), WithLimit(&limit),
transport.DefaultAuthentication) gitea.transport.DefaultAuthentication)
if err != nil { if err != nil {
return false, err return false, err
@ -285,7 +267,7 @@ func (h *RequestHandler) IsReviewed(pr *models.PullRequest) (bool, error) {
next_review: next_review:
for i, reviewer := range reviewers { for i, reviewer := range reviewers {
if review.User.UserName == reviewer.UserName { if review.User.UserName == reviewer.UserName {
switch (review.State) { switch review.State {
case ReviewStateApproved: case ReviewStateApproved:
reviewers = slices.Delete(reviewers, i, i) reviewers = slices.Delete(reviewers, i, i)
break next_review break next_review
@ -299,12 +281,8 @@ func (h *RequestHandler) IsReviewed(pr *models.PullRequest) (bool, error) {
return len(reviewers) == 0, nil return len(reviewers) == 0, nil
} }
func (h *RequestHandler) AddReviewComment(pr *models.PullRequest, state models.ReviewStateType, comment string) (*models.PullReview, error) { func (gitea *GiteaTransport) AddReviewComment(pr *models.PullRequest, state models.ReviewStateType, comment string) (*models.PullReview, error) {
transport, client := h.allocateGiteaTransport() c, err := gitea.client.Repository.RepoCreatePullReview(
h.StdLogger.Printf("%#v", *pr)
c, err := client.Repository.RepoCreatePullReview(
repository.NewRepoCreatePullReviewParams(). repository.NewRepoCreatePullReviewParams().
WithDefaults(). WithDefaults().
WithOwner(pr.Base.Repo.Owner.UserName). WithOwner(pr.Base.Repo.Owner.UserName).
@ -314,7 +292,7 @@ func (h *RequestHandler) AddReviewComment(pr *models.PullRequest, state models.R
Event: state, Event: state,
Body: comment, Body: comment,
}), }),
transport.DefaultAuthentication, gitea.transport.DefaultAuthentication,
) )
/* /*
c, err := client.Repository.RepoSubmitPullReview( c, err := client.Repository.RepoSubmitPullReview(
@ -350,14 +328,12 @@ func (h *RequestHandler) AddReviewComment(pr *models.PullRequest, state models.R
return c.Payload, nil return c.Payload, nil
} }
func (h *RequestHandler) GetAssociatedPrjGitPR(pr *PullRequestWebhookEvent) (*models.PullRequest, error) { func (gitea *GiteaTransport) GetAssociatedPrjGitPR(pr *PullRequestWebhookEvent) (*models.PullRequest, error) {
transport, client := h.allocateGiteaTransport()
var page, maxSize int64 var page, maxSize int64
page = 1 page = 1
maxSize = 10000 maxSize = 10000
state := "open" state := "open"
prs, err := client.Repository.RepoListPullRequests( prs, err := gitea.client.Repository.RepoListPullRequests(
repository. repository.
NewRepoListPullRequestsParams(). NewRepoListPullRequestsParams().
WithDefaults(). WithDefaults().
@ -366,14 +342,14 @@ func (h *RequestHandler) GetAssociatedPrjGitPR(pr *PullRequestWebhookEvent) (*mo
WithState(&state). WithState(&state).
WithLimit(&maxSize). WithLimit(&maxSize).
WithPage(&page), WithPage(&page),
transport.DefaultAuthentication) gitea.transport.DefaultAuthentication)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot fetch PR list for %s / %s : %w", pr.Repository.Owner.Username, pr.Repository.Name, err) return nil, fmt.Errorf("cannot fetch PR list for %s / %s : %w", pr.Repository.Owner.Username, pr.Repository.Name, err)
} }
prLine := fmt.Sprintf(PrPattern, pr.Repository.Owner.Username, pr.Repository.Name, pr.Number) prLine := fmt.Sprintf(PrPattern, pr.Repository.Owner.Username, pr.Repository.Name, pr.Number)
h.StdLogger.Printf("attemping to match line: '%s'\n", prLine) // h.StdLogger.Printf("attemping to match line: '%s'\n", prLine)
// payload_processing: // payload_processing:
for _, pr := range prs.Payload { for _, pr := range prs.Payload {
@ -389,8 +365,7 @@ func (h *RequestHandler) GetAssociatedPrjGitPR(pr *PullRequestWebhookEvent) (*mo
return nil, nil return nil, nil
} }
func (h *RequestHandler) GetRepositoryFileContent(repo *models.Repository, hash, path string) ([]byte, error) { func (gitea *GiteaTransport) GetRepositoryFileContent(repo *models.Repository, hash, path string) ([]byte, error) {
transport, client := h.allocateGiteaTransport()
var retData []byte var retData []byte
dataOut := writeFunc(func(data []byte) (int, error) { dataOut := writeFunc(func(data []byte) (int, error) {
@ -400,13 +375,13 @@ func (h *RequestHandler) GetRepositoryFileContent(repo *models.Repository, hash,
retData = data retData = data
return len(data), nil return len(data), nil
}) })
_, err := client.Repository.RepoGetRawFile( _, err := gitea.client.Repository.RepoGetRawFile(
repository.NewRepoGetRawFileParams(). repository.NewRepoGetRawFileParams().
WithOwner(repo.Owner.UserName). WithOwner(repo.Owner.UserName).
WithRepo(repo.Name). WithRepo(repo.Name).
WithFilepath(path). WithFilepath(path).
WithRef(&hash), WithRef(&hash),
transport.DefaultAuthentication, gitea.transport.DefaultAuthentication,
dataOut, dataOut,
repository.WithContentTypeApplicationOctetStream, repository.WithContentTypeApplicationOctetStream,
) )
@ -418,6 +393,6 @@ func (h *RequestHandler) GetRepositoryFileContent(repo *models.Repository, hash,
return retData, nil return retData, nil
} }
func (h *RequestHandler) GetPullRequestFileContent(pr *models.PullRequest, path string) ([]byte, error) { func (gitea *GiteaTransport) GetPullRequestFileContent(pr *models.PullRequest, path string) ([]byte, error) {
return h.GetRepositoryFileContent(pr.Head.Repo, pr.Head.Sha, path) return gitea.GetRepositoryFileContent(pr.Head.Repo, pr.Head.Sha, path)
} }

View File

@ -20,6 +20,7 @@ type ConfigRepos struct {
} }
var configuredRepos map[string]ConfigRepos var configuredRepos map[string]ConfigRepos
var gitea *common.GiteaTransport
func isConfiguredOrg(org *common.Organization) bool { func isConfiguredOrg(org *common.Organization) bool {
_, found := configuredRepos[org.Username] _, found := configuredRepos[org.Username]
@ -45,7 +46,7 @@ func processRepositoryAction(h *common.RequestHandler) error {
return nil return nil
} }
prjGitRepo, err := h.CreateRepositoryIfNotExist(*action.Organization, prjgit) prjGitRepo, err := gitea.CreateRepositoryIfNotExist(h.Git, *action.Organization, prjgit)
if err != nil { if err != nil {
return fmt.Errorf("Error accessing/creating prjgit: %s err: %w", prjgit, err) return fmt.Errorf("Error accessing/creating prjgit: %s err: %w", prjgit, err)
} }
@ -94,7 +95,7 @@ func processPushAction(h *common.RequestHandler) error {
return nil return nil
} }
prjGitRepo, err := h.CreateRepositoryIfNotExist(*action.Repository.Owner, prjgit) prjGitRepo, err := gitea.CreateRepositoryIfNotExist(h.Git, *action.Repository.Owner, prjgit)
if err != nil { if err != nil {
return fmt.Errorf("Error accessing/creating prjgit: %s err: %w", prjgit, err) return fmt.Errorf("Error accessing/creating prjgit: %s err: %w", prjgit, err)
} }
@ -159,6 +160,7 @@ var debugMode bool
func main() { func main() {
workflowConfig := flag.String("config", "", "Repository and workflow definition file") workflowConfig := flag.String("config", "", "Repository and workflow definition file")
giteaHost := flag.String("gitea", "src.opensuse.org", "Gitea instance")
rabbitUrl := flag.String("url", "amqps://rabbit.opensuse.org", "URL for RabbitMQ instance") rabbitUrl := flag.String("url", "amqps://rabbit.opensuse.org", "URL for RabbitMQ instance")
flag.BoolVar(&debugMode, "debug", false, "Extra debugging information") flag.BoolVar(&debugMode, "debug", false, "Extra debugging information")
flag.BoolVar(&checkOnStart, "check-on-start", false, "Check all repositories for consistency on start, without delays") flag.BoolVar(&checkOnStart, "check-on-start", false, "Check all repositories for consistency on start, without delays")
@ -191,6 +193,8 @@ func main() {
} }
} }
gitea = common.AllocateGiteaTransport(*giteaHost)
var defs common.ListenDefinitions var defs common.ListenDefinitions
defs.GitAuthor = "GiteaBot - AutoDevel" defs.GitAuthor = "GiteaBot - AutoDevel"