tests(integration): add TestPullMergeBranchProtect

Verify variations of branch protection that are in play when merging a
pull request as:

* instance admin
* repository admin / owner
* user with write permissions on the repository

In all cases the result is expected to be the same when merging
the pull request via:

* API
* web

Although the implementations are different.

(cherry picked from commit 793421bf59)

Conflicts:
	tests/integration/pull_merge_test.go
	trivial context conflict
This commit is contained in:
Earl Warren 2024-06-01 10:58:46 +02:00
parent 6827a4a669
commit bad8e72bcd
No known key found for this signature in database
GPG key ID: 0579CB2928A78A00
7 changed files with 174 additions and 0 deletions

View file

@ -0,0 +1,7 @@
#!/usr/bin/env bash
ORI_DIR=`pwd`
SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
cd "$ORI_DIR"
for i in `ls "$SHELL_FOLDER/post-receive.d"`; do
sh "$SHELL_FOLDER/post-receive.d/$i"
done

View file

@ -0,0 +1,2 @@
#!/usr/bin/env bash
"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" post-receive

View file

@ -0,0 +1,7 @@
#!/usr/bin/env bash
ORI_DIR=`pwd`
SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
cd "$ORI_DIR"
for i in `ls "$SHELL_FOLDER/pre-receive.d"`; do
sh "$SHELL_FOLDER/pre-receive.d/$i"
done

View file

@ -0,0 +1,2 @@
#!/usr/bin/env bash
"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" pre-receive

View file

@ -0,0 +1,7 @@
#!/usr/bin/env bash
ORI_DIR=`pwd`
SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
cd "$ORI_DIR"
for i in `ls "$SHELL_FOLDER/update.d"`; do
sh "$SHELL_FOLDER/update.d/$i" $1 $2 $3
done

View file

@ -0,0 +1,2 @@
#!/usr/bin/env bash
"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" update $1 $2 $3

View file

@ -32,6 +32,7 @@ import (
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/modules/translation" "code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/pull" "code.gitea.io/gitea/services/pull"
files_service "code.gitea.io/gitea/services/repository/files" files_service "code.gitea.io/gitea/services/repository/files"
webhook_service "code.gitea.io/gitea/services/webhook" webhook_service "code.gitea.io/gitea/services/webhook"
@ -674,3 +675,149 @@ func TestPullMergeIndexerNotifier(t *testing.T) {
} }
}) })
} }
func TestPullMergeBranchProtect(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) {
admin := "user1"
owner := "user5"
notOwner := "user4"
repo := "repo4"
dstPath := t.TempDir()
u.Path = fmt.Sprintf("%s/%s.git", owner, repo)
u.User = url.UserPassword(owner, userPassword)
t.Run("Clone", doGitClone(dstPath, u))
for _, testCase := range []struct {
name string
doer string
expectedCode map[string]int
filename string
protectBranch parameterProtectBranch
}{
{
name: "SuccessAdminNotEnoughMergeRequiredApprovals",
doer: admin,
expectedCode: map[string]int{"api": http.StatusOK, "web": http.StatusOK},
filename: "branch-data-file-",
protectBranch: parameterProtectBranch{
"required_approvals": "1",
"apply_to_admins": "true",
},
},
{
name: "FailOwnerProtectedFile",
doer: owner,
expectedCode: map[string]int{"api": http.StatusMethodNotAllowed, "web": http.StatusBadRequest},
filename: "protected-file-",
protectBranch: parameterProtectBranch{
"protected_file_patterns": "protected-file-*",
"apply_to_admins": "true",
},
},
{
name: "OwnerProtectedFile",
doer: owner,
expectedCode: map[string]int{"api": http.StatusOK, "web": http.StatusOK},
filename: "protected-file-",
protectBranch: parameterProtectBranch{
"protected_file_patterns": "protected-file-*",
"apply_to_admins": "false",
},
},
{
name: "FailNotOwnerProtectedFile",
doer: notOwner,
expectedCode: map[string]int{"api": http.StatusMethodNotAllowed, "web": http.StatusBadRequest},
filename: "protected-file-",
protectBranch: parameterProtectBranch{
"protected_file_patterns": "protected-file-*",
},
},
{
name: "FailOwnerNotEnoughMergeRequiredApprovals",
doer: owner,
expectedCode: map[string]int{"api": http.StatusMethodNotAllowed, "web": http.StatusBadRequest},
filename: "branch-data-file-",
protectBranch: parameterProtectBranch{
"required_approvals": "1",
"apply_to_admins": "true",
},
},
{
name: "SuccessOwnerNotEnoughMergeRequiredApprovals",
doer: owner,
expectedCode: map[string]int{"api": http.StatusOK, "web": http.StatusOK},
filename: "branch-data-file-",
protectBranch: parameterProtectBranch{
"required_approvals": "1",
"apply_to_admins": "false",
},
},
{
name: "FailNotOwnerNotEnoughMergeRequiredApprovals",
doer: notOwner,
expectedCode: map[string]int{"api": http.StatusMethodNotAllowed, "web": http.StatusBadRequest},
filename: "branch-data-file-",
protectBranch: parameterProtectBranch{
"required_approvals": "1",
"apply_to_admins": "false",
},
},
{
name: "SuccessNotOwner",
doer: notOwner,
expectedCode: map[string]int{"api": http.StatusOK, "web": http.StatusOK},
filename: "branch-data-file-",
protectBranch: parameterProtectBranch{
"required_approvals": "0",
},
},
} {
mergeWith := func(t *testing.T, ctx APITestContext, apiOrWeb string, expectedCode int, pr int64) {
switch apiOrWeb {
case "api":
ctx.ExpectedCode = expectedCode
doAPIMergePullRequestForm(t, ctx, owner, repo, pr,
&forms.MergePullRequestForm{
MergeMessageField: "doAPIMergePullRequest Merge",
Do: string(repo_model.MergeStyleMerge),
ForceMerge: true,
})
ctx.ExpectedCode = 0
case "web":
testPullMergeForm(t, ctx.Session, expectedCode, owner, repo, fmt.Sprintf("%d", pr), optionsPullMerge{
"do": string(repo_model.MergeStyleMerge),
"force_merge": "true",
})
default:
panic(apiOrWeb)
}
}
for _, withAPIOrWeb := range []string{"api", "web"} {
t.Run(testCase.name+" "+withAPIOrWeb, func(t *testing.T) {
branch := testCase.name + "-" + withAPIOrWeb
unprotected := branch + "-unprotected"
doGitCheckoutBranch(dstPath, "master")(t)
doGitCreateBranch(dstPath, branch)(t)
doGitPushTestRepository(dstPath, "origin", branch)(t)
ctx := NewAPITestContext(t, owner, repo, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
doProtectBranch(ctx, branch, testCase.protectBranch)(t)
ctx = NewAPITestContext(t, testCase.doer, "not used", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
ctx.Username = owner
ctx.Reponame = repo
_, err := generateCommitWithNewData(littleSize, dstPath, "user2@example.com", "User Two", testCase.filename)
assert.NoError(t, err)
doGitPushTestRepository(dstPath, "origin", branch+":"+unprotected)(t)
pr, err := doAPICreatePullRequest(ctx, owner, repo, branch, unprotected)(t)
assert.NoError(t, err)
mergeWith(t, ctx, withAPIOrWeb, testCase.expectedCode[withAPIOrWeb], pr.Index)
})
}
}
})
}