当前位置: 首页 > news >正文

Jenkins上实现CI集成软件信息Teams群通知案例实现。

“为了方便 CI(持续集成/编译)、CT(持续测试)、CD(持续部署)与 Teams 群通知的联动。”

我们可以完整地定义并实现一个自动化闭环系统:
CI → CT → CD → Teams 通知

下面我帮你系统地写出完整思路与实现建议。


🚀 一、整体目标

实现以下自动化流程:

  1. CI 阶段:持续编译与静态分析
  2. CT 阶段:持续自动化测试
  3. CD 阶段:持续部署(到测试或生产环境)
  4. 通知阶段:将每个阶段的状态(成功 / 失败 / 日志 / 报告链接)实时发送到 Microsoft Teams 群聊

🧩 二、系统架构(推荐基于 Jenkins)

┌──────────────┐
│  Developer   │
│   (Git Push) │
└──────┬───────┘│▼
┌──────────────────┐
│ Jenkins Pipeline │
│ ─────────────────│
│  Stage 1: CI     │→ Build, Lint, QAC, Unit Test
│  Stage 2: CT     │→ Integration & Regression Test
│  Stage 3: CD     │→ Deploy to Staging/Prod
│  Stage 4: Notify │→ Send Teams Message
└──────────────────┘│▼
┌────────────────────┐
│ Microsoft Teams 群 │
│   (实时通知消息)   │
└────────────────────┘

⚙️ 三、各阶段核心逻辑

1️⃣ CI(持续编译 / 集成)

执行构建 + 静态检查:

stage('CI - Build') {steps {echo 'Building project...'sh 'python build_project.py'sh 'python run_qac_analysis.py'}
}

2️⃣ CT(持续测试)

执行自动测试,生成报告:

stage('CT - Testing') {steps {echo 'Running automated tests...'sh 'pytest tests/ --junitxml=report.xml'}
}

3️⃣ CD(持续部署)

部署到测试或生产环境:

stage('CD - Deployment') {steps {echo 'Deploying application...'sh 'python deploy_to_env.py --env staging'}
}

4️⃣ Teams 群通知

在 Jenkins 或 Python 中发送消息到 Teams,有两种实现方式:

:直接用 Python + Microsoft Graph API

Python 示例:

import requests
import json# Teams webhook URL(可在群中添加“传入Webhook”连接器获取)
webhook_url = "https://outlook.office.com/webhook/XXXXXX"def send_teams_message(title, message, color="00FF00"):payload = {"@type": "MessageCard","@context": "https://schema.org/extensions","themeColor": color,"summary": title,"sections": [{"activityTitle": title,"text": message}]}requests.post(webhook_url, headers={"Content-Type": "application/json"}, data=json.dumps(payload))# 使用示例
send_teams_message("✅ CI/CD Pipeline 成功", "构建、测试、部署均通过 ✅")

你也可以选择使用 Microsoft Graph API + OAuth2 Token 的方式,从 Python 直接向 Teams 群聊(非 webhook)发送消息,这种方式安全性更高且支持富文本消息。
👉 我之前帮你实现过 Graph API + Python 发送 Teams 消息的版本,可以无缝集成在这里。


📦 四、最终效果(通知示例)

Teams 群中会出现自动消息:

✅ CI/CD 通知

  • 项目:MyApp
  • 构建状态:✅ 成功
  • 持续测试:通过 157 / 157
  • 部署环境:Staging
  • 报告链接:点击查看报告

时间:2025-10-24 14:03:22


🧠 五、扩展思路

  • 支持 每日自动 CT 触发(例如晚上 23:00 执行回归测试)
  • 支持 Teams 通知带上 Jenkins 构建日志或附件
  • 支持失败自动重试与通知分级(@负责人)
  • 可接入 Helix QAC / SCA / Python 自动分析结果

🔗 直接访问 Azure 应用注册页面:https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade


❗️可能原因 + 解决办法

问题原因解决办法
❌ 看不到 App registrations你没有 Azure AD 管理员权限 或所在租户禁用了自助注册联系你们 IT 管理员,请其分配 应用管理员角色 或开通权限
❌ 搜索不到已注册的 App可能你当前视图是“我的应用”而不是“所有应用”在 App registrations 页面 → 点击“所有应用”视图
✅ 页面空白当前租户中没有注册任何应用点击右上角“新注册”创建新的应用注册即可

向群里发消息需要申请这两个 ChatMessage.Read(delegated), ChatMessage.Send (delegated)

列了下面几种可以向Teams发送CI信息的方式, 咱们选择的是Microsoft Graph API方式。

