79b7089360
- Currently protected branch rules do not apply to admins, however in some cases (like in the case of Forgejo project) you might also want to apply these rules to admins to avoid accidental merges. - Add new option to configure this on a per-rule basis. - Adds integration tests. - Resolves #65
396 lines
17 KiB
Go HTML Template
396 lines
17 KiB
Go HTML Template
{{if and .Issue.PullRequest.HasMerged (not .IsPullBranchDeletable)}}
|
|
{{/* Then the merge box will not be displayed because this page already contains enough information */}}
|
|
{{else}}
|
|
<div class="timeline-item comment merge box">
|
|
<div class="timeline-avatar text {{if .Issue.PullRequest.HasMerged}}purple
|
|
{{- else if .Issue.IsClosed}}grey
|
|
{{- else if .IsPullWorkInProgress}}grey
|
|
{{- else if .IsFilesConflicted}}grey
|
|
{{- else if .IsPullRequestBroken}}red
|
|
{{- else if .IsBlockedByApprovals}}red
|
|
{{- else if .IsBlockedByRejection}}red
|
|
{{- else if .IsBlockedByOfficialReviewRequests}}red
|
|
{{- else if .IsBlockedByOutdatedBranch}}red
|
|
{{- else if .IsBlockedByChangedProtectedFiles}}red
|
|
{{- else if and .EnableStatusCheck (or .RequiredStatusCheckState.IsFailure .RequiredStatusCheckState.IsError)}}red
|
|
{{- else if and .EnableStatusCheck (or (not $.LatestCommitStatus) .RequiredStatusCheckState.IsPending .RequiredStatusCheckState.IsWarning)}}yellow
|
|
{{- else if and .AllowMerge .RequireSigned (not .WillSign)}}red
|
|
{{- else if .Issue.PullRequest.IsChecking}}yellow
|
|
{{- else if .Issue.PullRequest.IsEmpty}}grey
|
|
{{- else if .Issue.PullRequest.CanAutoMerge}}green
|
|
{{- else}}red{{end}}">{{svg "octicon-git-merge" 40}}</div>
|
|
<div class="content">
|
|
<div class="ui attached segment fitted">
|
|
{{template "repo/pulls/status" (dict
|
|
"CommitStatus" .LatestCommitStatus
|
|
"CommitStatuses" .LatestCommitStatuses
|
|
"MissingRequiredChecks" .MissingRequiredChecks
|
|
"ShowHideChecks" true
|
|
"is_context_required" .is_context_required
|
|
)}}
|
|
</div>
|
|
{{$showGeneralMergeForm := false}}
|
|
<div class="ui attached merge-section segment {{if not $.LatestCommitStatus}}no-header{{end}} flex-items-block">
|
|
{{if .Issue.PullRequest.HasMerged}}
|
|
{{if .IsPullBranchDeletable}}
|
|
<div class="item item-section text tw-flex-1">
|
|
<div class="item-section-left">
|
|
<h3 class="gt-mb-3">
|
|
{{ctx.Locale.Tr "repo.pulls.merged_success"}}
|
|
</h3>
|
|
<div class="merge-section-info">
|
|
{{ctx.Locale.Tr "repo.pulls.merged_info_text" (HTMLFormat "<code>%s</code>" .HeadTarget)}}
|
|
</div>
|
|
</div>
|
|
<div class="item-section-right">
|
|
<button class="delete-button ui button" data-url="{{.DeleteBranchLink}}">{{ctx.Locale.Tr "repo.branch.delete_html"}}</button>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
{{else if .Issue.IsClosed}}
|
|
<div class="item item-section text tw-flex-1">
|
|
<div class="item-section-left">
|
|
<h3 class="gt-mb-3">{{ctx.Locale.Tr "repo.pulls.closed"}}</h3>
|
|
<div class="merge-section-info">
|
|
{{if .IsPullRequestBroken}}
|
|
{{ctx.Locale.Tr "repo.pulls.cant_reopen_deleted_branch"}}
|
|
{{else}}
|
|
{{ctx.Locale.Tr "repo.pulls.reopen_to_merge"}}
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
{{if and .IsPullBranchDeletable (not .IsPullRequestBroken)}}
|
|
<div class="item-section-right">
|
|
<button class="delete-button ui button" data-url="{{.DeleteBranchLink}}">{{ctx.Locale.Tr "repo.branch.delete_html"}}</button>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
{{else if .IsPullFilesConflicted}}
|
|
<div class="item">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.Tr "repo.pulls.files_conflicted"}}
|
|
</div>
|
|
<ul>
|
|
{{range .ConflictedFiles}}
|
|
<li>{{.}}</li>
|
|
{{end}}
|
|
</ul>
|
|
{{else if .IsPullRequestBroken}}
|
|
<div class="item">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.Tr "repo.pulls.data_broken"}}
|
|
</div>
|
|
{{else if .IsPullWorkInProgress}}
|
|
<div class="item toggle-wip" data-title="{{.Issue.Title}}" data-wip-prefix="{{.WorkInProgressPrefix}}" data-update-url="{{.Issue.Link}}/title">
|
|
<div class="item-section-left flex-text-inline tw-flex-1">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.Tr "repo.pulls.cannot_merge_work_in_progress"}}
|
|
</div>
|
|
{{if or .HasIssuesOrPullsWritePermission .IsIssuePoster}}
|
|
<button class="ui compact button">
|
|
{{ctx.Locale.Tr "repo.pulls.remove_prefix" .WorkInProgressPrefix}}
|
|
</button>
|
|
{{end}}
|
|
</div>
|
|
{{template "repo/issue/view_content/update_branch_by_merge" $}}
|
|
{{else if .Issue.PullRequest.IsChecking}}
|
|
<div class="item">
|
|
{{svg "octicon-sync"}}
|
|
{{ctx.Locale.Tr "repo.pulls.is_checking"}}
|
|
</div>
|
|
{{else if .Issue.PullRequest.IsAncestor}}
|
|
<div class="item">
|
|
{{svg "octicon-alert"}}
|
|
{{ctx.Locale.Tr "repo.pulls.is_ancestor"}}
|
|
</div>
|
|
{{else if or .Issue.PullRequest.CanAutoMerge .Issue.PullRequest.IsEmpty}}
|
|
{{if .IsBlockedByApprovals}}
|
|
<div class="item">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.Tr "repo.pulls.blocked_by_approvals" .GrantedApprovals .ProtectedBranch.RequiredApprovals}}
|
|
</div>
|
|
{{else if .IsBlockedByRejection}}
|
|
<div class="item">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.Tr "repo.pulls.blocked_by_rejection"}}
|
|
</div>
|
|
{{else if .IsBlockedByOfficialReviewRequests}}
|
|
<div class="item">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.Tr "repo.pulls.blocked_by_official_review_requests"}}
|
|
</div>
|
|
{{else if .IsBlockedByOutdatedBranch}}
|
|
<div class="item">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.Tr "repo.pulls.blocked_by_outdated_branch"}}
|
|
</div>
|
|
{{else if .IsBlockedByChangedProtectedFiles}}
|
|
<div class="item">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.TrN $.ChangedProtectedFilesNum "repo.pulls.blocked_by_changed_protected_files_1" "repo.pulls.blocked_by_changed_protected_files_n"}}
|
|
</div>
|
|
<ul>
|
|
{{range .ChangedProtectedFiles}}
|
|
<li>{{.}}</li>
|
|
{{end}}
|
|
</ul>
|
|
{{else if and .EnableStatusCheck (or .RequiredStatusCheckState.IsError .RequiredStatusCheckState.IsFailure)}}
|
|
<div class="item">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.Tr "repo.pulls.required_status_check_failed"}}
|
|
</div>
|
|
{{else if and .EnableStatusCheck (not .RequiredStatusCheckState.IsSuccess)}}
|
|
<div class="item">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.Tr "repo.pulls.required_status_check_missing"}}
|
|
</div>
|
|
{{else if and .AllowMerge .RequireSigned (not .WillSign)}}
|
|
<div class="item">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.Tr "repo.pulls.require_signed_wont_sign"}}
|
|
</div>
|
|
<div class="item">
|
|
{{svg "octicon-unlock"}}
|
|
{{ctx.Locale.Tr (printf "repo.signing.wont_sign.%s" .WontSignReason)}}
|
|
</div>
|
|
{{end}}
|
|
|
|
{{$notAllOverridableChecksOk := or .IsBlockedByApprovals .IsBlockedByRejection .IsBlockedByOfficialReviewRequests .IsBlockedByOutdatedBranch .IsBlockedByChangedProtectedFiles (and .EnableStatusCheck (not .RequiredStatusCheckState.IsSuccess))}}
|
|
|
|
{{/* admin can merge without checks, writer can merge when checks succeed */}}
|
|
{{$canMergeNow := and (or (and $.IsRepoAdmin (not .ProtectedBranch.ApplyToAdmins)) (not $notAllOverridableChecksOk)) (or (not .AllowMerge) (not .RequireSigned) .WillSign)}}
|
|
{{/* admin and writer both can make an auto merge schedule */}}
|
|
|
|
{{if $canMergeNow}}
|
|
{{if $notAllOverridableChecksOk}}
|
|
<div class="item">
|
|
{{svg "octicon-dot-fill"}}
|
|
{{ctx.Locale.Tr "repo.pulls.required_status_check_administrator"}}
|
|
</div>
|
|
{{else}}
|
|
<div class="item">
|
|
{{svg "octicon-check"}}
|
|
{{ctx.Locale.Tr "repo.pulls.can_auto_merge_desc"}}
|
|
</div>
|
|
{{end}}
|
|
{{if .WillSign}}
|
|
<div class="item">
|
|
{{svg "octicon-lock" 16 "text green"}}
|
|
{{ctx.Locale.Tr "repo.signing.will_sign" .SigningKey}}
|
|
</div>
|
|
{{else if .IsSigned}}
|
|
<div class="item">
|
|
{{svg "octicon-unlock"}}
|
|
{{ctx.Locale.Tr (printf "repo.signing.wont_sign.%s" .WontSignReason)}}
|
|
</div>
|
|
{{end}}
|
|
{{end}}
|
|
{{template "repo/issue/view_content/update_branch_by_merge" $}}
|
|
{{if .Issue.PullRequest.IsEmpty}}
|
|
<div class="divider"></div>
|
|
|
|
<div class="item">
|
|
{{svg "octicon-alert"}}
|
|
{{ctx.Locale.Tr "repo.pulls.is_empty"}}
|
|
</div>
|
|
{{end}}
|
|
|
|
{{if .AllowMerge}} {{/* user is allowed to merge */}}
|
|
{{$prUnit := .Repository.MustGetUnit $.Context $.UnitTypePullRequests}}
|
|
{{$approvers := (.Issue.PullRequest.GetApprovers ctx)}}
|
|
{{if or $prUnit.PullRequestsConfig.AllowMerge $prUnit.PullRequestsConfig.AllowRebase $prUnit.PullRequestsConfig.AllowRebaseMerge $prUnit.PullRequestsConfig.AllowSquash $prUnit.PullRequestsConfig.AllowFastForwardOnly}}
|
|
{{$hasPendingPullRequestMergeTip := ""}}
|
|
{{if .HasPendingPullRequestMerge}}
|
|
{{$createdPRMergeStr := TimeSinceUnix .PendingPullRequestMerge.CreatedUnix ctx.Locale}}
|
|
{{$hasPendingPullRequestMergeTip = ctx.Locale.Tr "repo.pulls.auto_merge_has_pending_schedule" .PendingPullRequestMerge.Doer.Name $createdPRMergeStr}}
|
|
{{end}}
|
|
<div class="divider"></div>
|
|
<script type="module">
|
|
const issueUrl = window.location.origin + {{$.Issue.Link}};
|
|
const defaultMergeTitle = {{.DefaultMergeMessage}};
|
|
const defaultSquashMergeTitle = {{.DefaultSquashMergeMessage}};
|
|
const defaultMergeMessage = {{if .DefaultMergeBody}}{{.DefaultMergeBody}}{{else}}`Reviewed-on: ${issueUrl}\n` + {{$approvers}}{{end}};
|
|
const defaultSquashMergeMessage = {{if .DefaultSquashMergeBody}}{{.DefaultSquashMergeBody}}{{else}}`Reviewed-on: ${issueUrl}\n` + {{$approvers}}{{end}};
|
|
const mergeForm = {
|
|
'baseLink': {{.Link}},
|
|
'textCancel': {{ctx.Locale.Tr "cancel"}},
|
|
'textDeleteBranch': {{ctx.Locale.Tr "repo.branch.delete" .HeadTarget}},
|
|
'textAutoMergeButtonWhenSucceed': {{ctx.Locale.Tr "repo.pulls.auto_merge_button_when_succeed"}},
|
|
'textAutoMergeWhenSucceed': {{ctx.Locale.Tr "repo.pulls.auto_merge_when_succeed"}},
|
|
'textAutoMergeCancelSchedule': {{ctx.Locale.Tr "repo.pulls.auto_merge_cancel_schedule"}},
|
|
'textClearMergeMessage': {{ctx.Locale.Tr "repo.pulls.clear_merge_message"}},
|
|
'textClearMergeMessageHint': {{ctx.Locale.Tr "repo.pulls.clear_merge_message_hint"}},
|
|
'textMergeCommitId': {{ctx.Locale.Tr "repo.pulls.merge_commit_id"}},
|
|
|
|
'canMergeNow': {{$canMergeNow}},
|
|
'allOverridableChecksOk': {{not $notAllOverridableChecksOk}},
|
|
'emptyCommit': {{.Issue.PullRequest.IsEmpty}},
|
|
'pullHeadCommitID': {{.PullHeadCommitID}},
|
|
'isPullBranchDeletable': {{.IsPullBranchDeletable}},
|
|
'defaultMergeStyle': {{.MergeStyle}},
|
|
'defaultDeleteBranchAfterMerge': {{$prUnit.PullRequestsConfig.DefaultDeleteBranchAfterMerge}},
|
|
'mergeMessageFieldPlaceHolder': {{ctx.Locale.Tr "repo.editor.commit_message_desc"}},
|
|
'defaultMergeMessage': defaultMergeMessage,
|
|
|
|
'hasPendingPullRequestMerge': {{.HasPendingPullRequestMerge}},
|
|
'hasPendingPullRequestMergeTip': {{$hasPendingPullRequestMergeTip}},
|
|
};
|
|
|
|
const generalHideAutoMerge = mergeForm.canMergeNow && mergeForm.allOverridableChecksOk; // if this pr can be merged now, then hide the auto merge
|
|
mergeForm['mergeStyles'] = [
|
|
{
|
|
'name': 'merge',
|
|
'allowed': {{$prUnit.PullRequestsConfig.AllowMerge}},
|
|
'textDoMerge': {{ctx.Locale.Tr "repo.pulls.merge_pull_request"}},
|
|
'mergeTitleFieldText': defaultMergeTitle,
|
|
'mergeMessageFieldText': defaultMergeMessage,
|
|
'hideAutoMerge': generalHideAutoMerge,
|
|
},
|
|
{
|
|
'name': 'rebase',
|
|
'allowed': {{$prUnit.PullRequestsConfig.AllowRebase}},
|
|
'textDoMerge': {{ctx.Locale.Tr "repo.pulls.rebase_merge_pull_request"}},
|
|
'hideMergeMessageTexts': true,
|
|
'hideAutoMerge': generalHideAutoMerge,
|
|
},
|
|
{
|
|
'name': 'rebase-merge',
|
|
'allowed': {{$prUnit.PullRequestsConfig.AllowRebaseMerge}},
|
|
'textDoMerge': {{ctx.Locale.Tr "repo.pulls.rebase_merge_commit_pull_request"}},
|
|
'mergeTitleFieldText': defaultMergeTitle,
|
|
'mergeMessageFieldText': defaultMergeMessage,
|
|
'hideAutoMerge': generalHideAutoMerge,
|
|
},
|
|
{
|
|
'name': 'squash',
|
|
'allowed': {{$prUnit.PullRequestsConfig.AllowSquash}},
|
|
'textDoMerge': {{ctx.Locale.Tr "repo.pulls.squash_merge_pull_request"}},
|
|
'mergeTitleFieldText': defaultSquashMergeTitle,
|
|
'mergeMessageFieldText': {{.GetCommitMessages}} + defaultSquashMergeMessage,
|
|
'hideAutoMerge': generalHideAutoMerge,
|
|
},
|
|
{
|
|
'name': 'fast-forward-only',
|
|
'allowed': {{and $prUnit.PullRequestsConfig.AllowFastForwardOnly (eq .Issue.PullRequest.CommitsBehind 0)}},
|
|
'textDoMerge': {{ctx.Locale.Tr "repo.pulls.fast_forward_only_merge_pull_request"}},
|
|
'hideMergeMessageTexts': true,
|
|
'hideAutoMerge': generalHideAutoMerge,
|
|
},
|
|
{
|
|
'name': 'manually-merged',
|
|
'allowed': {{$prUnit.PullRequestsConfig.AllowManualMerge}},
|
|
'textDoMerge': {{ctx.Locale.Tr "repo.pulls.merge_manually"}},
|
|
'hideMergeMessageTexts': true,
|
|
'hideAutoMerge': true,
|
|
}
|
|
];
|
|
window.config.pageData.pullRequestMergeForm = mergeForm;
|
|
</script>
|
|
|
|
{{$showGeneralMergeForm = true}}
|
|
<div id="pull-request-merge-form"></div>
|
|
{{else}}
|
|
{{/* no merge style was set in repo setting: not or ($prUnit.PullRequestsConfig.AllowMerge ...) */}}
|
|
<div class="divider"></div>
|
|
<div class="item text red">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.Tr "repo.pulls.no_merge_desc"}}
|
|
</div>
|
|
<div class="item">
|
|
{{svg "octicon-info"}}
|
|
{{ctx.Locale.Tr "repo.pulls.no_merge_helper"}}
|
|
</div>
|
|
{{end}} {{/* end if the repo was set to use any merge style */}}
|
|
{{else}}
|
|
{{/* user is not allowed to merge */}}
|
|
<div class="divider"></div>
|
|
<div class="item">
|
|
{{svg "octicon-info"}}
|
|
{{ctx.Locale.Tr "repo.pulls.no_merge_access"}}
|
|
</div>
|
|
{{end}} {{/* end if user is allowed to merge or not */}}
|
|
{{else}}
|
|
{{/* Merge conflict without specific file. Suggest manual merge, only if all reviews and status checks OK. */}}
|
|
{{if .IsBlockedByApprovals}}
|
|
<div class="item text red">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.Tr "repo.pulls.blocked_by_approvals" .GrantedApprovals .ProtectedBranch.RequiredApprovals}}
|
|
</div>
|
|
{{else if .IsBlockedByRejection}}
|
|
<div class="item text red">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.Tr "repo.pulls.blocked_by_rejection"}}
|
|
</div>
|
|
{{else if .IsBlockedByOfficialReviewRequests}}
|
|
<div class="item text red">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.Tr "repo.pulls.blocked_by_official_review_requests"}}
|
|
</div>
|
|
{{else if .IsBlockedByOutdatedBranch}}
|
|
<div class="item text red">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.Tr "repo.pulls.blocked_by_outdated_branch"}}
|
|
</div>
|
|
{{else if .IsBlockedByChangedProtectedFiles}}
|
|
<div class="item text red">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.TrN $.ChangedProtectedFilesNum "repo.pulls.blocked_by_changed_protected_files_1" "repo.pulls.blocked_by_changed_protected_files_n"}}
|
|
</div>
|
|
<ul>
|
|
{{range .ChangedProtectedFiles}}
|
|
<li>{{.}}</li>
|
|
{{end}}
|
|
</ul>
|
|
{{else if and .EnableStatusCheck (not .RequiredStatusCheckState.IsSuccess)}}
|
|
<div class="item text red">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.Tr "repo.pulls.required_status_check_failed"}}
|
|
</div>
|
|
{{else if and .RequireSigned (not .WillSign)}}
|
|
<div class="item text red">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.Tr "repo.pulls.require_signed_wont_sign"}}
|
|
</div>
|
|
{{else}}
|
|
<div class="item text red">
|
|
{{svg "octicon-x"}}
|
|
{{ctx.Locale.Tr "repo.pulls.cannot_auto_merge_desc"}}
|
|
</div>
|
|
<div class="item">
|
|
{{svg "octicon-info"}}
|
|
{{ctx.Locale.Tr "repo.pulls.cannot_auto_merge_helper"}}
|
|
</div>
|
|
{{end}}
|
|
{{end}}{{/* end if: pull request status */}}
|
|
|
|
{{/*
|
|
Manually Merged is not a well-known feature, it is used to mark a non-mergeable PR (already merged, conflicted) as merged
|
|
To test it:
|
|
* Enable "Manually Merged" feature in the Repository Settings
|
|
* Create a pull request, either:
|
|
* - Merge the pull request branch locally and push the merged commit to Gitea
|
|
* - Make some conflicts between the base branch and the pull request branch
|
|
* Then the Manually Merged form will be shown in the merge form
|
|
*/}}
|
|
{{if and $.StillCanManualMerge (not $showGeneralMergeForm)}}
|
|
<div class="divider"></div>
|
|
<div class="ui form">
|
|
<form action="{{.Link}}/merge" method="post" class="form-fetch-action">
|
|
{{.CsrfTokenHtml}}
|
|
<div class="field">
|
|
<input type="text" name="merge_commit_id" placeholder="{{ctx.Locale.Tr "repo.pulls.merge_commit_id"}}">
|
|
</div>
|
|
<button class="ui red button" type="submit" name="do" value="manually-merged">
|
|
{{ctx.Locale.Tr "repo.pulls.merge_manually"}}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
{{end}}
|
|
|
|
{{if and .Issue.PullRequest.HeadRepo (not .Issue.PullRequest.HasMerged) (not .Issue.IsClosed)}}
|
|
{{template "repo/issue/view_content/pull_merge_instruction" dict "PullRequest" .Issue.PullRequest "ShowMergeInstructions" .ShowMergeInstructions}}
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{end}}
|