出于协作的要求, 需要在把gitlab的push event勾到rocket chat上面, 通知协作的其他人.
BUT rocket chat提供的脚本没有具体的文件diff, so, 只好修改一下, 以下是小改一下的脚本,
1 /* eslint no-console:0, max-len:0 */ 2 // see https://gitlab.com/help/web_hooks/web_hooks for full json posted by GitLab 3 const MENTION_ALL_ALLOWED = false; // <- check that bot permission allow has mention-all before passing this to true. 4 const NOTIF_COLOR = '#6498CC'; 5 const refParser = (ref) => ref.replace(/^refs\/(?:tags|heads)\/(.+)$/, '$1'); 6 const displayName = (name) => (name && name.toLowerCase().replace(/\s+/g, '.')); 7 const atName = (user) => (user && user.name ? '@' + displayName(user.name) : ''); 8 const makeAttachment = (author, text) => { 9 return { 10 author_name: author ? displayName(author.name) : '', 11 author_icon: author ? author.avatar_url : '', 12 text, 13 color: NOTIF_COLOR 14 }; 15 }; 16 const pushUniq = (array, val) => ~array.indexOf(val) || array.push(val); // eslint-disable-line 17 18 class Script { // eslint-disable-line 19 process_incoming_request({ request }) { 20 try { 21 let result = null; 22 const channel = request.url.query.channel; 23 const event = request.headers['x-gitlab-event']; 24 switch (event) { 25 case 'Push Hook': 26 result = this.pushEvent(request.content); 27 break; 28 case 'Merge Request Hook': 29 result = this.mergeRequestEvent(request.content); 30 break; 31 case 'Note Hook': 32 result = this.commentEvent(request.content); 33 break; 34 case 'Issue Hook': 35 result = this.issueEvent(request.content); 36 break; 37 case 'Tag Push Hook': 38 result = this.tagEvent(request.content); 39 break; 40 case 'Pipeline Hook': 41 result = this.pipelineEvent(request.content); 42 break; 43 case 'Build Hook': 44 result = this.buildEvent(request.content); 45 break; 46 default: 47 result = this.unknownEvent(request, event); 48 break; 49 } 50 if (result && result.content && channel) { 51 result.content.channel = '#' + channel; 52 } 53 return result; 54 } catch (e) { 55 console.log('gitlabevent error', e); 56 return this.createErrorChatMessage(e); 57 } 58 } 59 60 createErrorChatMessage(error) { 61 return { 62 content: { 63 username: 'Rocket.Cat ErrorHandler', 64 text: 'Error occured while parsing an incoming webhook request. Details attached.', 65 icon_url: '', 66 attachments: [ 67 { 68 text: `Error: '${error}', \n Message: '${error.message}', \n Stack: '${error.stack}'`, 69 color: NOTIF_COLOR 70 } 71 ] 72 } 73 }; 74 } 75 76 unknownEvent(data, event) { 77 return { 78 content: { 79 username: data.user ? data.user.name : (data.user_name || 'Unknown user'), 80 text: `Unknown event '${event}' occured. Data attached.`, 81 icon_url: data.user ? data.user.avatar_url : (data.user_avatar || ''), 82 attachments: [ 83 { 84 text: `${JSON.stringify(data, null, 4)}`, 85 color: NOTIF_COLOR 86 } 87 ] 88 } 89 }; 90 } 91 issueEvent(data) { 92 const state = data.object_attributes.state; 93 const action = data.object_attributes.action; 94 let user_action = state; 95 let assigned = ''; 96 97 if (action === 'update') { 98 user_action = 'updated'; 99 } 100 101 if (data.assignee) { 102 assigned = `*Assigned to*: @${data.assignee.username}\n`; 103 } 104 105 return { 106 content: { 107 username: 'gitlab/' + data.project.name, 108 icon_url: data.project.avatar_url || data.user.avatar_url || '', 109 text: (data.assignee && data.assignee.name !== data.user.name) ? atName(data.assignee) : '', 110 attachments: [ 111 makeAttachment( 112 data.user, `${user_action} an issue _${data.object_attributes.title}_ on ${data.project.name}. 113 *Description:* ${data.object_attributes.description}. 114 ${assigned} 115 See: ${data.object_attributes.url}` 116 ) 117 ] 118 } 119 }; 120 } 121 122 commentEvent(data) { 123 const comment = data.object_attributes; 124 const user = data.user; 125 const at = []; 126 let text; 127 if (data.merge_request) { 128 const mr = data.merge_request; 129 const lastCommitAuthor = mr.last_commit && mr.last_commit.author; 130 if (mr.assignee && mr.assignee.name !== user.name) { 131 at.push(atName(mr.assignee)); 132 } 133 if (lastCommitAuthor && lastCommitAuthor.name !== user.name) { 134 pushUniq(at, atName(lastCommitAuthor)); 135 } 136 text = `commented on MR [#${mr.id} ${mr.title}](${comment.url})`; 137 } else if (data.commit) { 138 const commit = data.commit; 139 const message = commit.message.replace(/\n[^\s\S]+/, '...').replace(/\n$/, ''); 140 if (commit.author && commit.author.name !== user.name) { 141 at.push(atName(commit.author)); 142 } 143 text = `commented on commit [${commit.id.slice(0, 8)} ${message}](${comment.url})`; 144 } else if (data.issue) { 145 const issue = data.issue; 146 text = `commented on issue [#${issue.id} ${issue.title}](${comment.url})`; 147 } else if (data.snippet) { 148 const snippet = data.snippet; 149 text = `commented on code snippet [#${snippet.id} ${snippet.title}](${comment.url})`; 150 } 151 return { 152 content: { 153 username: 'gitlab/' + data.project.name, 154 icon_url: data.project.avatar_url || user.avatar_url || '', 155 text: at.join(' '), 156 attachments: [ 157 makeAttachment(user, `${text}\n${comment.note}`) 158 ] 159 } 160 }; 161 } 162 163 mergeRequestEvent(data) { 164 const user = data.user; 165 const mr = data.object_attributes; 166 const assignee = mr.assignee; 167 let at = []; 168 169 if (mr.action === 'open' && assignee) { 170 at = '\n' + atName(assignee); 171 } else if (mr.action === 'merge') { 172 const lastCommitAuthor = mr.last_commit && mr.last_commit.author; 173 if (assignee && assignee.name !== user.name) { 174 at.push(atName(assignee)); 175 } 176 if (lastCommitAuthor && lastCommitAuthor.name !== user.name) { 177 pushUniq(at, atName(lastCommitAuthor)); 178 } 179 } 180 return { 181 content: { 182 username: `gitlab/${mr.target.name}`, 183 icon_url: mr.target.avatar_url || mr.source.avatar_url || user.avatar_url || '', 184 text: at.join(' '), 185 attachments: [ 186 makeAttachment(user, `${mr.action} MR [#${mr.iid} ${mr.title}](${mr.url})\n${mr.source_branch} into ${mr.target_branch}`) 187 ] 188 } 189 }; 190 } 191 192 pushEvent(data) { 193 const project = data.project; 194 const user = { 195 name: data.user_name, 196 avatar_url: data.user_avatar 197 }; 198 // branch removal 199 if (data.checkout_sha === null && !data.commits.length) { 200 return { 201 content: { 202 username: `gitlab/${project.name}`, 203 icon_url: project.avatar_url || data.user_avatar || '', 204 attachments: [ 205 makeAttachment(user, `从项目 [${project.name}](${project.web_url}) 移除分支 ${refParser(data.ref)} `) 206 ] 207 } 208 }; 209 } 210 // new branch 211 if (data.before == 0) { // eslint-disable-line 212 return { 213 content: { 214 username: `gitlab/${project.name}`, 215 icon_url: project.avatar_url || data.user_avatar || '', 216 attachments: [ 217 makeAttachment(user, `推送了新分支 [${refParser(data.ref)}](${project.web_url}/commits/${refParser(data.ref)}) 到 [${project.name}](${project.web_url}), 领先master分支 ${data.total_commits_count} 个提交`) 218 ] 219 } 220 }; 221 } 222 return { 223 content: { 224 username: `gitlab/${project.name}`, 225 icon_url: project.avatar_url || data.user_avatar || '', 226 attachments: [ 227 makeAttachment(user, `推送了 ${data.total_commits_count} 个提交到项目 [${project.name}](${project.web_url}) 的 [${refParser(data.ref)}](${project.web_url}/commits/${refParser(data.ref)}) 分支`), 228 { 229 text: data.commits.map((commit) => `--------------------\n - ${new Date(commit.timestamp).toLocaleString()} [${commit.id.slice(0, 8)}](${commit.url}) 由 ${commit.author.name} 提交, 内容: \n ${commit.message.replace(/\s*$/, '')} \n\n增加了 ${commit.added.length} 个文件: ${commit.added.map((addfile)=>`\n[${addfile}](${project.web_url}/raw/${refParser(data.ref)}/${addfile})`)} \n\n修改了 ${commit.modified.length} 个文件: ${commit.modified.map((modifiedfile)=>`\n[${modifiedfile}](${project.web_url}/raw/${refParser(data.ref)}/${modifiedfile})`)} \n\n删除了 ${commit.removed.length} 个文件: ${commit.removed.map((removedfile)=>`\n${removedfile}`)} \n--------------------`).join('\n'), 230 color: NOTIF_COLOR 231 } 232 ] 233 } 234 }; 235 } 236 237 tagEvent(data) { 238 const tag = refParser(data.ref); 239 const user = { 240 name: data.user_name, 241 avatar_url: data.user_avatar 242 }; 243 let message; 244 if (data.checkout_sha === null) { 245 message = `deleted tag [${tag}](${data.project.web_url}/tags/)`; 246 } else { 247 message = `pushed tag [${tag} ${data.checkout_sha.slice(0, 8)}](${data.project.web_url}/tags/${tag})`; 248 } 249 return { 250 content: { 251 username: `gitlab/${data.project.name}`, 252 icon_url: data.project.avatar_url || data.user_avatar || '', 253 text: MENTION_ALL_ALLOWED ? '@all' : '', 254 attachments: [ 255 makeAttachment(user, message) 256 ] 257 } 258 }; 259 } 260 261 pipelineEvent(data) { 262 const commit = data.commit; 263 const user = { 264 name: data.user_name, 265 avatar_url: data.user_avatar 266 }; 267 const pipeline = data.object_attributes; 268 269 return { 270 content: { 271 username: `gitlab/${data.project.name}`, 272 icon_url: data.project.avatar_url || data.user_avatar || '', 273 attachments: [ 274 makeAttachment(user, `pipeline returned *${pipeline.status}* for commit [${commit.id.slice(0, 8)}](${commit.url}) made by *${commit.author.name}*`) 275 ] 276 } 277 }; 278 } 279 280 buildEvent(data) { 281 const user = { 282 name: data.user_name, 283 avatar_url: data.user_avatar 284 }; 285 286 return { 287 content: { 288 username: `gitlab/${data.repository.name}`, 289 icon_url: '', 290 attachments: [ 291 makeAttachment(user, `build named *${data.build_name}* returned *${data.build_status}* for [${data.project_name}](${data.repository.homepage})`) 292 ] 293 } 294 }; 295 } 296 }
本人还是比较懒, 是只搞了push event, 其他的有时间再搞吧!