@ -12,6 +12,8 @@ import (
"net/url"
"os"
"path"
"path/filepath"
"strconv"
"strings"
"testing"
"time"
@ -19,7 +21,9 @@ import (
"code.gitea.io/gitea/models"
auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
pull_model "code.gitea.io/gitea/models/pull"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
@ -30,8 +34,10 @@ import (
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/services/automerge"
"code.gitea.io/gitea/services/pull"
repo_service "code.gitea.io/gitea/services/repository"
commitstatus_service "code.gitea.io/gitea/services/repository/commitstatus"
files_service "code.gitea.io/gitea/services/repository/files"
"github.com/stretchr/testify/assert"
@ -648,3 +654,195 @@ func TestPullMergeIndexerNotifier(t *testing.T) {
}
} )
}
func testResetRepo ( t * testing . T , repoPath , branch , commitID string ) {
f , err := os . OpenFile ( filepath . Join ( repoPath , "refs" , "heads" , branch ) , os . O_WRONLY | os . O_CREATE | os . O_TRUNC , 0 o644 )
assert . NoError ( t , err )
_ , err = f . WriteString ( commitID + "\n" )
assert . NoError ( t , err )
f . Close ( )
repo , err := git . OpenRepository ( context . Background ( ) , repoPath )
assert . NoError ( t , err )
defer repo . Close ( )
id , err := repo . GetBranchCommitID ( branch )
assert . NoError ( t , err )
assert . EqualValues ( t , commitID , id )
}
func TestPullAutoMergeAfterCommitStatusSucceed ( t * testing . T ) {
onGiteaRun ( t , func ( t * testing . T , giteaURL * url . URL ) {
// create a pull request
session := loginUser ( t , "user1" )
user1 := unittest . AssertExistsAndLoadBean ( t , & user_model . User { ID : 1 } )
forkedName := "repo1-1"
testRepoFork ( t , session , "user2" , "repo1" , "user1" , forkedName )
defer func ( ) {
testDeleteRepository ( t , session , "user1" , forkedName )
} ( )
testEditFile ( t , session , "user1" , forkedName , "master" , "README.md" , "Hello, World (Edited)\n" )
testPullCreate ( t , session , "user1" , forkedName , false , "master" , "master" , "Indexer notifier test pull" )
baseRepo := unittest . AssertExistsAndLoadBean ( t , & repo_model . Repository { OwnerName : "user2" , Name : "repo1" } )
forkedRepo := unittest . AssertExistsAndLoadBean ( t , & repo_model . Repository { OwnerName : "user1" , Name : forkedName } )
pr := unittest . AssertExistsAndLoadBean ( t , & issues_model . PullRequest {
BaseRepoID : baseRepo . ID ,
BaseBranch : "master" ,
HeadRepoID : forkedRepo . ID ,
HeadBranch : "master" ,
} )
// add protected branch for commit status
csrf := GetCSRF ( t , session , "/user2/repo1/settings/branches" )
// Change master branch to protected
req := NewRequestWithValues ( t , "POST" , "/user2/repo1/settings/branches/edit" , map [ string ] string {
"_csrf" : csrf ,
"rule_name" : "master" ,
"enable_push" : "true" ,
"enable_status_check" : "true" ,
"status_check_contexts" : "gitea/actions" ,
} )
session . MakeRequest ( t , req , http . StatusSeeOther )
// first time insert automerge record, return true
scheduled , err := automerge . ScheduleAutoMerge ( db . DefaultContext , user1 , pr , repo_model . MergeStyleMerge , "auto merge test" )
assert . NoError ( t , err )
assert . True ( t , scheduled )
// second time insert automerge record, return false because it does exist
scheduled , err = automerge . ScheduleAutoMerge ( db . DefaultContext , user1 , pr , repo_model . MergeStyleMerge , "auto merge test" )
assert . Error ( t , err )
assert . False ( t , scheduled )
// reload pr again
pr = unittest . AssertExistsAndLoadBean ( t , & issues_model . PullRequest { ID : pr . ID } )
assert . False ( t , pr . HasMerged )
assert . Empty ( t , pr . MergedCommitID )
// update commit status to success, then it should be merged automatically
baseGitRepo , err := gitrepo . OpenRepository ( db . DefaultContext , baseRepo )
assert . NoError ( t , err )
sha , err := baseGitRepo . GetRefCommitID ( pr . GetGitRefName ( ) )
assert . NoError ( t , err )
masterCommitID , err := baseGitRepo . GetBranchCommitID ( "master" )
assert . NoError ( t , err )
branches , _ , err := baseGitRepo . GetBranchNames ( 0 , 100 )
assert . NoError ( t , err )
assert . ElementsMatch ( t , [ ] string { "sub-home-md-img-check" , "home-md-img-check" , "pr-to-update" , "branch2" , "DefaultBranch" , "develop" , "feature/1" , "master" } , branches )
baseGitRepo . Close ( )
defer func ( ) {
testResetRepo ( t , baseRepo . RepoPath ( ) , "master" , masterCommitID )
} ( )
err = commitstatus_service . CreateCommitStatus ( db . DefaultContext , baseRepo , user1 , sha , & git_model . CommitStatus {
State : api . CommitStatusSuccess ,
TargetURL : "https://gitea.com" ,
Context : "gitea/actions" ,
} )
assert . NoError ( t , err )
time . Sleep ( 2 * time . Second )
// realod pr again
pr = unittest . AssertExistsAndLoadBean ( t , & issues_model . PullRequest { ID : pr . ID } )
assert . True ( t , pr . HasMerged )
assert . NotEmpty ( t , pr . MergedCommitID )
unittest . AssertNotExistsBean ( t , & pull_model . AutoMerge { PullID : pr . ID } )
} )
}
func TestPullAutoMergeAfterCommitStatusSucceedAndApproval ( t * testing . T ) {
onGiteaRun ( t , func ( t * testing . T , giteaURL * url . URL ) {
// create a pull request
session := loginUser ( t , "user1" )
user1 := unittest . AssertExistsAndLoadBean ( t , & user_model . User { ID : 1 } )
forkedName := "repo1-2"
testRepoFork ( t , session , "user2" , "repo1" , "user1" , forkedName )
defer func ( ) {
testDeleteRepository ( t , session , "user1" , forkedName )
} ( )
testEditFile ( t , session , "user1" , forkedName , "master" , "README.md" , "Hello, World (Edited)\n" )
testPullCreate ( t , session , "user1" , forkedName , false , "master" , "master" , "Indexer notifier test pull" )
baseRepo := unittest . AssertExistsAndLoadBean ( t , & repo_model . Repository { OwnerName : "user2" , Name : "repo1" } )
forkedRepo := unittest . AssertExistsAndLoadBean ( t , & repo_model . Repository { OwnerName : "user1" , Name : forkedName } )
pr := unittest . AssertExistsAndLoadBean ( t , & issues_model . PullRequest {
BaseRepoID : baseRepo . ID ,
BaseBranch : "master" ,
HeadRepoID : forkedRepo . ID ,
HeadBranch : "master" ,
} )
// add protected branch for commit status
csrf := GetCSRF ( t , session , "/user2/repo1/settings/branches" )
// Change master branch to protected
req := NewRequestWithValues ( t , "POST" , "/user2/repo1/settings/branches/edit" , map [ string ] string {
"_csrf" : csrf ,
"rule_name" : "master" ,
"enable_push" : "true" ,
"enable_status_check" : "true" ,
"status_check_contexts" : "gitea/actions" ,
"required_approvals" : "1" ,
} )
session . MakeRequest ( t , req , http . StatusSeeOther )
// first time insert automerge record, return true
scheduled , err := automerge . ScheduleAutoMerge ( db . DefaultContext , user1 , pr , repo_model . MergeStyleMerge , "auto merge test" )
assert . NoError ( t , err )
assert . True ( t , scheduled )
// second time insert automerge record, return false because it does exist
scheduled , err = automerge . ScheduleAutoMerge ( db . DefaultContext , user1 , pr , repo_model . MergeStyleMerge , "auto merge test" )
assert . Error ( t , err )
assert . False ( t , scheduled )
// reload pr again
pr = unittest . AssertExistsAndLoadBean ( t , & issues_model . PullRequest { ID : pr . ID } )
assert . False ( t , pr . HasMerged )
assert . Empty ( t , pr . MergedCommitID )
// update commit status to success, then it should be merged automatically
baseGitRepo , err := gitrepo . OpenRepository ( db . DefaultContext , baseRepo )
assert . NoError ( t , err )
sha , err := baseGitRepo . GetRefCommitID ( pr . GetGitRefName ( ) )
assert . NoError ( t , err )
masterCommitID , err := baseGitRepo . GetBranchCommitID ( "master" )
assert . NoError ( t , err )
baseGitRepo . Close ( )
defer func ( ) {
testResetRepo ( t , baseRepo . RepoPath ( ) , "master" , masterCommitID )
} ( )
err = commitstatus_service . CreateCommitStatus ( db . DefaultContext , baseRepo , user1 , sha , & git_model . CommitStatus {
State : api . CommitStatusSuccess ,
TargetURL : "https://gitea.com" ,
Context : "gitea/actions" ,
} )
assert . NoError ( t , err )
time . Sleep ( 2 * time . Second )
// reload pr again
pr = unittest . AssertExistsAndLoadBean ( t , & issues_model . PullRequest { ID : pr . ID } )
assert . False ( t , pr . HasMerged )
assert . Empty ( t , pr . MergedCommitID )
// approve the PR from non-author
approveSession := loginUser ( t , "user2" )
req = NewRequest ( t , "GET" , fmt . Sprintf ( "/user2/repo1/pulls/%d" , pr . Index ) )
resp := approveSession . MakeRequest ( t , req , http . StatusOK )
htmlDoc := NewHTMLParser ( t , resp . Body )
testSubmitReview ( t , approveSession , htmlDoc . GetCSRF ( ) , "user2" , "repo1" , strconv . Itoa ( int ( pr . Index ) ) , sha , "approve" , http . StatusOK )
time . Sleep ( 2 * time . Second )
// realod pr again
pr = unittest . AssertExistsAndLoadBean ( t , & issues_model . PullRequest { ID : pr . ID } )
assert . True ( t , pr . HasMerged )
assert . NotEmpty ( t , pr . MergedCommitID )
unittest . AssertNotExistsBean ( t , & pull_model . AutoMerge { PullID : pr . ID } )
} )
}