一、项目背景CI/CD通知的集体痛点上周我们团队终于解决了困扰半年的Jenkins通知问题以前每次代码提交构建不管成功失败都所有人开发群一天能刷出50多条通知大家嫌吵直接屏蔽了群消息。结果上周三一个核心分支构建失败了3个小时没人发现导致测试环境一直不可用整个测试团队都在等耽误了一整天的进度。我试过很多传统方案Jenkins自带的邮件通知没人看直接进垃圾箱飞书机器人简单通知只能发固定格式的消息永远所有人网上找的Python脚本写了200多行只能获取基本的构建状态提取不了错误日志付费CI/CD工具太贵小团队用不起就在我准备花两天时间自己写一个完整的通知系统时我想到了OpenClaw。我试着把需求告诉它结果让我大吃一惊只用了10分钟OpenClaw就生成了一个完整的飞书通知脚本支持自动提交人、智能过滤成功通知、提取构建错误日志摘要、生成带跳转链接的富文本消息代码量不到100行直接就能集成到Jenkins流水线。本文将分享我用OpenClaw飞书搭建智能CI/CD通知系统的完整过程所有代码和提示词均可直接复制支持Jenkins、GitLab CI、GitHub Actions等所有主流CI/CD工具。二、技术栈选型全程零复杂依赖单文件部署开箱即用AI辅助开发OpenClaw v0.3.0自动生成完整可运行代码智能分析构建日志CI/CD工具Jenkins 2.450工业标准团队最常用通知渠道飞书自定义机器人支持富文本、人、按钮跳转免费易用脚本语言Python 3.10跨平台所有CI/CD工具都支持日志处理OpenClaw内置的文本分析能力自动提取错误摘要三、系统整体架构极简设计一个脚本搞定所有功能无需任何额外服务渲染错误:Mermaid 渲染失败: Parse error on line 9: ...H[生成失败通知] E -- I[自动对应提交人] H -- ----------------------^ Expecting AMP, COLON, PIPE, TESTSTR, DOWN, DEFAULT, NUM, COMMA, NODE_STRING, BRKT, MINUS, MULT, UNICODE_TEXT, got LINK_ID四、核心实战步骤4.1 第一步创建飞书自定义机器人这是最基础的一步2分钟就能搞定打开飞书群点击右上角的…“选择群机器人”点击添加机器人选择自定义机器人输入机器人名称CI/CD通知机器人上传头像点击添加复制生成的Webhook地址和签名密钥保存好后面会用到安全设置里勾选签名校验提高安全性4.2 第二步一条提示词生成完整通知脚本这是最神奇的一步你不需要懂飞书机器人API不需要懂Jenkins环境变量只需要把你的需求清晰地告诉OpenClaw它就能生成完整可运行的代码。我用的OpenClaw提示词帮我写一个Python飞书CI/CD通知脚本要求 1. 支持飞书机器人签名校验使用HMAC-SHA256算法 2. 从Jenkins环境变量获取以下信息 - JOB_NAME任务名称 - BUILD_NUMBER构建编号 - BUILD_URL构建页面链接 - GIT_COMMIT提交哈希 - GIT_AUTHOR_NAME提交人姓名 - GIT_COMMIT_MESSAGE提交信息 3. 支持两种通知类型 - 构建成功绿色主题只提交人不所有人 - 构建失败红色主题提交人同时所有人 4. 构建失败时读取控制台日志文件提取最后50行错误信息 5. 消息使用飞书富文本格式包含跳转Jenkins的按钮 6. 加入完整的异常处理避免脚本本身崩溃影响构建 7. 代码注释清晰结构规范可直接运行 只输出最终的Python代码不要输出任何解释性文字。1分钟后OpenClaw就生成了一个92行的完整脚本包含了所有我要求的功能而且代码质量非常高注释清晰异常处理完善。我只需要修改一下飞书机器人的Webhook地址和签名密钥就能直接运行了。4.3 生成的核心代码展示importosimportsysimporthmacimporthashlibimportbase64importtimeimportrequestsimportjson# 飞书机器人配置WEBHOOK_URLhttps://open.feishu.cn/open-apis/bot/v2/hook/你的webhook地址SECRET你的签名密钥defgenerate_sign(timestamp):生成飞书机器人签名string_to_signf{timestamp}\n{SECRET}hmac_codehmac.new(string_to_sign.encode(utf-8),digestmodhashlib.sha256).digest()returnbase64.b64encode(hmac_code).decode(utf-8)defsend_feishu_message(content):发送飞书消息timestampstr(int(time.time()))signgenerate_sign(timestamp)headers{Content-Type:application/json}data{timestamp:timestamp,sign:sign,msg_type:interactive,card:content}try:responserequests.post(WEBHOOK_URL,jsondata,headersheaders,timeout10)response.raise_for_status()print(飞书消息发送成功)exceptExceptionase:print(f飞书消息发送失败{e})defbuild_success_card(job_name,build_number,build_url,git_commit,git_author,git_message):生成构建成功的飞书卡片return{config:{wide_screen_mode:True},header:{title:{tag:plain_text,content:✅ 构建成功},template:green},elements:[{tag:div,text:{tag:lark_md,content:f**任务名称**{job_name}}},{tag:div,text:{tag:lark_md,content:f**构建编号**#{build_number}}},{tag:div,text:{tag:lark_md,content:f**提交人**{git_author}}},{tag:div,text:{tag:lark_md,content:f**提交信息**{git_message}}},{tag:action,actions:[{tag:button,text:{tag:plain_text,content:查看构建详情},url:build_url,type:primary}]}]}defbuild_failure_card(job_name,build_number,build_url,git_commit,git_author,git_message,error_log):生成构建失败的飞书卡片return{config:{wide_screen_mode:True},header:{title:{tag:plain_text,content:❌ 构建失败},template:red},elements:[{tag:div,text:{tag:lark_md,content:f**任务名称**{job_name}}},{tag:div,text:{tag:lark_md,content:f**构建编号**#{build_number}}},{tag:div,text:{tag:lark_md,content:f**提交人**{git_author}}},{tag:div,text:{tag:lark_md,content:f**提交信息**{git_message}}},{tag:hr},{tag:div,text:{tag:lark_md,content:**错误日志摘要**}},{tag:div,text:{tag:lark_md,content:f\n{error_log}\n}},{tag:action,actions:[{tag:button,text:{tag:plain_text,content:查看完整日志},url:f{build_url}console,type:danger}]}]}if__name____main__:# 获取Jenkins环境变量job_nameos.environ.get(JOB_NAME,未知任务)build_numberos.environ.get(BUILD_NUMBER,0)build_urlos.environ.get(BUILD_URL,)git_commitos.environ.get(GIT_COMMIT,)[:7]git_authoros.environ.get(GIT_AUTHOR_NAME,未知提交人)git_messageos.environ.get(GIT_COMMIT_MESSAGE,无提交信息)# 获取构建结果build_resultsys.argv[1]iflen(sys.argv)1elseFAILUREifbuild_resultSUCCESS:cardbuild_success_card(job_name,build_number,build_url,git_commit,git_author,git_message)at_users[git_author]else:# 读取最后50行错误日志try:withopen(console.log,r,encodingutf-8)asf:error_log.join(f.readlines()[-50:])except:error_log无法读取错误日志cardbuild_failure_card(job_name,build_number,build_url,git_commit,git_author,git_message,error_log)at_users[git_author,all]# 添加人card[elements].append({tag:div,text:{tag:lark_md,content: .join([fat id{user}/atforuserinat_users])}})send_feishu_message(card)4.4 第三步集成到Jenkins流水线这是最关键的一步只需要在Jenkinsfile中添加几行代码就能实现构建完成后自动发送飞书通知。Jenkinsfile示例pipeline{agent any stages{stage(拉取代码){steps{git url:你的代码仓库地址,branch:main}}stage(构建){steps{shpython -m pip install -r requirements.txtshpython -m pytest tests/}}}post{success{shpython notify.py SUCCESS}failure{shcat $BUILD_LOGFILE console.logshpython notify.py FAILURE}always{shrm -f console.log}}}现在每次有人提交代码Jenkins都会自动构建然后根据构建结果发送对应的飞书通知构建成功只提交人构建失败提交人和所有人并且自动提取最后50行错误日志开发者不用再翻几百行日志找问题了。五、高级功能扩展如果你需要更多功能只需要把需求告诉OpenClaw它就能自动扩展代码。我又加了几个非常实用的功能智能错误分析OpenClaw自动分析构建日志识别常见的错误类型如依赖安装失败、单元测试失败、语法错误并给出可能的解决方案多分支支持不同分支的构建结果发送到不同的飞书群比如main分支发送到开发群dev分支发送到测试群构建时长统计统计每次构建的时长超过阈值时发送告警历史记录统计每天生成构建统计报告统计每个人的构建成功率和平均构建时长六、踩坑避坑指南这是我实际使用中遇到的几个坑一定要注意飞书机器人签名校验一定要开启签名校验否则任何人知道你的Webhook地址都能往群里发消息。OpenClaw生成的代码已经包含了签名逻辑只需要填入你的SECRET即可。Jenkins环境变量问题有些Jenkins环境变量在post阶段才会有值比如BUILD_URL。如果获取不到可以在构建阶段把需要的变量写入文件然后在post阶段读取。中文乱码问题读取日志文件时一定要指定编码为utf-8否则中文会变成乱码。OpenClaw生成的代码已经处理了这个问题。人问题飞书人需要使用用户的飞书ID而不是用户名。你需要在脚本中维护一个Git用户名到飞书ID的映射表。日志大小问题不要把完整的构建日志都发送到飞书飞书消息有长度限制。只发送最后50行错误日志就足够了。七、最终效果对比三种通知方式的核心指标对比指标Jenkins邮件通知简单飞书机器人OpenClaw飞书智能通知开发部署时间10分钟30分钟10分钟代码量050行92行信息精准度低中高自动提交人不支持不支持支持错误日志提取不支持不支持支持消息打扰度低没人看高永远所有人低只相关人问题定位时间10分钟5分钟1分钟维护成本低中极低八、总结与展望以前我觉得写一个这样的通知系统至少要花一天时间还要调试各种飞书API和Jenkins环境变量。但现在用OpenClaw只需要一条提示词10分钟就能搞定而且代码质量比我自己写的还要好。这就是AI辅助开发的魅力它不是要替代开发者而是要把我们从重复的、机械的写脚本工作中解放出来让我们有更多时间去做更有价值的事情。未来我计划在这个通知系统的基础上加入AI自动修复功能对于一些常见的构建错误如依赖版本冲突、语法错误OpenClaw自动生成修复补丁提交PR真正实现CI/CD的全自动化。