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群通知的一个案例。希望能帮到大家。

相关推荐
爱看老照片3 小时前
计算机端口
1024程序员节
go_bai3 小时前
Linux_基础IO(2)
linux·开发语言·经验分享·笔记·学习方法·1024程序员节
西部森林牧歌3 小时前
拒绝笨重,一款轻量、极致简洁的开源CI/CD工具 - Arbess
1024程序员节·cicd·tiklab·arbess
浆果02073 小时前
【图像超分】论文复现:轻量化超分 | RLFN的Pytorch源码复现,跑通源码,整合到EDSR-PyTorch中进行训练、测试
人工智能·python·深度学习·超分辨率重建·1024程序员节
Arnold.Shen4 小时前
Vcenter7使用主机配置文件重置ESXI主机 root 密码
1024程序员节
ai_moe4 小时前
MapAnything: 通用前馈式度量3D重建
1024程序员节
tritone4 小时前
在优豆云免费云服务器上搭建与配置Apache的实践笔记
服务器·网络·apache·1024程序员节
不良人龍木木4 小时前
云图-地基云图
图像处理·算法·计算机视觉·1024程序员节
YongCheng_Liang4 小时前
Windows CMD 常用命令:7 大核心模块速查指南(附实战场景)
运维·服务器·windows·1024程序员节