Compare commits
1 Commits
new-packag
...
always-rev
| Author | SHA256 | Date | |
|---|---|---|---|
| 51403713be |
@@ -65,7 +65,6 @@ const (
|
||||
Label_StagingAuto = "staging/Auto"
|
||||
Label_ReviewPending = "review/Pending"
|
||||
Label_ReviewDone = "review/Done"
|
||||
Label_NewRepository = "new/New Repository"
|
||||
)
|
||||
|
||||
func LabelKey(tag_value string) string {
|
||||
@@ -92,6 +91,7 @@ type AutogitConfig struct {
|
||||
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
|
||||
ReviewRequired bool // always require a maintainer review, even if maintainer submits it. Only ignored if no other package or project reviewers
|
||||
}
|
||||
|
||||
type AutogitConfigs []*AutogitConfig
|
||||
@@ -293,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
|
||||
}
|
||||
|
||||
@@ -42,7 +42,6 @@ type GitSubmoduleLister interface {
|
||||
|
||||
type GitDirectoryLister interface {
|
||||
GitDirectoryList(gitPath, commitId string) (dirlist map[string]string, err error)
|
||||
GitDirectoryContentList(gitPath, commitId string) (dirlist map[string]string, err error)
|
||||
}
|
||||
|
||||
type GitStatusLister interface {
|
||||
@@ -273,11 +272,7 @@ func (e *GitHandlerImpl) GitClone(repo, branch, remoteUrl string) (string, error
|
||||
LogDebug("branch", branch)
|
||||
}
|
||||
*/
|
||||
args := []string{"fetch", "--prune", remoteName}
|
||||
if len(branch) > 0 {
|
||||
args = append(args, branch)
|
||||
}
|
||||
|
||||
args := []string{"fetch", "--prune", remoteName, branch}
|
||||
if strings.TrimSpace(e.GitExecWithOutputOrPanic(repo, "rev-parse", "--is-shallow-repository")) == "true" {
|
||||
args = slices.Insert(args, 1, "--unshallow")
|
||||
}
|
||||
@@ -792,7 +787,7 @@ func (e *GitHandlerImpl) GitCatFile(cwd, commitId, filename string) (data []byte
|
||||
return
|
||||
}
|
||||
|
||||
// return (directory) -> (hash) map for all submodules
|
||||
// return (filename) -> (hash) map for all submodules
|
||||
func (e *GitHandlerImpl) GitDirectoryList(gitPath, commitId string) (directoryList map[string]string, err error) {
|
||||
var done sync.Mutex
|
||||
directoryList = make(map[string]string)
|
||||
@@ -866,82 +861,6 @@ func (e *GitHandlerImpl) GitDirectoryList(gitPath, commitId string) (directoryLi
|
||||
return directoryList, err
|
||||
}
|
||||
|
||||
// return (directory) -> (hash) map for all submodules
|
||||
func (e *GitHandlerImpl) GitDirectoryContentList(gitPath, commitId string) (directoryList map[string]string, err error) {
|
||||
var done sync.Mutex
|
||||
directoryList = make(map[string]string)
|
||||
|
||||
done.Lock()
|
||||
data_in, data_out := ChanIO{make(chan byte)}, ChanIO{make(chan byte)}
|
||||
|
||||
LogDebug("Getting directory content for:", commitId)
|
||||
|
||||
go func() {
|
||||
defer done.Unlock()
|
||||
defer close(data_out.ch)
|
||||
|
||||
data_out.Write([]byte(commitId))
|
||||
data_out.ch <- '\x00'
|
||||
var c GitCommit
|
||||
c, err = parseGitCommit(data_in.ch)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Error parsing git commit. Err: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
trees := make(map[string]string)
|
||||
trees[""] = c.Tree
|
||||
|
||||
for len(trees) > 0 {
|
||||
for p, tree := range trees {
|
||||
delete(trees, p)
|
||||
|
||||
data_out.Write([]byte(tree))
|
||||
data_out.ch <- '\x00'
|
||||
var tree GitTree
|
||||
tree, err = parseGitTree(data_in.ch)
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Error parsing git tree: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, te := range tree.items {
|
||||
if te.isBlob() || te.isSubmodule() {
|
||||
directoryList[p+te.name] = te.hash
|
||||
} else if te.isTree() {
|
||||
trees[p+te.name] = te.hash
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
cmd := exec.Command("/usr/bin/git", "cat-file", "--batch", "-Z")
|
||||
cmd.Env = []string{
|
||||
"GIT_CEILING_DIRECTORIES=" + e.GitPath,
|
||||
"GIT_LFS_SKIP_SMUDGE=1",
|
||||
"GIT_CONFIG_GLOBAL=/dev/null",
|
||||
}
|
||||
cmd.Dir = filepath.Join(e.GitPath, gitPath)
|
||||
cmd.Stdout = &data_in
|
||||
cmd.Stdin = &data_out
|
||||
cmd.Stderr = writeFunc(func(data []byte) (int, error) {
|
||||
LogError(string(data))
|
||||
return len(data), nil
|
||||
})
|
||||
LogDebug("command run:", cmd.Args)
|
||||
if e := cmd.Run(); e != nil {
|
||||
LogError(e)
|
||||
close(data_in.ch)
|
||||
close(data_out.ch)
|
||||
return directoryList, e
|
||||
}
|
||||
|
||||
done.Lock()
|
||||
return directoryList, err
|
||||
}
|
||||
|
||||
// return (filename) -> (hash) map for all submodules
|
||||
func (e *GitHandlerImpl) GitSubmoduleList(gitPath, commitId string) (submoduleList map[string]string, err error) {
|
||||
var done sync.Mutex
|
||||
|
||||
@@ -75,10 +75,6 @@ type GiteaLabelSettter interface {
|
||||
SetLabels(org, repo string, idx int64, labels []string) ([]*models.Label, error)
|
||||
}
|
||||
|
||||
type GiteaIssueFetcher interface {
|
||||
GetIssue(org, repo string, idx int64) (*models.Issue, error)
|
||||
}
|
||||
|
||||
type GiteaTimelineFetcher interface {
|
||||
GetTimeline(org, repo string, idx int64) ([]*models.TimelineComment, error)
|
||||
}
|
||||
@@ -151,7 +147,6 @@ type GiteaReviewRequester interface {
|
||||
|
||||
type GiteaReviewUnrequester interface {
|
||||
UnrequestReview(org, repo string, id int64, reviwers ...string) error
|
||||
UpdateIssue(org, repo string, idx int64, options *models.EditIssueOption) (*models.Issue, error)
|
||||
}
|
||||
|
||||
type GiteaReviewer interface {
|
||||
@@ -205,7 +200,6 @@ type Gitea interface {
|
||||
GiteaSetRepoOptions
|
||||
GiteaLabelGetter
|
||||
GiteaLabelSettter
|
||||
GiteaIssueFetcher
|
||||
|
||||
GetNotifications(Type string, since *time.Time) ([]*models.NotificationThread, error)
|
||||
GetDoneNotifications(Type string, page int64) ([]*models.NotificationThread, error)
|
||||
@@ -514,26 +508,6 @@ func (gitea *GiteaTransport) SetLabels(owner, repo string, idx int64, labels []s
|
||||
return ret.Payload, nil
|
||||
}
|
||||
|
||||
func (gitea *GiteaTransport) GetIssue(owner, repo string, idx int64) (*models.Issue, error) {
|
||||
ret, err := gitea.client.Issue.IssueGetIssue(
|
||||
issue.NewIssueGetIssueParams().WithOwner(owner).WithRepo(repo).WithIndex(idx),
|
||||
gitea.transport.DefaultAuthentication)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret.Payload, nil
|
||||
}
|
||||
|
||||
func (gitea *GiteaTransport) UpdateIssue(owner, repo string, idx int64, options *models.EditIssueOption) (*models.Issue, error) {
|
||||
ret, err := gitea.client.Issue.IssueEditIssue(
|
||||
issue.NewIssueEditIssueParams().WithOwner(owner).WithRepo(repo).WithIndex(idx).WithBody(options),
|
||||
gitea.transport.DefaultAuthentication)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret.Payload, nil
|
||||
}
|
||||
|
||||
const (
|
||||
GiteaNotificationType_Pull = "Pull"
|
||||
)
|
||||
@@ -741,7 +715,6 @@ func (gitea *GiteaTransport) CreatePullRequestIfNotExist(repo *models.Repository
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
LogError("owner:", repo.Owner.UserName, " repo:", repo.Name, " body:", prOptions)
|
||||
return nil, fmt.Errorf("Cannot create pull request. %w", err), true
|
||||
}
|
||||
|
||||
|
||||
@@ -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.ReviewRequired || 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 TestReviewRequired(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
maintainers []string
|
||||
config *common.AutogitConfig
|
||||
is_approved bool
|
||||
}{
|
||||
{
|
||||
name: "ReviewRequired=false",
|
||||
maintainers: []string{"maintainer1", "maintainer2"},
|
||||
config: &common.AutogitConfig{ReviewRequired: false},
|
||||
is_approved: true,
|
||||
},
|
||||
{
|
||||
name: "ReviewRequired=true",
|
||||
maintainers: []string{"maintainer1", "maintainer2"},
|
||||
config: &common.AutogitConfig{ReviewRequired: true},
|
||||
is_approved: false,
|
||||
},
|
||||
{
|
||||
name: "ReviewRequired=true",
|
||||
maintainers: []string{"maintainer1"},
|
||||
config: &common.AutogitConfig{ReviewRequired: 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")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,45 +142,6 @@ func (m *MockGitDirectoryLister) EXPECT() *MockGitDirectoryListerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// GitDirectoryContentList mocks base method.
|
||||
func (m *MockGitDirectoryLister) GitDirectoryContentList(gitPath, commitId string) (map[string]string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GitDirectoryContentList", gitPath, commitId)
|
||||
ret0, _ := ret[0].(map[string]string)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GitDirectoryContentList indicates an expected call of GitDirectoryContentList.
|
||||
func (mr *MockGitDirectoryListerMockRecorder) GitDirectoryContentList(gitPath, commitId any) *MockGitDirectoryListerGitDirectoryContentListCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GitDirectoryContentList", reflect.TypeOf((*MockGitDirectoryLister)(nil).GitDirectoryContentList), gitPath, commitId)
|
||||
return &MockGitDirectoryListerGitDirectoryContentListCall{Call: call}
|
||||
}
|
||||
|
||||
// MockGitDirectoryListerGitDirectoryContentListCall wrap *gomock.Call
|
||||
type MockGitDirectoryListerGitDirectoryContentListCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockGitDirectoryListerGitDirectoryContentListCall) Return(dirlist map[string]string, err error) *MockGitDirectoryListerGitDirectoryContentListCall {
|
||||
c.Call = c.Call.Return(dirlist, err)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockGitDirectoryListerGitDirectoryContentListCall) Do(f func(string, string) (map[string]string, error)) *MockGitDirectoryListerGitDirectoryContentListCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockGitDirectoryListerGitDirectoryContentListCall) DoAndReturn(f func(string, string) (map[string]string, error)) *MockGitDirectoryListerGitDirectoryContentListCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// GitDirectoryList mocks base method.
|
||||
func (m *MockGitDirectoryLister) GitDirectoryList(gitPath, commitId string) (map[string]string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -602,45 +563,6 @@ func (c *MockGitGitDiffCall) DoAndReturn(f func(string, string, string) (string,
|
||||
return c
|
||||
}
|
||||
|
||||
// GitDirectoryContentList mocks base method.
|
||||
func (m *MockGit) GitDirectoryContentList(gitPath, commitId string) (map[string]string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GitDirectoryContentList", gitPath, commitId)
|
||||
ret0, _ := ret[0].(map[string]string)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GitDirectoryContentList indicates an expected call of GitDirectoryContentList.
|
||||
func (mr *MockGitMockRecorder) GitDirectoryContentList(gitPath, commitId any) *MockGitGitDirectoryContentListCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GitDirectoryContentList", reflect.TypeOf((*MockGit)(nil).GitDirectoryContentList), gitPath, commitId)
|
||||
return &MockGitGitDirectoryContentListCall{Call: call}
|
||||
}
|
||||
|
||||
// MockGitGitDirectoryContentListCall wrap *gomock.Call
|
||||
type MockGitGitDirectoryContentListCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockGitGitDirectoryContentListCall) Return(dirlist map[string]string, err error) *MockGitGitDirectoryContentListCall {
|
||||
c.Call = c.Call.Return(dirlist, err)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockGitGitDirectoryContentListCall) Do(f func(string, string) (map[string]string, error)) *MockGitGitDirectoryContentListCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockGitGitDirectoryContentListCall) DoAndReturn(f func(string, string) (map[string]string, error)) *MockGitGitDirectoryContentListCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// GitDirectoryList mocks base method.
|
||||
func (m *MockGit) GitDirectoryList(gitPath, commitId string) (map[string]string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
||||
@@ -144,69 +144,6 @@ func (c *MockGiteaLabelSettterSetLabelsCall) DoAndReturn(f func(string, string,
|
||||
return c
|
||||
}
|
||||
|
||||
// MockGiteaIssueFetcher is a mock of GiteaIssueFetcher interface.
|
||||
type MockGiteaIssueFetcher struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockGiteaIssueFetcherMockRecorder
|
||||
isgomock struct{}
|
||||
}
|
||||
|
||||
// MockGiteaIssueFetcherMockRecorder is the mock recorder for MockGiteaIssueFetcher.
|
||||
type MockGiteaIssueFetcherMockRecorder struct {
|
||||
mock *MockGiteaIssueFetcher
|
||||
}
|
||||
|
||||
// NewMockGiteaIssueFetcher creates a new mock instance.
|
||||
func NewMockGiteaIssueFetcher(ctrl *gomock.Controller) *MockGiteaIssueFetcher {
|
||||
mock := &MockGiteaIssueFetcher{ctrl: ctrl}
|
||||
mock.recorder = &MockGiteaIssueFetcherMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockGiteaIssueFetcher) EXPECT() *MockGiteaIssueFetcherMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// GetIssue mocks base method.
|
||||
func (m *MockGiteaIssueFetcher) GetIssue(org, repo string, idx int64) (*models.Issue, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetIssue", org, repo, idx)
|
||||
ret0, _ := ret[0].(*models.Issue)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetIssue indicates an expected call of GetIssue.
|
||||
func (mr *MockGiteaIssueFetcherMockRecorder) GetIssue(org, repo, idx any) *MockGiteaIssueFetcherGetIssueCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIssue", reflect.TypeOf((*MockGiteaIssueFetcher)(nil).GetIssue), org, repo, idx)
|
||||
return &MockGiteaIssueFetcherGetIssueCall{Call: call}
|
||||
}
|
||||
|
||||
// MockGiteaIssueFetcherGetIssueCall wrap *gomock.Call
|
||||
type MockGiteaIssueFetcherGetIssueCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockGiteaIssueFetcherGetIssueCall) Return(arg0 *models.Issue, arg1 error) *MockGiteaIssueFetcherGetIssueCall {
|
||||
c.Call = c.Call.Return(arg0, arg1)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockGiteaIssueFetcherGetIssueCall) Do(f func(string, string, int64) (*models.Issue, error)) *MockGiteaIssueFetcherGetIssueCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockGiteaIssueFetcherGetIssueCall) DoAndReturn(f func(string, string, int64) (*models.Issue, error)) *MockGiteaIssueFetcherGetIssueCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// MockGiteaTimelineFetcher is a mock of GiteaTimelineFetcher interface.
|
||||
type MockGiteaTimelineFetcher struct {
|
||||
ctrl *gomock.Controller
|
||||
@@ -1506,45 +1443,6 @@ func (c *MockGiteaReviewFetcherAndRequesterAndUnrequesterUnrequestReviewCall) Do
|
||||
return c
|
||||
}
|
||||
|
||||
// UpdateIssue mocks base method.
|
||||
func (m *MockGiteaReviewFetcherAndRequesterAndUnrequester) UpdateIssue(org, repo string, idx int64, options *models.EditIssueOption) (*models.Issue, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdateIssue", org, repo, idx, options)
|
||||
ret0, _ := ret[0].(*models.Issue)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// UpdateIssue indicates an expected call of UpdateIssue.
|
||||
func (mr *MockGiteaReviewFetcherAndRequesterAndUnrequesterMockRecorder) UpdateIssue(org, repo, idx, options any) *MockGiteaReviewFetcherAndRequesterAndUnrequesterUpdateIssueCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateIssue", reflect.TypeOf((*MockGiteaReviewFetcherAndRequesterAndUnrequester)(nil).UpdateIssue), org, repo, idx, options)
|
||||
return &MockGiteaReviewFetcherAndRequesterAndUnrequesterUpdateIssueCall{Call: call}
|
||||
}
|
||||
|
||||
// MockGiteaReviewFetcherAndRequesterAndUnrequesterUpdateIssueCall wrap *gomock.Call
|
||||
type MockGiteaReviewFetcherAndRequesterAndUnrequesterUpdateIssueCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockGiteaReviewFetcherAndRequesterAndUnrequesterUpdateIssueCall) Return(arg0 *models.Issue, arg1 error) *MockGiteaReviewFetcherAndRequesterAndUnrequesterUpdateIssueCall {
|
||||
c.Call = c.Call.Return(arg0, arg1)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockGiteaReviewFetcherAndRequesterAndUnrequesterUpdateIssueCall) Do(f func(string, string, int64, *models.EditIssueOption) (*models.Issue, error)) *MockGiteaReviewFetcherAndRequesterAndUnrequesterUpdateIssueCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockGiteaReviewFetcherAndRequesterAndUnrequesterUpdateIssueCall) DoAndReturn(f func(string, string, int64, *models.EditIssueOption) (*models.Issue, error)) *MockGiteaReviewFetcherAndRequesterAndUnrequesterUpdateIssueCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// MockGiteaUnreviewTimelineFetcher is a mock of GiteaUnreviewTimelineFetcher interface.
|
||||
type MockGiteaUnreviewTimelineFetcher struct {
|
||||
ctrl *gomock.Controller
|
||||
@@ -1651,45 +1549,6 @@ func (c *MockGiteaUnreviewTimelineFetcherUnrequestReviewCall) DoAndReturn(f func
|
||||
return c
|
||||
}
|
||||
|
||||
// UpdateIssue mocks base method.
|
||||
func (m *MockGiteaUnreviewTimelineFetcher) UpdateIssue(org, repo string, idx int64, options *models.EditIssueOption) (*models.Issue, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdateIssue", org, repo, idx, options)
|
||||
ret0, _ := ret[0].(*models.Issue)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// UpdateIssue indicates an expected call of UpdateIssue.
|
||||
func (mr *MockGiteaUnreviewTimelineFetcherMockRecorder) UpdateIssue(org, repo, idx, options any) *MockGiteaUnreviewTimelineFetcherUpdateIssueCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateIssue", reflect.TypeOf((*MockGiteaUnreviewTimelineFetcher)(nil).UpdateIssue), org, repo, idx, options)
|
||||
return &MockGiteaUnreviewTimelineFetcherUpdateIssueCall{Call: call}
|
||||
}
|
||||
|
||||
// MockGiteaUnreviewTimelineFetcherUpdateIssueCall wrap *gomock.Call
|
||||
type MockGiteaUnreviewTimelineFetcherUpdateIssueCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockGiteaUnreviewTimelineFetcherUpdateIssueCall) Return(arg0 *models.Issue, arg1 error) *MockGiteaUnreviewTimelineFetcherUpdateIssueCall {
|
||||
c.Call = c.Call.Return(arg0, arg1)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockGiteaUnreviewTimelineFetcherUpdateIssueCall) Do(f func(string, string, int64, *models.EditIssueOption) (*models.Issue, error)) *MockGiteaUnreviewTimelineFetcherUpdateIssueCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockGiteaUnreviewTimelineFetcherUpdateIssueCall) DoAndReturn(f func(string, string, int64, *models.EditIssueOption) (*models.Issue, error)) *MockGiteaUnreviewTimelineFetcherUpdateIssueCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// MockGiteaReviewRequester is a mock of GiteaReviewRequester interface.
|
||||
type MockGiteaReviewRequester struct {
|
||||
ctrl *gomock.Controller
|
||||
@@ -1825,45 +1684,6 @@ func (c *MockGiteaReviewUnrequesterUnrequestReviewCall) DoAndReturn(f func(strin
|
||||
return c
|
||||
}
|
||||
|
||||
// UpdateIssue mocks base method.
|
||||
func (m *MockGiteaReviewUnrequester) UpdateIssue(org, repo string, idx int64, options *models.EditIssueOption) (*models.Issue, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdateIssue", org, repo, idx, options)
|
||||
ret0, _ := ret[0].(*models.Issue)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// UpdateIssue indicates an expected call of UpdateIssue.
|
||||
func (mr *MockGiteaReviewUnrequesterMockRecorder) UpdateIssue(org, repo, idx, options any) *MockGiteaReviewUnrequesterUpdateIssueCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateIssue", reflect.TypeOf((*MockGiteaReviewUnrequester)(nil).UpdateIssue), org, repo, idx, options)
|
||||
return &MockGiteaReviewUnrequesterUpdateIssueCall{Call: call}
|
||||
}
|
||||
|
||||
// MockGiteaReviewUnrequesterUpdateIssueCall wrap *gomock.Call
|
||||
type MockGiteaReviewUnrequesterUpdateIssueCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockGiteaReviewUnrequesterUpdateIssueCall) Return(arg0 *models.Issue, arg1 error) *MockGiteaReviewUnrequesterUpdateIssueCall {
|
||||
c.Call = c.Call.Return(arg0, arg1)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockGiteaReviewUnrequesterUpdateIssueCall) Do(f func(string, string, int64, *models.EditIssueOption) (*models.Issue, error)) *MockGiteaReviewUnrequesterUpdateIssueCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockGiteaReviewUnrequesterUpdateIssueCall) DoAndReturn(f func(string, string, int64, *models.EditIssueOption) (*models.Issue, error)) *MockGiteaReviewUnrequesterUpdateIssueCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// MockGiteaReviewer is a mock of GiteaReviewer interface.
|
||||
type MockGiteaReviewer struct {
|
||||
ctrl *gomock.Controller
|
||||
@@ -2658,45 +2478,6 @@ func (c *MockGiteaGetDoneNotificationsCall) DoAndReturn(f func(string, int64) ([
|
||||
return c
|
||||
}
|
||||
|
||||
// GetIssue mocks base method.
|
||||
func (m *MockGitea) GetIssue(org, repo string, idx int64) (*models.Issue, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetIssue", org, repo, idx)
|
||||
ret0, _ := ret[0].(*models.Issue)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetIssue indicates an expected call of GetIssue.
|
||||
func (mr *MockGiteaMockRecorder) GetIssue(org, repo, idx any) *MockGiteaGetIssueCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIssue", reflect.TypeOf((*MockGitea)(nil).GetIssue), org, repo, idx)
|
||||
return &MockGiteaGetIssueCall{Call: call}
|
||||
}
|
||||
|
||||
// MockGiteaGetIssueCall wrap *gomock.Call
|
||||
type MockGiteaGetIssueCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockGiteaGetIssueCall) Return(arg0 *models.Issue, arg1 error) *MockGiteaGetIssueCall {
|
||||
c.Call = c.Call.Return(arg0, arg1)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockGiteaGetIssueCall) Do(f func(string, string, int64) (*models.Issue, error)) *MockGiteaGetIssueCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockGiteaGetIssueCall) DoAndReturn(f func(string, string, int64) (*models.Issue, error)) *MockGiteaGetIssueCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// GetIssueComments mocks base method.
|
||||
func (m *MockGitea) GetIssueComments(org, project string, issueNo int64) ([]*models.Comment, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -3525,45 +3306,6 @@ func (c *MockGiteaUnrequestReviewCall) DoAndReturn(f func(string, string, int64,
|
||||
return c
|
||||
}
|
||||
|
||||
// UpdateIssue mocks base method.
|
||||
func (m *MockGitea) UpdateIssue(org, repo string, idx int64, options *models.EditIssueOption) (*models.Issue, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdateIssue", org, repo, idx, options)
|
||||
ret0, _ := ret[0].(*models.Issue)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// UpdateIssue indicates an expected call of UpdateIssue.
|
||||
func (mr *MockGiteaMockRecorder) UpdateIssue(org, repo, idx, options any) *MockGiteaUpdateIssueCall {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateIssue", reflect.TypeOf((*MockGitea)(nil).UpdateIssue), org, repo, idx, options)
|
||||
return &MockGiteaUpdateIssueCall{Call: call}
|
||||
}
|
||||
|
||||
// MockGiteaUpdateIssueCall wrap *gomock.Call
|
||||
type MockGiteaUpdateIssueCall struct {
|
||||
*gomock.Call
|
||||
}
|
||||
|
||||
// Return rewrite *gomock.Call.Return
|
||||
func (c *MockGiteaUpdateIssueCall) Return(arg0 *models.Issue, arg1 error) *MockGiteaUpdateIssueCall {
|
||||
c.Call = c.Call.Return(arg0, arg1)
|
||||
return c
|
||||
}
|
||||
|
||||
// Do rewrite *gomock.Call.Do
|
||||
func (c *MockGiteaUpdateIssueCall) Do(f func(string, string, int64, *models.EditIssueOption) (*models.Issue, error)) *MockGiteaUpdateIssueCall {
|
||||
c.Call = c.Call.Do(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// DoAndReturn rewrite *gomock.Call.DoAndReturn
|
||||
func (c *MockGiteaUpdateIssueCall) DoAndReturn(f func(string, string, int64, *models.EditIssueOption) (*models.Issue, error)) *MockGiteaUpdateIssueCall {
|
||||
c.Call = c.Call.DoAndReturn(f)
|
||||
return c
|
||||
}
|
||||
|
||||
// UpdatePullRequest mocks base method.
|
||||
func (m *MockGitea) UpdatePullRequest(org, repo string, num int64, options *models.EditPullRequestOption) (*models.PullRequest, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
||||
71
common/pr.go
71
common/pr.go
@@ -6,9 +6,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"src.opensuse.org/autogits/common/gitea-generated/client/repository"
|
||||
@@ -318,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.ReviewRequired {
|
||||
noReviewPRCreators = prjMaintainers
|
||||
}
|
||||
if len(rs.PRs) > 1 {
|
||||
noReviewPRCreators = append(noReviewPRCreators, rs.BotUser)
|
||||
}
|
||||
@@ -341,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.ReviewRequired {
|
||||
noReviewPkgPRCreators = pkgMaintainers
|
||||
}
|
||||
|
||||
LogDebug("packakge maintainers:", Maintainers)
|
||||
|
||||
@@ -652,8 +656,6 @@ func (rs *PRSet) Merge(gitea GiteaReviewUnrequester, git Git) error {
|
||||
}
|
||||
|
||||
// FF all non-prj git and unrequest reviews.
|
||||
newRepoIssues := make(map[int64]string) // issue index -> org/repo
|
||||
|
||||
for _, prinfo := range rs.PRs {
|
||||
// remove pending review requests
|
||||
repo := prinfo.PR.Base.Repo
|
||||
@@ -675,15 +677,6 @@ func (rs *PRSet) Merge(gitea GiteaReviewUnrequester, git Git) error {
|
||||
if rs.IsPrjGitPR(prinfo.PR) {
|
||||
continue
|
||||
}
|
||||
|
||||
isNewRepo := false
|
||||
for _, l := range prinfo.PR.Labels {
|
||||
if l.Name == Label_NewRepository {
|
||||
isNewRepo = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
br := rs.Config.Branch
|
||||
if len(br) == 0 {
|
||||
// if branch is unspecified, take it from the PR as it
|
||||
@@ -692,30 +685,11 @@ func (rs *PRSet) Merge(gitea GiteaReviewUnrequester, git Git) error {
|
||||
} else if br != prinfo.PR.Base.Name {
|
||||
panic(prinfo.PR.Base.Name + " is expected to match " + br)
|
||||
}
|
||||
|
||||
if isNewRepo {
|
||||
// Extract issue reference from body: "See issue #XYZ"
|
||||
rx := regexp.MustCompile(`See issue #(\d+)`)
|
||||
if matches := rx.FindStringSubmatch(prinfo.PR.Body); len(matches) > 1 {
|
||||
if issueIdx, err := strconv.ParseInt(matches[1], 10, 64); err == nil {
|
||||
// We need to know which project git this issue belongs to.
|
||||
// Since the PR set is linked to a ProjectGit, we can use its org/repo.
|
||||
prjGitOrg, prjGitRepo, _ := rs.Config.GetPrjGit()
|
||||
newRepoIssues[issueIdx] = prjGitOrg + "/" + prjGitRepo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prinfo.RemoteName, err = git.GitClone(repo.Name, br, repo.SSHURL)
|
||||
PanicOnError(err)
|
||||
git.GitExecOrPanic(repo.Name, "fetch", prinfo.RemoteName, head.Sha)
|
||||
git.GitExecOrPanic(repo.Name, "merge", "--ff", head.Sha)
|
||||
|
||||
if isNewRepo {
|
||||
LogInfo("Force-pushing new repository branch", br, "to", head.Sha)
|
||||
// we don't merge, we just set the branch to this commit
|
||||
} else {
|
||||
git.GitExecOrPanic(repo.Name, "merge", "--ff", head.Sha)
|
||||
}
|
||||
}
|
||||
|
||||
// push changes
|
||||
@@ -730,37 +704,12 @@ func (rs *PRSet) Merge(gitea GiteaReviewUnrequester, git Git) error {
|
||||
}
|
||||
repo := prinfo.PR.Base.Repo
|
||||
|
||||
isNewRepo := false
|
||||
for _, l := range prinfo.PR.Labels {
|
||||
if l.Name == Label_NewRepository {
|
||||
isNewRepo = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !IsDryRun {
|
||||
if isNewRepo {
|
||||
git.GitExecOrPanic(repo.Name, "push", "-f", prinfo.RemoteName, prinfo.PR.Head.Sha+":"+prinfo.PR.Base.Name)
|
||||
} else {
|
||||
git.GitExecOrPanic(repo.Name, "push", prinfo.RemoteName)
|
||||
}
|
||||
git.GitExecOrPanic(repo.Name, "push", prinfo.RemoteName)
|
||||
} else {
|
||||
LogInfo("*** WOULD push", repo.Name, "to", prinfo.RemoteName)
|
||||
}
|
||||
}
|
||||
|
||||
// Close referencing issues
|
||||
if !IsDryRun {
|
||||
for issueIdx, prjPath := range newRepoIssues {
|
||||
parts := strings.Split(prjPath, "/")
|
||||
if len(parts) == 2 {
|
||||
LogInfo("Closing issue", prjPath+"#"+strconv.FormatInt(issueIdx, 10))
|
||||
gitea.UpdateIssue(parts[0], parts[1], issueIdx, &models.EditIssueOption{
|
||||
State: "closed",
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
package common_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"go.uber.org/mock/gomock"
|
||||
"src.opensuse.org/autogits/common"
|
||||
"src.opensuse.org/autogits/common/gitea-generated/models"
|
||||
mock_common "src.opensuse.org/autogits/common/mock"
|
||||
)
|
||||
|
||||
func TestFetchPRSet_Linkage(t *testing.T) {
|
||||
config := &common.AutogitConfig{
|
||||
Organization: "target-org",
|
||||
GitProjectName: "test-org/prjgit#main",
|
||||
}
|
||||
|
||||
// 1. Mock a package PR
|
||||
pkgPR := &models.PullRequest{
|
||||
Index: 101,
|
||||
State: "open",
|
||||
Base: &models.PRBranchInfo{
|
||||
Ref: "main",
|
||||
Repo: &models.Repository{
|
||||
Name: "pkg1",
|
||||
Owner: &models.User{UserName: "target-org"},
|
||||
},
|
||||
},
|
||||
Head: &models.PRBranchInfo{Sha: "pkg-sha"},
|
||||
}
|
||||
|
||||
// 2. Mock a ProjectGit PR that references the package PR
|
||||
prjGitPR := &models.PullRequest{
|
||||
Index: 500,
|
||||
State: "open",
|
||||
Base: &models.PRBranchInfo{
|
||||
Ref: "main",
|
||||
Name: "main",
|
||||
Repo: &models.Repository{
|
||||
Name: "prjgit",
|
||||
Owner: &models.User{UserName: "test-org"},
|
||||
},
|
||||
},
|
||||
Body: "Forwarded PRs: pkg1\n\nPR: target-org/pkg1!101",
|
||||
}
|
||||
|
||||
t.Run("Fetch from ProjectGit PR", func(t *testing.T) {
|
||||
ctl := gomock.NewController(t)
|
||||
defer ctl.Finish()
|
||||
mockGitea := mock_common.NewMockGiteaPRTimelineReviewFetcher(ctl)
|
||||
|
||||
// Expect fetch of prjGitPR
|
||||
mockGitea.EXPECT().GetPullRequest("test-org", "prjgit", int64(500)).Return(prjGitPR, nil)
|
||||
// Expect fetch of pkgPR because it's linked in body
|
||||
mockGitea.EXPECT().GetPullRequest("target-org", "pkg1", int64(101)).Return(pkgPR, nil)
|
||||
|
||||
// Expect review fetching (part of FetchPRSet)
|
||||
mockGitea.EXPECT().GetPullRequestReviews(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*models.PullReview{}, nil).AnyTimes()
|
||||
mockGitea.EXPECT().GetTimeline(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*models.TimelineComment{}, nil).AnyTimes()
|
||||
|
||||
prset, err := common.FetchPRSet("bot", mockGitea, "test-org", "prjgit", 500, config)
|
||||
if err != nil {
|
||||
t.Fatalf("FetchPRSet failed: %v", err)
|
||||
}
|
||||
|
||||
if len(prset.PRs) != 2 {
|
||||
t.Errorf("Expected 2 PRs in set, got %d", len(prset.PRs))
|
||||
}
|
||||
|
||||
if !prset.IsConsistent() {
|
||||
t.Error("PR set should be consistent")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Fetch from Package PR via Timeline", func(t *testing.T) {
|
||||
ctl := gomock.NewController(t)
|
||||
defer ctl.Finish()
|
||||
mockGitea := mock_common.NewMockGiteaPRTimelineReviewFetcher(ctl)
|
||||
|
||||
// 1. FetchPRSet for pkgPR will call LastPrjGitRefOnTimeline
|
||||
mockGitea.EXPECT().GetTimeline("target-org", "pkg1", int64(101)).Return([]*models.TimelineComment{
|
||||
{
|
||||
Type: common.TimelineCommentType_PullRequestRef,
|
||||
RefIssue: &models.Issue{
|
||||
Index: 500,
|
||||
Body: "PR: target-org/pkg1!101",
|
||||
Repository: &models.RepositoryMeta{
|
||||
Owner: "test-org",
|
||||
Name: "prjgit",
|
||||
},
|
||||
User: &models.User{UserName: "bot"},
|
||||
},
|
||||
},
|
||||
}, nil)
|
||||
|
||||
// 2. It will then fetch the prjGitPR found in timeline (twice in LastPrjGitRefOnTimeline)
|
||||
mockGitea.EXPECT().GetPullRequest("test-org", "prjgit", int64(500)).Return(prjGitPR, nil).Times(2)
|
||||
|
||||
// 3. Then it will recursively fetch linked PRs from prjGitPR body in readPRData
|
||||
mockGitea.EXPECT().GetPullRequest("target-org", "pkg1", int64(101)).Return(pkgPR, nil)
|
||||
|
||||
// Review fetching for all PRs in the set
|
||||
mockGitea.EXPECT().GetPullRequestReviews(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*models.PullReview{}, nil).AnyTimes()
|
||||
mockGitea.EXPECT().GetTimeline("test-org", "prjgit", int64(500)).Return([]*models.TimelineComment{}, nil).AnyTimes()
|
||||
mockGitea.EXPECT().GetTimeline("target-org", "pkg1", int64(101)).Return([]*models.TimelineComment{}, nil).AnyTimes()
|
||||
|
||||
prset, err := common.FetchPRSet("bot", mockGitea, "target-org", "pkg1", 101, config)
|
||||
if err != nil {
|
||||
t.Fatalf("FetchPRSet failed: %v", err)
|
||||
}
|
||||
|
||||
if len(prset.PRs) != 2 {
|
||||
t.Errorf("Expected 2 PRs in set, got %d", len(prset.PRs))
|
||||
}
|
||||
|
||||
prjPRInfo, err := prset.GetPrjGitPR()
|
||||
if err != nil || prjPRInfo.PR.Index != 500 {
|
||||
t.Errorf("Expected ProjectGit PR 500 to be found, got %v", prjPRInfo)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
package common_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"go.uber.org/mock/gomock"
|
||||
"src.opensuse.org/autogits/common"
|
||||
"src.opensuse.org/autogits/common/gitea-generated/models"
|
||||
mock_common "src.opensuse.org/autogits/common/mock"
|
||||
)
|
||||
|
||||
func TestPRSet_Merge_Special(t *testing.T) {
|
||||
ctl := gomock.NewController(t)
|
||||
defer ctl.Finish()
|
||||
|
||||
mockGitea := mock_common.NewMockGiteaReviewUnrequester(ctl)
|
||||
mockGit := mock_common.NewMockGit(ctl)
|
||||
|
||||
config := &common.AutogitConfig{
|
||||
Organization: "target-org",
|
||||
GitProjectName: "test-org/prjgit#main",
|
||||
Branch: "main",
|
||||
}
|
||||
|
||||
// 1. Regular ProjectGit PR
|
||||
prjGitPR := &models.PullRequest{
|
||||
Index: 500,
|
||||
Base: &models.PRBranchInfo{
|
||||
Ref: "main",
|
||||
Name: "main",
|
||||
Repo: &models.Repository{Name: "prjgit", Owner: &models.User{UserName: "test-org"}, SSHURL: "prj-ssh-url"},
|
||||
Sha: "base-sha",
|
||||
},
|
||||
Head: &models.PRBranchInfo{Sha: "prj-head-sha"},
|
||||
}
|
||||
|
||||
// 2. "new/New Repository" Package PR
|
||||
newPkgPR := &models.PullRequest{
|
||||
Index: 101,
|
||||
Base: &models.PRBranchInfo{
|
||||
Ref: "main",
|
||||
Name: "main",
|
||||
Repo: &models.Repository{Name: "new-pkg", Owner: &models.User{UserName: "target-org"}, SSHURL: "pkg-ssh-url"},
|
||||
},
|
||||
Head: &models.PRBranchInfo{Sha: "pkg-head-sha"},
|
||||
Labels: []*models.Label{
|
||||
{Name: "new/New Repository"},
|
||||
},
|
||||
Body: "See issue #123",
|
||||
}
|
||||
|
||||
prset := &common.PRSet{
|
||||
Config: config,
|
||||
PRs: []*common.PRInfo{
|
||||
{PR: prjGitPR},
|
||||
{PR: newPkgPR},
|
||||
},
|
||||
}
|
||||
|
||||
common.IsDryRun = false
|
||||
|
||||
// Mock expectations for Merge
|
||||
// Clone and fetch for PrjGit
|
||||
mockGit.EXPECT().GitClone("_ObsPrj", "main", "prj-ssh-url").Return("origin", nil)
|
||||
mockGit.EXPECT().GitExecOrPanic("_ObsPrj", "fetch", "origin", "prj-head-sha")
|
||||
// mockGit.EXPECT().GitExecWithOutputOrPanic("_ObsPrj", "merge-base", "HEAD", "base-sha", "prj-head-sha").Return("base-sha")
|
||||
mockGit.EXPECT().GitExec("_ObsPrj", "merge", "--no-ff", "-m", gomock.Any(), "prj-head-sha").Return(nil)
|
||||
|
||||
// Unrequest reviews
|
||||
mockGitea.EXPECT().UnrequestReview("test-org", "prjgit", int64(500), gomock.Any()).Return(nil)
|
||||
mockGitea.EXPECT().UnrequestReview("target-org", "new-pkg", int64(101), gomock.Any()).Return(nil)
|
||||
|
||||
// Clone and fetch for new-pkg
|
||||
mockGit.EXPECT().GitClone("new-pkg", "main", "pkg-ssh-url").Return("origin", nil)
|
||||
mockGit.EXPECT().GitExecOrPanic("new-pkg", "fetch", "origin", "pkg-head-sha")
|
||||
|
||||
// Pushing changes
|
||||
mockGit.EXPECT().GitExecOrPanic("_ObsPrj", "push", "origin")
|
||||
// Special push for new repo: git push -f origin pkg-head-sha:main
|
||||
mockGit.EXPECT().GitExecOrPanic("new-pkg", "push", "-f", "origin", "pkg-head-sha:main")
|
||||
|
||||
// Closing issue
|
||||
mockGitea.EXPECT().UpdateIssue("test-org", "prjgit", int64(123), gomock.Any()).DoAndReturn(func(org, repo string, idx int64, opt *models.EditIssueOption) (*models.Issue, error) {
|
||||
if opt.State != "closed" {
|
||||
t.Errorf("Expected issue state to be closed, got %s", opt.State)
|
||||
}
|
||||
return nil, nil
|
||||
})
|
||||
|
||||
err := prset.Merge(mockGitea, mockGit)
|
||||
if err != nil {
|
||||
t.Fatalf("Merge failed: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -48,6 +48,8 @@ func reviewsToTimeline(reviews []*models.PullReview) []*models.TimelineComment {
|
||||
}
|
||||
|
||||
func TestPR(t *testing.T) {
|
||||
return
|
||||
|
||||
baseConfig := common.AutogitConfig{
|
||||
Reviewers: []string{"+super1", "*super2", "m1", "-m2"},
|
||||
Branch: "branch",
|
||||
@@ -78,21 +80,21 @@ func TestPR(t *testing.T) {
|
||||
{
|
||||
name: "Error fetching PullRequest",
|
||||
data: []prdata{
|
||||
{pr: &models.PullRequest{Body: "", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "test"}}}, State: "open"}, pr_err: errors.New("Missing PR")},
|
||||
{pr: &models.PullRequest{Body: "", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "test"}}}, State: "opened"}, pr_err: errors.New("Missing PR")},
|
||||
},
|
||||
prjGitPRIndex: -1,
|
||||
},
|
||||
{
|
||||
name: "Error fetching PullRequest in PrjGit",
|
||||
data: []prdata{
|
||||
{pr: &models.PullRequest{Body: "PR: foo/barPrj#22", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "test"}}}, State: "open"}, pr_err: errors.New("missing PR")},
|
||||
{pr: &models.PullRequest{Body: "", Index: 22, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}, Name: "master"}, State: "open"}},
|
||||
{pr: &models.PullRequest{Body: "PR: foo/barPrj#22", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "test"}}}, State: "opened"}, pr_err: errors.New("missing PR")},
|
||||
{pr: &models.PullRequest{Body: "", Index: 22, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}}, State: "opened"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Error fetching prjgit",
|
||||
data: []prdata{
|
||||
{pr: &models.PullRequest{Body: "", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "test"}}}, State: "open"}},
|
||||
{pr: &models.PullRequest{Body: "", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "test"}}}, State: "opened"}},
|
||||
},
|
||||
resLen: 1,
|
||||
prjGitPRIndex: -1,
|
||||
@@ -100,20 +102,8 @@ func TestPR(t *testing.T) {
|
||||
{
|
||||
name: "Review set is consistent",
|
||||
data: []prdata{
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#22", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "test"}}}, State: "open"},
|
||||
timeline: []*models.TimelineComment{
|
||||
{
|
||||
Type: common.TimelineCommentType_PullRequestRef,
|
||||
RefIssue: &models.Issue{
|
||||
Index: 22,
|
||||
Repository: &models.RepositoryMeta{Name: "barPrj", Owner: "foo"},
|
||||
User: &models.User{UserName: "test"},
|
||||
Body: "PR: test/repo#42",
|
||||
},
|
||||
},
|
||||
}},
|
||||
{pr: &models.PullRequest{Body: "PR: test/repo#42", Index: 22, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}, Name: "master"}, State: "open"}},
|
||||
{pr: &models.PullRequest{Body: "", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "test"}}}, State: "opened"}},
|
||||
{pr: &models.PullRequest{Body: "PR: test/repo#42", Index: 22, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}}, State: "opened"}},
|
||||
},
|
||||
resLen: 2,
|
||||
prjGitPRIndex: 1,
|
||||
@@ -123,21 +113,8 @@ func TestPR(t *testing.T) {
|
||||
{
|
||||
name: "Review set is consistent: 1pkg",
|
||||
data: []prdata{
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#22", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "test"}}}, State: "open"},
|
||||
timeline: []*models.TimelineComment{
|
||||
{
|
||||
Type: common.TimelineCommentType_PullRequestRef,
|
||||
RefIssue: &models.Issue{
|
||||
Index: 22,
|
||||
Repository: &models.RepositoryMeta{Name: "barPrj", Owner: "foo"},
|
||||
User: &models.User{UserName: "test"},
|
||||
Body: "PR: test/repo#42",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{pr: &models.PullRequest{Body: "PR: test/repo#42", Index: 22, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}, Name: "master"}, State: "open"}},
|
||||
{pr: &models.PullRequest{Body: "PR: foo/barPrj#22", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "test"}}}, State: "opened"}},
|
||||
{pr: &models.PullRequest{Body: "PR: test/repo#42", Index: 22, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}}, State: "opened"}},
|
||||
},
|
||||
resLen: 2,
|
||||
prjGitPRIndex: 1,
|
||||
@@ -146,22 +123,9 @@ func TestPR(t *testing.T) {
|
||||
{
|
||||
name: "Review set is consistent: 2pkg",
|
||||
data: []prdata{
|
||||
{
|
||||
pr: &models.PullRequest{Body: "some desc\nPR: foo/barPrj#22", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "test"}}}, State: "open"},
|
||||
timeline: []*models.TimelineComment{
|
||||
{
|
||||
Type: common.TimelineCommentType_PullRequestRef,
|
||||
RefIssue: &models.Issue{
|
||||
Index: 22,
|
||||
Repository: &models.RepositoryMeta{Name: "barPrj", Owner: "foo"},
|
||||
User: &models.User{UserName: "test"},
|
||||
Body: "PR: test/repo#42\nPR: test/repo2#41",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{pr: &models.PullRequest{Body: "PR: test/repo#42\nPR: test/repo2#41", Index: 22, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}, Name: "master"}, State: "open"}},
|
||||
{pr: &models.PullRequest{Body: "some other desc\nPR: foo/barPrj#22", Index: 41, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo2", Owner: &models.User{UserName: "test"}}}, State: "open"}},
|
||||
{pr: &models.PullRequest{Body: "some desc", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "test"}}}, State: "opened"}},
|
||||
{pr: &models.PullRequest{Body: "PR: test/repo#42\nPR: test/repo2#41", Index: 22, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}}, State: "opened"}},
|
||||
{pr: &models.PullRequest{Body: "some other desc\nPR: foo/fer#33", Index: 41, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo2", Owner: &models.User{UserName: "test"}}}, State: "opened"}},
|
||||
},
|
||||
resLen: 3,
|
||||
prjGitPRIndex: 1,
|
||||
@@ -171,7 +135,7 @@ func TestPR(t *testing.T) {
|
||||
name: "Review set of prjgit PR is consistent",
|
||||
data: []prdata{
|
||||
{
|
||||
pr: &models.PullRequest{Body: "", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}, Name: "master"}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "LGTM", User: &models.User{UserName: "m2"}, State: common.ReviewStateApproved},
|
||||
{Body: "LGTM", User: &models.User{UserName: "super2"}, State: common.ReviewStateApproved},
|
||||
@@ -190,23 +154,10 @@ func TestPR(t *testing.T) {
|
||||
{
|
||||
name: "Review set is consistent: 2pkg",
|
||||
data: []prdata{
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#222", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "test"}}}, State: "open"},
|
||||
timeline: []*models.TimelineComment{
|
||||
{
|
||||
Type: common.TimelineCommentType_PullRequestRef,
|
||||
RefIssue: &models.Issue{
|
||||
Index: 22,
|
||||
Repository: &models.RepositoryMeta{Name: "barPrj", Owner: "foo"},
|
||||
User: &models.User{UserName: "test"},
|
||||
Body: "PR: test/repo#42\nPR: test/repo2#41",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{pr: &models.PullRequest{Body: "PR: test/repo2#41", Index: 20, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}, Name: "master"}, State: "open"}},
|
||||
{pr: &models.PullRequest{Body: "PR: test/repo#42\nPR: test/repo2#41", Index: 22, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}, Name: "master"}, State: "open"}},
|
||||
{pr: &models.PullRequest{Body: "PR: foo/barPrj#20", Index: 41, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo2", Owner: &models.User{UserName: "test"}}}, State: "open"}},
|
||||
{pr: &models.PullRequest{Body: "PR: foo/barPrj#222", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "test"}}}, State: "opened"}},
|
||||
{pr: &models.PullRequest{Body: "PR: test/repo2#41", Index: 20, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}}, State: "opened"}},
|
||||
{pr: &models.PullRequest{Body: "PR: test/repo#42\nPR: test/repo2#41", Index: 22, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}}, State: "opened"}},
|
||||
{pr: &models.PullRequest{Body: "PR: foo/barPrj#20", Index: 41, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo2", Owner: &models.User{UserName: "test"}}}, State: "opened"}},
|
||||
},
|
||||
resLen: 3,
|
||||
prjGitPRIndex: 2,
|
||||
@@ -216,7 +167,7 @@ func TestPR(t *testing.T) {
|
||||
name: "WIP PR is not approved",
|
||||
data: []prdata{
|
||||
{
|
||||
pr: &models.PullRequest{Body: "", Title: "WIP: some title", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}, Name: "master"}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "", Title: "WIP: some title", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "LGTM", User: &models.User{UserName: "m2"}, State: common.ReviewStateApproved},
|
||||
{Body: "LGTM", User: &models.User{UserName: "super2"}, State: common.ReviewStateApproved},
|
||||
@@ -233,9 +184,10 @@ func TestPR(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Manual review is missing", data: []prdata{
|
||||
name: "Manual review is missing",
|
||||
data: []prdata{
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/repo#20", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}, Name: "master"}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "PR: foo/repo#20", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "LGTM", User: &models.User{UserName: "m2"}, State: common.ReviewStateApproved},
|
||||
{Body: "LGTM", User: &models.User{UserName: "super2"}, State: common.ReviewStateApproved},
|
||||
@@ -243,7 +195,7 @@ func TestPR(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#42", Index: 20, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#42", Index: 20, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "LGTM", User: &models.User{UserName: "m1"}, State: common.ReviewStateApproved},
|
||||
{Body: "LGTM", User: &models.User{UserName: "super1"}, State: common.ReviewStateApproved},
|
||||
@@ -260,15 +212,16 @@ func TestPR(t *testing.T) {
|
||||
Reviewers: []string{"+super1", "*super2", "m1", "-m2"},
|
||||
Branch: "branch",
|
||||
Organization: "foo",
|
||||
GitProjectName: "barPrj#master",
|
||||
GitProjectName: "barPrj",
|
||||
ManualMergeOnly: true,
|
||||
})
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Manual review is done, via PrjGit",
|
||||
data: []prdata{
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/repo#20", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}, Name: "master"}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "PR: foo/repo#20", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "merge ok", User: &models.User{UserName: "m2"}, State: common.ReviewStateApproved},
|
||||
{Body: "LGTM", User: &models.User{UserName: "super2"}, State: common.ReviewStateApproved},
|
||||
@@ -276,7 +229,7 @@ func TestPR(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#42", Index: 20, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#42", Index: 20, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "LGTM", User: &models.User{UserName: "m1"}, State: common.ReviewStateApproved},
|
||||
{Body: "LGTM", User: &models.User{UserName: "super1"}, State: common.ReviewStateApproved},
|
||||
@@ -293,7 +246,7 @@ func TestPR(t *testing.T) {
|
||||
Reviewers: []string{"+super1", "*super2", "m1", "-m2"},
|
||||
Branch: "branch",
|
||||
Organization: "foo",
|
||||
GitProjectName: "barPrj#master",
|
||||
GitProjectName: "barPrj",
|
||||
ManualMergeOnly: true,
|
||||
})
|
||||
},
|
||||
@@ -302,7 +255,7 @@ func TestPR(t *testing.T) {
|
||||
name: "Manual review is done, via PrjGit",
|
||||
data: []prdata{
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/repo#20", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}, Name: "master"}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "PR: foo/repo#20", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "merge ok", User: &models.User{UserName: "m2"}, State: common.ReviewStateApproved},
|
||||
{Body: "LGTM", User: &models.User{UserName: "super2"}, State: common.ReviewStateApproved},
|
||||
@@ -310,7 +263,7 @@ func TestPR(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#42", Index: 20, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#42", Index: 20, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "LGTM", User: &models.User{UserName: "m1"}, State: common.ReviewStateApproved},
|
||||
{Body: "LGTM", User: &models.User{UserName: "super1"}, State: common.ReviewStateApproved},
|
||||
@@ -327,7 +280,7 @@ func TestPR(t *testing.T) {
|
||||
Reviewers: []string{"+super1", "*super2", "m1", "-m2"},
|
||||
Branch: "branch",
|
||||
Organization: "foo",
|
||||
GitProjectName: "barPrj#master",
|
||||
GitProjectName: "barPrj",
|
||||
ManualMergeOnly: true,
|
||||
ManualMergeProject: true,
|
||||
})
|
||||
@@ -337,7 +290,7 @@ func TestPR(t *testing.T) {
|
||||
name: "Manual review is not done, via PrjGit",
|
||||
data: []prdata{
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/repo#20", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}, Name: "master"}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "PR: foo/repo#20", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "merge ok", User: &models.User{UserName: "notm2"}, State: common.ReviewStateApproved},
|
||||
{Body: "merge not ok", User: &models.User{UserName: "m2"}, State: common.ReviewStateApproved},
|
||||
@@ -346,7 +299,7 @@ func TestPR(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#42", Index: 20, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#42", Index: 20, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "LGTM", User: &models.User{UserName: "m1"}, State: common.ReviewStateApproved},
|
||||
{Body: "LGTM", User: &models.User{UserName: "super1"}, State: common.ReviewStateApproved},
|
||||
@@ -363,7 +316,7 @@ func TestPR(t *testing.T) {
|
||||
Reviewers: []string{"+super1", "*super2", "m1", "-m2"},
|
||||
Branch: "branch",
|
||||
Organization: "foo",
|
||||
GitProjectName: "barPrj#master",
|
||||
GitProjectName: "barPrj",
|
||||
ManualMergeOnly: true,
|
||||
ManualMergeProject: true,
|
||||
})
|
||||
@@ -373,7 +326,7 @@ func TestPR(t *testing.T) {
|
||||
name: "Manual review is done via PackageGit",
|
||||
data: []prdata{
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/repo#20", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}, Name: "master"}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "PR: foo/repo#20", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "LGTM", User: &models.User{UserName: "m2"}, State: common.ReviewStateApproved},
|
||||
{Body: "LGTM", User: &models.User{UserName: "super2"}, State: common.ReviewStateApproved},
|
||||
@@ -381,7 +334,7 @@ func TestPR(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/repo#42", Index: 20, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#42", Index: 20, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "LGTM", User: &models.User{UserName: "m1"}, State: common.ReviewStateApproved},
|
||||
{Body: "Merge ok", User: &models.User{UserName: "super1"}, State: common.ReviewStateApproved},
|
||||
@@ -398,7 +351,7 @@ func TestPR(t *testing.T) {
|
||||
Reviewers: []string{"+super1", "*super2", "m1", "-m2"},
|
||||
Branch: "branch",
|
||||
Organization: "foo",
|
||||
GitProjectName: "barPrj#master",
|
||||
GitProjectName: "barPrj",
|
||||
ManualMergeOnly: true,
|
||||
})
|
||||
},
|
||||
@@ -407,7 +360,7 @@ func TestPR(t *testing.T) {
|
||||
name: "Manual review done via PkgGits",
|
||||
data: []prdata{
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/repo#20\nPR: foo/repo#21", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}, Name: "master"}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "PR: foo/repo#20\nPR: foo/repo#21", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "LGTM", User: &models.User{UserName: "m2"}, State: common.ReviewStateApproved},
|
||||
{Body: "LGTM", User: &models.User{UserName: "super2"}, State: common.ReviewStateApproved},
|
||||
@@ -415,7 +368,7 @@ func TestPR(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/repo#42", Index: 20, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#42", Index: 20, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "LGTM", User: &models.User{UserName: "m1"}, State: common.ReviewStateApproved},
|
||||
{Body: "Merge OK!", User: &models.User{UserName: "super1"}, State: common.ReviewStateApproved},
|
||||
@@ -423,7 +376,7 @@ func TestPR(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#42", Index: 21, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#42", Index: 21, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "LGTM", User: &models.User{UserName: "m1"}, State: common.ReviewStateApproved},
|
||||
{Body: "merge ok", User: &models.User{UserName: "super1"}, State: common.ReviewStateApproved},
|
||||
@@ -440,7 +393,7 @@ func TestPR(t *testing.T) {
|
||||
Reviewers: []string{"+super1", "*super2", "m1", "-m2"},
|
||||
Branch: "branch",
|
||||
Organization: "foo",
|
||||
GitProjectName: "barPrj#master",
|
||||
GitProjectName: "barPrj",
|
||||
ManualMergeOnly: true,
|
||||
})
|
||||
},
|
||||
@@ -449,7 +402,7 @@ func TestPR(t *testing.T) {
|
||||
name: "Manual review done via PkgGits not allowed",
|
||||
data: []prdata{
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/repo#20\nPR: foo/repo#21", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}, Name: "master"}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "PR: foo/repo#20\nPR: foo/repo#21", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "LGTM", User: &models.User{UserName: "m2"}, State: common.ReviewStateApproved},
|
||||
{Body: "LGTM", User: &models.User{UserName: "super2"}, State: common.ReviewStateApproved},
|
||||
@@ -457,7 +410,7 @@ func TestPR(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/repo#42", Index: 20, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#42", Index: 20, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "LGTM", User: &models.User{UserName: "m1"}, State: common.ReviewStateApproved},
|
||||
{Body: "Merge OK!", User: &models.User{UserName: "super1"}, State: common.ReviewStateApproved},
|
||||
@@ -465,7 +418,7 @@ func TestPR(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#42", Index: 21, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#42", Index: 21, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "LGTM", User: &models.User{UserName: "m1"}, State: common.ReviewStateApproved},
|
||||
{Body: "merge ok", User: &models.User{UserName: "super1"}, State: common.ReviewStateApproved},
|
||||
@@ -482,7 +435,7 @@ func TestPR(t *testing.T) {
|
||||
Reviewers: []string{"+super1", "*super2", "m1", "-m2"},
|
||||
Branch: "branch",
|
||||
Organization: "foo",
|
||||
GitProjectName: "barPrj#master",
|
||||
GitProjectName: "barPrj",
|
||||
ManualMergeOnly: true,
|
||||
ManualMergeProject: true,
|
||||
})
|
||||
@@ -492,7 +445,7 @@ func TestPR(t *testing.T) {
|
||||
name: "Manual review is is missing on one PR",
|
||||
data: []prdata{
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/repo#20\nPR: foo/repo#21", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}, Name: "master"}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "PR: foo/repo#20\nPR: foo/repo#21", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "LGTM", User: &models.User{UserName: "m2"}, State: common.ReviewStateApproved},
|
||||
{Body: "LGTM", User: &models.User{UserName: "super2"}, State: common.ReviewStateApproved},
|
||||
@@ -500,7 +453,7 @@ func TestPR(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#42", Index: 20, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#42", Index: 20, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "LGTM", User: &models.User{UserName: "m1"}, State: common.ReviewStateApproved},
|
||||
{Body: "LGTM", User: &models.User{UserName: "super1"}, State: common.ReviewStateApproved},
|
||||
@@ -508,7 +461,7 @@ func TestPR(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#42", Index: 21, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "PR: foo/barPrj#42", Index: 21, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "repo", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "LGTM", User: &models.User{UserName: "m1"}, State: common.ReviewStateApproved},
|
||||
{Body: "LGTM", User: &models.User{UserName: "super1"}, State: common.ReviewStateApproved},
|
||||
@@ -525,7 +478,7 @@ func TestPR(t *testing.T) {
|
||||
Reviewers: []string{"+super1", "*super2", "m1", "-m2"},
|
||||
Branch: "branch",
|
||||
Organization: "foo",
|
||||
GitProjectName: "barPrj#master",
|
||||
GitProjectName: "barPrj",
|
||||
ManualMergeOnly: true,
|
||||
})
|
||||
},
|
||||
@@ -534,7 +487,7 @@ func TestPR(t *testing.T) {
|
||||
name: "PR is approved with negative optional review",
|
||||
data: []prdata{
|
||||
{
|
||||
pr: &models.PullRequest{Body: "", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}, Name: "master"}, User: &models.User{UserName: "submitter"}, State: "open"},
|
||||
pr: &models.PullRequest{Body: "", Index: 42, Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "barPrj", Owner: &models.User{UserName: "foo"}}}, User: &models.User{UserName: "submitter"}, State: "opened"},
|
||||
reviews: []*models.PullReview{
|
||||
{Body: "LGTM", User: &models.User{UserName: "m2"}, State: common.ReviewStateApproved},
|
||||
{Body: "LGTM", User: &models.User{UserName: "super2"}, State: common.ReviewStateApproved},
|
||||
@@ -552,7 +505,7 @@ func TestPR(t *testing.T) {
|
||||
Reviewers: []string{"+super1", "*super2", "m1", "-m2", "~*bot"},
|
||||
Branch: "branch",
|
||||
Organization: "foo",
|
||||
GitProjectName: "barPrj#master",
|
||||
GitProjectName: "barPrj",
|
||||
}
|
||||
return common.FetchPRSet("test", mock, "foo", "barPrj", 42, &config)
|
||||
},
|
||||
@@ -566,31 +519,27 @@ func TestPR(t *testing.T) {
|
||||
review_mock := mock_common.NewMockGiteaPRChecker(ctl)
|
||||
// reviewer_mock := mock_common.NewMockGiteaReviewRequester(ctl)
|
||||
|
||||
prjGitOrg, prjGitRepo, _ := baseConfig.GetPrjGit()
|
||||
if test.reviewSetFetcher == nil { // if we are fetching the prjgit directly, the these mocks are not called
|
||||
if test.prjGitPRIndex >= 0 {
|
||||
pr_mock.EXPECT().GetPullRequest(prjGitOrg, prjGitRepo, int64(test.data[test.prjGitPRIndex].pr.Index)).
|
||||
Return(test.data[test.prjGitPRIndex].pr, test.data[test.prjGitPRIndex].pr_err).AnyTimes()
|
||||
pr_mock.EXPECT().GetPullRequest(baseConfig.Organization, baseConfig.GitProjectName, test.prjGitPRIndex).
|
||||
Return(test.data[test.prjGitPRIndex].pr, test.data[test.prjGitPRIndex].pr_err)
|
||||
} else if test.prjGitPRIndex < 0 {
|
||||
// no prjgit PR
|
||||
pr_mock.EXPECT().GetPullRequest(prjGitOrg, prjGitRepo, gomock.Any()).
|
||||
Return(nil, nil).AnyTimes()
|
||||
pr_mock.EXPECT().GetPullRequest(baseConfig.Organization, baseConfig.GitProjectName, gomock.Any()).
|
||||
Return(nil, nil)
|
||||
}
|
||||
}
|
||||
|
||||
var test_err error
|
||||
for _, data := range test.data {
|
||||
pr_mock.EXPECT().GetPullRequest(data.pr.Base.Repo.Owner.UserName, data.pr.Base.Repo.Name, data.pr.Index).Return(data.pr, data.pr_err).AnyTimes()
|
||||
if data.pr_err != nil {
|
||||
// test_err is not used and was causing a build error.
|
||||
// data.pr_err is directly used in the previous EXPECT call.
|
||||
test_err = data.pr_err
|
||||
}
|
||||
review_mock.EXPECT().GetPullRequestReviews(data.pr.Base.Repo.Owner.UserName, data.pr.Base.Repo.Name, data.pr.Index).Return(data.reviews, data.review_error).AnyTimes()
|
||||
if data.timeline == nil {
|
||||
data.timeline = reviewsToTimeline(data.reviews)
|
||||
}
|
||||
pr_mock.EXPECT().GetTimeline(data.pr.Base.Repo.Owner.UserName, data.pr.Base.Repo.Name, data.pr.Index).Return(data.timeline, nil).AnyTimes()
|
||||
pr_mock.EXPECT().GetPullRequestReviews(data.pr.Base.Repo.Owner.UserName, data.pr.Base.Repo.Name, data.pr.Index).Return(data.reviews, data.review_error).AnyTimes()
|
||||
|
||||
review_mock.EXPECT().GetPullRequestReviews(data.pr.Base.Repo.Owner.UserName, data.pr.Base.Repo.Name, data.pr.Index).Return(data.reviews, data.review_error).AnyTimes()
|
||||
review_mock.EXPECT().GetTimeline(data.pr.Base.Repo.Owner.UserName, data.pr.Base.Repo.Name, data.pr.Index).Return(data.timeline, nil).AnyTimes()
|
||||
}
|
||||
|
||||
@@ -603,12 +552,27 @@ func TestPR(t *testing.T) {
|
||||
res, err = common.FetchPRSet("test", pr_mock, "test", "repo", 42, &baseConfig)
|
||||
}
|
||||
|
||||
if res == nil {
|
||||
if err == nil {
|
||||
if test_err != nil {
|
||||
t.Fatal("Expected", test_err, "but got", err)
|
||||
}
|
||||
} else {
|
||||
if res != nil {
|
||||
t.Fatal("error but got ReviewSet?")
|
||||
}
|
||||
|
||||
if test.api_error != "" {
|
||||
if err.Error() != test.api_error {
|
||||
t.Fatal("expected", test.api_error, "but got", err)
|
||||
}
|
||||
} else if test_err != err {
|
||||
t.Fatal("expected", test_err, "but got", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if len(res.PRs) != test.resLen {
|
||||
t.Errorf("Test Case '%s': expected result len %d but got %d", test.name, test.resLen, len(res.PRs))
|
||||
if test.resLen != len(res.PRs) {
|
||||
t.Error("expected result len", test.resLen, "but got", len(res.PRs))
|
||||
}
|
||||
|
||||
PrjGitPR, err := res.GetPrjGitPR()
|
||||
@@ -619,9 +583,6 @@ func TestPR(t *testing.T) {
|
||||
}
|
||||
pr_found := false
|
||||
if test.prjGitPRIndex >= 0 {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
for i := range test.data {
|
||||
if PrjGitPR.PR == test.data[i].pr && i == test.prjGitPRIndex {
|
||||
t.Log("found at index", i)
|
||||
@@ -872,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{
|
||||
@@ -1134,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{},
|
||||
ReviewRequired: 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{},
|
||||
ReviewRequired: 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
|
||||
@@ -1165,6 +1184,7 @@ func TestFindMissingAndExtraReviewers(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPRMerge(t *testing.T) {
|
||||
t.Skip("FAIL: No PrjGit PR found, missing calls")
|
||||
repoDir := t.TempDir()
|
||||
|
||||
cwd, _ := os.Getwd()
|
||||
@@ -1174,11 +1194,7 @@ func TestPRMerge(t *testing.T) {
|
||||
t.Fatal(string(out))
|
||||
}
|
||||
|
||||
t.Skip("No tests of PRMerge yet")
|
||||
return
|
||||
|
||||
common.ExtraGitParams = []string{
|
||||
"TZ=UTC",
|
||||
"GIT_CONFIG_COUNT=1",
|
||||
"GIT_CONFIG_KEY_0=protocol.file.allow",
|
||||
"GIT_CONFIG_VALUE_0=always",
|
||||
@@ -1193,7 +1209,7 @@ func TestPRMerge(t *testing.T) {
|
||||
|
||||
config := &common.AutogitConfig{
|
||||
Organization: "org",
|
||||
GitProjectName: "org/prj#main",
|
||||
GitProjectName: "org/prj#master",
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
@@ -1205,10 +1221,8 @@ func TestPRMerge(t *testing.T) {
|
||||
name: "Merge base not merged in main",
|
||||
|
||||
pr: &models.PullRequest{
|
||||
Index: 1,
|
||||
Base: &models.PRBranchInfo{
|
||||
Name: "main",
|
||||
Sha: "96515c092626c716a4613ba4f68a8d1cc4894317658342c450e656390f524ec3", // "base_add_b1"
|
||||
Sha: "e8b0de43d757c96a9d2c7101f4bff404e322f53a1fa4041fb85d646110c38ad4", // "base_add_b1"
|
||||
Repo: &models.Repository{
|
||||
Name: "prj",
|
||||
Owner: &models.User{
|
||||
@@ -1218,7 +1232,7 @@ func TestPRMerge(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Head: &models.PRBranchInfo{
|
||||
Sha: "4119fc725dc11cdf11f982d5bb0a8ba2a138f1180c4323862a18b8e08def5603", // "base_add_b2"
|
||||
Sha: "88584433de1c917c1d773f62b82381848d882491940b5e9b427a540aa9057d9a", // "base_add_b2"
|
||||
},
|
||||
},
|
||||
mergeError: "Aborting merge",
|
||||
@@ -1227,10 +1241,8 @@ func TestPRMerge(t *testing.T) {
|
||||
name: "Merge conflict in modules, auto-resolved",
|
||||
|
||||
pr: &models.PullRequest{
|
||||
Index: 1,
|
||||
Base: &models.PRBranchInfo{
|
||||
Name: "main",
|
||||
Sha: "85f59f7aa732b742e58b48356cd46cb1ab1b5c4349eb5c0eda324e2dbea8f9e7",
|
||||
Sha: "4fbd1026b2d7462ebe9229a49100c11f1ad6555520a21ba515122d8bc41328a8",
|
||||
Repo: &models.Repository{
|
||||
Name: "prj",
|
||||
Owner: &models.User{
|
||||
@@ -1240,7 +1252,7 @@ func TestPRMerge(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Head: &models.PRBranchInfo{
|
||||
Sha: "4119fc725dc11cdf11f982d5bb0a8ba2a138f1180c4323862a18b8e08def5603", // "base_add_b2"
|
||||
Sha: "88584433de1c917c1d773f62b82381848d882491940b5e9b427a540aa9057d9a", // "base_add_b2"
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1252,13 +1264,11 @@ func TestPRMerge(t *testing.T) {
|
||||
mock := mock_common.NewMockGiteaPRTimelineReviewFetcher(ctl)
|
||||
reviewUnrequestMock := mock_common.NewMockGiteaReviewUnrequester(ctl)
|
||||
|
||||
reviewUnrequestMock.EXPECT().UnrequestReview(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
|
||||
reviewUnrequestMock.EXPECT().UnrequestReview(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
|
||||
|
||||
testDir := t.TempDir()
|
||||
t.Log("dir:", testDir)
|
||||
mock.EXPECT().GetPullRequest("org", "prj", int64(1)).Return(test.pr, nil)
|
||||
mock.EXPECT().GetTimeline("org", "prj", int64(1)).Return(nil, nil).AnyTimes()
|
||||
mock.EXPECT().GetPullRequestReviews("org", "prj", int64(1)).Return(nil, nil).AnyTimes()
|
||||
|
||||
set, err := common.FetchPRSet("test", mock, "org", "prj", 1, config)
|
||||
if err != nil {
|
||||
@@ -1279,11 +1289,11 @@ func TestPRMerge(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPRChanges(t *testing.T) {
|
||||
t.Skip("FAIL: unexpected calls, missing calls")
|
||||
tests := []struct {
|
||||
name string
|
||||
PRs []*models.PullRequest
|
||||
PrjPRs *models.PullRequest
|
||||
Timeline []*models.TimelineComment
|
||||
name string
|
||||
PRs []*models.PullRequest
|
||||
PrjPRs *models.PullRequest
|
||||
}{
|
||||
{
|
||||
name: "Pkg PR is closed",
|
||||
@@ -1295,22 +1305,10 @@ func TestPRChanges(t *testing.T) {
|
||||
},
|
||||
},
|
||||
PrjPRs: &models.PullRequest{
|
||||
Index: 42,
|
||||
Title: "some PR",
|
||||
Base: &models.PRBranchInfo{Name: "branch", Repo: &models.Repository{Name: "prjgit", Owner: &models.User{UserName: "org"}}},
|
||||
Base: &models.PRBranchInfo{Repo: &models.Repository{Name: "prjgit", Owner: &models.User{UserName: "org"}}},
|
||||
Body: "PR: org/repo#42",
|
||||
State: "open",
|
||||
},
|
||||
Timeline: []*models.TimelineComment{
|
||||
{
|
||||
Type: common.TimelineCommentType_PullRequestRef,
|
||||
RefIssue: &models.Issue{
|
||||
Index: 42,
|
||||
Repository: &models.RepositoryMeta{Name: "prjgit", Owner: "org"},
|
||||
User: &models.User{UserName: "user"},
|
||||
Body: "PR: org/repo#42",
|
||||
},
|
||||
},
|
||||
State: "opened",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1323,13 +1321,9 @@ func TestPRChanges(t *testing.T) {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
ctl := gomock.NewController(t)
|
||||
mock_fetcher := mock_common.NewMockGiteaPRTimelineReviewFetcher(ctl)
|
||||
mock_fetcher.EXPECT().GetPullRequest("org", "prjgit", int64(42)).Return(test.PrjPRs, nil).AnyTimes()
|
||||
mock_fetcher.EXPECT().GetTimeline("org", "prjgit", int64(42)).Return(nil, nil).AnyTimes()
|
||||
mock_fetcher.EXPECT().GetPullRequestReviews("org", "prjgit", int64(42)).Return(nil, nil).AnyTimes()
|
||||
mock_fetcher.EXPECT().GetPullRequest("org", "prjgit", int64(42)).Return(test.PrjPRs, nil)
|
||||
for _, pr := range test.PRs {
|
||||
mock_fetcher.EXPECT().GetPullRequest(pr.Base.Repo.Owner.UserName, pr.Base.Repo.Name, pr.Index).Return(pr, nil)
|
||||
mock_fetcher.EXPECT().GetTimeline(pr.Base.Repo.Owner.UserName, pr.Base.Repo.Name, pr.Index).Return(test.Timeline, nil).AnyTimes()
|
||||
mock_fetcher.EXPECT().GetPullRequestReviews(pr.Base.Repo.Owner.UserName, pr.Base.Repo.Name, pr.Index).Return(nil, nil).AnyTimes()
|
||||
}
|
||||
|
||||
PRs, err := common.FetchPRSet("user", mock_fetcher, "org", "repo", 42, &config)
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
set -x
|
||||
|
||||
export TZ=UTC
|
||||
export GIT_CONFIG_COUNT=2
|
||||
|
||||
export GIT_CONFIG_KEY_0=protocol.file.allow
|
||||
|
||||
@@ -146,19 +146,15 @@ func main() {
|
||||
num, err := strconv.ParseInt(data[3], 10, 64)
|
||||
common.LogInfo("Processing:", org, "/", repo, "#", num)
|
||||
common.PanicOnError(err)
|
||||
if pr, err := Gitea.GetPullRequest(org, repo, num); err == nil && pr != nil {
|
||||
if err = ProcesPullRequest(pr, configs); err != nil {
|
||||
common.LogError("PR processor returned error", err)
|
||||
}
|
||||
} else if issue, err := Gitea.GetIssue(org, repo, num); err == nil && issue != nil {
|
||||
if err = ProcessIssue(issue, configs); err != nil {
|
||||
common.LogError("issue processor returned error:", err)
|
||||
}
|
||||
} else {
|
||||
common.LogError("Cannot fetch PR or Issue", err)
|
||||
pr, err := Gitea.GetPullRequest(org, repo, num)
|
||||
if err != nil {
|
||||
common.LogError("Cannot fetch PR", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = ProcesPullRequest(pr, configs); err != nil {
|
||||
common.LogError("processor returned error", err)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
@@ -190,14 +190,7 @@ func (pr *PRProcessor) SetSubmodulesToMatchPRSet(prset *common.PRSet) error {
|
||||
}
|
||||
|
||||
if !submodule_found {
|
||||
common.LogInfo("Adding new submodule", repo, "to PrjGit")
|
||||
ref := fmt.Sprintf(common.PrPattern, org, repo, idx)
|
||||
commitMsg := fmt.Sprintln("Add package", repo, "\n\nThis commit was autocreated by", GitAuthor, "\n\nreferencing PRs:\n", ref)
|
||||
|
||||
git.GitExecOrPanic(common.DefaultGitPrj, "submodule", "add", "-b", pr.PR.Base.Name, pr.PR.Base.Repo.SSHURL, repo)
|
||||
|
||||
updateSubmoduleInPR(repo, prHead, git)
|
||||
common.PanicOnError(git.GitExec(common.DefaultGitPrj, "commit", "-a", "-m", commitMsg))
|
||||
common.LogError("Failed to find expected repo:", repo)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -505,7 +498,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")
|
||||
@@ -554,7 +547,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
|
||||
}
|
||||
@@ -615,14 +608,6 @@ type RequestProcessor struct {
|
||||
recursive int
|
||||
}
|
||||
|
||||
func (w *RequestProcessor) Process(pr *models.PullRequest) error {
|
||||
configs, ok := w.configuredRepos[pr.Base.Repo.Owner.UserName]
|
||||
if !ok {
|
||||
return fmt.Errorf("no config found for org %s", pr.Base.Repo.Owner.UserName)
|
||||
}
|
||||
return ProcesPullRequest(pr, configs)
|
||||
}
|
||||
|
||||
func ProcesPullRequest(pr *models.PullRequest, configs []*common.AutogitConfig) error {
|
||||
if len(configs) < 1 {
|
||||
// ignoring pull request against unconfigured project (could be just regular sources?)
|
||||
@@ -639,184 +624,13 @@ func ProcesPullRequest(pr *models.PullRequest, configs []*common.AutogitConfig)
|
||||
return PRProcessor.Process(pr)
|
||||
}
|
||||
|
||||
func ProcessIssue(issue *models.Issue, configs []*common.AutogitConfig) error {
|
||||
title := issue.Title
|
||||
/*
|
||||
org := issue.Repository.Owner
|
||||
repo := issue.Repository.Name
|
||||
idx := issue.Index
|
||||
*/
|
||||
const BranchPrefix = "refs/heads/"
|
||||
branch := issue.Ref
|
||||
|
||||
if strings.HasPrefix(branch, BranchPrefix) {
|
||||
branch = strings.TrimPrefix(branch, BranchPrefix)
|
||||
} else {
|
||||
common.LogDebug("Invalid branch specified:", branch, ". Using default.")
|
||||
branch = ""
|
||||
func (w *RequestProcessor) Process(pr *models.PullRequest) error {
|
||||
configs, ok := w.configuredRepos[pr.Base.Repo.Owner.UserName]
|
||||
if !ok {
|
||||
common.LogError("*** Cannot find config for org:", pr.Base.Repo.Owner.UserName)
|
||||
return fmt.Errorf("*** Cannot find config for org: %s", pr.Base.Repo.Owner.UserName)
|
||||
}
|
||||
|
||||
// out, _ := json.MarshalIndent(issue, "", " ")
|
||||
// common.LogDebug(string(out))
|
||||
common.LogDebug("issue processing:", common.IssueToString(issue), "@", branch)
|
||||
|
||||
if len(title) > 5 && strings.EqualFold(title[0:5], "[ADD]") {
|
||||
// we need "New Package" label and "Approval Required" label, unless already approved
|
||||
// either via Label "Approved" or via review comment.
|
||||
NewIssues := common.FindNewReposInIssueBody(issue.Body)
|
||||
if NewIssues == nil {
|
||||
common.LogDebug("No new repos found in issue body")
|
||||
return nil
|
||||
}
|
||||
|
||||
org := issue.Repository.Owner
|
||||
repo := issue.Repository.Name
|
||||
|
||||
config := common.AutogitConfigs(configs).GetPrjGitConfig(org, repo, branch)
|
||||
if config == nil {
|
||||
return fmt.Errorf("Cannot find config for %s/%s#%s", org, repo, branch)
|
||||
}
|
||||
|
||||
if len(branch) == 0 {
|
||||
branch = config.Branch
|
||||
}
|
||||
|
||||
git, err := GitHandler.CreateGitHandler(config.Organization)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer git.Close()
|
||||
|
||||
for _, nr := range NewIssues.Repos {
|
||||
common.LogDebug(" - Processing new repository src:", nr.Organization+"/"+nr.PackageName+"#"+nr.Branch)
|
||||
targetRepo, err := Gitea.GetRepository(config.Organization, nr.PackageName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if targetRepo == nil {
|
||||
common.LogInfo(" - Repository", config.Organization+"/"+nr.PackageName, "does not exist. Labeling issue.")
|
||||
if !common.IsDryRun {
|
||||
Gitea.SetLabels(org, repo, issue.Index, []string{config.Label(common.Label_NewRepository)})
|
||||
}
|
||||
common.LogDebug(" # Done for now with this repo")
|
||||
continue
|
||||
}
|
||||
|
||||
srcRepo, err := Gitea.GetRepository(nr.Organization, nr.Repository)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if srcRepo == nil {
|
||||
common.LogError("Source repository not found:", nr.Organization+"/"+nr.Repository)
|
||||
continue
|
||||
}
|
||||
|
||||
if srcRepo.Parent == nil {
|
||||
common.LogError("Source has no parents.")
|
||||
continue
|
||||
}
|
||||
|
||||
if len(nr.Branch) == 0 {
|
||||
nr.Branch = srcRepo.DefaultBranch
|
||||
}
|
||||
|
||||
remoteName, err := git.GitClone(nr.PackageName, nr.Branch, targetRepo.SSHURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check that fork/parent repository relationship exists
|
||||
if srcRepo.Parent.Name != targetRepo.Name || srcRepo.Parent.Owner.UserName != targetRepo.Owner.UserName {
|
||||
common.LogError("Source repository is not fork of the Target repository. Fork of:", srcRepo.Parent.Owner.UserName+"/"+srcRepo.Parent.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
srcBranch := nr.Branch
|
||||
if srcBranch == "" {
|
||||
srcBranch = srcRepo.DefaultBranch
|
||||
}
|
||||
|
||||
// We are ready to setup a pending PR.
|
||||
// 1. empty target branch with empty commit, this will be discarded no merge
|
||||
// 2. create PR from source to target
|
||||
// a) if source is not branch, create a source branch in target repo that contains the relevant commit
|
||||
CreateEmptyBranch := true
|
||||
if err := git.GitExec(nr.PackageName, "checkout", "-B", nr.Branch, remoteName+"/"+nr.Branch); err == nil {
|
||||
// verify that our branch is empty
|
||||
dir, err := git.GitDirectoryContentList(nr.PackageName, "HEAD")
|
||||
if err != nil {
|
||||
common.LogError("Failed to list directory of", nr.Branch, "Aborting", err)
|
||||
return err
|
||||
}
|
||||
if len(dir) == 0 {
|
||||
common.LogDebug("New package branch is already empty.")
|
||||
CreateEmptyBranch = false
|
||||
}
|
||||
}
|
||||
if CreateEmptyBranch {
|
||||
git.GitExecOrPanic(nr.PackageName, "checkout", "--detach")
|
||||
git.GitExec(nr.PackageName, "branch", "-D", nr.Branch)
|
||||
git.GitExecOrPanic(nr.PackageName, "checkout", "-f", "--orphan", nr.Branch)
|
||||
git.GitExecOrPanic(nr.PackageName, "rm", "-rf", ".")
|
||||
git.GitExecOrPanic(nr.PackageName, "commit", "--allow-empty", "-m", "Initial empty branch")
|
||||
if !common.IsDryRun {
|
||||
git.GitExecOrPanic(nr.PackageName, "push", "-f", remoteName, nr.Branch)
|
||||
}
|
||||
}
|
||||
|
||||
head := nr.Organization + ":" + srcBranch
|
||||
isBranch := false
|
||||
// Hash can be branch name! Check if it's a branch or tag on the remote
|
||||
out, err := git.GitExecWithOutput(nr.PackageName, "ls-remote", "--heads", srcRepo.SSHURL, srcBranch)
|
||||
if err == nil && strings.Contains(out, "refs/heads/"+srcBranch) {
|
||||
isBranch = true
|
||||
}
|
||||
|
||||
if !isBranch {
|
||||
tempBranch := fmt.Sprintf("new_package_%d_%s", issue.Index, nr.PackageName)
|
||||
// Re-clone or use existing if branch check was done above
|
||||
remoteName, err := git.GitClone(nr.PackageName, srcBranch, targetRepo.SSHURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
git.GitExecOrPanic(nr.PackageName, "remote", "add", "source", srcRepo.SSHURL)
|
||||
git.GitExecOrPanic(nr.PackageName, "fetch", "source", srcBranch)
|
||||
git.GitExecOrPanic(nr.PackageName, "checkout", "-B", tempBranch, "FETCH_HEAD")
|
||||
if !common.IsDryRun {
|
||||
git.GitExecOrPanic(nr.PackageName, "push", "-f", remoteName, tempBranch)
|
||||
}
|
||||
head = tempBranch
|
||||
}
|
||||
|
||||
title := fmt.Sprintf("Add package %s", nr.PackageName)
|
||||
body := fmt.Sprintf("See issue %s/%s#%d", org, repo, issue.Index)
|
||||
br := branch
|
||||
if len(br) == 0 {
|
||||
br = targetRepo.DefaultBranch
|
||||
}
|
||||
pr, err, isNew := Gitea.CreatePullRequestIfNotExist(targetRepo, head, br, title, body)
|
||||
if err != nil {
|
||||
common.LogError(targetRepo.Name, head, branch, title, body)
|
||||
return err
|
||||
}
|
||||
|
||||
if isNew {
|
||||
if _, err := Gitea.SetLabels(config.Organization, nr.PackageName, pr.Index, []string{config.Label(common.Label_NewRepository)}); err != nil {
|
||||
common.LogError("Failed to set label:", common.Label_NewRepository, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if len(title) > 4 && strings.EqualFold(title[0:4], "[RM]") {
|
||||
// to remove a package, no approval is required. This should happen via
|
||||
// project git PR reviews
|
||||
} else {
|
||||
common.LogError("Non-standard issue created. Ignoring", common.IssueToString(issue))
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
return ProcesPullRequest(pr, configs)
|
||||
}
|
||||
|
||||
func (w *RequestProcessor) ProcessFunc(request *common.Request) (err error) {
|
||||
@@ -847,18 +661,6 @@ func (w *RequestProcessor) ProcessFunc(request *common.Request) (err error) {
|
||||
common.LogError("Cannot find PR for issue:", req.Repository.Owner.Username, req.Repository.Name, int64(req.Issue.Number))
|
||||
return err
|
||||
}
|
||||
} else if req, ok := request.Data.(*common.IssueWebhookEvent); ok {
|
||||
issue, err := Gitea.GetIssue(req.Repository.Owner.Username, req.Repository.Name, int64(req.Issue.Number))
|
||||
if err != nil {
|
||||
common.LogError("Cannot find issue for issue event:", req.Repository.Owner.Username, req.Repository.Name, int64(req.Issue.Number))
|
||||
return err
|
||||
}
|
||||
configs, ok := w.configuredRepos[req.Repository.Owner.Username]
|
||||
if !ok {
|
||||
common.LogError("*** Cannot find config for org:", req.Repository.Owner.Username)
|
||||
return nil
|
||||
}
|
||||
return ProcessIssue(issue, configs)
|
||||
} else {
|
||||
common.LogError("*** Invalid data format for PR processing.")
|
||||
return fmt.Errorf("*** Invalid data format for PR processing.")
|
||||
|
||||
@@ -1,381 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"go.uber.org/mock/gomock"
|
||||
"src.opensuse.org/autogits/common"
|
||||
"src.opensuse.org/autogits/common/gitea-generated/models"
|
||||
mock_common "src.opensuse.org/autogits/common/mock"
|
||||
)
|
||||
|
||||
func TestProcessIssue_Add(t *testing.T) {
|
||||
ctl := gomock.NewController(t)
|
||||
defer ctl.Finish()
|
||||
|
||||
gitea := mock_common.NewMockGitea(ctl)
|
||||
Gitea = gitea
|
||||
common.IsDryRun = false
|
||||
|
||||
config := &common.AutogitConfig{
|
||||
Organization: "target-org",
|
||||
GitProjectName: "test-org/test-prj#main",
|
||||
}
|
||||
configs := []*common.AutogitConfig{config}
|
||||
|
||||
issue := &models.Issue{
|
||||
Title: "[ADD] pkg1",
|
||||
Body: "src-org/pkg1#master",
|
||||
Index: 123,
|
||||
Repository: &models.RepositoryMeta{
|
||||
Owner: "test-org",
|
||||
Name: "test-prj",
|
||||
},
|
||||
Ref: "refs/heads/main",
|
||||
}
|
||||
|
||||
t.Run("Repository does not exist - labels issue", func(t *testing.T) {
|
||||
mockGitGen := mock_common.NewMockGitHandlerGenerator(ctl)
|
||||
GitHandler = mockGitGen
|
||||
mockGit := mock_common.NewMockGit(ctl)
|
||||
|
||||
mockGitGen.EXPECT().CreateGitHandler("target-org").Return(mockGit, nil)
|
||||
mockGit.EXPECT().Close().Return(nil)
|
||||
|
||||
gitea.EXPECT().GetRepository("target-org", "pkg1").Return(nil, nil)
|
||||
gitea.EXPECT().SetLabels("test-org", "test-prj", int64(123), []string{"new/New Repository"}).Return(nil, nil)
|
||||
|
||||
err := ProcessIssue(issue, configs)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Source is SHA - creates temp branch in target", func(t *testing.T) {
|
||||
mockGitGen := mock_common.NewMockGitHandlerGenerator(ctl)
|
||||
GitHandler = mockGitGen
|
||||
mockGit := mock_common.NewMockGit(ctl)
|
||||
|
||||
mockGitGen.EXPECT().CreateGitHandler("target-org").Return(mockGit, nil)
|
||||
mockGit.EXPECT().GetPath().Return("/tmp/test").AnyTimes()
|
||||
mockGit.EXPECT().Close().Return(nil)
|
||||
|
||||
targetRepo := &models.Repository{
|
||||
Name: "pkg1",
|
||||
SSHURL: "target-ssh-url",
|
||||
Owner: &models.User{UserName: "target-org"},
|
||||
}
|
||||
srcRepo := &models.Repository{
|
||||
Name: "pkg1",
|
||||
SSHURL: "src-ssh-url",
|
||||
DefaultBranch: "master",
|
||||
Owner: &models.User{UserName: "src-org"},
|
||||
Parent: &models.Repository{
|
||||
Name: "pkg1",
|
||||
Owner: &models.User{UserName: "target-org"},
|
||||
},
|
||||
}
|
||||
|
||||
issueSHA := &models.Issue{
|
||||
Title: "[ADD] pkg1",
|
||||
Body: "src-org/pkg1#abcdef0123456789abcdef0123456789abcdef01",
|
||||
Index: 123,
|
||||
Repository: &models.RepositoryMeta{Owner: "test-org", Name: "test-prj"},
|
||||
Ref: "refs/heads/main",
|
||||
}
|
||||
|
||||
gitea.EXPECT().GetRepository("target-org", "pkg1").Return(targetRepo, nil)
|
||||
mockGit.EXPECT().GitClone("pkg1", "abcdef0123456789abcdef0123456789abcdef01", "target-ssh-url").Return("origin", nil)
|
||||
|
||||
// New orphan branch logic
|
||||
mockGit.EXPECT().GitExec("pkg1", "checkout", "-B", "abcdef0123456789abcdef0123456789abcdef01", "origin/abcdef0123456789abcdef0123456789abcdef01").Return(fmt.Errorf("error"))
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "checkout", "--detach")
|
||||
mockGit.EXPECT().GitExec("pkg1", "branch", "-D", "abcdef0123456789abcdef0123456789abcdef01")
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "checkout", "-f", "--orphan", "abcdef0123456789abcdef0123456789abcdef01")
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "rm", "-rf", ".")
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "commit", "--allow-empty", "-m", "Initial empty branch")
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "push", "-f", "origin", "abcdef0123456789abcdef0123456789abcdef01")
|
||||
|
||||
gitea.EXPECT().GetRepository("src-org", "pkg1").Return(srcRepo, nil)
|
||||
mockGit.EXPECT().GitExecWithOutput("pkg1", "ls-remote", "--heads", "src-ssh-url", "abcdef0123456789abcdef0123456789abcdef01").Return("", nil)
|
||||
|
||||
// SHA source logic
|
||||
tempBranch := "new_package_123_pkg1"
|
||||
mockGit.EXPECT().GitClone("pkg1", "abcdef0123456789abcdef0123456789abcdef01", "target-ssh-url").Return("origin", nil)
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "remote", "add", "source", "src-ssh-url")
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "fetch", "source", "abcdef0123456789abcdef0123456789abcdef01")
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "checkout", "-B", tempBranch, "FETCH_HEAD")
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "push", "-f", "origin", tempBranch)
|
||||
|
||||
// PR creation using temp branch
|
||||
gitea.EXPECT().CreatePullRequestIfNotExist(targetRepo, tempBranch, "main", gomock.Any(), gomock.Any()).Return(&models.PullRequest{Index: 456}, nil, false)
|
||||
|
||||
err := ProcessIssue(issueSHA, configs)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Repository exists - continue processing and create PR", func(t *testing.T) {
|
||||
mockGitGen := mock_common.NewMockGitHandlerGenerator(ctl)
|
||||
GitHandler = mockGitGen
|
||||
mockGit := mock_common.NewMockGit(ctl)
|
||||
|
||||
mockGitGen.EXPECT().CreateGitHandler("target-org").Return(mockGit, nil)
|
||||
mockGit.EXPECT().Close().Return(nil)
|
||||
|
||||
targetRepo := &models.Repository{
|
||||
Name: "pkg1",
|
||||
SSHURL: "target-ssh-url",
|
||||
Owner: &models.User{UserName: "target-org"},
|
||||
}
|
||||
srcRepo := &models.Repository{
|
||||
Name: "pkg1",
|
||||
SSHURL: "src-ssh-url",
|
||||
DefaultBranch: "master",
|
||||
Owner: &models.User{UserName: "src-org"},
|
||||
Parent: &models.Repository{
|
||||
Name: "pkg1",
|
||||
Owner: &models.User{UserName: "target-org"},
|
||||
},
|
||||
}
|
||||
|
||||
gitea.EXPECT().GetRepository("target-org", "pkg1").Return(targetRepo, nil)
|
||||
// 4. Branch check - exists via local git
|
||||
mockGit.EXPECT().GitClone("pkg1", "master", "target-ssh-url").Return("origin", nil)
|
||||
mockGit.EXPECT().GitExec("pkg1", "checkout", "-B", "master", "origin/master").Return(nil)
|
||||
mockGit.EXPECT().GitDirectoryContentList("pkg1", "HEAD").Return(map[string]string{"some-file": "some-sha"}, nil)
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "checkout", "--detach")
|
||||
mockGit.EXPECT().GitExec("pkg1", "branch", "-D", "master")
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "checkout", "-f", "--orphan", "master")
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "rm", "-rf", ".")
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "commit", "--allow-empty", "-m", gomock.Any())
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "push", "-f", "origin", "master")
|
||||
|
||||
// 5. Source repo fetch
|
||||
gitea.EXPECT().GetRepository("src-org", "pkg1").Return(srcRepo, nil)
|
||||
// Check if source is a branch via ls-remote
|
||||
mockGit.EXPECT().GitExecWithOutput("pkg1", "ls-remote", "--heads", "src-ssh-url", "master").Return("src-sha refs/heads/master", nil)
|
||||
|
||||
// PR creation
|
||||
packagePR := &models.PullRequest{
|
||||
Index: 456,
|
||||
Base: &models.PRBranchInfo{
|
||||
Ref: "main",
|
||||
Repo: targetRepo,
|
||||
Name: "main",
|
||||
},
|
||||
Head: &models.PRBranchInfo{
|
||||
Ref: "master",
|
||||
Repo: srcRepo,
|
||||
Sha: "src-sha",
|
||||
},
|
||||
URL: "http://gitea/pr/456",
|
||||
}
|
||||
gitea.EXPECT().CreatePullRequestIfNotExist(targetRepo, "src-org:master", "main", gomock.Any(), gomock.Any()).Return(packagePR, nil, true)
|
||||
gitea.EXPECT().SetLabels("target-org", "pkg1", int64(456), []string{"new/New Repository"}).Return(nil, nil)
|
||||
|
||||
err := ProcessIssue(issue, configs)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Source repository is not fork of target repository - aborts", func(t *testing.T) {
|
||||
mockGitGen := mock_common.NewMockGitHandlerGenerator(ctl)
|
||||
GitHandler = mockGitGen
|
||||
mockGit := mock_common.NewMockGit(ctl)
|
||||
|
||||
mockGitGen.EXPECT().CreateGitHandler("target-org").Return(mockGit, nil)
|
||||
mockGit.EXPECT().Close().Return(nil)
|
||||
|
||||
targetRepo := &models.Repository{
|
||||
Name: "pkg1",
|
||||
SSHURL: "target-ssh-url",
|
||||
Owner: &models.User{UserName: "target-org"},
|
||||
}
|
||||
srcRepo := &models.Repository{
|
||||
Name: "pkg1",
|
||||
Owner: &models.User{UserName: "src-org"},
|
||||
Parent: &models.Repository{
|
||||
Name: "other-repo",
|
||||
Owner: &models.User{UserName: "other-org"},
|
||||
},
|
||||
}
|
||||
|
||||
gitea.EXPECT().GetRepository("target-org", "pkg1").Return(targetRepo, nil)
|
||||
mockGit.EXPECT().GitClone("pkg1", "master", "target-ssh-url").Return("origin", nil)
|
||||
|
||||
gitea.EXPECT().GetRepository("src-org", "pkg1").Return(srcRepo, nil)
|
||||
|
||||
err := ProcessIssue(issue, configs)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Source repository is fork of target repository - proceeds", func(t *testing.T) {
|
||||
mockGitGen := mock_common.NewMockGitHandlerGenerator(ctl)
|
||||
GitHandler = mockGitGen
|
||||
mockGit := mock_common.NewMockGit(ctl)
|
||||
|
||||
mockGitGen.EXPECT().CreateGitHandler("target-org").Return(mockGit, nil)
|
||||
mockGit.EXPECT().Close().Return(nil)
|
||||
|
||||
targetRepo := &models.Repository{
|
||||
Name: "pkg1",
|
||||
Owner: &models.User{UserName: "target-org"},
|
||||
SSHURL: "target-ssh-url",
|
||||
}
|
||||
srcRepo := &models.Repository{
|
||||
Name: "pkg1",
|
||||
Owner: &models.User{UserName: "src-org"},
|
||||
SSHURL: "src-ssh-url",
|
||||
Parent: &models.Repository{
|
||||
Name: "pkg1",
|
||||
Owner: &models.User{UserName: "target-org"},
|
||||
},
|
||||
DefaultBranch: "master",
|
||||
}
|
||||
|
||||
gitea.EXPECT().GetRepository("target-org", "pkg1").Return(targetRepo, nil)
|
||||
mockGit.EXPECT().GitClone("pkg1", "master", "target-ssh-url").Return("origin", nil)
|
||||
mockGit.EXPECT().GitExec("pkg1", "checkout", "-B", "master", "origin/master").Return(nil)
|
||||
mockGit.EXPECT().GitDirectoryContentList("pkg1", "HEAD").Return(map[string]string{"some-file": "some-sha"}, nil)
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "checkout", "--detach")
|
||||
mockGit.EXPECT().GitExec("pkg1", "branch", "-D", "master")
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "checkout", "-f", "--orphan", "master")
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "rm", "-rf", ".")
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "commit", "--allow-empty", "-m", gomock.Any())
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "push", "-f", "origin", "master")
|
||||
|
||||
gitea.EXPECT().GetRepository("src-org", "pkg1").Return(srcRepo, nil)
|
||||
mockGit.EXPECT().GitExecWithOutput("pkg1", "ls-remote", "--heads", "src-ssh-url", "master").Return("src-sha refs/heads/master", nil)
|
||||
gitea.EXPECT().CreatePullRequestIfNotExist(targetRepo, "src-org:master", "main", gomock.Any(), gomock.Any()).Return(&models.PullRequest{Index: 456}, nil, false)
|
||||
|
||||
err := ProcessIssue(issue, configs)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Source repository has no parent (not a fork) - aborts", func(t *testing.T) {
|
||||
mockGitGen := mock_common.NewMockGitHandlerGenerator(ctl)
|
||||
GitHandler = mockGitGen
|
||||
mockGit := mock_common.NewMockGit(ctl)
|
||||
|
||||
mockGitGen.EXPECT().CreateGitHandler("target-org").Return(mockGit, nil)
|
||||
mockGit.EXPECT().Close().Return(nil)
|
||||
|
||||
targetRepo := &models.Repository{
|
||||
Name: "pkg1",
|
||||
Owner: &models.User{UserName: "target-org"},
|
||||
SSHURL: "target-ssh-url",
|
||||
}
|
||||
srcRepo := &models.Repository{
|
||||
Name: "pkg1",
|
||||
Owner: &models.User{UserName: "src-org"},
|
||||
SSHURL: "src-ssh-url",
|
||||
Parent: nil,
|
||||
DefaultBranch: "master",
|
||||
}
|
||||
|
||||
gitea.EXPECT().GetRepository("target-org", "pkg1").Return(targetRepo, nil)
|
||||
|
||||
gitea.EXPECT().GetRepository("src-org", "pkg1").Return(srcRepo, nil)
|
||||
|
||||
err := ProcessIssue(issue, configs)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Target branch missing - creates orphan branch", func(t *testing.T) {
|
||||
mockGitGen := mock_common.NewMockGitHandlerGenerator(ctl)
|
||||
GitHandler = mockGitGen
|
||||
mockGit := mock_common.NewMockGit(ctl)
|
||||
|
||||
mockGitGen.EXPECT().CreateGitHandler("target-org").Return(mockGit, nil)
|
||||
mockGit.EXPECT().GetPath().Return("/tmp/test").AnyTimes()
|
||||
mockGit.EXPECT().Close().Return(nil)
|
||||
|
||||
targetRepo := &models.Repository{
|
||||
Name: "pkg1",
|
||||
SSHURL: "target-ssh-url",
|
||||
Owner: &models.User{UserName: "target-org"},
|
||||
}
|
||||
srcRepo := &models.Repository{
|
||||
Name: "pkg1",
|
||||
SSHURL: "src-ssh-url",
|
||||
DefaultBranch: "master",
|
||||
Owner: &models.User{UserName: "src-org"},
|
||||
Parent: &models.Repository{
|
||||
Name: "pkg1",
|
||||
Owner: &models.User{UserName: "target-org"},
|
||||
},
|
||||
}
|
||||
|
||||
gitea.EXPECT().GetRepository("target-org", "pkg1").Return(targetRepo, nil)
|
||||
// 4. Branch check - missing
|
||||
mockGit.EXPECT().GitClone("pkg1", "master", "target-ssh-url").Return("origin", nil)
|
||||
mockGit.EXPECT().GitExec(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(fmt.Errorf("not found"))
|
||||
|
||||
// Orphan branch creation
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "checkout", "--detach")
|
||||
mockGit.EXPECT().GitExec("pkg1", "branch", "-D", "master")
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "checkout", "-f", "--orphan", "master")
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "rm", "-rf", ".")
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "commit", "--allow-empty", "-m", "Initial empty branch")
|
||||
mockGit.EXPECT().GitExecOrPanic("pkg1", "push", "-f", "origin", "master")
|
||||
|
||||
// 5. Source repo fetch
|
||||
gitea.EXPECT().GetRepository("src-org", "pkg1").Return(srcRepo, nil)
|
||||
mockGit.EXPECT().GitExecWithOutput("pkg1", "ls-remote", "--heads", "src-ssh-url", "master").Return("src-sha refs/heads/master", nil)
|
||||
|
||||
// PR creation
|
||||
gitea.EXPECT().CreatePullRequestIfNotExist(targetRepo, "src-org:master", "main", gomock.Any(), gomock.Any()).Return(&models.PullRequest{Index: 456}, nil, false)
|
||||
|
||||
err := ProcessIssue(issue, configs)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Config not found", func(t *testing.T) {
|
||||
issueNoConfig := &models.Issue{
|
||||
Title: "[ADD] pkg1",
|
||||
Body: "src-org/pkg1#master",
|
||||
Index: 123,
|
||||
Repository: &models.RepositoryMeta{
|
||||
Owner: "other-org",
|
||||
Name: "other-prj",
|
||||
},
|
||||
Ref: "refs/heads/main",
|
||||
}
|
||||
err := ProcessIssue(issueNoConfig, configs)
|
||||
if err == nil || err.Error() != "Cannot find config for other-org/other-prj#main" {
|
||||
t.Errorf("Expected config not found error, got %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("No repos in body", func(t *testing.T) {
|
||||
mockGitGen := mock_common.NewMockGitHandlerGenerator(ctl)
|
||||
GitHandler = mockGitGen
|
||||
err := ProcessIssue(&models.Issue{
|
||||
Title: "[ADD] pkg1",
|
||||
Body: "nothing here",
|
||||
Ref: "refs/heads/main",
|
||||
Repository: &models.RepositoryMeta{
|
||||
Owner: "test-org",
|
||||
Name: "test-prj",
|
||||
},
|
||||
}, configs)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
)
|
||||
|
||||
func TestSyncPR(t *testing.T) {
|
||||
CurrentUser = &models.User{UserName: "testuser"}
|
||||
config := &common.AutogitConfig{
|
||||
Reviewers: []string{"reviewer1", "reviewer2"},
|
||||
Branch: "testing",
|
||||
@@ -152,3 +151,4 @@ func TestSyncPR(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ func commandsForPackages(dir, prefix string, startN, endN int) [][]string {
|
||||
|
||||
func setupGitForTests(t *testing.T, git *common.GitHandlerImpl) {
|
||||
common.ExtraGitParams = []string{
|
||||
"TZ=UTC",
|
||||
"GIT_CONFIG_COUNT=1",
|
||||
"GIT_CONFIG_KEY_0=protocol.file.allow",
|
||||
"GIT_CONFIG_VALUE_0=always",
|
||||
|
||||
Reference in New Issue
Block a user