From 32374f76c17446d132336cc44dcad7e4be6809faa6c700d5c4a8c130fac5ca77 Mon Sep 17 00:00:00 2001 From: Adam Majer Date: Wed, 23 Apr 2025 17:51:59 +0200 Subject: [PATCH] status --- common/obs_utils.go | 16 +++++++++++++ obs-status-service/README.md | 5 ++++ obs-status-service/status.go | 39 +++++++++++++++++++++++++++++++ obs-status-service/status_test.go | 34 +++++++++++++++++++++++++++ 4 files changed, 94 insertions(+) create mode 100644 obs-status-service/status.go create mode 100644 obs-status-service/status_test.go diff --git a/common/obs_utils.go b/common/obs_utils.go index b3a6a0e..4fecd2e 100644 --- a/common/obs_utils.go +++ b/common/obs_utils.go @@ -36,6 +36,12 @@ import ( "time" ) +//go:generate mockgen -source=obs_utils.go -destination=mock/obs_utils.go -typed + +type ObsStatusFetcherWithState interface { + BuildStatusWithState(project string, oldstate string, packages ...string) (*BuildResultList, error) +} + type ObsClient struct { baseUrl *url.URL client *http.Client @@ -438,6 +444,8 @@ type BuildResult struct { Arch string `xml:"arch,attr"` Code string `xml:"code,attr"` Dirty bool `xml:"dirty,attr"` + ScmSync string `xml:"scmsync"` + ScmInfo string `xml:"scminfo"` Status []PackageBuildStatus `xml:"status"` Binaries []BinaryList `xml:"binarylist"` } @@ -455,6 +463,7 @@ type BinaryList struct { type BuildResultList struct { XMLName xml.Name `xml:"resultlist"` + State string `xml:"state,attr"` Result []BuildResult `xml:"result"` } @@ -682,11 +691,18 @@ func (c *ObsClient) ProjectConfig(project string) (string, error) { } func (c *ObsClient) BuildStatus(project string, packages ...string) (*BuildResultList, error) { + return c.BuildStatusWithState(project, "", packages...) +} + +func (c *ObsClient) BuildStatusWithState(project string, oldstate 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") + if len(oldstate) > 0 { + query.Add("oldstate", oldstate) + } if len(packages) > 0 { query.Add("lastbuild", "1") for _, pkg := range packages { diff --git a/obs-status-service/README.md b/obs-status-service/README.md index 0533394..fb950b3 100644 --- a/obs-status-service/README.md +++ b/obs-status-service/README.md @@ -3,6 +3,11 @@ OBS Status Service Reports build status of OBS service as an easily to produce SVG +Requests for individual build results: + /obs:project/package/repo/arch +Requests for project results + /obs:project + Areas of Responsibility ----------------------- diff --git a/obs-status-service/status.go b/obs-status-service/status.go new file mode 100644 index 0000000..1e93dde --- /dev/null +++ b/obs-status-service/status.go @@ -0,0 +1,39 @@ +package main + +import ( + "log" + "slices" + "sync" + "time" + + "src.opensuse.org/autogits/common" +) + +var WatchedRepos []string +var mutex sync.Mutex + +var StatusUpdateCh chan *common.BuildResultList + +func WatchObsProject(obs common.ObsStatusFetcherWithState, ObsProject string) { + old_state := "" + + mutex.Lock() + if pos, found := slices.BinarySearch(WatchedRepos, ObsProject); found { + mutex.Unlock() + return + } else { + WatchedRepos = slices.Insert(WatchedRepos, pos, ObsProject) + mutex.Unlock() + } + + for { + state, err := obs.BuildStatusWithState(ObsProject, old_state) + if err != nil { + log.Println(" *** Error fetching build for", ObsProject, err) + time.Sleep(time.Minute) + } else { + old_state = state.State + StatusUpdateCh <- state + } + } +} diff --git a/obs-status-service/status_test.go b/obs-status-service/status_test.go new file mode 100644 index 0000000..2eed878 --- /dev/null +++ b/obs-status-service/status_test.go @@ -0,0 +1,34 @@ +package main + +import ( + "testing" + + "go.uber.org/mock/gomock" + "src.opensuse.org/autogits/common" + mock_common "src.opensuse.org/autogits/common/mock" +) + +func TestWatchObsProject(t *testing.T) { + tests := []struct { + name string + res common.BuildResultList + }{ + { + name: "two requests", + res: common.BuildResultList{ + State: "success", + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ctl := gomock.NewController(t) + obs := mock_common.NewMockObsStatusFetcherWithState(ctl) + + obs.EXPECT().BuildStatusWithState("test:foo", "").Return(&test.res, nil) + + WatchObsProject(obs, "test:foo") + }) + } +}