diff --git a/common/git_utils.go b/common/git_utils.go index a86e335..6707113 100644 --- a/common/git_utils.go +++ b/common/git_utils.go @@ -802,6 +802,7 @@ func (e *GitHandlerImpl) GitSubmoduleList(gitPath, commitId string) (submoduleLi for _, te := range tree.items { if te.isTree() { trees[p+te.name+"/"] = te.hash + submoduleList[p+te.name] = te.hash } else if te.isSubmodule() { submoduleList[p+te.name] = te.hash } diff --git a/common/gitea_utils.go b/common/gitea_utils.go index c06a8c6..a44b031 100644 --- a/common/gitea_utils.go +++ b/common/gitea_utils.go @@ -603,14 +603,14 @@ func (gitea *GiteaTransport) CreateRepositoryIfNotExist(git Git, org, repoName s func (gitea *GiteaTransport) CreatePullRequestIfNotExist(repo *models.Repository, srcId, targetId, title, body string) (*models.PullRequest, error) { prOptions := models.CreatePullRequestOption{ - Base: repo.DefaultBranch, + Base: targetId, Head: srcId, Title: title, Body: body, } if pr, err := gitea.client.Repository.RepoGetPullRequestByBaseHead( - repository.NewRepoGetPullRequestByBaseHeadParams().WithOwner(repo.Owner.UserName).WithRepo(repo.Name).WithBase(repo.DefaultBranch).WithHead(srcId), + repository.NewRepoGetPullRequestByBaseHeadParams().WithOwner(repo.Owner.UserName).WithRepo(repo.Name).WithBase(targetId).WithHead(srcId), gitea.transport.DefaultAuthentication, ); err == nil { return pr.Payload, nil diff --git a/common/obs_utils.go b/common/obs_utils.go index c611ec8..6f12388 100644 --- a/common/obs_utils.go +++ b/common/obs_utils.go @@ -551,7 +551,6 @@ func (c *ObsClient) DeleteProject(project string) error { query.Add("force", "1") url.RawQuery = query.Encode() res, err := c.ObsRequestRaw("DELETE", url.String(), nil) - if err != nil { return err } diff --git a/obs-staging-bot/main.go b/obs-staging-bot/main.go index 6822875..6714166 100644 --- a/obs-staging-bot/main.go +++ b/obs-staging-bot/main.go @@ -263,7 +263,7 @@ func ProcessRepoBuildStatus(results, ref []common.PackageBuildStatus) (status Bu return BuildStatusSummarySuccess, SomeSuccess } -func GenerateObsPrjMeta(git common.Git, gitea common.Gitea, pr *models.PullRequest, stagingPrj, buildPrj string) (*common.ProjectMeta, error) { +func GenerateObsPrjMeta(git common.Git, gitea common.Gitea, pr *models.PullRequest, stagingPrj, buildPrj string, stagingMasterPrj string) (*common.ProjectMeta, error) { common.LogDebug("repo content fetching ...") err := FetchPrGit(git, pr) if err != nil { @@ -289,7 +289,15 @@ func GenerateObsPrjMeta(git common.Git, gitea common.Gitea, pr *models.PullReque } } - meta, err := ObsClient.GetProjectMeta(buildPrj) + common.LogDebug("Trying first staging master project: ", stagingMasterPrj) + meta, err := ObsClient.GetProjectMeta(stagingMasterPrj) + if err == nil { + // success, so we use that staging master project as our build project + buildPrj = stagingMasterPrj + } else { + common.LogInfo("error fetching project meta for ", stagingMasterPrj, ". Fall Back to ", buildPrj) + meta, err = ObsClient.GetProjectMeta(buildPrj) + } if err != nil { common.LogError("error fetching project meta for", buildPrj, ". Err:", err) return nil, err @@ -315,7 +323,9 @@ func GenerateObsPrjMeta(git common.Git, gitea common.Gitea, pr *models.PullReque } meta.ScmSync = pr.Head.Repo.CloneURL + "?" + strings.Join(urlPkg, "&") + "#" + pr.Head.Sha meta.Title = fmt.Sprintf("PR#%d to %s", pr.Index, pr.Base.Name) - meta.PublicFlags = common.Flags{Contents: ""} +// QE wants it published ... also we should not hardcode it here, since +// it is configurable via the :PullRequest project +// meta.PublicFlags = common.Flags{Contents: ""} meta.Groups = nil meta.Persons = nil @@ -412,7 +422,8 @@ func StartOrUpdateBuild(config *common.StagingConfig, git common.Git, gitea comm var state RequestModification = RequestModificationSourceChanged if meta == nil { // new build - meta, err = GenerateObsPrjMeta(git, gitea, pr, obsPrProject, config.ObsProject) + common.LogDebug(" Staging master:", config.StagingProject) + meta, err = GenerateObsPrjMeta(git, gitea, pr, obsPrProject, config.ObsProject, config.StagingProject) if err != nil { return RequestModificationNoChange, err } @@ -426,6 +437,8 @@ func StartOrUpdateBuild(config *common.StagingConfig, git common.Git, gitea comm } else { err = ObsClient.SetProjectMeta(meta) if err != nil { + x, _ := xml.MarshalIndent(meta, "", " ") + common.LogDebug(" meta:", string(x)) common.LogError("cannot create meta project:", err) return RequestModificationNoChange, err } @@ -459,7 +472,7 @@ func FetchOurLatestActionableReview(gitea common.Gitea, org, repo string, id int for idx := len(reviews) - 1; idx >= 0; idx-- { review := reviews[idx] - if review.User != nil || review.User.UserName == Username { + if review.User == nil || review.User.UserName == Username { if IsDryRun { // for purposes of moving forward a no-op check return review, nil @@ -547,7 +560,7 @@ func CleanupPullNotification(gitea common.Gitea, thread *models.NotificationThre } if pr.State != "closed" { - common.LogInfo(" ignoring peding PR", thread.Subject.HTMLURL, " state:", pr.State) + common.LogInfo(" ignoring pending PR", thread.Subject.HTMLURL, " state:", pr.State) return false } @@ -641,7 +654,6 @@ func ProcessPullRequest(gitea common.Gitea, org, repo string, id int64) (bool, e common.LogError("No PR associated with review:", org, "/", repo, "#", id, "Error:", err) return true, err } - common.LogDebug("PR state:", pr.State) if pr.State == "closed" { // dismiss the review @@ -658,40 +670,68 @@ func ProcessPullRequest(gitea common.Gitea, org, repo string, id int64) (bool, e } } - if review, err := FetchOurLatestActionableReview(gitea, org, repo, id); err == nil { - common.LogInfo("processing review", review.HTMLURL, "state", review.State) + // Fetching data + review, review_error := FetchOurLatestActionableReview(gitea, org, repo, id) + if pr.State != "closed" && review_error != nil { + // Nothing to do + return true, nil + } - err = FetchPrGit(git, pr) - if err != nil { - common.LogError("Cannot fetch PR git:", pr.URL) - return false, err + err = FetchPrGit(git, pr) + if err != nil { + common.LogError("Cannot fetch PR git:", pr.URL) + return false, err + } + + // we want the possibly pending modification here, in case stagings are added, etc. + // jobs of review team to deal with issues + common.LogDebug("QA configuration fetching ...", common.StagingConfigFile) + data, err := git.GitCatFile(pr.Head.Sha, pr.Head.Sha, common.StagingConfigFile) + if err != nil { + common.LogError("Staging config", common.StagingConfigFile, "not found in PR to the project. Aborting.") + if !IsDryRun { + _, err = gitea.AddReviewComment(pr, common.ReviewStateRequestChanges, "Cannot find project config in PR: "+common.ProjectConfigFile) } + return true, err + } - // we want the possibly pending modification here, in case stagings are added, etc. - // jobs of review team to deal with issues - common.LogDebug("QA configuration fetching ...", common.StagingConfigFile) - data, err := git.GitCatFile(pr.Head.Sha, pr.Head.Sha, common.StagingConfigFile) - if err != nil { - common.LogError("Staging config", common.StagingConfigFile, "not found in PR to the project. Aborting.") - if !IsDryRun { - _, err = gitea.AddReviewComment(pr, common.ReviewStateRequestChanges, "Cannot find project config in PR: "+common.ProjectConfigFile) - } + stagingConfig, err := common.ParseStagingConfig(data) + if err != nil { + common.LogError("Error parsing config file", common.StagingConfigFile, err) + } + + if stagingConfig.ObsProject == "" { + common.LogError("Cannot find reference project for PR#", pr.Index) + if !IsDryRun && review_error == nil { + _, err := gitea.AddReviewComment(pr, common.ReviewStateRequestChanges, "Cannot find reference project") return true, err } + return true, nil + } - stagingConfig, err := common.ParseStagingConfig(data) - if err != nil { - common.LogError("Error parsing config file", common.StagingConfigFile, err) - } + common.LogDebug("ObsProject:", stagingConfig.ObsProject) + stagingProject := GetObsProjectAssociatedWithPr(stagingConfig, ObsClient.HomeProject, pr) - if stagingConfig.ObsProject == "" { - common.LogError("Cannot find reference project for PR#", pr.Index) + // Cleanup projects + if pr.State == "closed" { + // review is done, cleanup + common.LogInfo(" -- closed request, cleanup staging projects") + for _, setup := range stagingConfig.QA { if !IsDryRun { - _, err := gitea.AddReviewComment(pr, common.ReviewStateRequestChanges, "Cannot find reference project") - return true, err + ObsClient.DeleteProject(stagingProject + ":" + setup.Name) } - return true, nil } + if stagingProject != "" { + if !IsDryRun { + ObsClient.DeleteProject(stagingProject) + } + } + return true, nil + } + + // Process review aka setup projects + if review_error == nil { + common.LogInfo("processing review", review.HTMLURL, "state", review.State) meta, err := ObsClient.GetProjectMeta(stagingConfig.ObsProject) if err != nil { @@ -725,16 +765,6 @@ func ProcessPullRequest(gitea common.Gitea, org, repo string, id int64) (bool, e } } - if stagingConfig.StagingProject != "" { - // staging project must either be nothing or be *under* the target project. - // other setups are currently not supported - // NOTE: this is user input, so we need some limits here - l := len(stagingConfig.ObsProject) - if l >= len(stagingConfig.StagingProject) || stagingConfig.ObsProject != stagingConfig.StagingProject[0:l] { - common.LogError("StagingProject (", stagingConfig.StagingProject, ") is not child of target project", stagingConfig.ObsProject) - } - } - if meta.Name != stagingConfig.ObsProject { common.LogError("staging.config . ObsProject:", stagingConfig.ObsProject, " is not target project name", meta.Name) if !IsDryRun { @@ -755,17 +785,22 @@ func ProcessPullRequest(gitea common.Gitea, org, repo string, id int64) (bool, e common.LogDebug(" # head submodules:", len(headSubmodules)) common.LogDebug(" # base submodules:", len(baseSubmodules)) - modifiedOrNew := make([]string, 0, 16) + modifiedPackages := make([]string, 0, 16) + newPackages := make([]string, 0, 16) if !stagingConfig.RebuildAll { for pkg, headOid := range headSubmodules { if baseOid, exists := baseSubmodules[pkg]; !exists || baseOid != headOid { - modifiedOrNew = append(modifiedOrNew, pkg) + if len(baseOid) > 0 { + modifiedPackages = append(modifiedPackages, pkg) + } else { + newPackages = append(newPackages, pkg) + } common.LogDebug(pkg, ":", baseOid, "->", headOid) } } } - if len(modifiedOrNew) == 0 { + if len(modifiedPackages) == 0 && len(newPackages) == 0 { rebuild_all := false || stagingConfig.RebuildAll reviews, err := gitea.GetPullRequestReviews(pr.Base.Repo.Owner.UserName, pr.Base.Repo.Name, pr.Index) @@ -842,13 +877,13 @@ func ProcessPullRequest(gitea common.Gitea, org, repo string, id int64) (bool, e gitea.AddComment(pr, msg) } - baseResult, err := ObsClient.LastBuildResults(stagingConfig.ObsProject, modifiedOrNew...) + 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) if err != nil { - common.LogError("failed fetching ref project status for", stagingProject, ":", err) + common.LogError("failed fetching stage project status for", stagingProject, ":", err) } buildStatus := ProcessBuildStatus(stagingResult, baseResult) diff --git a/workflow-pr/pr_processor.go b/workflow-pr/pr_processor.go index cde94d1..8569482 100644 --- a/workflow-pr/pr_processor.go +++ b/workflow-pr/pr_processor.go @@ -87,11 +87,6 @@ func AllocatePRProcessor(req *common.PullRequestWebhookEvent, configs common.Aut } func (pr *PRProcessor) SetSubmodulesToMatchPRSet(prset *common.PRSet) ([]string, []string, error) { - prjGitPR, err := prset.GetPrjGitPR() - if err != nil { - return nil, nil, err - } - git := pr.git subList, err := git.GitSubmoduleList(common.DefaultGitPrj, "HEAD") if err != nil { @@ -113,13 +108,15 @@ func (pr *PRProcessor) SetSubmodulesToMatchPRSet(prset *common.PRSet) ([]string, revert := false if pr.PR.State != "open" { - // remove PR from PrjGit - var valid bool - if prHead, valid = git.GitSubmoduleCommitId(common.DefaultGitPrj, repo, prjGitPR.PR.MergeBase); !valid { - common.LogError("Failed fetching original submodule commit id for repo") - return nil, nil, err + prjGitPR, err := prset.GetPrjGitPR() + if prjGitPR != nil { + // remove PR from PrjGit + var valid bool + if prHead, valid = git.GitSubmoduleCommitId(common.DefaultGitPrj, repo, prjGitPR.PR.MergeBase); !valid { + common.LogError("Failed fetching original submodule commit id for repo") + return nil, nil, err + } } - revert = true }