Compare commits

..

1 Commits

Author SHA256 Message Date
Andrii Nikitin
61bcd5caf4 common, staging: sync Gitea cache TTL with poll interval
All checks were successful
go-generate-check / go-generate-check (pull_request) Successful in 8s
Integration tests / t (pull_request) Successful in 11m50s
Make the Gitea timeline cache TTL configurable and allow the
obs-staging-bot to dynamically reduce it if the poll interval is
shorter than the current cache duration. This prevents the bot from
posting duplicate comments when its polling cycle is faster than
the cache TTL.

- Add SetCacheTTL and GetCacheTTL to Gitea interface and GiteaTransport
- Implement GetCacheTTL and use the set TTL in GetTimeline
- Update obs-staging-bot to sync TTL if PollInterval < gitea.GetCacheTTL()
2026-03-11 10:42:09 +01:00
9 changed files with 94 additions and 459 deletions

View File

@@ -221,11 +221,14 @@ type Gitea interface {
GetPullRequests(org, project string) ([]*models.PullRequest, error)
GetCurrentUser() (*models.User, error)
SetCacheTTL(ttl time.Duration)
GetCacheTTL() time.Duration
}
type GiteaTransport struct {
transport *transport.Runtime
client *apiclient.GiteaAPI
cacheTTL time.Duration
}
func AllocateGiteaTransport(giteaUrl string) Gitea {
@@ -240,10 +243,19 @@ func AllocateGiteaTransport(giteaUrl string) Gitea {
r.transport.DefaultAuthentication = transport.BearerToken(giteaToken)
r.client = apiclient.New(r.transport, nil)
r.cacheTTL = time.Second * 5
return &r
}
func (gitea *GiteaTransport) SetCacheTTL(ttl time.Duration) {
gitea.cacheTTL = ttl
}
func (gitea *GiteaTransport) GetCacheTTL() time.Duration {
return gitea.cacheTTL
}
func (gitea *GiteaTransport) FetchMaintainershipFile(org, repo, branch string) ([]byte, string, error) {
return gitea.GetRepositoryFileContent(org, repo, branch, MaintainershipFile)
}
@@ -868,8 +880,8 @@ func (gitea *GiteaTransport) GetTimeline(org, repo string, idx int64) ([]*models
LastCachedTime = TimelineCache.data[0].Updated
}
// cache data for 5 seconds
if TimelineCache.lastCheck.Add(time.Second*5).Compare(time.Now()) > 0 {
// cache data
if TimelineCache.lastCheck.Add(gitea.cacheTTL).Compare(time.Now()) > 0 {
giteaTimelineCacheMutex.RUnlock()
return TimelineCache.data, nil
}

View File

@@ -2718,6 +2718,44 @@ func (c *MockGiteaFetchMaintainershipFileCall) DoAndReturn(f func(string, string
return c
}
// GetCacheTTL mocks base method.
func (m *MockGitea) GetCacheTTL() time.Duration {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetCacheTTL")
ret0, _ := ret[0].(time.Duration)
return ret0
}
// GetCacheTTL indicates an expected call of GetCacheTTL.
func (mr *MockGiteaMockRecorder) GetCacheTTL() *MockGiteaGetCacheTTLCall {
mr.mock.ctrl.T.Helper()
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCacheTTL", reflect.TypeOf((*MockGitea)(nil).GetCacheTTL))
return &MockGiteaGetCacheTTLCall{Call: call}
}
// MockGiteaGetCacheTTLCall wrap *gomock.Call
type MockGiteaGetCacheTTLCall struct {
*gomock.Call
}
// Return rewrite *gomock.Call.Return
func (c *MockGiteaGetCacheTTLCall) Return(arg0 time.Duration) *MockGiteaGetCacheTTLCall {
c.Call = c.Call.Return(arg0)
return c
}
// Do rewrite *gomock.Call.Do
func (c *MockGiteaGetCacheTTLCall) Do(f func() time.Duration) *MockGiteaGetCacheTTLCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
func (c *MockGiteaGetCacheTTLCall) DoAndReturn(f func() time.Duration) *MockGiteaGetCacheTTLCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
// GetCommit mocks base method.
func (m *MockGitea) GetCommit(org, repo, sha string) (*models.Commit, error) {
m.ctrl.T.Helper()
@@ -3579,6 +3617,42 @@ func (c *MockGiteaResetTimelineCacheCall) DoAndReturn(f func(string, string, int
return c
}
// SetCacheTTL mocks base method.
func (m *MockGitea) SetCacheTTL(ttl time.Duration) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetCacheTTL", ttl)
}
// SetCacheTTL indicates an expected call of SetCacheTTL.
func (mr *MockGiteaMockRecorder) SetCacheTTL(ttl any) *MockGiteaSetCacheTTLCall {
mr.mock.ctrl.T.Helper()
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetCacheTTL", reflect.TypeOf((*MockGitea)(nil).SetCacheTTL), ttl)
return &MockGiteaSetCacheTTLCall{Call: call}
}
// MockGiteaSetCacheTTLCall wrap *gomock.Call
type MockGiteaSetCacheTTLCall struct {
*gomock.Call
}
// Return rewrite *gomock.Call.Return
func (c *MockGiteaSetCacheTTLCall) Return() *MockGiteaSetCacheTTLCall {
c.Call = c.Call.Return()
return c
}
// Do rewrite *gomock.Call.Do
func (c *MockGiteaSetCacheTTLCall) Do(f func(time.Duration)) *MockGiteaSetCacheTTLCall {
c.Call = c.Call.Do(f)
return c
}
// DoAndReturn rewrite *gomock.Call.DoAndReturn
func (c *MockGiteaSetCacheTTLCall) DoAndReturn(f func(time.Duration)) *MockGiteaSetCacheTTLCall {
c.Call = c.Call.DoAndReturn(f)
return c
}
// SetCommitStatus mocks base method.
func (m *MockGitea) SetCommitStatus(org, repo, hash string, status *models.CommitStatus) (*models.CommitStatus, error) {
m.ctrl.T.Helper()

View File

@@ -139,7 +139,7 @@ services:
environment:
- OBS_USER=mock
- OBS_PASSWORD=mock-long-password
- AUTOGITS_STAGING_BOT_POLL_INTERVAL=6s
- AUTOGITS_STAGING_BOT_POLL_INTERVAL=2s
volumes:
- ./gitea-data:/gitea-data:ro,z
command:

View File

@@ -65,12 +65,6 @@ class GiteaAPIClient:
return None
raise
def get_submodule_sha(self, owner: str, repo: str, submodule_path: str, ref: str = "main"):
info = self.get_file_info(owner, repo, submodule_path, branch=ref)
if info and info.get("type") == "submodule":
return info.get("sha")
return None
def create_user(self, username, password, email):
vprint(f"--- Creating user: {username} ---")
data = {
@@ -531,14 +525,6 @@ index 00000000..{pkg_b_sha}
return review
def request_reviewers(self, repo_full_name: str, pr_number: int, reviewers: list):
owner, repo = repo_full_name.split("/")
url = f"repos/{owner}/{repo}/pulls/{pr_number}/requested_reviewers"
data = {"reviewers": reviewers}
vprint(f"--- Requesting reviewers for {repo_full_name} PR #{pr_number}: {reviewers} ---")
response, duration = self._request("POST", url, json=data)
return response.json()
def list_reviews(self, repo_full_name: str, pr_number: int):
owner, repo = repo_full_name.split("/")
url = f"repos/{owner}/{repo}/pulls/{pr_number}/reviews"
@@ -604,35 +590,3 @@ index 00000000..{pkg_b_sha}
time.sleep(1)
return package_merged, project_merged
def wait_for_comment(self, repo_full_name: str, pr_number: int, text_to_find: str, subtext: str = None, timeout: int = 60):
"""Wait for a specific comment in the PR timeline."""
vprint(f"Waiting for comment '{text_to_find}'" + (f" with subtext '{subtext}'" if subtext else "") + f" in {repo_full_name} PR #{pr_number}...")
for _ in range(timeout):
time.sleep(1)
try:
events = self.get_timeline_events(repo_full_name, pr_number)
except Exception:
continue
for event in events:
body = event.get("body", "")
if not body:
continue
if subtext:
if text_to_find in body and subtext in body:
return True
else:
if text_to_find == body.strip():
return True
return False
def create_submodule_diff(submodule_name, old_sha, new_sha):
"""Create a git diff string for updating a submodule commit ID."""
return f"""diff --git a/{submodule_name} b/{submodule_name}
index {old_sha[:7]}..{new_sha[:7]} 160000
--- a/{submodule_name}
+++ b/{submodule_name}
@@ -1 +1 @@
-Subproject commit {old_sha}
+Subproject commit {new_sha}
"""

View File

@@ -1,123 +0,0 @@
import time
import re
from tests.lib.common_test_utils import vprint, create_submodule_diff
def wait_for_staging_bot_reviewer(gitea_env, prj_pr_number, timeout=30):
"""Wait for staging-bot to be added as a reviewer."""
for _ in range(timeout):
time.sleep(1)
pr_details = gitea_env.get_pr_details("myproducts/mySLFO", prj_pr_number)
if any(
r.get("login") == "autogits_obs_staging_bot"
for r in pr_details.get("requested_reviewers", [])
):
return True
return False
# This will hold the current status for the mock OBS server.
_obs_mock_state = {
"project_name": "",
"repo_arch_package_status": {}
}
def setup_obs_mock(httpserver, project_name, repo_arch_package_status):
"""Setup OBS mock handlers using the provided status dictionary."""
_obs_mock_state["project_name"] = project_name
_obs_mock_state["repo_arch_package_status"] = repo_arch_package_status
def general_project_meta_handler(request):
project = request.path.split("/")[2]
return f'<project name="{project}"><scmsync>http://gitea-test:3000/myproducts/mySLFO.git</scmsync></project>'
def build_result_handler(request):
return create_build_result_xml(_obs_mock_state["project_name"], _obs_mock_state["repo_arch_package_status"])
httpserver.clear()
httpserver.expect_request(re.compile(r"/source/[^/]+/_meta$"), method="GET").respond_with_handler(general_project_meta_handler)
httpserver.expect_request(re.compile(f"/build/{project_name}/_result"), method="GET").respond_with_handler(build_result_handler)
httpserver.expect_request(re.compile(r"/source/[^/]+/_meta$"), method="PUT").respond_with_data("OK")
httpserver.expect_request(re.compile(r"/source/[^/]+$"), method="DELETE").respond_with_data("OK")
## We don't clear anymore to preserve conftest defaults
# httpserver.expect_request(re.compile(f"/source/{project_name}/_meta$"), method="GET").respond_with_handler(general_project_meta_handler)
# httpserver.expect_request(re.compile(f"/build/{project_name}/_result"), method="GET").respond_with_handler(build_result_handler)
# httpserver.expect_request(re.compile(f"/source/{project_name}/_meta$"), method="PUT").respond_with_data("OK")
# httpserver.expect_request(re.compile(f"/source/{project_name}$"), method="DELETE").respond_with_data("OK")
def create_build_result_xml(project_name, repo_arch_package_status):
"""Create the XML response for OBS build results."""
results_xml = ""
grouped = {}
for (repo, arch, package), (repo_code, pkg_code) in repo_arch_package_status.items():
if (repo, arch) not in grouped:
grouped[(repo, arch)] = {"repo_code": repo_code, "packages": []}
grouped[(repo, arch)]["packages"].append((package, pkg_code))
for (repo, arch), data in grouped.items():
repo_code = data["repo_code"]
pkg_statuses = "".join([f'\n <status package="{p}" code="{c}"/>' for p, c in data["packages"]])
results_xml += f"""
<result project="{project_name}" repository="{repo}" arch="{arch}" code="{repo_code}" state="{repo_code}">{pkg_statuses}
</result>"""
return f'<resultlist state="mock">{results_xml}\n</resultlist>'
def prepare_multi_package_test(gitea_env, merge_branch_name, test_name_suffix):
"""
Step 1: Create package PRs and project PR with submodule updates.
Returns (pkg_pr_num1, pkg_pr_num2, prj_pr_number)
"""
diff = f"diff --git a/test_br_{test_name_suffix}_pkgA.txt b/test_br_{test_name_suffix}_pkgA.txt\nnew file mode 100644\nindex 00000000..473a0f4c\n"
pr1 = gitea_env.create_gitea_pr("mypool/pkgA", diff, f"Test BR {test_name_suffix} PR A", False, base_branch=merge_branch_name)
pkg_pr_number1 = pr1["number"]
pkg_head_sha1 = pr1["head"]["sha"]
diff2 = f"diff --git a/test_br_{test_name_suffix}_pkgB.txt b/test_br_{test_name_suffix}_pkgB.txt\nnew file mode 100644\nindex 00000000..473a0f4c\n"
pr2 = gitea_env.create_gitea_pr("mypool/pkgB", diff2, f"Test BR {test_name_suffix} PR B", False, base_branch=merge_branch_name)
pkg_pr_number2 = pr2["number"]
pkg_head_sha2 = pr2["head"]["sha"]
# Close automatically created project PRs for each package PR
for repo, num in [("mypool/pkgA", pkg_pr_number1), ("mypool/pkgB", pkg_pr_number2)]:
prj_pr_num = gitea_env.wait_for_project_pr(repo, num)
if prj_pr_num:
vprint(f"Closing automatically created project PR #{prj_pr_num} for {repo}#{num}")
gitea_env.update_gitea_pr_properties("myproducts/mySLFO", prj_pr_num, state="closed")
old_sha1 = gitea_env.get_submodule_sha("myproducts", "mySLFO", "pkgA", ref=merge_branch_name)
old_sha2 = gitea_env.get_submodule_sha("myproducts", "mySLFO", "pkgB", ref=merge_branch_name)
prj_diff = create_submodule_diff("pkgA", old_sha1, pkg_head_sha1)
prj_diff += create_submodule_diff("pkgB", old_sha2, pkg_head_sha2)
body = f"PR: mypool/pkgA!{pkg_pr_number1}\nPR: mypool/pkgB!{pkg_pr_number2}"
prj_pr = gitea_env.create_gitea_pr("myproducts/mySLFO", prj_diff, f"Test Project PR Multi {test_name_suffix}", False, base_branch=merge_branch_name, body=body)
prj_pr_number = prj_pr["number"]
return pkg_pr_number1, pkg_pr_number2, prj_pr_number
def finish_multi_package_setup(gitea_env, prj_pr_number, httpserver):
"""
Step 2: Configure OBS mock and only THEN add staging_bot as reviewer.
Returns (project_name, repo_arch_package_status, repos, archs)
"""
project_name = f"openSUSE:Leap:16.0:PullRequest:{prj_pr_number}"
repos = ["repo1", "repo2"]
archs = ["x86_64", "aarch64"]
packages = ["pkgA", "pkgB"]
repo_arch_package_status = {}
for r in repos:
for a in archs:
for p in packages:
repo_arch_package_status[(r, a, p)] = ("building", "building")
setup_obs_mock(httpserver, project_name, repo_arch_package_status)
# Add staging_bot as a reviewer AFTER mock is ready
gitea_env.request_reviewers("myproducts/mySLFO", prj_pr_number, ["autogits_obs_staging_bot"])
assert wait_for_staging_bot_reviewer(gitea_env, prj_pr_number), "Staging bot was not added as a reviewer."
# Expected Result 1: "Build is started in..."
assert gitea_env.wait_for_comment("myproducts/mySLFO", prj_pr_number, "Build is started in", project_name), "Staging bot did not post 'Build is started' comment."
return project_name, repo_arch_package_status, repos, archs

View File

@@ -1,285 +0,0 @@
import pytest
import time
from tests.lib.common_test_utils import GiteaAPIClient, vprint, create_submodule_diff
from tests.lib.staging_test_utils import (
wait_for_staging_bot_reviewer,
setup_obs_mock,
create_build_result_xml,
prepare_multi_package_test,
finish_multi_package_setup
)
@pytest.mark.t001
def test_001_build_on_all_archs_success(staging_main_env, httpserver):
gitea_env, test_full_repo_name, merge_branch_name = staging_main_env
# 1. Create a package PR.
diff = "diff --git a/test_br.txt b/test_br.txt\nnew file mode 100644\nindex 00000000..473a0f4c\n"
pr = gitea_env.create_gitea_pr("mypool/pkgA", diff, "Test BR PR", False, base_branch=merge_branch_name)
pkg_pr_number = pr["number"]
# 2. Wait for the workflow-pr bot to create the related project PR.
prj_pr_number = gitea_env.wait_for_project_pr("mypool/pkgA", pkg_pr_number)
assert prj_pr_number is not None, "Workflow bot did not create a project PR."
# 3. Mock the OBS result list.
project_name = f"openSUSE:Leap:16.0:PullRequest:{prj_pr_number}"
repos = ["repo1", "repo2"]
archs = ["x86_64", "aarch64"]
repo_arch_package_status = {}
for r in repos:
for a in archs:
repo_arch_package_status[(r, a, "pkgA")] = ("building", "building")
setup_obs_mock(httpserver, project_name, repo_arch_package_status)
# 4. Wait for staging-bot to be added as a reviewer.
assert wait_for_staging_bot_reviewer(gitea_env, prj_pr_number), "Staging bot was not added as a reviewer."
# Expected Result 1: "Build is started in..."
assert gitea_env.wait_for_comment("myproducts/mySLFO", prj_pr_number, "Build is started in", project_name), "Staging bot did not post 'Build is started' comment."
# 5. Transition all to success.
for r in repos:
for a in archs:
repo_arch_package_status[(r, a, "pkgA")] = ("published", "succeeded")
# Expected Result 2: "Build successful" on project PR.
assert gitea_env.wait_for_comment("myproducts/mySLFO", prj_pr_number, "Build successful"), "Staging bot did not post 'Build successful' comment on project PR."
# Expected Result 3: "Build successful..." on package PR.
assert gitea_env.wait_for_comment("mypool/pkgA", pkg_pr_number, "Build successful, for more information go in", project_name), "Staging bot did not post 'Build successful' comment on package PR."
@pytest.mark.t002
def test_002_build_on_all_archs_mix(staging_main_env, httpserver):
gitea_env, test_full_repo_name, merge_branch_name = staging_main_env
# 1. Create a package PR.
diff = "diff --git a/test_br_mix.txt b/test_br_mix.txt\nnew file mode 100644\nindex 00000000..473a0f4c\n"
pr = gitea_env.create_gitea_pr("mypool/pkgA", diff, "Test BR Mix PR", False, base_branch=merge_branch_name)
pkg_pr_number = pr["number"]
# 2. Wait for the workflow-pr bot to create the related project PR.
prj_pr_number = gitea_env.wait_for_project_pr("mypool/pkgA", pkg_pr_number)
assert prj_pr_number is not None, "Workflow bot did not create a project PR."
# 4. Mock the OBS result list BEFORE adding reviewer.
project_name = f"openSUSE:Leap:16.0:PullRequest:{prj_pr_number}"
repos = ["repo1", "repo2"]
archs = ["x86_64", "aarch64"]
repo_arch_package_status = {}
for r in repos:
for a in archs:
repo_arch_package_status[(r, a, "pkgA")] = ("building", "building")
setup_obs_mock(httpserver, project_name, repo_arch_package_status)
# 3. Add staging-bot as a reviewer.
gitea_env.request_reviewers("myproducts/mySLFO", prj_pr_number, ["autogits_obs_staging_bot"])
assert wait_for_staging_bot_reviewer(gitea_env, prj_pr_number), "Staging bot was not added as a reviewer."
# Expected Result 1: "Build is started in..."
assert gitea_env.wait_for_comment("myproducts/mySLFO", prj_pr_number, "Build is started in", project_name), "Staging bot did not post 'Build is started' comment."
# 6. Transition the first repository (all architectures) to "finished" mode and set its package statuses to "success" (e.g., code="succeeded").
for a in archs:
repo_arch_package_status[("repo1", a, "pkgA")] = ("published", "succeeded")
# 7. Transition the second repository (all architectures) to "finished" mode and set its package statuses to "failed" (e.g., code="failed").
for a in archs:
repo_arch_package_status[("repo2", a, "pkgA")] = ("finished", "failed")
# Expected Result 2: "Build failed" on project PR.
assert gitea_env.wait_for_comment("myproducts/mySLFO", prj_pr_number, "Build failed"), "Staging bot did not post 'Build failed' comment on project PR."
# Expected Result 3: "Build failed, for more information go in..." on package PR.
assert gitea_env.wait_for_comment("mypool/pkgA", pkg_pr_number, "Build failed, for more information go in", project_name), "Staging bot did not post 'Build failed' comment on package PR."
@pytest.mark.t003
def test_003_build_on_some_archs_failed(staging_main_env, httpserver):
gitea_env, test_full_repo_name, merge_branch_name = staging_main_env
# 1. Create a package PR.
diff = "diff --git a/test_br_some_fail.txt b/test_br_some_fail.txt\nnew file mode 100644\nindex 00000000..473a0f4c\n"
pr = gitea_env.create_gitea_pr("mypool/pkgA", diff, "Test BR Some Fail PR", False, base_branch=merge_branch_name)
pkg_pr_number = pr["number"]
# 2. Wait for the workflow-pr bot to create the related project PR.
prj_pr_number = gitea_env.wait_for_project_pr("mypool/pkgA", pkg_pr_number)
assert prj_pr_number is not None, "Workflow bot did not create a project PR."
# 4. Mock the OBS result list BEFORE adding reviewer.
project_name = f"openSUSE:Leap:16.0:PullRequest:{prj_pr_number}"
repos = ["repo1", "repo2"]
archs = ["x86_64", "aarch64"]
repo_arch_package_status = {}
for r in repos:
for a in archs:
repo_arch_package_status[(r, a, "pkgA")] = ("building", "building")
setup_obs_mock(httpserver, project_name, repo_arch_package_status)
# 3. Add staging-bot as a reviewer.
gitea_env.request_reviewers("myproducts/mySLFO", prj_pr_number, ["autogits_obs_staging_bot"])
assert wait_for_staging_bot_reviewer(gitea_env, prj_pr_number), "Staging bot was not added as a reviewer."
# Expected Result 1: "Build is started in..."
assert gitea_env.wait_for_comment("myproducts/mySLFO", prj_pr_number, "Build is started in", project_name), "Staging bot did not post 'Build is started' comment."
# 6. Transition the first repository (all architectures) to "finished" mode and set its package statuses to "success" (e.g., code="succeeded").
for a in archs:
repo_arch_package_status[("repo1", a, "pkgA")] = ("published", "succeeded")
# 7. Transition the second repository to "finished" mode, setting the first architecture to "failed" (code="failed") and the second architecture to "success" (code="succeeded").
repo_arch_package_status[("repo2", archs[0], "pkgA")] = ("finished", "failed")
repo_arch_package_status[("repo2", archs[1], "pkgA")] = ("finished", "succeeded")
# Expected Result 2: "Build failed" on project PR.
assert gitea_env.wait_for_comment("myproducts/mySLFO", prj_pr_number, "Build failed"), "Staging bot did not post 'Build failed' comment on project PR."
# Expected Result 3: "Build failed, for more information go in..." on package PR.
assert gitea_env.wait_for_comment("mypool/pkgA", pkg_pr_number, "Build failed, for more information go in", project_name), "Staging bot did not post 'Build failed' comment on package PR."
@pytest.mark.t004
def test_004_build_multiple_packages_success(staging_main_env, httpserver):
gitea_env, test_full_repo_name, merge_branch_name = staging_main_env
pkg_pr_number1, pkg_pr_number2, prj_pr_number = prepare_multi_package_test(
gitea_env, merge_branch_name, "multi"
)
project_name, repo_arch_package_status, repos, archs = finish_multi_package_setup(
gitea_env, prj_pr_number, httpserver
)
# 6. Transition all repositories and architectures for the first package to "finished" mode and set its package statuses to "success" (e.g., code="succeeded").
for r in repos:
for a in archs:
repo_arch_package_status[(r, a, "pkgA")] = ("published", "succeeded")
# Verify "Build successful" is NOT yet posted
time.sleep(5)
events = gitea_env.get_timeline_events("myproducts/mySLFO", prj_pr_number)
assert not any(e.get("body") == "Build successful" for e in events), "Build successful posted prematurely."
# 7. Transition all repositories and architectures for the second package to "finished" mode and set its package statuses to "success" (e.g., code="succeeded").
for r in repos:
for a in archs:
repo_arch_package_status[(r, a, "pkgB")] = ("published", "succeeded")
# Expected Result 2: "Build successful" on project PR.
assert gitea_env.wait_for_comment("myproducts/mySLFO", prj_pr_number, "Build successful"), "Staging bot did not post 'Build successful' comment on project PR."
# Expected Result 3: "Build successful..." on each package PR.
assert gitea_env.wait_for_comment("mypool/pkgA", pkg_pr_number1, "Build successful, for more information go in", project_name), "Staging bot did not post 'Build successful' comment on package PR A."
assert gitea_env.wait_for_comment("mypool/pkgB", pkg_pr_number2, "Build successful, for more information go in", project_name), "Staging bot did not post 'Build successful' comment on package PR B."
@pytest.mark.t005
def test_005_build_multiple_packages_mix(staging_main_env, httpserver):
gitea_env, test_full_repo_name, merge_branch_name = staging_main_env
pkg_pr_number1, pkg_pr_number2, prj_pr_number = prepare_multi_package_test(
gitea_env, merge_branch_name, "mix_multi"
)
project_name, repo_arch_package_status, repos, archs = finish_multi_package_setup(
gitea_env, prj_pr_number, httpserver
)
# 6. Transition the first package (all repositories and architectures) to "finished" mode and set its package statuses to "success" (e.g., code="succeeded").
for r in repos:
for a in archs:
repo_arch_package_status[(r, a, "pkgA")] = ("published", "succeeded")
# 7. Transition the second package (all repositories and architectures) to "finished" mode and set its package statuses to "failed" (e.g., code="failed").
for r in repos:
for a in archs:
repo_arch_package_status[(r, a, "pkgB")] = ("finished", "failed")
# Give the bot some time to see the final state
time.sleep(2)
# Expected Result 2: "Build failed" on project PR.
assert gitea_env.wait_for_comment("myproducts/mySLFO", prj_pr_number, "Build failed"), "Staging bot did not post 'Build failed' comment on project PR."
# Expected Result 3: "Build successful..." on the successful package's PR.
assert gitea_env.wait_for_comment("mypool/pkgA", pkg_pr_number1, "Build successful, for more information go in", project_name), "Staging bot did not post 'Build successful' comment on package PR A."
# Expected Result 4: "Build failed..." on the failed package's PR.
assert gitea_env.wait_for_comment("mypool/pkgB", pkg_pr_number2, "Build failed, for more information go in", project_name), "Staging bot did not post 'Build failed' comment on package PR B."
@pytest.mark.t006
def test_006_build_multiple_packages_partial_fail(staging_main_env, httpserver):
gitea_env, test_full_repo_name, merge_branch_name = staging_main_env
pkg_pr_number1, pkg_pr_number2, prj_pr_number = prepare_multi_package_test(
gitea_env, merge_branch_name, "partial_multi"
)
project_name, repo_arch_package_status, repos, archs = finish_multi_package_setup(
gitea_env, prj_pr_number, httpserver
)
# 6. Transition the first package (all repositories and architectures) to "finished" mode and set its package statuses to "success" (e.g., code="succeeded").
for r in repos:
for a in archs:
repo_arch_package_status[(r, a, "pkgA")] = ("published", "succeeded")
# 7. Transition the second package:
# Repository 1 (all architectures) to "finished" mode with "success" (e.g., code="succeeded").
for a in archs:
repo_arch_package_status[("repo1", a, "pkgB")] = ("published", "succeeded")
# Repository 2 (all architectures) to "finished" mode with "failed" (e.g., code="failed").
for a in archs:
repo_arch_package_status[("repo2", a, "pkgB")] = ("finished", "failed")
# Give the bot some time to see the final state
time.sleep(2)
# Expected Result 2: "Build failed" on project PR.
assert gitea_env.wait_for_comment("myproducts/mySLFO", prj_pr_number, "Build failed"), "Staging bot did not post 'Build failed' comment on project PR."
# Expected Result 3: "Build successful..." on the first (successful) package's PR.
assert gitea_env.wait_for_comment("mypool/pkgA", pkg_pr_number1, "Build successful, for more information go in", project_name), "Staging bot did not post 'Build successful' comment on package PR A."
# Expected Result 4: "Build failed..." on the second (failed) package's PR.
assert gitea_env.wait_for_comment("mypool/pkgB", pkg_pr_number2, "Build failed, for more information go in", project_name), "Staging bot did not post 'Build failed' comment on package PR B."
@pytest.mark.t007
def test_007_build_multiple_packages_arch_fail(staging_main_env, httpserver):
gitea_env, test_full_repo_name, merge_branch_name = staging_main_env
pkg_pr_number1, pkg_pr_number2, prj_pr_number = prepare_multi_package_test(
gitea_env, merge_branch_name, "arch_multi"
)
project_name, repo_arch_package_status, repos, archs = finish_multi_package_setup(
gitea_env, prj_pr_number, httpserver
)
# 6. Transition the first package (all repositories and architectures) to "finished" mode and set its package statuses to "success" (e.g., code="succeeded").
for r in repos:
for a in archs:
repo_arch_package_status[(r, a, "pkgA")] = ("published", "succeeded")
# 7. Transition the second package:
# Architecture 1 (all repositories) to "finished" mode with "success" (e.g., code="succeeded").
for r in repos:
repo_arch_package_status[(r, archs[0], "pkgB")] = ("published", "succeeded")
# Architecture 2 (all repositories) to "finished" mode with "failed" (e.g., code="failed").
for r in repos:
repo_arch_package_status[(r, archs[1], "pkgB")] = ("finished", "failed")
# Give the bot some time to see the final state
time.sleep(2)
# Expected Result 2: "Build failed" on project PR.
assert gitea_env.wait_for_comment("myproducts/mySLFO", prj_pr_number, "Build failed"), "Staging bot did not post 'Build failed' comment on project PR."
# Expected Result 3: "Build successful..." on the first (successful) package's PR.
assert gitea_env.wait_for_comment("mypool/pkgA", pkg_pr_number1, "Build successful, for more information go in", project_name), "Staging bot did not post 'Build successful' comment on package PR A."
# Expected Result 4: "Build failed..." on the second (failed) package's PR.
assert gitea_env.wait_for_comment("mypool/pkgB", pkg_pr_number2, "Build failed, for more information go in", project_name), "Staging bot did not post 'Build failed' comment on package PR B."

View File

@@ -6,7 +6,7 @@ COPY integration/rabbitmq-config/certs/cert.pem /usr/share/pki/trust/anchors/git
RUN update-ca-certificates
# Install git and ssh
RUN zypper -n in git-core openssh-clients binutils git-lfs procps gawk || (tail -n 1000 /var/log/zypper.log; exit 1)
RUN zypper -n in git-core openssh-clients binutils git-lfs || (tail -n 1000 /var/log/zypper.log; exit 1)
# Copy the pre-built binary into the container
COPY workflow-pr/workflow-pr /usr/local/bin/workflow-pr

View File

@@ -9,7 +9,7 @@ RUN zypper ar -f http://download.opensuse.org/repositories/devel:/Factory:/git-w
RUN zypper --gpg-auto-import-keys ref
# Install git and ssh
RUN zypper -n in git-core openssh-clients autogits-workflow-pr binutils git-lfs procps gawk || ( tail -n 1000 /var/log/zypper.log; exit 1 )
RUN zypper -n in git-core openssh-clients autogits-workflow-pr binutils git-lfs || ( tail -n 1000 /var/log/zypper.log; exit 1 )
COPY integration/workflow-pr/entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +4755 /usr/local/bin/entrypoint.sh

View File

@@ -1249,6 +1249,9 @@ func main() {
}
gitea := common.AllocateGiteaTransport(GiteaUrl)
if PollInterval < gitea.GetCacheTTL() {
gitea.SetCacheTTL(PollInterval)
}
user, err := gitea.GetCurrentUser()
if err != nil {