方法优点缺点场景
Incoming Webhook简单、快速,容易集成脚本或 CI/CD只能发到指定频道,功能有限,不支持用户交互,不支持消息发群里简单通知、自动化脚本、CI/CD 报告
Microsoft Graph API功能强大,可发送消息、附件、Adaptive Card,可读取消息、支持机器人配置复杂,需要注册 Azure AD 应用,获取 token企业自动化、复杂机器人、双向交互、系统集成
通过邮箱发送简单,无需开发,只需频道邮箱无法格式化消息,灵活性低,无法交互快速通知、邮件转 Teams 方案
Teams Bot(Bot Framework)可实现双向对话、复杂逻辑、交互式消息开发和配置复杂,需要注册 Bot,部署服务智能机器人、自动客服、交互式通知
Power Automate / Logic Apps无需写代码,易于可视化自动化,支持多平台集成灵活性和定制性有限,依赖 Microsoft 云服务自动化流程、条件触发通知、低代码方案
直接 SharePoint / OneDrive 文件触发可与 Teams 频道绑定文件操作事件,自动通知需要 SharePoint/OneDrive 环境,依赖微软生态文件上传/修改触发通知、文档协作场景
第三方集成工具(如 Zapier、IFTTT)简单易用,支持多平台数据流转需要额外账号或付费,功能受限跨平台通知、快速自动化、低代码

六、使用Microsoft Graph API方式(推荐)

🧭 操作路径:确认你进入的是对的位置

  1. 登录 Azure 门户:
    👉 https://portal.azure.com

  2. 左侧菜单点击:Azure Active Directory

  3. 在左边菜单中找到并点击:应用注册 (App registrations)

    如果你没有看到这个选项,可以尝试以下操作:

    • 点击左上角搜索栏,输入 App registrations
    • 或者从 URL 直接进入:https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade

创建 APP

点击上面链接创建一个APP,内容如下:
在这里插入图片描述

需要注意: 应用程序(客户端) ID目录(租户) ID 这两个ID,再python创建脚本中会用到,不要泄露。

2. 向Teams IT管理员申请可以向Teams发送,读写,接收的API权限

需要联系管理员,如果是个人的话可能不需要。如下图:
在这里插入图片描述

3.首先要获取API Token(一般有效期三个月)

获取token时需要先在刚注册的APP中,打开 允许公共客户端流,如下图所示:
在这里插入图片描述

4. 然后使用python结合API获取当前账号Teams的群信息和一对一聊天的群消息。

下面是获取群id 和私聊id源码

import os
import time
import html
import msal
import requests
import subprocessclass TeamsCIReporter:def __init__(self, client_id, tenant_id):self.client_id = client_idself.tenant_id = tenant_idself.token = Nonedef authenticate(self):"""使用 Device Code Flow 登录"""app = msal.PublicClientApplication(client_id=self.client_id,authority=f"https://login.microsoftonline.com/{self.tenant_id}")# 使用你授权的 ChatMessage.Send + ChatMessage.Readscopes = ["Chat.ReadWrite","ChatMessage.Send","ChatMessage.Read",]flow = app.initiate_device_flow(scopes=[f"https://graph.microsoft.com/{s}" for s in scopes])if "user_code" not in flow:raise Exception(f"启动设备码登录失败: {flow}")print(flow["message"])  # 提示去网页输入验证码self.token = app.acquire_token_by_device_flow(flow)if "access_token" not in self.token:raise Exception(f"获取Token失败: {self.token}")print("✅ 登录成功!")def list_chats(self):"""获取所有群聊 ID"""headers = {"Authorization": f"Bearer {self.token['access_token']}"}url = "https://graph.microsoft.com/v1.0/me/chats"resp = requests.get(url, headers=headers)if resp.status_code != 200:raise Exception(f"获取群聊失败: {resp.status_code} - {resp.text}")chats = resp.json().get("value", [])print("=== 群聊列表 ===")for c in chats:print(f"ID: {c['id']} | 主题: {c.get('topic', '无主题')} | 类型: {c['chatType']}")return chatsdef list_messages(self, chat_id, top=10):"""获取指定聊天 ID 的最新 N 条消息"""headers = {"Authorization": f"Bearer {self.token['access_token']}"}url = f"https://graph.microsoft.com/v1.0/chats/{chat_id}/messages?$top={top}&$orderby=createdDateTime desc"resp = requests.get(url, headers=headers)if resp.status_code != 200:raise Exception(f"获取消息失败: {resp.status_code} - {resp.text}")messages = resp.json().get("value", [])print(f"=== 聊天 {chat_id} 的最新 {top} 条消息 ===")for m in messages:sender_info = m.get("from")if sender_info and "user" in sender_info:sender = sender_info["user"].get("displayName", "未知")else:sender = "系统消息/未知发送者"content = m.get("body", {}).get("content", "")time = m.get("createdDateTime", "")print(f"[{time}] {sender}: {content}")return messagesdef send_message(self, chat_id, message):"""发送消息到指定群聊"""headers = {"Authorization": f"Bearer {self.token['access_token']}","Content-Type": "application/json"}url = f"https://graph.microsoft.com/v1.0/chats/{chat_id}/messages"payload = {"body": {"contentType": "html","content": message}}resp = requests.post(url, headers=headers, json=payload)if resp.status_code != 201:raise Exception(f"发送消息失败: {resp.status_code} - {resp.text}")print("✅ 消息发送成功!")if __name__ == "__main__":CLIENT_ID = "dssdvdsvsdsvd9csfsfsf62bfb"  # 应用程序(客户端) ID,复制即可TENANT_ID = "0aeffsafsffsasad10f4"  # 你的租户 ID  目录(租户) IDreporter = TeamsCIReporter(CLIENT_ID, TENANT_ID)reporter.authenticate()chats = reporter.list_chats()   #获取群聊IDprint(chats)# ci_message = """CI 集成第三版软件请查阅"""# target_chat_id="19:06cb25dsssddsgdfsgshakfhsfsf@thread.v2"# reporter.send_message(target_chat_id, ci_message)

