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(持续编译 / 集成)

执行构建 + 静态检查:

groovy 复制代码
stage('CI - Build') {
    steps {
        echo 'Building project...'
        sh 'python build_project.py'
        sh 'python run_qac_analysis.py'
    }
}

2️⃣ CT(持续测试)

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

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

3️⃣ CD(持续部署)

部署到测试或生产环境:

groovy 复制代码
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 示例:

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

点击上面链接创建一个APP,内容如下:

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

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

需要联系管理员,如果是个人的话可能不需要。如下图:

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

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

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

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

python 复制代码
import os
import time
import html
import msal
import requests
import subprocess

class TeamsCIReporter:
    def __init__(self, client_id, tenant_id):
        self.client_id = client_id
        self.tenant_id = tenant_id
        self.token = None

    def 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.Read
        scopes = [
            "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 chats

    def 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 messages

    def 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  目录(租户) ID
        reporter = TeamsCIReporter(CLIENT_ID, TENANT_ID)
        reporter.authenticate()

        chats = reporter.list_chats()   #获取群聊ID
        print(chats)
        # ci_message = """CI 集成第三版软件请查阅"""
        # target_chat_id="19:06cb25dsssddsgdfsgshakfhsfsf@thread.v2"
        # reporter.send_message(target_chat_id, ci_message)

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

txt 复制代码
=== 群聊列表 ===
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群通知的一个案例。希望能帮到大家。

相关推荐
新之助小锅40 分钟前
java版连接汇川PLC,发送数据,读取数据,保持重新链接,适用安卓
android·java·python
海琴烟Sunshine43 分钟前
leetcode 383. 赎金信 python
python·算法·leetcode
惊讶的猫7 小时前
LSTM论文解读
开发语言·python
测试老哥7 小时前
软件测试之单元测试知识总结
自动化测试·软件测试·python·测试工具·职场和发展·单元测试·测试用例
buvsvdp50059ac7 小时前
如何在VSCode中设置Python解释器?
ide·vscode·python
njxiejing8 小时前
Python进度条工具tqdm的安装与使用
开发语言·python
Mr_Dwj9 小时前
【Python】Python 基本概念
开发语言·人工智能·python·大模型·编程语言
2401_8414956410 小时前
【自然语言处理】基于规则基句子边界检测算法
人工智能·python·自然语言处理·规则·文本·语言·句子边界检测算法