WIP: Various extensions for IBS #72

Draft
adrianSuSE wants to merge 11 commits from adrianSuSE/autogits:ibs_state into main
4 changed files with 42 additions and 132 deletions

View File

@@ -904,6 +904,7 @@ func (e *GitHandlerImpl) GitSubmoduleList(gitPath, commitId string) (submoduleLi
for _, te := range tree.items { for _, te := range tree.items {
if te.isTree() { if te.isTree() {
trees[p+te.name+"/"] = te.hash trees[p+te.name+"/"] = te.hash
submoduleList[p+te.name] = te.hash
} else if te.isSubmodule() { } else if te.isSubmodule() {
submoduleList[p+te.name] = te.hash submoduleList[p+te.name] = te.hash
} }

View File

@@ -26,6 +26,7 @@ import (
"net/url" "net/url"
"os" "os"
"path" "path"
"path/filepath"
"regexp" "regexp"
"runtime/debug" "runtime/debug"
"slices" "slices"
@@ -109,161 +110,67 @@ const (
BuildStatusSummaryUnknown = 4 BuildStatusSummaryUnknown = 4
) )
func ProcessBuildStatus(project, refProject *common.BuildResultList) BuildStatusSummary { func ProcessBuildStatus(project *common.BuildResultList) BuildStatusSummary {
if _, finished := refProject.BuildResultSummary(); !finished {
common.LogDebug("refProject not finished building??")
return BuildStatusSummaryUnknown
}
if _, finished := project.BuildResultSummary(); !finished { if _, finished := project.BuildResultSummary(); !finished {
common.LogDebug("Still building...") common.LogDebug("Still building...")
return BuildStatusSummaryBuilding return BuildStatusSummaryBuilding
} }
// the repositories should be setup equally between the projects. We //slices.SortFunc(project.Result, BuildResultSorter)
// need to verify that packages that are building in `refProject` are not
// failing in the `project`
BuildResultSorter := func(a, b *common.BuildResult) int {
if c := strings.Compare(a.Repository, b.Repository); c != 0 {
return c
}
if c := strings.Compare(a.Arch, b.Arch); c != 0 {
return c
}
panic("Should not happen -- BuiltResultSorter equal repos?") common.LogDebug("build results", len(project.Result))
}
slices.SortFunc(project.Result, BuildResultSorter)
if refProject == nil {
// just return if buid finished and have some successes, since new package
common.LogInfo("New package. Only need some success...")
SomeSuccess := false
for i := 0; i < len(project.Result); i++ {
repoRes := project.Result[i]
repoResStatus, ok := common.ObsRepoStatusDetails[repoRes.Code]
if !ok {
common.LogDebug("cannot find code:", repoRes.Code)
return BuildStatusSummaryUnknown
}
if !repoResStatus.Finished {
return BuildStatusSummaryBuilding
}
for _, pkg := range repoRes.Status {
pkgStatus, ok := common.ObsBuildStatusDetails[pkg.Code]
if !ok {
common.LogInfo("Unknown package build status:", pkg.Code, "for", pkg.Package)
common.LogDebug("Details:", pkg.Details)
}
if pkgStatus.Success {
SomeSuccess = true
}
}
}
if SomeSuccess {
return BuildStatusSummarySuccess
}
return BuildStatusSummaryFailed
}
slices.SortFunc(refProject.Result, BuildResultSorter)
common.LogDebug("comparing results", len(project.Result), "vs. ref", len(refProject.Result))
SomeSuccess := false
for i := 0; i < len(project.Result); i++ { for i := 0; i < len(project.Result); i++ {
common.LogDebug("searching for", project.Result[i].Repository, "/", project.Result[i].Arch) common.LogDebug("searching for", project.Result[i].Repository, "/", project.Result[i].Arch)
j := 0 j := 0
found: found:
for ; j < len(refProject.Result); j++ { for j = 0; j < len(project.Result); j++ {
if project.Result[i].Repository != refProject.Result[j].Repository ||
project.Result[i].Arch != refProject.Result[j].Arch {
continue
}
common.LogDebug(" found match for @ idx:", j) common.LogDebug(" found match for @ idx:", j)
res, success := ProcessRepoBuildStatus(project.Result[i].Status, refProject.Result[j].Status) res := ProcessRepoBuildStatus(project.Result[i].Status)
switch res { switch res {
case BuildStatusSummarySuccess: case BuildStatusSummarySuccess:
SomeSuccess = SomeSuccess || success
break found break found
case BuildStatusSummaryFailed:
return BuildStatusSummaryFailed
default: default:
return res return res
} }
} }
if j >= len(refProject.Result) {
common.LogDebug("Cannot find results...")
common.LogDebug(project.Result[i])
common.LogDebug(refProject.Result)
return BuildStatusSummaryUnknown
}
} }
if SomeSuccess { return BuildStatusSummarySuccess
return BuildStatusSummarySuccess
}
return BuildStatusSummaryFailed
} }
func ProcessRepoBuildStatus(results, ref []*common.PackageBuildStatus) (status BuildStatusSummary, SomeSuccess bool) { func ProcessRepoBuildStatus(results []*common.PackageBuildStatus) (status BuildStatusSummary) {
PackageBuildStatusSorter := func(a, b *common.PackageBuildStatus) int {
return strings.Compare(a.Package, b.Package) PackageBuildStatusSorter := func(a, b *common.PackageBuildStatus) int {
} return strings.Compare(a.Package, b.Package)
}
common.LogDebug("******** REF: ")
data, _ := xml.MarshalIndent(ref, "", " ")
common.LogDebug(string(data))
common.LogDebug("******* RESULTS: ") common.LogDebug("******* RESULTS: ")
data, _ = xml.MarshalIndent(results, "", " ") data, _ := xml.MarshalIndent(results, "", " ")
common.LogDebug(string(data)) common.LogDebug(string(data))
common.LogDebug("*******") common.LogDebug("*******")
// compare build result // compare build result
slices.SortFunc(results, PackageBuildStatusSorter) slices.SortFunc(results, PackageBuildStatusSorter)
slices.SortFunc(ref, PackageBuildStatusSorter)
j := 0
SomeSuccess = false
for i := 0; i < len(results); i++ { for i := 0; i < len(results); i++ {
res, ok := common.ObsBuildStatusDetails[results[i].Code] res, ok := common.ObsBuildStatusDetails[results[i].Code]
if !ok { if !ok {
common.LogInfo("unknown package result code:", results[i].Code, "for package:", results[i].Package) common.LogInfo("unknown package result code:", results[i].Code, "for package:", results[i].Package)
return BuildStatusSummaryUnknown, SomeSuccess return BuildStatusSummaryUnknown
} }
if !res.Finished { if !res.Finished {
return BuildStatusSummaryBuilding, SomeSuccess return BuildStatusSummaryBuilding
} }
if !res.Success { if !res.Success {
// not failed if reference project also failed for same package here return BuildStatusSummaryFailed
for ; j < len(results) && strings.Compare(results[i].Package, ref[j].Package) < 0; j++ {
}
if j < len(results) && results[i].Package == ref[j].Package {
refRes, ok := common.ObsBuildStatusDetails[ref[j].Code]
if !ok {
common.LogInfo("unknown ref package result code:", ref[j].Code, "package:", ref[j].Package)
return BuildStatusSummaryUnknown, SomeSuccess
}
if !refRes.Finished {
common.LogDebug("Not finished building in reference project?")
}
if refRes.Success {
return BuildStatusSummaryFailed, SomeSuccess
}
}
} else {
SomeSuccess = true
} }
} }
return BuildStatusSummarySuccess, SomeSuccess return BuildStatusSummarySuccess
} }
func GenerateObsPrjMeta(git common.Git, gitea common.Gitea, pr *models.PullRequest, stagingPrj, buildPrj string, stagingMasterPrj string) (*common.ProjectMeta, error) { func GenerateObsPrjMeta(git common.Git, gitea common.Gitea, pr *models.PullRequest, stagingPrj, buildPrj string, stagingMasterPrj string) (*common.ProjectMeta, error) {
@@ -322,9 +229,9 @@ func GenerateObsPrjMeta(git common.Git, gitea common.Gitea, pr *models.PullReque
common.LogError("error fetching project meta for", buildPrj, ". Err:", err) common.LogError("error fetching project meta for", buildPrj, ". Err:", err)
return nil, err return nil, err
} }
common.LogInfo("Meta: ", meta)
// generate new project with paths pointinig back to original repos // generate new project with paths pointinig back to original repos
// disable publishing
meta.Name = stagingPrj meta.Name = stagingPrj
meta.Description = fmt.Sprintf(`Pull request build job PR#%d to branch %s of %s/%s`, meta.Description = fmt.Sprintf(`Pull request build job PR#%d to branch %s of %s/%s`,
@@ -339,7 +246,10 @@ func GenerateObsPrjMeta(git common.Git, gitea common.Gitea, pr *models.PullReque
urlPkg := make([]string, 0, len(modifiedOrNew)) urlPkg := make([]string, 0, len(modifiedOrNew))
for _, pkg := range modifiedOrNew { for _, pkg := range modifiedOrNew {
urlPkg = append(urlPkg, "onlybuild="+url.QueryEscape(pkg)) // FIXME: skip manifest subdirectories itself
// strip any leading directory name and just hand over last directory as package name
onlybuilds := strings.Split(pkg, "/")
urlPkg = append(urlPkg, "onlybuild="+url.QueryEscape(onlybuilds[len(onlybuilds)-1]))
} }
meta.ScmSync = pr.Head.Repo.CloneURL + "?" + strings.Join(urlPkg, "&") + "#" + pr.Head.Sha meta.ScmSync = pr.Head.Repo.CloneURL + "?" + strings.Join(urlPkg, "&") + "#" + pr.Head.Sha
if len(meta.ScmSync) >= 65535 { if len(meta.ScmSync) >= 65535 {
@@ -824,10 +734,13 @@ func ProcessPullRequest(gitea common.Gitea, org, repo string, id int64) (bool, e
if !stagingConfig.RebuildAll { if !stagingConfig.RebuildAll {
for pkg, headOid := range headSubmodules { for pkg, headOid := range headSubmodules {
if baseOid, exists := baseSubmodules[pkg]; !exists || baseOid != headOid { if baseOid, exists := baseSubmodules[pkg]; !exists || baseOid != headOid {
if pkg != "rpms" && pkg != "dependencies" {
_, spkg := filepath.Split(pkg)
if exists { if exists {
modifiedPackages = append(modifiedPackages, pkg) modifiedPackages = append(modifiedPackages, spkg)
} else { } else {
newPackages = append(newPackages, pkg) newPackages = append(newPackages, spkg)
}
} }
common.LogDebug(pkg, ":", baseOid, "->", headOid) common.LogDebug(pkg, ":", baseOid, "->", headOid)
} }
@@ -931,15 +844,11 @@ func ProcessPullRequest(gitea common.Gitea, org, repo string, id int64) (bool, e
gitea.AddComment(pr, msg) gitea.AddComment(pr, msg)
} }
baseResult, err := ObsClient.LastBuildResults(stagingConfig.ObsProject, modifiedPackages...)
if err != nil {
common.LogError("failed fetching ref project status for", stagingConfig.ObsProject, ":", err)
}
stagingResult, err := ObsClient.BuildStatus(stagingProject) stagingResult, err := ObsClient.BuildStatus(stagingProject)
if err != nil { if err != nil {
common.LogError("failed fetching stage project status for", stagingProject, ":", err) common.LogError("failed fetching stage project status for", stagingProject, ":", err)
} }
buildStatus := ProcessBuildStatus(stagingResult, baseResult) buildStatus := ProcessBuildStatus(stagingResult)
done := false done := false
switch buildStatus { switch buildStatus {

View File

@@ -107,7 +107,7 @@ func processConfiguredRepositoryAction(action *common.RepositoryWebhookEvent, co
common.LogError(" - ", action.Repository.Name, "repo is not sha256. Ignoring.") common.LogError(" - ", action.Repository.Name, "repo is not sha256. Ignoring.")
return return
} }
common.PanicOnError(git.GitExec(gitPrj, "submodule", "--quiet", "add", "--depth", "1", action.Repository.Clone_Url, action.Repository.Name)) common.PanicOnError(git.GitExec(gitPrj, "submodule", "--quiet", "add", "--depth", "1", "../" + action.Repository.Name, action.Repository.Name))
defer git.GitExecQuietOrPanic(gitPrj, "submodule", "deinit", "--all", "-f") defer git.GitExecQuietOrPanic(gitPrj, "submodule", "deinit", "--all", "-f")
branch := strings.TrimSpace(git.GitExecWithOutputOrPanic(path.Join(gitPrj, action.Repository.Name), "branch", "--show-current")) branch := strings.TrimSpace(git.GitExecWithOutputOrPanic(path.Join(gitPrj, action.Repository.Name), "branch", "--show-current"))
@@ -198,7 +198,7 @@ func processConfiguredPushAction(action *common.PushWebhookEvent, config *common
} }
if stat, err := os.Stat(filepath.Join(git.GetPath(), gitPrj, action.Repository.Name)); err != nil { if stat, err := os.Stat(filepath.Join(git.GetPath(), gitPrj, action.Repository.Name)); err != nil {
git.GitExecOrPanic(gitPrj, "submodule", "--quiet", "add", "--depth", "1", action.Repository.Clone_Url, action.Repository.Name) git.GitExecOrPanic(gitPrj, "submodule", "--quiet", "add", "--depth", "1", "../" + action.Repository.Name, action.Repository.Name)
common.LogDebug("Pushed to package that is not part of the project. Re-adding...", err) common.LogDebug("Pushed to package that is not part of the project. Re-adding...", err)
} else if !stat.IsDir() { } else if !stat.IsDir() {
common.LogError("Pushed to a package that is not a submodule but exists in the project. Ignoring.") common.LogError("Pushed to a package that is not a submodule but exists in the project. Ignoring.")
@@ -402,7 +402,7 @@ next_repo:
} }
// add repository to git project // add repository to git project
common.PanicOnError(git.GitExec(gitPrj, "submodule", "--quiet", "add", "--depth", "1", r.CloneURL, r.Name)) common.PanicOnError(git.GitExec(gitPrj, "submodule", "--quiet", "add", "--depth", "1", "../" + r.Name, r.Name))
curBranch := strings.TrimSpace(git.GitExecWithOutputOrPanic(path.Join(gitPrj, r.Name), "branch", "--show-current")) curBranch := strings.TrimSpace(git.GitExecWithOutputOrPanic(path.Join(gitPrj, r.Name), "branch", "--show-current"))
if branch != curBranch { if branch != curBranch {

View File

@@ -443,11 +443,11 @@ func (pr *PRProcessor) Process(req *models.PullRequest) error {
if _, ok := err.(*repository.RepoMergePullRequestConflict); !ok { if _, ok := err.(*repository.RepoMergePullRequestConflict); !ok {
common.PanicOnError(err) common.PanicOnError(err)
} }
} else { // } else {
Gitea.AddComment(pr.PR, "Closing here because the associated Project PR has been closed.") // Gitea.AddComment(pr.PR, "Closing here because the associated Project PR has been closed.")
Gitea.UpdatePullRequest(org, repo, idx, &models.EditPullRequestOption{ // Gitea.UpdatePullRequest(org, repo, idx, &models.EditPullRequestOption{
State: "closed", // State: "closed",
}) // })
} }
} }
} }
@@ -460,10 +460,10 @@ func (pr *PRProcessor) Process(req *models.PullRequest) error {
continue continue
} }
} }
}
if err = pr.UpdatePrjGitPR(prset); err != nil { if err = pr.UpdatePrjGitPR(prset); err != nil {
return err return err
}
} }
} }