用 simple-git 编写自动化发版通知机器人
·
用 simple-git 编写自动化发版通知机器人

在开源项目维护和企业级敏捷迭代中,“软件发版”是一个重要的里程碑。每次我们在 Git 仓库打上新的 Tag 并推送到远端(如 git tag v1.5.0 && git push --tags),除了触发 CI 构建与 npm/Docker 发布之外,还有一项关键任务:将本次版本的更新要点(Changelog)及时同步给开源社区群、用户社群或内部开发团队。
如果依赖人工去梳理 Git 提交记录、手写通知文案并在各个群聊中逐个粘贴,不仅效率低下,还极易遗漏关键改动或在深夜发版时延误。
本文介绍如何利用轻量级 Node.js 库 simple-git,编写一个仅需百行代码的自动化发版机器人。它能自动计算两个 Tag 之间的增量提交、按语义化分类归纳,并一键推送到钉钉、企业微信、飞书或 Discord 群组。
1. 自动化流水线流程设计
机器人的核心工作流极其精炼:
[ Git 仓库触发发版 Tag: v1.5.0 ]
|
v (simple-git 获取最近两个语义化 Tag)
[ 计算差异区间: v1.4.0...v1.5.0 ]
|
v (解析区间内的 Commit 记录与作者信息)
[ 语义化分类器: feat / fix / perf / docs ]
|
v (组装精美的 Markdown 发布卡片)
[ Webhook 广播至飞书 / 企微 / 钉钉 / Discord 社区群 ]
2. 核心代码实现
整个脚本无需复杂的框架,只需安装 simple-git 作为核心依赖:
pnpm add simple-git
pnpm add -D typescript @types/node tsx
2.1 提取与分类提交记录
// scripts/release-notifier.ts
import { simpleGit, SimpleGit } from 'simple-git';
const git: SimpleGit = simpleGit();
interface CategorizedChanges {
features: string[];
fixes: string[];
performance: string[];
others: string[];
}
export async function generateReleaseNotes(): Promise<{ currentTag: string; previousTag: string; changes: CategorizedChanges }> {
// 1. 获取所有 Tag 并按版本倒序排序
const tagsResult = await git.tags({ '--sort': '-v:refname' });
const allTags = tagsResult.all;
if (allTags.length === 0) {
throw new Error('未找到任何 Git Tag,请先打 Tag 后运行!');
}
const currentTag = allTags[0];
const previousTag = allTags.length > 1 ? allTags[1] : '';
console.log(`📌 检测到当前最新版本: ${currentTag}, 上一版本: ${previousTag || '初始提交'}`);
// 2. 获取两个 Tag 之间的 commit 列表
const logRange = previousTag ? `${previousTag}..${currentTag}` : currentTag;
const logSummary = await git.log({ from: previousTag || undefined, to: currentTag });
const changes: CategorizedChanges = {
features: [],
fixes: [],
performance: [],
others: []
};
// 3. 按照 Conventional Commits 规范进行正则归类
for (const commit of logSummary.all) {
const msg = commit.message.trim();
const author = commit.author_name;
const item = `${msg} (@${author})`;
if (/^feat(\(.*\))?:/i.test(msg)) {
changes.features.push(item);
} else if (/^fix(\(.*\))?:/i.test(msg)) {
changes.fixes.push(item);
} else if (/^perf(\(.*\))?:/i.test(msg)) {
changes.performance.push(item);
} else if (!/^chore\(release\)/i.test(msg)) {
// 过滤掉自动化发版提交
changes.others.push(item);
}
}
return { currentTag, previousTag, changes };
}
2.2 组装 Markdown 并通过 Webhook 发送
// scripts/release-notifier.ts (续)
function buildMarkdownPayload(projectName: string, currentTag: string, changes: CategorizedChanges): string {
let content = `🎉 **${projectName} ${currentTag} 正式发布!**\n\n`;
if (changes.features.length > 0) {
content += `### 🚀 新特性 (Features)\n`;
changes.features.forEach(f => { content += `- ${f}\n`; });
content += `\n`;
}
if (changes.fixes.length > 0) {
content += `### 🐛 Bug 修复 (Bug Fixes)\n`;
changes.fixes.forEach(f => { content += `- ${f}\n`; });
content += `\n`;
}
if (changes.performance.length > 0) {
content += `### ⚡ 性能优化 (Performance)\n`;
changes.performance.forEach(p => { content += `- ${p}\n`; });
content += `\n`;
}
content += `🔗 **源码与下载**: [GitHub Release 查看详情](https://github.com/example-org/${projectName}/releases/tag/${currentTag})\n`;
return content;
}
// 统一的 Webhook 发送器 (以标准飞书/企微机器人格式为例)
export async function sendWebhookNotification(webhookUrl: string, markdownText: string) {
const payload = {
msg_type: 'interactive',
card: {
header: {
title: { tag: 'plain_text', content: '📦 生产环境发版通知' },
template: 'turquoise'
},
elements: [
{
tag: 'markdown',
content: markdownText
}
]
}
};
const res = await fetch(webhookUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
if (!res.ok) {
throw new Error(`Webhook 推送失败: ${res.status} ${res.statusText}`);
}
console.log('✅ 发版通知已成功推送到社区群聊!');
}
// 执行入口
async function main() {
const webhookUrl = process.env.RELEASE_WEBHOOK_URL;
if (!webhookUrl) {
console.warn('⚠️ 未配置 RELEASE_WEBHOOK_URL 环境变量,跳过群消息推送。');
return;
}
try {
const { currentTag, changes } = await generateReleaseNotes();
const markdown = buildMarkdownPayload('my-awesome-tool', currentTag, changes);
await sendWebhookNotification(webhookUrl, markdown);
} catch (error) {
console.error('❌ 发版通知执行失败:', error);
process.exit(1);
}
}
main();
3. 集成到 GitHub Actions CI 流水线
通过在 .github/workflows/release.yml 中添加一步,即可实现推送 Tag 时全自动广播:
name: Publish & Notify
on:
push:
tags:
- 'v*'
jobs:
notify:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # 必须拉取完整历史以获取所有 Tag
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: pnpm install
- name: Run Release Notifier
env:
RELEASE_WEBHOOK_URL: ${{ secrets.COMMUNITY_WEBHOOK_URL }}
run: npx tsx scripts/release-notifier.ts
4. 落地收益与极简哲学
- 零外部服务账单:无需采购专门的 Release SaaS 工具,纯靠几行脚本与免费的 Webhook 即可实现秒级响应。
- 倒逼提交规范化:团队成员看到自己的
feat:或fix:提交信息能直接作为特性高光展示在官方社群公告中,会自发、自觉地规范 Git 提交文案。 - 闭环体验:从本地打 Tag 推送,到 npm 包发版、社区公告展示,全程无需人工干预,极大地释放了维护者的心智带宽。
工程效率的提升往往不在于引入多么庞大的平台,而在于用最朴素的工具把重复发生的例行小事彻底自动化。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)