Merge pull request '[FEAT] Configure if protected branch rule should apply to admins' (#2867) from gusted/forgejo-protectedbranch-admins into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/2867 Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
This commit is contained in:
commit
ec091b59af
16 changed files with 167 additions and 26 deletions
|
@ -162,6 +162,7 @@ func ToBranchProtection(ctx context.Context, bp *git_model.ProtectedBranch) *api
|
|||
RequireSignedCommits: bp.RequireSignedCommits,
|
||||
ProtectedFilePatterns: bp.ProtectedFilePatterns,
|
||||
UnprotectedFilePatterns: bp.UnprotectedFilePatterns,
|
||||
ApplyToAdmins: bp.ApplyToAdmins,
|
||||
Created: bp.CreatedUnix.AsTime(),
|
||||
Updated: bp.UpdatedUnix.AsTime(),
|
||||
}
|
||||
|
|
|
@ -219,6 +219,7 @@ type ProtectBranchForm struct {
|
|||
RequireSignedCommits bool
|
||||
ProtectedFilePatterns string
|
||||
UnprotectedFilePatterns string
|
||||
ApplyToAdmins bool
|
||||
}
|
||||
|
||||
// Validate validates the fields
|
||||
|
|
|
@ -104,7 +104,7 @@ func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *acce
|
|||
return ErrIsChecking
|
||||
}
|
||||
|
||||
if err := CheckPullBranchProtections(ctx, pr, false); err != nil {
|
||||
if pb, err := CheckPullBranchProtections(ctx, pr, false); err != nil {
|
||||
if !models.IsErrDisallowedToMerge(err) {
|
||||
log.Error("Error whilst checking pull branch protection for %-v: %v", pr, err)
|
||||
return err
|
||||
|
@ -117,8 +117,9 @@ func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *acce
|
|||
err = nil
|
||||
}
|
||||
|
||||
// * if the doer is admin, they could skip the branch protection check
|
||||
if adminSkipProtectionCheck {
|
||||
// * if the doer is admin, they could skip the branch protection check,
|
||||
// if that's allowed by the protected branch rule.
|
||||
if adminSkipProtectionCheck && !pb.ApplyToAdmins {
|
||||
if isRepoAdmin, errCheckAdmin := access_model.IsUserRepoAdmin(ctx, pr.BaseRepo, doer); errCheckAdmin != nil {
|
||||
log.Error("Unable to check if %-v is a repo admin in %-v: %v", doer, pr.BaseRepo, errCheckAdmin)
|
||||
return errCheckAdmin
|
||||
|
|
|
@ -424,63 +424,64 @@ func IsUserAllowedToMerge(ctx context.Context, pr *issues_model.PullRequest, p a
|
|||
return false, nil
|
||||
}
|
||||
|
||||
// CheckPullBranchProtections checks whether the PR is ready to be merged (reviews and status checks)
|
||||
func CheckPullBranchProtections(ctx context.Context, pr *issues_model.PullRequest, skipProtectedFilesCheck bool) (err error) {
|
||||
// CheckPullBranchProtections checks whether the PR is ready to be merged (reviews and status checks).
|
||||
// Returns the protected branch rule when `ErrDisallowedToMerge` is returned as error.
|
||||
func CheckPullBranchProtections(ctx context.Context, pr *issues_model.PullRequest, skipProtectedFilesCheck bool) (protectedBranchRule *git_model.ProtectedBranch, err error) {
|
||||
if err = pr.LoadBaseRepo(ctx); err != nil {
|
||||
return fmt.Errorf("LoadBaseRepo: %w", err)
|
||||
return nil, fmt.Errorf("LoadBaseRepo: %w", err)
|
||||
}
|
||||
|
||||
pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, pr.BaseBranch)
|
||||
if err != nil {
|
||||
return fmt.Errorf("LoadProtectedBranch: %v", err)
|
||||
return nil, fmt.Errorf("LoadProtectedBranch: %v", err)
|
||||
}
|
||||
if pb == nil {
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
isPass, err := IsPullCommitStatusPass(ctx, pr)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
if !isPass {
|
||||
return models.ErrDisallowedToMerge{
|
||||
return pb, models.ErrDisallowedToMerge{
|
||||
Reason: "Not all required status checks successful",
|
||||
}
|
||||
}
|
||||
|
||||
if !issues_model.HasEnoughApprovals(ctx, pb, pr) {
|
||||
return models.ErrDisallowedToMerge{
|
||||
return pb, models.ErrDisallowedToMerge{
|
||||
Reason: "Does not have enough approvals",
|
||||
}
|
||||
}
|
||||
if issues_model.MergeBlockedByRejectedReview(ctx, pb, pr) {
|
||||
return models.ErrDisallowedToMerge{
|
||||
return pb, models.ErrDisallowedToMerge{
|
||||
Reason: "There are requested changes",
|
||||
}
|
||||
}
|
||||
if issues_model.MergeBlockedByOfficialReviewRequests(ctx, pb, pr) {
|
||||
return models.ErrDisallowedToMerge{
|
||||
return pb, models.ErrDisallowedToMerge{
|
||||
Reason: "There are official review requests",
|
||||
}
|
||||
}
|
||||
|
||||
if issues_model.MergeBlockedByOutdatedBranch(pb, pr) {
|
||||
return models.ErrDisallowedToMerge{
|
||||
return pb, models.ErrDisallowedToMerge{
|
||||
Reason: "The head branch is behind the base branch",
|
||||
}
|
||||
}
|
||||
|
||||
if skipProtectedFilesCheck {
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if pb.MergeBlockedByProtectedFiles(pr.ChangedProtectedFiles) {
|
||||
return models.ErrDisallowedToMerge{
|
||||
return pb, models.ErrDisallowedToMerge{
|
||||
Reason: "Changed protected files",
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// MergedManually mark pr as merged manually
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue