This commit is contained in:
Adam Majer 2024-07-31 16:52:02 +02:00
parent 249fbab882
commit 00ecf8ee85
5 changed files with 190 additions and 33 deletions

View File

@ -561,6 +561,10 @@ func (e *RequestHandler) GitSubmoduleList(cwd, commitId string) map[string]strin
var done sync.Mutex
submoduleList := make(map[string]string)
if e.HasError() {
return submoduleList
}
done.Lock()
data_in, data_out := ChanIO{make(chan byte, 256)}, ChanIO{make(chan byte, 70)}

View File

@ -219,12 +219,15 @@ func parseBuildResults(data []byte) (*BuildResultList, error) {
return &result, nil
}
func (c *ObsClient) BuildStatus(project string) (*BuildResultList, error) {
func (c *ObsClient) BuildStatus(project string, packages ...string) (*BuildResultList, error) {
u := c.baseUrl.JoinPath("build", project, "_result")
query := u.Query()
query.Add("view", "status")
query.Add("view", "binarylist")
query.Add("multibuild", "1")
for _, pkg := range packages {
query.Add("package", pkg)
}
u.RawQuery = query.Encode()
req, err := http.NewRequest("GET", u.String(), nil)
log.Print(u.String())

View File

@ -35,6 +35,9 @@ func failOnError(err error, msg string) {
func fetchPrGit(h *common.RequestHandler, 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)
@ -55,6 +58,27 @@ func getObsProjectAssociatedWithPr(baseProject string, pr *models.PullRequest) s
)
}
type BuildStatusSummary string
const BuildUnresolveable = BuildStatusSummary("unresolveable")
const BuildBuilding = BuildStatusSummary("building")
const BuildFailed = BuildStatusSummary("failed")
const BuildSuccess = BuildStatusSummary("success")
type BuildStatus struct {
Status BuildStatusSummary
Detail string
}
var buildStatus map[string]BuildStatus
func processBuildStatusUpdate() {
}
func processBuildStatus(project, refProject *common.BuildResultList) BuildStatusSummary {
return BuildBuilding
}
func processPullNotification(h *common.RequestHandler, notification *models.NotificationSubject) {
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]+)$`)
match := rx.FindStringSubmatch(notification.URL)
@ -192,11 +216,70 @@ func processPullNotification(h *common.RequestHandler, notification *models.Noti
// set the review state to pending
case common.ReviewStatePending:
err := fetchPrGit(h, pr)
if err != nil {
h.LogError("Cannot fetch PR git: %s", 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)
modifiedOrNew := make([]string, 0, 16)
for pkg, headOid := range headSubmodules {
if baseOid, exists := baseSubmodules[pkg]; !exists || baseOid != headOid {
modifiedOrNew = append(modifiedOrNew, pkg)
}
}
h.Log("repo content fetching ...")
refProject := string(h.GitCatFile(dir, pr.Head.Sha, "project.build"))
// buildPrjBytes, err := h.GetPullRequestFileContent(pr, "project.build")
if h.HasError() {
h.LogPlainError(h.Error)
/*
_, err := h.AddReviewComment(pr, common.ReviewStateRequestChanges, "Cannot find reference project")
if err != nil {
h.LogPlainError(err)
}
*/
return
}
obsProject := getObsProjectAssociatedWithPr(obsClient.HomeProject, pr)
prjResult, err := obsClient.BuildStatus(obsProject)
if err != nil {
h.LogError("failed fetching build status for '%s': %v", obsProject, err)
return
}
refProjectResult, err := obsClient.BuildStatus(refProject)
if err != nil {
h.LogError("failed fetching ref project status for '%s': %v", refProject, err)
}
buildStatus := processBuildStatus(prjResult, refProjectResult)
switch buildStatus {
case BuildSuccess:
_, err := h.AddReviewComment(pr, common.ReviewStateApproved, "Build successful")
if err != nil {
h.LogPlainError(err)
}
case BuildFailed:
_, err := h.AddReviewComment(pr, common.ReviewStateRequestChanges, "Build failed")
if err != nil {
h.LogPlainError(err)
}
case BuildBuilding:
}
// waiting for build results
// project := getObsProjectAssociatedWithPr(obsClient.HomeProject, pr)
case common.ReviewStateApproved:
// done, mark notification as read
h.Log("processing request for success build ...")
case common.ReviewStateRequestChanges:
// build failures, nothing to do here, mark notification as read
h.Log("processing request for failed request changes...")
@ -229,37 +312,16 @@ func pollWorkNotifications() {
}
func main() {
var defs common.ListenDefinitions
defs.Url = ObsBuildBot
defs.GitAuthor = GitAuthor
failOnError(common.RequireGiteaSecretToken(), "Cannot find GITEA_TOKEN")
failOnError(common.RequireObsSecretToken(), "Cannot find OBS_USER and OBS_PASSWORD")
// go ProcessingObsMessages("rabbit.opensuse.org", "opensuse", "opensuse", "")
// for {
pollWorkNotifications()
// time.Sleep(1000)
// }
/*
h := allocateRequestHandler()
//" autogits/_ObsPrj/raw/project.build?ref=9680b770855e4fc2e9d9cebbd87e6a0d119693c3e03db187494e3aeff727312f"
// https://src.opensuse.org/adamm/autogits/commit/8db4d8c3021fc21baa606b87eaad0e476bb7f624f76cb37b6a1819bdb5f04b43#diff-6e698c75c21cd4458440e8a71408c6301ba3a562
f, err := h.GetRepositoryFileContent(
&models.Repository{
Owner: &models.User{
UserName: "adamm",
},
Name: "autogits",
},
"54e418acaf960c5ed8be7f4a29616ae7b5eb75f797f7ed4d487f79485d056108",
"bots-common/obs/client.go")
if err != nil {
h.LogPlainError(err)
}
h.Log("len: %d", len(f))
*/
stuck := make(chan int)
<-stuck
}

View File

@ -1,2 +1,38 @@
package main
import (
"testing"
"src.opensuse.org/autogits/common/gitea-generated/models"
)
func TestPRtoObsProjectMapping(t *testing.T) {
pr := models.PullRequest{
Base: &models.PRBranchInfo {
Repo: &models.Repository {
Name: "Repo",
Owner: &models.User {
UserName: "foobar",
},
},
},
Index: 10,
}
p := getObsProjectAssociatedWithPr("home:foo", &pr)
if p != "home:foo:foobar:Repo:PR:10" {
t.Errorf("invalid project: %s", p)
}
pr.Base.Repo.Name = "_FooBar"
p = getObsProjectAssociatedWithPr("home:foo", &pr)
if p != "home:foo:foobar:XFooBar:PR:10" {
t.Errorf("invalid project: %s", p)
}
pr.Base.Repo.Owner.UserName = "_some_thing"
p = getObsProjectAssociatedWithPr("home:foo", &pr)
if p != "home:foo:Xsome_thing:XFooBar:PR:10" {
t.Errorf("invalid project: %s", p)
}
}

View File

@ -5,10 +5,13 @@ import (
"encoding/json"
"log"
"strings"
"sync"
"time"
_ "github.com/mattn/go-sqlite3"
rabbitmq "github.com/rabbitmq/amqp091-go"
"src.opensuse.org/autogits/common"
"src.opensuse.org/autogits/common/gitea-generated/models"
)
type BuildNotification struct {
@ -17,6 +20,50 @@ type BuildNotification struct {
Starttime, Endtime, Readytime string
}
var obsNotifications map[string]*BuildNotification // Project/Package/Repositry/Arch as key
var notificationMutex sync.RWMutex
var notificationChannels map[string][]chan *BuildNotification
func getProjectBuildStatus(project string) []*BuildNotification {
notificationMutex.RLock()
defer notificationMutex.RUnlock()
data := make([]*BuildNotification, 0, 4)
for _, val := range obsNotifications {
if val.Package == project {
data = append(data, val)
}
}
return data
}
func addProjectWatcher(meta *common.ProjectMeta, pr *models.PullReview) {
}
func addObsNotificationToCache(notification *BuildNotification) {
key := strings.Join(
[]string{
notification.Project,
notification.Package,
notification.Repository,
notification.Arch,
},
"/",
)
notificationMutex.Lock()
obsNotifications[key] = notification
chns, ok := notificationChannels[notification.Project]
notificationMutex.Unlock()
if ok {
for _, ch := range chns {
ch <- notification
}
}
}
func processObsMessage(msg *rabbitmq.Delivery) {
key := strings.SplitN(msg.RoutingKey, ".", 4)
if len(key) != 4 || len(key[3]) < 7 || key[3][:6] != "build_" {
@ -44,7 +91,7 @@ func processObsMessage(msg *rabbitmq.Delivery) {
}
log.Printf("%v\n", notification)
addObsNotificationToCache(notification)
}
func ProcessingObsMessages(host, username, password, queueName string) {
@ -56,6 +103,11 @@ func ProcessingObsMessages(host, username, password, queueName string) {
}
}()
if obsNotifications == nil {
obsNotifications = make(map[string]*BuildNotification)
// notificationChannels = make(map[string]chan *BuildNotification)
}
auth := ""
if len(username) > 0 && len(password) > 0 {
auth = username + ":" + password + "@"