From 94d83ccf80339a64550201971556742a93309dd1e14501877691018286d24fd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Schr=C3=B6ter?= Date: Tue, 14 Oct 2025 16:08:20 +0200 Subject: [PATCH 1/9] Fix build status check when package source is in subdir We must not use the upper directory name as part of the package name. --- obs-staging-bot/main.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/obs-staging-bot/main.go b/obs-staging-bot/main.go index cb07981..2f3171b 100644 --- a/obs-staging-bot/main.go +++ b/obs-staging-bot/main.go @@ -27,6 +27,7 @@ import ( "net/url" "os" "path" + "path/filepath" "regexp" "runtime/debug" "slices" @@ -910,10 +911,13 @@ func ProcessPullRequest(obs common.ObsClientInterface, gitea common.Gitea, org, if !stagingConfig.RebuildAll { for pkg, headOid := range headSubmodules { if baseOid, exists := baseSubmodules[pkg]; !exists || baseOid != headOid { + if pkg != "rpms" && pkg != "dependencies" { + _, spkg := filepath.Split(pkg) if exists { - modifiedPackages = append(modifiedPackages, pkg) + modifiedPackages = append(modifiedPackages, spkg) } else { - newPackages = append(newPackages, pkg) + newPackages = append(newPackages, spkg) + } } common.LogDebug(pkg, ":", baseOid, "->", headOid) } -- 2.51.1 From 57a4860d67caf85d3b265bfedaa32f58d747b3e6211eefbe07407c6e3d4f2a3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Schr=C3=B6ter?= Date: Thu, 20 Nov 2025 12:58:01 +0100 Subject: [PATCH 2/9] workflow-direct: use relative path when adding a submodule This solves the issue of using the right credentials based on the main repo. Also it allows to rename the organisation. --- workflow-direct/main.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/workflow-direct/main.go b/workflow-direct/main.go index b6f1dfc..416f9ec 100644 --- a/workflow-direct/main.go +++ b/workflow-direct/main.go @@ -123,7 +123,7 @@ func processConfiguredRepositoryAction(action *common.RepositoryWebhookEvent, co common.LogError(" - ", action.Repository.Name, "repo is not sha256. Ignoring.") return } - common.PanicOnError(git.GitExec(gitPrj, "submodule", "--quiet", "add", "--force", "--depth", "1", action.Repository.Clone_Url, action.Repository.Name)) + common.PanicOnError(git.GitExec(gitPrj, "submodule", "--quiet", "add", "--force", "--depth", "1", "../" + action.Repository.Name, action.Repository.Name)) defer git.GitExecQuietOrPanic(gitPrj, "submodule", "deinit", "--all", "-f") branch := strings.TrimSpace(git.GitExecWithOutputOrPanic(path.Join(gitPrj, action.Repository.Name), "branch", "--show-current")) @@ -215,7 +215,7 @@ func processConfiguredPushAction(action *common.PushWebhookEvent, config *common } if stat, err := os.Stat(filepath.Join(git.GetPath(), gitPrj, action.Repository.Name)); err != nil { - git.GitExecOrPanic(gitPrj, "submodule", "--quiet", "add", "--force", "--depth", "1", action.Repository.Clone_Url, action.Repository.Name) + git.GitExecOrPanic(gitPrj, "submodule", "--quiet", "add", "--force", "--depth", "1", "../" + action.Repository.Name, action.Repository.Name) common.LogDebug("Pushed to package that is not part of the project. Re-adding...", err) } else if !stat.IsDir() { common.LogError("Pushed to a package that is not a submodule but exists in the project. Ignoring.") @@ -420,7 +420,7 @@ next_repo: } // add repository to git project - common.PanicOnError(git.GitExec(gitPrj, "submodule", "--quiet", "add", "--force", "--depth", "1", r.CloneURL, r.Name)) + common.PanicOnError(git.GitExec(gitPrj, "submodule", "--quiet", "add", "--force", "--depth", "1", "../" + r.Name, r.Name)) curBranch := strings.TrimSpace(git.GitExecWithOutputOrPanic(path.Join(gitPrj, r.Name), "branch", "--show-current")) if branch != curBranch { -- 2.51.1 From ef61736d70e9f36941d7c44cbbeb065befba5b72e7c1ac5eb66974579e871d3e Mon Sep 17 00:00:00 2001 From: Adam Majer Date: Fri, 28 Nov 2025 12:25:58 +0100 Subject: [PATCH 3/9] pr: only update PR if elided title not changed Gitea trims long titles so we need to compare if the trimmed length is same, not entire string that will always differ. --- workflow-pr/pr_processor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflow-pr/pr_processor.go b/workflow-pr/pr_processor.go index 72542be..d6c5741 100644 --- a/workflow-pr/pr_processor.go +++ b/workflow-pr/pr_processor.go @@ -384,7 +384,7 @@ func (pr *PRProcessor) UpdatePrjGitPR(prset *common.PRSet) error { } return CurrentTitle == NewTitle } - if PrjGitPR.PR.User.UserName == CurrentUser.UserName && (PrjGitPR.PR.Body != PrjGitBody || !isPrTitleSame(PrjGitPR.PR.Title, PrjGitTitle)) { + if !pr.config.NoProjectGitPR && PrjGitPR.PR.User.UserName == CurrentUser.UserName && (PrjGitPR.PR.Body != PrjGitBody || !isPrTitleSame(PrjGitPR.PR.Title, PrjGitTitle)) { Gitea.UpdatePullRequest(PrjGit.Owner.UserName, PrjGit.Name, PrjGitPR.PR.Index, &models.EditPullRequestOption{ RemoveDeadline: true, Title: PrjGitTitle, -- 2.51.1 From 2c891ded6a7c20586995cb888ea91cc4170b6c397e327f9144cc12faff6aa670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Schr=C3=B6ter?= Date: Fri, 28 Nov 2025 13:34:01 +0100 Subject: [PATCH 4/9] Disable temporary comment adding in case of lacking permissions --- workflow-pr/pr_processor.go | 1 + 1 file changed, 1 insertion(+) diff --git a/workflow-pr/pr_processor.go b/workflow-pr/pr_processor.go index d6c5741..74c6482 100644 --- a/workflow-pr/pr_processor.go +++ b/workflow-pr/pr_processor.go @@ -314,6 +314,7 @@ func (pr *PRProcessor) UpdatePrjGitPR(prset *common.PRSet) error { // well, wrong place... // common.LogError("Warning: source and target branch are in different repositories. We may not have the right permissions...") // Gitea.AddComment(PrjGitPR.PR, "This PR does not allow maintainer changes, but referenced package branch has changed!") + common.LogError("Warning: source and target branch are in different repositories. We may not have the right permissions...") return nil } } -- 2.51.1 From 1c63899e495fc2103ac622a2b4c88c8dd61c50e0c63c7b447da06fd6bb8baaa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Schr=C3=B6ter?= Date: Tue, 13 Jan 2026 14:00:28 +0100 Subject: [PATCH 5/9] Add an "lfs fsck" check after submodule update to avoid merging pull requests where lfs objects are not correctly registered. Can happen when user has not installed lfs for example. --- workflow-pr/pr_processor.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/workflow-pr/pr_processor.go b/workflow-pr/pr_processor.go index 74c6482..0cfab67 100644 --- a/workflow-pr/pr_processor.go +++ b/workflow-pr/pr_processor.go @@ -180,6 +180,33 @@ func (pr *PRProcessor) SetSubmodulesToMatchPRSet(prset *common.PRSet) error { } updateSubmoduleInPR(submodulePath, prHead, git) + err := git.GitExec(path.Join(common.DefaultGitPrj, submodulePath), "lfs", "fetch") + common.LogError("lfs fetch err: ", err) + if err = git.GitExec(path.Join(common.DefaultGitPrj, submodulePath), "lfs", "fsck"); err != nil { + + found_comment := false + timeline, terr := common.FetchTimelineSinceLastPush(Gitea, prHead, org, repo, idx) + if terr != nil { + common.LogError("lfs fsck error, but timeline fetch failed") + break + } + msgPrefix := "The LFS objects are broken!" + for _, t := range timeline { + if t.Type == common.TimelineCommentType_Comment && strings.HasPrefix(t.Body, msgPrefix) { + found_comment = true + common.LogError("lfs fsck Comment already found") + + break + } + } + + if !found_comment && !common.IsDryRun { + Gitea.AddComment(pr.PR, msgPrefix + " Please verify with 'git lfs fsck'") + } + common.LogError("lfs fsck failed with: ", err.Error()) + return err + } + status, err := git.GitStatus(common.DefaultGitPrj) common.LogDebug("status:", status) common.LogDebug("submodule", repo, " hash:", id, " -> ", prHead) -- 2.51.1 From 98d701bfe829c1699c23ebe437436697fab48a68fe56e2e1b058668b13920123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Schr=C3=B6ter?= Date: Wed, 4 Feb 2026 17:59:07 +0100 Subject: [PATCH 6/9] staging: Fix service file to work with obs ssh connections We need a fixed user for that --- systemd/obs-staging-bot.service | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/systemd/obs-staging-bot.service b/systemd/obs-staging-bot.service index d3dce81..ce39f00 100644 --- a/systemd/obs-staging-bot.service +++ b/systemd/obs-staging-bot.service @@ -6,9 +6,13 @@ After=network-online.target Type=exec ExecStart=/usr/bin/obs-staging-bot EnvironmentFile=-/etc/default/obs-staging-bot.env -DynamicUser=yes -NoNewPrivileges=yes -ProtectSystem=strict +User=obs_staging_bot +Group=users + +# This may work when not using ssh api connections: +#DynamicUser=yes +#NoNewPrivileges=yes +#ProtectSystem=strict [Install] WantedBy=multi-user.target -- 2.51.1 From e43833c2ed8fbf8beec6f585ec7f91f5f4eca6b51039ea17248cc725f1f743fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Schr=C3=B6ter?= Date: Wed, 4 Feb 2026 17:59:07 +0100 Subject: [PATCH 7/9] staging: Hardcode currently used user of IBS We should consolidate to a nicer user name... --- systemd/obs-staging-bot.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/systemd/obs-staging-bot.service b/systemd/obs-staging-bot.service index ce39f00..cce596a 100644 --- a/systemd/obs-staging-bot.service +++ b/systemd/obs-staging-bot.service @@ -6,7 +6,7 @@ After=network-online.target Type=exec ExecStart=/usr/bin/obs-staging-bot EnvironmentFile=-/etc/default/obs-staging-bot.env -User=obs_staging_bot +User=autogits_obs_staging_bot Group=users # This may work when not using ssh api connections: -- 2.51.1 From 1f6ec2a1c3f0d4b6cb7f85cdee193602a7c55a6ce61269a089177c2c0d9cdc42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Schr=C3=B6ter?= Date: Fri, 13 Feb 2026 08:21:01 +0100 Subject: [PATCH 8/9] Use our IBS branch for packaging Need to use it from internal resource policy wise, but will be mirrored outside. --- autogits.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autogits.spec b/autogits.spec index 3e95bc2..d2c010a 100644 --- a/autogits.spec +++ b/autogits.spec @@ -22,6 +22,8 @@ Release: 0 Summary: GitWorkflow utilities License: GPL-2.0-or-later URL: https://src.opensuse.org/adamm/autogits +#!RemoteAsset: git+https://src.suse.de/adrianSuSE/autogits#ibs_state +Source0: %name-%version.tar.xz BuildRequires: git BuildRequires: systemd-rpm-macros BuildRequires: go -- 2.51.1 From 4da7a62404aca667f2345fb965a3b8b7500c8f39be2439f33035ad4ce9f71b75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Schr=C3=B6ter?= Date: Mon, 9 Mar 2026 11:38:14 +0100 Subject: [PATCH 9/9] staging: Support multiple Labels per QA project This is required to handle base projects for binary snapshotting --- common/config.go | 8 ++++++++ obs-staging-bot/main.go | 13 +++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/common/config.go b/common/config.go index 7a4a53f..c19fb24 100644 --- a/common/config.go +++ b/common/config.go @@ -59,6 +59,7 @@ type QAConfig struct { Name string Origin string Label string // requires this gitea lable to be set or skipped + Labels []string // requires any of the lables to be set BuildDisableRepos []string // which repos to build disable in the new project } @@ -342,6 +343,13 @@ func ParseStagingConfig(data []byte) (*StagingConfig, error) { if err := json.Unmarshal(data, &staging); err != nil { return nil, err } + // backward compability, transfer legacy Label to new Labels array + for _, setup := range staging.QA { + if len(setup.Labels) == 0 && len(setup.Label) > 0 { + setup.Labels = []string{setup.Label} + setup.Label = "" + } + } return &staging, nil } diff --git a/obs-staging-bot/main.go b/obs-staging-bot/main.go index 2f3171b..ca66862 100644 --- a/obs-staging-bot/main.go +++ b/obs-staging-bot/main.go @@ -734,8 +734,16 @@ func ProcessQaProjects(obs common.ObsClientInterface, stagingConfig *common.Stag var qa_projects []string for _, setup := range stagingConfig.QA { QAproject := stagingProject + ":" + setup.Name - if len(setup.Label) > 0 { - if _, ok := prLabelNames[setup.Label]; !ok { + if len(setup.Labels) > 0 { + matchedLabel := false + for labelName := range prLabelNames { + if slices.Contains(setup.Labels, labelName) { + matchedLabel = true + break + } + } + + if matchedLabel == false { if !IsDryRun { // blindly remove, will fail when not existing obs.DeleteProject(QAproject) @@ -1027,6 +1035,7 @@ func ProcessPullRequest(obs common.ObsClientInterface, gitea common.Gitea, org, done := false overallBuildStatus := ProcessBuildStatus(stagingResult) commentSuffix := "" + common.LogDebug("Number of QA Projects: ", len(qaProjects)) if len(qaProjects) > 0 && overallBuildStatus == BuildStatusSummarySuccess { seperator := " in " for _, qaProject := range qaProjects { -- 2.51.1