Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only check for conflicts/merging if the PR has not been merged in the interim #10132

Merged
merged 37 commits into from
Feb 9, 2020
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
ef1a8a5
Only check for merging if the PR has not been merged in the interim
zeripath Feb 3, 2020
e29a6de
fixup! Only check for merging if the PR has not been merged in the in…
zeripath Feb 3, 2020
1205165
Try to fix test failure
zeripath Feb 3, 2020
ee7d5f7
Use PR2 not PR1 in tests as PR1 merges automatically
zeripath Feb 4, 2020
4c00eb6
Merge branch 'master' into improve-pr-check
zeripath Feb 4, 2020
9a90443
return already merged error
zeripath Feb 4, 2020
ad20cd2
Merge branch 'master' into improve-pr-check
zeripath Feb 5, 2020
fdc055e
enforce locking
zeripath Feb 6, 2020
0f9e498
enforce locking - fix-test
zeripath Feb 6, 2020
5551c6d
enforce locking - fix-testx2
zeripath Feb 6, 2020
7d5772f
enforce locking - fix-testx3
zeripath Feb 6, 2020
76f7eef
move pullrequest checking to after merge
zeripath Feb 9, 2020
a60c5b8
Remove minor race with getting merge commit id
zeripath Feb 9, 2020
87f5793
fixup
zeripath Feb 9, 2020
f8f886f
move check pr after merge
zeripath Feb 9, 2020
389342c
Remove unnecessary prepareTestEnv - onGiteaRun does this for us
zeripath Feb 9, 2020
203ff71
Add information about when merging occuring
zeripath Feb 9, 2020
bd6badc
Merge remote-tracking branch 'origin/master' into improve-pr-check
zeripath Feb 9, 2020
ab79a00
fix fmt
zeripath Feb 9, 2020
9c79c73
More logging
zeripath Feb 9, 2020
36c3771
Attempt to fix mysql
zeripath Feb 9, 2020
3a9768f
Try MySQL fix again
zeripath Feb 9, 2020
f055a73
try again
zeripath Feb 9, 2020
ca9103d
Try again?!
zeripath Feb 9, 2020
22631c2
Try again?!
zeripath Feb 9, 2020
fa8f010
Sigh
zeripath Feb 9, 2020
441ff1a
remove the count - perhaps that will help
zeripath Feb 9, 2020
52cd67c
next remove the update id
zeripath Feb 9, 2020
8373df4
next remove the update id - make it updated_unix instead
zeripath Feb 9, 2020
c8c5809
On failure to merge ensure that the pr is rechecked for conflict errors
zeripath Feb 9, 2020
f505332
On failure to merge ensure that the pr is rechecked for conflict errors
zeripath Feb 9, 2020
0140315
Merge branch 'master' into improve-pr-check
zeripath Feb 9, 2020
bd7c2eb
Merge branch 'master' into improve-pr-check
lafriks Feb 9, 2020
7486e16
Update models/pull.go
zeripath Feb 9, 2020
7955006
Update models/pull.go
zeripath Feb 9, 2020
6bd8699
Apply suggestions from code review
zeripath Feb 9, 2020
1ffd6bc
Merge branch 'master' into improve-pr-check
zeripath Feb 9, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 1 addition & 9 deletions integrations/pull_merge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,6 @@ func TestPullRebase(t *testing.T) {

func TestPullRebaseMerge(t *testing.T) {
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
defer prepareTestEnv(t)()
lafriks marked this conversation as resolved.
Show resolved Hide resolved

hookTasks, err := models.HookTasks(1, 1) //Retrieve previous hook number
assert.NoError(t, err)
hookTasksLenBefore := len(hookTasks)
Expand All @@ -129,8 +127,6 @@ func TestPullRebaseMerge(t *testing.T) {

func TestPullSquash(t *testing.T) {
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
defer prepareTestEnv(t)()

hookTasks, err := models.HookTasks(1, 1) //Retrieve previous hook number
assert.NoError(t, err)
hookTasksLenBefore := len(hookTasks)
Expand All @@ -154,10 +150,9 @@ func TestPullSquash(t *testing.T) {

func TestPullCleanUpAfterMerge(t *testing.T) {
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
defer prepareTestEnv(t)()
session := loginUser(t, "user1")
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
testEditFileToNewBranch(t, session, "user1", "repo1", "master", "feature/test", "README.md", "Hello, World (Edited)\n")
testEditFileToNewBranch(t, session, "user1", "repo1", "master", "feature/test", "README.md", "Hello, World (Edited - TestPullCleanUpAfterMerge)\n")

resp := testPullCreate(t, session, "user1", "repo1", "feature/test", "This is a pull title")

Expand Down Expand Up @@ -190,7 +185,6 @@ func TestPullCleanUpAfterMerge(t *testing.T) {

func TestCantMergeWorkInProgress(t *testing.T) {
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
defer prepareTestEnv(t)()
session := loginUser(t, "user1")
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
Expand All @@ -212,7 +206,6 @@ func TestCantMergeWorkInProgress(t *testing.T) {

func TestCantMergeConflict(t *testing.T) {
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
defer prepareTestEnv(t)()
session := loginUser(t, "user1")
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
testEditFileToNewBranch(t, session, "user1", "repo1", "master", "conflict", "README.md", "Hello, World (Edited Once)\n")
Expand Down Expand Up @@ -258,7 +251,6 @@ func TestCantMergeConflict(t *testing.T) {

func TestCantMergeUnrelated(t *testing.T) {
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
defer prepareTestEnv(t)()
session := loginUser(t, "user1")
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
testEditFileToNewBranch(t, session, "user1", "repo1", "master", "base", "README.md", "Hello, World (Edited Twice)\n")
Expand Down
65 changes: 47 additions & 18 deletions models/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -498,44 +498,67 @@ const (
)

// SetMerged sets a pull request to merged and closes the corresponding issue
func (pr *PullRequest) SetMerged() (err error) {
func (pr *PullRequest) SetMerged() (bool, error) {
if pr.HasMerged {
return fmt.Errorf("PullRequest[%d] already merged", pr.Index)
return false, fmt.Errorf("PullRequest[%d] already merged", pr.Index)
}
if pr.MergedCommitID == "" || pr.MergedUnix == 0 || pr.Merger == nil {
return fmt.Errorf("Unable to merge PullRequest[%d], some required fields are empty", pr.Index)
return false, fmt.Errorf("Unable to merge PullRequest[%d], some required fields are empty", pr.Index)
}

pr.HasMerged = true

sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
return err
if err := sess.Begin(); err != nil {
return false, err
}

if err = pr.loadIssue(sess); err != nil {
return err
if _, err := sess.Where("id = ?", pr.IssueID).Cols("updated_unix").Update(&Issue{
zeripath marked this conversation as resolved.
Show resolved Hide resolved
ID: pr.IssueID,
zeripath marked this conversation as resolved.
Show resolved Hide resolved
}); err != nil {
zeripath marked this conversation as resolved.
Show resolved Hide resolved
return false, err
}

if err = pr.Issue.loadRepo(sess); err != nil {
return err
if _, err := sess.Where("id = ?", pr.ID).Cols("updated_unix").Update(pr); err != nil {
lafriks marked this conversation as resolved.
Show resolved Hide resolved
zeripath marked this conversation as resolved.
Show resolved Hide resolved
return false, err
}
if err = pr.Issue.Repo.getOwner(sess); err != nil {
return err

if err := pr.loadIssue(sess); err != nil {
zeripath marked this conversation as resolved.
Show resolved Hide resolved
return false, err
}

if _, err = pr.Issue.changeStatus(sess, pr.Merger, true); err != nil {
return fmt.Errorf("Issue.changeStatus: %v", err)
if tmpPr, err := getPullRequestByID(sess, pr.ID); err != nil {
return false, err
} else if tmpPr.HasMerged {
if pr.Issue.IsClosed {
return false, nil
}
return false, fmt.Errorf("PullRequest[%d] already merged", pr.Index)
zeripath marked this conversation as resolved.
Show resolved Hide resolved
} else if pr.Issue.IsClosed {
return false, fmt.Errorf("PullRequest[%d] already closed", pr.Index)
}
if _, err = sess.ID(pr.ID).Cols("has_merged, status, merged_commit_id, merger_id, merged_unix").Update(pr); err != nil {
return fmt.Errorf("update pull request: %v", err)

if err := pr.Issue.loadRepo(sess); err != nil {
return false, err
}

if err = sess.Commit(); err != nil {
return fmt.Errorf("Commit: %v", err)
if err := pr.Issue.Repo.getOwner(sess); err != nil {
return false, err
}
return nil

if _, err := pr.Issue.changeStatus(sess, pr.Merger, true); err != nil {
return false, fmt.Errorf("Issue.changeStatus: %v", err)
}

if _, err := sess.Where("id = ?", pr.ID).Cols("has_merged, status, merged_commit_id, merger_id, merged_unix").Update(pr); err != nil {
return false, fmt.Errorf("Failed to update pr[%d]: %v", pr.ID, err)
}

if err := sess.Commit(); err != nil {
return false, fmt.Errorf("Commit: %v", err)
}
return true, nil
}

// NewPullRequest creates new pull request with labels for repository.
Expand Down Expand Up @@ -707,6 +730,12 @@ func (pr *PullRequest) UpdateCols(cols ...string) error {
return err
}

// UpdateColsIfNotMerged updates specific fields of a pull request if it has not been merged
func (pr *PullRequest) UpdateColsIfNotMerged(cols ...string) error {
_, err := x.Where("id = ? AND has_merged = ?", pr.ID, false).Cols(cols...).Update(pr)
return err
}

// IsWorkInProgress determine if the Pull Request is a Work In Progress by its title
func (pr *PullRequest) IsWorkInProgress() bool {
if err := pr.LoadIssue(); err != nil {
Expand Down
8 changes: 5 additions & 3 deletions services/pull/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func AddToTaskQueue(pr *models.PullRequest) {
go func() {
err := prQueue.PushFunc(strconv.FormatInt(pr.ID, 10), func() error {
pr.Status = models.PullRequestStatusChecking
err := pr.UpdateCols("status")
err := pr.UpdateColsIfNotMerged("status")
if err != nil {
log.Error("AddToTaskQueue.UpdateCols[%d].(add to queue): %v", pr.ID, err)
} else {
Expand Down Expand Up @@ -158,9 +158,11 @@ func manuallyMerged(pr *models.PullRequest) bool {
pr.Merger = merger
pr.MergerID = merger.ID

if err = pr.SetMerged(); err != nil {
if merged, err := pr.SetMerged(); err != nil {
log.Error("PullRequest[%d].setMerged : %v", pr.ID, err)
return false
} else if !merged {
return false
}

notification.NotifyMergePullRequest(pr, merger)
Expand Down Expand Up @@ -205,7 +207,7 @@ func handle(data ...queue.Data) {
if err != nil {
log.Error("GetPullRequestByID[%s]: %v", prID, err)
continue
} else if pr.Status != models.PullRequestStatusChecking {
} else if pr.HasMerged {
lafriks marked this conversation as resolved.
Show resolved Hide resolved
continue
} else if manuallyMerged(pr) {
continue
Expand Down
6 changes: 3 additions & 3 deletions services/pull/check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ func TestPullRequest_AddToTaskQueue(t *testing.T) {

prQueue = q.(queue.UniqueQueue)

pr := models.AssertExistsAndLoadBean(t, &models.PullRequest{ID: 1}).(*models.PullRequest)
pr := models.AssertExistsAndLoadBean(t, &models.PullRequest{ID: 2}).(*models.PullRequest)
AddToTaskQueue(pr)

assert.Eventually(t, func() bool {
pr = models.AssertExistsAndLoadBean(t, &models.PullRequest{ID: 1}).(*models.PullRequest)
pr = models.AssertExistsAndLoadBean(t, &models.PullRequest{ID: 2}).(*models.PullRequest)
return pr.Status == models.PullRequestStatusChecking
}, 1*time.Second, 100*time.Millisecond)

Expand All @@ -73,7 +73,7 @@ func TestPullRequest_AddToTaskQueue(t *testing.T) {
assert.False(t, has)
assert.NoError(t, err)

pr = models.AssertExistsAndLoadBean(t, &models.PullRequest{ID: 1}).(*models.PullRequest)
pr = models.AssertExistsAndLoadBean(t, &models.PullRequest{ID: 2}).(*models.PullRequest)
assert.Equal(t, models.PullRequestStatusChecking, pr.Status)

for _, callback := range queueShutdown {
Expand Down
Loading