mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2026-07-19 07:58:38 +00:00
fix: apply signed-merge checks by merge style (#11403)
Fixes #6438 When a protected branch requires signed commits and no signing key is available, fast-forward-only merges should still be allowed because they do not create a new commit. This patch applies signing checks by merge behaviour/style instead of one global gate: - pass `mergeStyle` through `CheckPullMergeable(...)` in web/API/automerge paths - require signing for commit-creating styles (`merge`, `rebase`, `rebase-merge`, `squash`) - bypass signing precheck only for `fast-forward-only` - align merge UI options with backend behaviour so signing-dependent styles are unavailable when signing cannot happen - add Go unit tests for merge-style signing requirements - add frontend unit coverage for the no-allowed-merge-styles guard Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11403 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Co-authored-by: abdo <dev@abdo.wtf> Co-committed-by: abdo <dev@abdo.wtf>
This commit is contained in:
parent
4e6a782a89
commit
e16dc2ebfd
8 changed files with 129 additions and 25 deletions
|
|
@ -32,3 +32,35 @@ test('renders escaped branch name', async () => {
|
|||
mergeform = await renderMergeForm('<script class="evil">alert("evil message");</script>');
|
||||
expect(mergeform.get('label[for="delete-branch-after-merge"]').text()).toBe('Delete branch "<script class="evil">alert("evil message");</script>"');
|
||||
});
|
||||
|
||||
test('hides merge controls when no merge style is allowed', () => {
|
||||
window.config.pageData.pullRequestMergeForm = {
|
||||
textDeleteBranch: 'Delete branch',
|
||||
textAutoMergeButtonWhenSucceed: 'when checks succeed',
|
||||
textAutoMergeWhenSucceed: 'Auto merge when checks succeed',
|
||||
textAutoMergeCancelSchedule: 'Cancel schedule',
|
||||
textCancel: 'Cancel',
|
||||
defaultDeleteBranchAfterMerge: false,
|
||||
defaultMergeMessage: '',
|
||||
defaultMergeStyle: 'merge',
|
||||
emptyCommit: false,
|
||||
hasPendingPullRequestMerge: false,
|
||||
hasPendingPullRequestMergeTip: '',
|
||||
isPullBranchDeletable: false,
|
||||
canMergeNow: true,
|
||||
allOverridableChecksOk: true,
|
||||
pullHeadCommitID: 'abc123',
|
||||
mergeStyles: [{
|
||||
name: 'merge',
|
||||
allowed: false,
|
||||
textDoMerge: 'Merge',
|
||||
mergeTitleFieldText: '',
|
||||
mergeMessageFieldText: '',
|
||||
hideAutoMerge: false,
|
||||
}],
|
||||
};
|
||||
|
||||
const mergeform = mount(PullRequestMergeForm);
|
||||
expect(mergeform.find('.merge-button').exists()).toBe(false);
|
||||
expect(mergeform.find('form.form-fetch-action').exists()).toBe(false);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@ export default {
|
|||
},
|
||||
watch: {
|
||||
mergeStyle(val) {
|
||||
this.mergeStyleDetail = this.mergeForm.mergeStyles.find((e) => e.name === val);
|
||||
const mergeStyleDetail = this.mergeForm.mergeStyles.find((e) => e.name === val);
|
||||
if (mergeStyleDetail) this.mergeStyleDetail = mergeStyleDetail;
|
||||
for (const elem of document.querySelectorAll('[data-pull-merge-style]')) {
|
||||
toggleElem(elem, elem.getAttribute('data-pull-merge-style') === val);
|
||||
}
|
||||
|
|
@ -49,6 +50,7 @@ export default {
|
|||
|
||||
let mergeStyle = this.mergeForm.mergeStyles.find((e) => e.allowed && e.name === this.mergeForm.defaultMergeStyle)?.name;
|
||||
if (!mergeStyle) mergeStyle = this.mergeForm.mergeStyles.find((e) => e.allowed)?.name;
|
||||
if (!mergeStyle) return;
|
||||
this.switchMergeStyle(mergeStyle, !this.mergeForm.canMergeNow);
|
||||
},
|
||||
mounted() {
|
||||
|
|
@ -62,6 +64,7 @@ export default {
|
|||
this.showMergeStyleMenu = false;
|
||||
},
|
||||
toggleActionForm(show) {
|
||||
if (show && this.mergeStyleAllowedCount === 0) return;
|
||||
this.showActionForm = show;
|
||||
if (!show) return;
|
||||
this.deleteBranchAfterMerge = this.mergeForm.defaultDeleteBranchAfterMerge;
|
||||
|
|
@ -134,7 +137,7 @@ export default {
|
|||
</div>
|
||||
</form>
|
||||
|
||||
<div v-if="!showActionForm" class="tw-flex">
|
||||
<div v-if="!showActionForm && mergeStyleAllowedCount > 0" class="tw-flex">
|
||||
<!-- the merge button -->
|
||||
<div class="ui buttons merge-button" :class="[mergeForm.emptyCommit ? 'grey' : mergeForm.allOverridableChecksOk ? 'primary' : 'red']" @click="toggleActionForm(true)">
|
||||
<button class="ui button">
|
||||
|
|
@ -146,7 +149,7 @@ export default {
|
|||
</template>
|
||||
</span>
|
||||
</button>
|
||||
<div class="ui dropdown icon button" @click.stop="showMergeStyleMenu = !showMergeStyleMenu" v-if="mergeStyleAllowedCount>1">
|
||||
<div class="ui dropdown icon button" @click.stop="showMergeStyleMenu = !showMergeStyleMenu" v-if="mergeStyleAllowedCount > 1">
|
||||
<svg-icon name="octicon-triangle-down" :size="14"/>
|
||||
<div class="menu" :class="{'show':showMergeStyleMenu}">
|
||||
<template v-for="msd in mergeForm.mergeStyles">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue