Compare commits
2 Commits
group-bot-
...
always-rev
| Author | SHA256 | Date | |
|---|---|---|---|
| a323cdb23f | |||
| 5b5bb9a5bc |
@@ -88,9 +88,10 @@ type AutogitConfig struct {
|
||||
|
||||
Labels map[string]string // list of tags, if not default, to apply
|
||||
|
||||
NoProjectGitPR bool // do not automatically create project git PRs, just assign reviewers and assume somethign else creates the ProjectGit PR
|
||||
ManualMergeOnly bool // only merge with "Merge OK" comment by Project Maintainers and/or Package Maintainers and/or reviewers
|
||||
ManualMergeProject bool // require merge of ProjectGit PRs with "Merge OK" by ProjectMaintainers and/or reviewers
|
||||
NoProjectGitPR bool // do not automatically create project git PRs, just assign reviewers and assume somethign else creates the ProjectGit PR
|
||||
ManualMergeOnly bool // only merge with "Merge OK" comment by Project Maintainers and/or Package Maintainers and/or reviewers
|
||||
ManualMergeProject bool // require merge of ProjectGit PRs with "Merge OK" by ProjectMaintainers and/or reviewers
|
||||
AlwaysRequireReview bool // always require a maintainer review, even if maintainer submits it. Only ignored if no other package or project reviewers
|
||||
}
|
||||
|
||||
type AutogitConfigs []*AutogitConfig
|
||||
@@ -292,9 +293,9 @@ func (config *AutogitConfig) GetRemoteBranch() string {
|
||||
}
|
||||
|
||||
func (config *AutogitConfig) Label(label string) string {
|
||||
if t, found := config.Labels[LabelKey(label)]; found {
|
||||
return t
|
||||
}
|
||||
if t, found := config.Labels[LabelKey(label)]; found {
|
||||
return t
|
||||
}
|
||||
|
||||
return label
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ const ProjectFileKey = "_project"
|
||||
type MaintainershipMap struct {
|
||||
Data map[string][]string
|
||||
IsDir bool
|
||||
Config *AutogitConfig
|
||||
FetchPackage func(string) ([]byte, error)
|
||||
}
|
||||
|
||||
@@ -39,7 +40,9 @@ func parseMaintainershipData(data []byte) (*MaintainershipMap, error) {
|
||||
return maintainers, nil
|
||||
}
|
||||
|
||||
func FetchProjectMaintainershipData(gitea GiteaMaintainershipReader, org, prjGit, branch string) (*MaintainershipMap, error) {
|
||||
func FetchProjectMaintainershipData(gitea GiteaMaintainershipReader, config *AutogitConfig) (*MaintainershipMap, error) {
|
||||
org, prjGit, branch := config.GetPrjGit()
|
||||
|
||||
data, _, err := gitea.FetchMaintainershipDirFile(org, prjGit, branch, ProjectFileKey)
|
||||
dir := true
|
||||
if err != nil || data == nil {
|
||||
@@ -61,6 +64,7 @@ func FetchProjectMaintainershipData(gitea GiteaMaintainershipReader, org, prjGit
|
||||
|
||||
m, err := parseMaintainershipData(data)
|
||||
if m != nil {
|
||||
m.Config = config
|
||||
m.IsDir = dir
|
||||
m.FetchPackage = func(pkg string) ([]byte, error) {
|
||||
data, _, err := gitea.FetchMaintainershipDirFile(org, prjGit, branch, pkg)
|
||||
@@ -149,7 +153,10 @@ func (data *MaintainershipMap) IsApproved(pkg string, reviews []*models.PullRevi
|
||||
}
|
||||
|
||||
LogDebug("Looking for review by:", reviewers)
|
||||
if slices.Contains(reviewers, submitter) {
|
||||
slices.Sort(reviewers)
|
||||
reviewers = slices.Compact(reviewers)
|
||||
SubmitterIdxInReviewers := slices.Index(reviewers, submitter)
|
||||
if SubmitterIdxInReviewers > -1 && (!data.Config.AlwaysRequireReview || len(reviewers) == 1) {
|
||||
LogDebug("Submitter is maintainer. Approving.")
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -13,10 +13,10 @@ import (
|
||||
)
|
||||
|
||||
func TestMaintainership(t *testing.T) {
|
||||
config := common.AutogitConfig{
|
||||
config := &common.AutogitConfig{
|
||||
Branch: "bar",
|
||||
Organization: "foo",
|
||||
GitProjectName: common.DefaultGitPrj,
|
||||
GitProjectName: common.DefaultGitPrj + "#bar",
|
||||
}
|
||||
|
||||
packageTests := []struct {
|
||||
@@ -141,7 +141,7 @@ func TestMaintainership(t *testing.T) {
|
||||
notFoundError := repository.NewRepoGetContentsNotFound()
|
||||
for _, test := range packageTests {
|
||||
runTests := func(t *testing.T, mi common.GiteaMaintainershipReader) {
|
||||
maintainers, err := common.FetchProjectMaintainershipData(mi, config.Organization, config.GitProjectName, config.Branch)
|
||||
maintainers, err := common.FetchProjectMaintainershipData(mi, config)
|
||||
if err != nil && !test.otherError {
|
||||
if test.maintainersFileErr == nil {
|
||||
t.Fatal("Unexpected error recieved", err)
|
||||
@@ -253,3 +253,43 @@ func TestMaintainershipFileWrite(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAlwaysRequireReview(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
maintainers []string
|
||||
config *common.AutogitConfig
|
||||
is_approved bool
|
||||
}{
|
||||
{
|
||||
name: "AlwaysRequireReview=false",
|
||||
maintainers: []string{"maintainer1", "maintainer2"},
|
||||
config: &common.AutogitConfig{AlwaysRequireReview: false},
|
||||
is_approved: true,
|
||||
},
|
||||
{
|
||||
name: "AlwaysRequireReview=true",
|
||||
maintainers: []string{"maintainer1", "maintainer2"},
|
||||
config: &common.AutogitConfig{AlwaysRequireReview: true},
|
||||
is_approved: false,
|
||||
},
|
||||
{
|
||||
name: "AlwaysRequireReview=true",
|
||||
maintainers: []string{"maintainer1"},
|
||||
config: &common.AutogitConfig{AlwaysRequireReview: true},
|
||||
is_approved: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
m := &common.MaintainershipMap{
|
||||
Data: map[string][]string{"": test.maintainers},
|
||||
}
|
||||
m.Config = test.config
|
||||
if approved := m.IsApproved("", nil, "maintainer1", nil); approved != test.is_approved {
|
||||
t.Error("Expected m.IsApproved()->", test.is_approved, "but didn't get it")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
10
common/pr.go
10
common/pr.go
@@ -316,7 +316,10 @@ func (rs *PRSet) FindMissingAndExtraReviewers(maintainers MaintainershipData, id
|
||||
// only need project maintainer reviews if:
|
||||
// * not created by a bot and has other PRs, or
|
||||
// * not created by maintainer
|
||||
noReviewPRCreators := prjMaintainers
|
||||
noReviewPRCreators := []string{}
|
||||
if !rs.Config.AlwaysRequireReview {
|
||||
noReviewPRCreators = prjMaintainers
|
||||
}
|
||||
if len(rs.PRs) > 1 {
|
||||
noReviewPRCreators = append(noReviewPRCreators, rs.BotUser)
|
||||
}
|
||||
@@ -339,7 +342,10 @@ func (rs *PRSet) FindMissingAndExtraReviewers(maintainers MaintainershipData, id
|
||||
pkg := pr.PR.Base.Repo.Name
|
||||
pkgMaintainers := maintainers.ListPackageMaintainers(pkg, nil)
|
||||
Maintainers := slices.Concat(prjMaintainers, pkgMaintainers)
|
||||
noReviewPkgPRCreators := pkgMaintainers
|
||||
noReviewPkgPRCreators := []string{}
|
||||
if !rs.Config.AlwaysRequireReview {
|
||||
noReviewPkgPRCreators = pkgMaintainers
|
||||
}
|
||||
|
||||
LogDebug("packakge maintainers:", Maintainers)
|
||||
|
||||
|
||||
@@ -833,7 +833,6 @@ func TestFindMissingAndExtraReviewers(t *testing.T) {
|
||||
[]string{"autogits_obs_staging_bot", "user1"},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "Add reviewer if also maintainer where review by maintainer is not needed",
|
||||
prset: &common.PRSet{
|
||||
@@ -1095,8 +1094,67 @@ func TestFindMissingAndExtraReviewers(t *testing.T) {
|
||||
expected_missing_reviewers: [][]string{{"pkgm2", "prj2"}},
|
||||
expected_extra_reviewers: [][]string{{}, {"prj1"}},
|
||||
},
|
||||
{
|
||||
name: "Package maintainer submitter, AlwaysRequireReview=false",
|
||||
prset: &common.PRSet{
|
||||
PRs: []*common.PRInfo{
|
||||
{
|
||||
PR: &models.PullRequest{
|
||||
User: &models.User{UserName: "pkgmaintainer"},
|
||||
Base: &models.PRBranchInfo{Name: "main", Repo: &models.Repository{Name: "pkg", Owner: &models.User{UserName: "org"}}},
|
||||
},
|
||||
Reviews: &common.PRReviews{},
|
||||
},
|
||||
},
|
||||
Config: &common.AutogitConfig{
|
||||
GitProjectName: "prg/repo#main",
|
||||
Organization: "org",
|
||||
Branch: "main",
|
||||
Reviewers: []string{},
|
||||
AlwaysRequireReview: false,
|
||||
},
|
||||
},
|
||||
maintainers: &common.MaintainershipMap{
|
||||
Data: map[string][]string{
|
||||
"pkg": {"pkgmaintainer", "pkgm1"},
|
||||
},
|
||||
},
|
||||
noAutoStaging: true,
|
||||
expected_missing_reviewers: [][]string{
|
||||
{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Package maintainer submitter, AlwaysRequireReview=true",
|
||||
prset: &common.PRSet{
|
||||
PRs: []*common.PRInfo{
|
||||
{
|
||||
PR: &models.PullRequest{
|
||||
User: &models.User{UserName: "pkgmaintainer"},
|
||||
Base: &models.PRBranchInfo{Name: "main", Repo: &models.Repository{Name: "pkg", Owner: &models.User{UserName: "org"}}},
|
||||
},
|
||||
Reviews: &common.PRReviews{},
|
||||
},
|
||||
},
|
||||
Config: &common.AutogitConfig{
|
||||
GitProjectName: "prg/repo#main",
|
||||
Organization: "org",
|
||||
Branch: "main",
|
||||
Reviewers: []string{},
|
||||
AlwaysRequireReview: true,
|
||||
},
|
||||
},
|
||||
maintainers: &common.MaintainershipMap{
|
||||
Data: map[string][]string{
|
||||
"pkg": {"pkgmaintainer", "pkgm1"},
|
||||
},
|
||||
},
|
||||
noAutoStaging: true,
|
||||
expected_missing_reviewers: [][]string{
|
||||
{"pkgm1"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
test.prset.HasAutoStaging = !test.noAutoStaging
|
||||
|
||||
@@ -444,7 +444,7 @@ func TestReviewApprovalCheck(t *testing.T) {
|
||||
Rejected: true,
|
||||
},
|
||||
{
|
||||
Name: "Multiline: Multiple group mentions, noise in between",
|
||||
Name: "Multiline: Approved on second line",
|
||||
GroupName: "group",
|
||||
InString: "noise\n@group: approve\nmore noise",
|
||||
Approved: true,
|
||||
|
||||
@@ -34,6 +34,7 @@ JSON
|
||||
* _ManualMergeProject_: (true, false) only merge if "merge ok" by project maintainers or reviewers
|
||||
* _ReviewRequired_: (true, false) ignores that submitter is a maintainer and require a review from other maintainer IFF available
|
||||
* _NoProjectGitPR_: (true, false) do not create PrjGit PRs, but still process reviews, etc.
|
||||
* _AlwaysRequireReview_: (true, false) always require review by a maintainer, even if submitter is maintainer, unless there are no other maintainers.
|
||||
* _Permissions_: permissions and associated accounts/groups. See below.
|
||||
* _Labels_: (string, string) Labels for PRs. See below.
|
||||
|
||||
|
||||
@@ -500,7 +500,7 @@ func (pr *PRProcessor) Process(req *models.PullRequest) error {
|
||||
// make sure that prjgit is consistent and only submodules that are to be *updated*
|
||||
// reset anything that changed that is not part of the prset
|
||||
// package removals/additions are *not* counted here
|
||||
org, repo, branch := config.GetPrjGit()
|
||||
|
||||
// TODO: this is broken...
|
||||
if pr, err := prset.GetPrjGitPR(); err == nil && false {
|
||||
common.LogDebug("Submodule parse begin")
|
||||
@@ -549,7 +549,7 @@ func (pr *PRProcessor) Process(req *models.PullRequest) error {
|
||||
} else {
|
||||
common.LogInfo("* No prjgit")
|
||||
}
|
||||
maintainers, err := common.FetchProjectMaintainershipData(Gitea, org, repo, branch)
|
||||
maintainers, err := common.FetchProjectMaintainershipData(Gitea, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user