使用 Worker 实现发版通知
目前的站点发版是由开发人员自己操作,运营人员通常需要等待开发人员完成发版后才知道进行了发版。
这就导致了如果开发人员在发版后如果忘记了通知运营人员,运营人员就无法知道网站进行了发版。为了解决这个问题,我们使用了 webhook
来实现发版通知。
当我们进行网站发版的时候,会触发一个 webhook
, 会收集信息调用机器人发送到工作群中。
目前,我们工作使用的通讯工具是企业微信,所以我们使用企业微信机器人来实现发版通知。
首先需要在企业微信中创建一个机器人,然后获取到机器人的 webhook
地址。
然后我们使用 worker
来实现发版通知。
因为公司使用的是 CloudFlare
作为部署平台,所以我们使用 CloudFlare
的 Worker
来实现发版通知。
具体操作可以查看 CloudFlare Worker 文档。
可以通过 开始使用 - 命令行 这一节来进行简单的入门。
使用 npm create cloudflare@latest
命令创建一个 Worker
项目,然后使用 npx wrangler dev
运行项目。
在 src/index.js
或 src/index.ts
中开始编写我们的代码。
先定义调用机器人的方法:
/**
* 发送信息
* @param url 机器人回调地址
* @param content 通知信息内容
* @returns 回调响应体
*/
const sendMessage = (url: string, content: string) => {
return fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
msgtype: 'markdown',
markdown: {
content,
},
}),
})
}
因为使用的是 TS
编写的代码,所以我们需要定义一下 Env
接口:
export interface Env {
// 机器人密钥
BOT_KEY: string
// 主分支名称
MAIN_BRANCH: string
// github token
GITHUB_TOKEN: string
// 人名映射, 因为 github 用户名和真实人名不一致
USER_NAME_MAP: Record<string, string>
}
接着我们导出一个 Worker
对象:
export default {
async fetch(request, env ctx): Promise<Response> {
// 我们的通知逻辑都将在这里编写
}
}
我们的仓库都是存储在 github
上,因此我们要使用到 github
提供的 webhook
, 可参阅 官方文档。
目前,只需要用到 push
事件,因此我们只需要关注 push
事件的请求体即可。可查阅 push
的 说明文档。
因为需要 push
事件传递给 webhook
的数据中不存在是否有 PR
信息。因此我们需要调用到 github
提供的 api
,这又需要用到 github
提供的 token
。我们通过访问 网页 进行创建。记得为令牌赋予 Pull requests
或 Contents
权限(只读即可)。
如果是公开仓库,那么就不需要使用到 token
了。
具体思路如下:
- 首先判断是否是发布分支
- 然后判断是否是
push
事件 - 再判断是否由
PR
而来 - 如果是
PR
而来,那么需要获取PR
的信息 - 接着,通过提取数据,获取到相关信息
- 最后,调用机器人发送消息
具体代码如下:
if (gitEvent === 'push' && data.ref === `refs/heads/${env.MAIN_BRANCH}`) {
// 推送到主分支
const commits = data.commits
const lastCommit = commits[commits.length - 1]
const message = lastCommit?.message ?? '未知提交'
const num = message.match(/^Merge pull request #(\d+) from .+/)?.[1]
console.clear()
console.log(data)
const name = data.repository.name
const description = data.repository.description
// const repo_url = data.repository.html_url
const push_at = new Date(data.repository.updated_at).toLocaleString('zh-CN', {
timeZone: 'Asia/Shanghai',
/** UTC+8 */ hour12: false,
})
const pusher = data.sender.id || data.pusher.name
await new Promise((resolve, reject) => {
if (num) {
const queryPullRequestDescriptionUrl = data.repository.pulls_url.replace('{/number}', `/${num}`)
fetch(queryPullRequestDescriptionUrl, {
method: 'GET',
headers: {
Authorization: `Bearer ${env.GITHUB_TOKEN}`,
Accept: 'application/vnd.github.v3+json',
'X-GitHub-Api-Version': '2022-11-28',
'User-Agent': 'CloudFlare Worker',
},
})
.then((response) => response.json())
.then(async (data) => {
const {
title,
body,
user: { id: creater },
merged_by: { id: operator },
} = data as Record<string, any>
resolve(
[
'# 发版通知',
`> 项目仓库:${name}`,
`> 项目说明:${description}`,
`> 发版标题:${title}`,
`> 创建者:${env.USER_NAME_MAP[`${creater}`] || 'ID' + creater}`,
`> 操作者:${env.USER_NAME_MAP[`${operator}`] || 'ID' + operator}`,
`> 发版时间: ${push_at}`,
'',
...body.split('\r\n'),
].join('\n'),
)
})
} else {
resolve(
[
'# 发版通知',
`> 项目仓库:${name}`,
`> 项目说明:${description}`,
`> 创建者:${env.USER_NAME_MAP[`${pusher}`] || pusher}`,
`> 操作者:${env.USER_NAME_MAP[`${pusher}`] || pusher}`,
`> 发版时间: ${push_at}`,
'',
...message.split('\r\n'),
].join('\n'),
)
}
})
.then((content) => {
console.log({ content })
if (typeof content === 'string') {
return sendMessage(baseUrl, content)
}
})
.then((response) => response?.json())
.then((data) => {
console.log({ data })
})
}
使用了 Markdown
格式的信息,这样格式会更好看一些。
如果需要进行测试的话,可以查看 官方给出的教程。
在完成以上代码编写和测试之后,我们可以通过 npx wrangler deploy
命令来将代码部署到 CloudFlare
上。
这样,我们就可以通过 webhook
来实现发版通知了。