Skip to content

Commit

Permalink
feat(gitlab): support for generating the merge request template
Browse files Browse the repository at this point in the history
  • Loading branch information
Arylo committed Nov 26, 2024
1 parent 39f089b commit 40ea763
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 2 deletions.
5 changes: 4 additions & 1 deletion src/monkey/gitlab-enhance/banner.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
"name:zh": "强化自托管 Gitlab 能力",
"include": [
"/^https:\\/\\/(git(lab)?|code)\\.[^\/]+\\/.*\\/-\\/settings\\/ci_cd$/",
"/^https:\\/\\/(git(lab)?|code)\\.[^\/]+\\/.*\\/-\\/merge_requests\\/new\\b/",
"/^https:\\/\\/(git(lab)?|code)\\.[^\/]+\\/.*\\/-\\/merge_requests\\/\\d+\/edit\\b/",
"/^https:\\/\\/(git(lab)?|code)\\.[^\/]+\\/dashboard\\/merge_requests\\b/"
],
"run-at": "document-end",
"grant": [
"GM_addStyle"
"GM_addStyle",
"GM_setClipboard"
]
}
1 change: 1 addition & 0 deletions src/monkey/gitlab-enhance/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import './settings/ci_cd'
import './dashboard/merge_requests'
import './merge_requests/new'

export {}
3 changes: 3 additions & 0 deletions src/monkey/gitlab-enhance/merge_requests/new.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.gl-display-flex:has([for=merge_request_description]) {
align-items: baseline;
}
107 changes: 107 additions & 0 deletions src/monkey/gitlab-enhance/merge_requests/new.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import * as templateUtils from './templateUtils'
import cssContent from './new.css'

enum BRANCH_TYPE {
FEATURE,
BUGFIX,
HOTFIX,
TASKS,
OTHERS,
}

const getBranchType = () => {
const fromBranchName = $('.align-self-center code:not([data-branch-name])').text()
const prefixBranchName = fromBranchName.split('/')[0].toLowerCase()
switch (prefixBranchName) {
case 'feature':
case 'feat':
return BRANCH_TYPE.FEATURE
case 'fix':
case 'bugfix':
return BRANCH_TYPE.BUGFIX
case 'hotfix':
return BRANCH_TYPE.HOTFIX
case 'devops':
case 'chore':
case 'test':
case 'doc':
case 'docs':
return BRANCH_TYPE.TASKS
default:
return BRANCH_TYPE.OTHERS
}
}

const generateTemplate = () => {
const branchType = getBranchType()
templateUtils.initTemplate()

templateUtils.h2('Type')
.taskItem('Feature (Story/Refactor)', { selected: branchType === BRANCH_TYPE.FEATURE })
.taskItem(`Bugfix`, { selected: branchType === BRANCH_TYPE.BUGFIX })
.taskItem(`Hotfix (Production Issues)`, { selected: branchType === BRANCH_TYPE.HOTFIX })
.taskItem(`Tasks (DevOps / Unit Test / Document Update)`, { selected: branchType === BRANCH_TYPE.TASKS })
.taskItem(`Others`, { selected: branchType === BRANCH_TYPE.OTHERS })
.end()

templateUtils.h2('Description')
if (branchType !== BRANCH_TYPE.FEATURE) {
templateUtils.h3('Why (Why does this happen?)')
.listItem()
.end()

templateUtils.h3('How (How can we avoid or solve it?)')
.listItem()
.end()
}

templateUtils.h3('What (What did you do this time?)')
.listItem()
.end()

if (branchType !== BRANCH_TYPE.TASKS) {
templateUtils.h3('Results (Screenshot, etc)')
templateUtils.h4('Before modification')
templateUtils.h4('After modification')

templateUtils.h2('Affected Zone')
.listItem('Affected Module(s):')
.listItem('Affected URL(s):')
.end()
}

templateUtils.h2('External resources (Mention, Resolves, or Closes)')

return templateUtils.getTemplate()
}

const appendButtons = () => {
const classnames = 'gl-font-sm! gl-ml-3 gl-button btn btn-default btn-sm'
const text = 'Copy Template'
const ele = $(`<a class="${classnames}">${text}</a>`)
const templateContent = generateTemplate()
const hint = $('<span class="gl-font-sm! gl-ml-3 gl-text-secondary"></span>')
let setTimeoutId: NodeJS.Timeout | undefined
ele.on('click', async () => {
hint.remove()
setTimeoutId && clearTimeout(setTimeoutId)
hint.text('Copying...')
ele.after(hint)
await GM_setClipboard(templateContent, 'text', () => {
hint.text('Copied!')
setTimeoutId = setTimeout(() => hint.remove(), 3000)
})
})

$('.gl-display-flex:has([for=merge_request_description])').append(ele)
}

if (
location.pathname.endsWith('/-/merge_requests/new') ||
/\/-\/merge_requests\/\d+\/edit$/.test(location.pathname)
) {
setTimeout(() => {
GM_addStyle(cssContent)
appendButtons()
}, 1000)
}
33 changes: 33 additions & 0 deletions src/monkey/gitlab-enhance/merge_requests/templateUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const INDENT_SPACE_LENGTH = 2

let templateContent = ''
const indent = (level: number) => Array(level * INDENT_SPACE_LENGTH).fill(' ').join('')
const enter = () => '\n'

export const emptyLine = () => (templateContent += enter())

const contentUtils = {
listItem: (text = '', { level = 1 } = {}) => {
templateContent += `${indent(level - 1)}- ${text}${enter()}`
return {
...contentUtils,
end: emptyLine,
}
},
taskItem: (text = '', { selected = false, level = 1 } = {}) => {
return contentUtils.listItem(`[${selected ? 'x' : ' '}] ${text}`, { level })
},
}

const header = (level: number) => (text: string) => {
templateContent += `${Array(level).fill('#').join('')} ${text}${enter()}${enter()}`
return contentUtils
}
export const h2 = header(2)
export const h3 = header(3)
export const h4 = header(4)

export const listItem = contentUtils.listItem
export const taskItem = contentUtils.taskItem
export const initTemplate = () => (templateContent = '')
export const getTemplate = () => templateContent
2 changes: 1 addition & 1 deletion src/monkey/gitlab-enhance/settings/ci_cd.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import css from './style.css';
import css from './ci_cd.css';

if (location.pathname.endsWith('/-/settings/ci_cd')) {
setTimeout(() => GM_addStyle(css), 25)
Expand Down
2 changes: 2 additions & 0 deletions types/monkey.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
declare function GM_addStyle(content: string): any;
declare function GM_setValue(key: string, value: T): undefined;
declare function GM_getValue<T>(key: string, defaultValue: T): T
declare function GM_setClipboard(content: string, type: 'text' | 'html', callback: () => void): Promise<never>;

declare interface Window {
GM: {
Expand All @@ -9,4 +10,5 @@ declare interface Window {
GM_addStyle: GM_addStyle,
GM_setValue: GM_setValue,
GM_getValue: GM_getValue,
GM_setClipboard: GM_setClipboard,
}

0 comments on commit 40ea763

Please sign in to comment.