最终获取的类似于下面这种群聊ID和 私聊ID,然后可以通过获取群聊ID 就可以向指定的群里发消息和获取消息了。

=== 群聊列表 ===
ID: 19:asafsdfsdfsdgdsg9@thread.v2 | 主题(群名): XXXXXX大分队  | 类型: group
ID: 19:asafasdsfsdfd7d@thread.v2 | 主题(群名): XXXXX小分队 | 类型: group
ID: 19:08safsfffsaff4sadsfassff7@unq.gbl.spaces | 主题(群名): None | 类型: oneOnOne(私聊的id)

建议:上面这个代码运行了需要手动登录刚注册的APP 平台后获取登录token,属于半自动的,所以可以在源码中加一个逻辑,将生成的token保存到一个文件中,就后面每次手动登录了 直接使用这个保存的token,一般这个token有效期3个月

我文章中发的这些群id的信息是错误的,请运行代码自己获取谢谢。
这样就是一个teams群通知的一个案例。希望能帮到大家。

http://www.dtcms.com/a/523756.html

相关文章:

  • ZYNQ平台中断服务函数中的变量不加volatile修饰导致的奇怪问题解决
  • 2026年UX/UI五大趋势:AI、AR与包容性设计将重新定义用户体验
  • 网站做跳转自己建网站卖鞋
  • 百度网站服务器外贸网站优化
  • 应广单片机烧录跳线J7专用PCB使用说明
  • Java 前后端加密与编码技术:从概念到实战场景全解析
  • 拒绝笨重,一款轻量、极致简洁的开源接口管理工具 - PostIn
  • 建设银行信用卡网站是哪个茶叶seo网站推广与优化方案
  • vant van-uploader上传file文件;回显时使用imageId拼接路径
  • Java常用中间件整理讲解——Redis,RabbitMQ
  • JavaEE初阶7.0
  • 从“天书”到源码:HarmonyOS NEXT 崩溃堆栈解析实战指南
  • 个人网站收款google play 应用商店
  • _撸猫websocket服务器端,手机远程服务端
  • 【论文精读】FDGaussian:基于几何感知扩散模型的单图快速高斯溅射 3D 重建
  • 功防世界-Web-bug
  • 做网站能拿多少钱平面设计 网站推荐
  • REST介绍,实质,六大约束,优缺点(数据冗余问题,身份验证困难(解决方式 -- JWT+集中式认证服务,使用代理))
  • Snapchat Data Scientist 面试经验分享|从 OA 到 Final Round 全流程复盘
  • 消息队列集群——RabbitMQ
  • 初识C语言14.动态内存管理
  • ks2e做网站高端品牌设计
  • 华为od-22届考研-C++面经
  • Win10 系统构建仿真 NVIDIA Jetson Orin Nano 环境部署 YOLOv8 模型
  • 英文网站开发付费下插件wordpress
  • 【面板数据】汽车之家及懂车帝汽车配置信息数据集(1999-2025.4)
  • Slotted Aloha
  • 「赤兔」Chitu 框架深度解读(六):剖析 Attention 机制后端实
  • 嵌入式开发中为啥常用do{}while(0)进行宏定义
  • 第六部分:VTK进阶(第172章 vtk-m加速器管线)