添加钉钉或者企业微信通知
直接加上最常用、最稳定的【企业微信 / 钉钉 机器人通知】,做了 双版本:
企业微信机器人通知(最常用)
钉钉机器人通知
完整版 Pipeline + 企业微信构建通知(推荐,直接复制)
ini
def WECHAT_WEBHOOK = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的key'
pipeline {
agent none
options {
timestamps()
timeout(time: 1, unit: 'HOURS')
buildDiscarder(logRotator(numToKeepStr: '10'))
}
environment {
// ========== GIT 配置 ==========
FRONTEND_GIT_URL = 'git@gitee.com:testpm/frontend-demo.git'
BACKEND_GIT_URL = 'git@gitee.com:testpm/backend-demo.git'
SLAVE_GIT_ID = 'jenkins-slave-git'
// ========== 镜像仓库配置 ==========
REGISTRY = '172.20.10.3'
BACK_NAMESPACE = 'backend'
BACK_APP_NAME = 'my-backend'
FRONT_NAMESPACE = 'frontend'
FRONT_APP_NAME = 'my-frontend'
// ========== 镜像仓库凭证 ==========
DOCKER_CRED = credentials('harbor-secret')
// ========== 企业微信机器人 ==========
WECHAT_WEBHOOK = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的key'
}
stages {
// ==========================
// 一、构建后端服务
// ==========================
stage('🚀 构建后端镜像') {
agent {
node {
label 'jenkins-slave'
customWorkspace '/home/jenkins/backend-docker'
}
}
steps {
echo '============ 拉取后端代码 ============'
git credentialsId: "${SLAVE_GIT_ID}", url: "${BACKEND_GIT_URL}", branch: 'master'
echo '============ 计算镜像版本号 ============'
// 关键修复:在 git 命令执行后,立即在当前目录计算 COMMIT_HASH
script {
// 这里会在 /home/jenkins/backend-docker 目录下执行,因为有 git 拉取,所以一定有 .git
env.COMMIT_HASH = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
env.BACK_FULL_IMAGE = "${REGISTRY}/${BACK_NAMESPACE}/${BACK_APP_NAME}:${COMMIT_HASH}"
}
echo "镜像地址:${BACK_FULL_IMAGE}"
sh 'pwd && ls -la | grep .git' // 验证目录和git存在
echo '============ 构建并推送后端镜像 ============'
sh '''
set -eux
echo "${DOCKER_CRED_PSW}" | docker login -u "${DOCKER_CRED_USR}" --password-stdin "${REGISTRY}"
docker build -t $BACK_FULL_IMAGE .
docker push $BACK_FULL_IMAGE
docker logout $REGISTRY
'''
}
}
// ==========================
// 二、构建前端服务
// ==========================
stage('🚀 构建前端镜像') {
agent {
node {
label 'jenkins-slave'
customWorkspace '/home/jenkins/frontend-docker'
}
}
steps {
echo '============ 拉取前端代码 ============'
git credentialsId: "${SLAVE_GIT_ID}", url: "${FRONTEND_GIT_URL}", branch: 'master'
echo '============ 计算镜像版本号 ============'
script {
// 前端目录计算版本号
env.COMMIT_HASH = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
env.FRONT_FULL_IMAGE = "${REGISTRY}/${FRONT_NAMESPACE}/${FRONT_APP_NAME}:${COMMIT_HASH}"
}
echo "镜像地址:${FRONT_FULL_IMAGE}"
sh 'pwd && ls -la | grep .git'
echo '============ 构建并推送前端镜像 ============'
sh '''
set -eux
docker login -u $DOCKER_CRED_USR -p $DOCKER_CRED_PSW $REGISTRY
docker build -t $FRONT_FULL_IMAGE .
docker push $FRONT_FULL_IMAGE
docker logout $REGISTRY
'''
}
}
}
post {
always {
script {
// 在 script 块内部使用 node
node('jenkins-slave') {
cleanWs()
}
}
}
success {
script {
node('jenkins-slave') {
sh """
curl '${WECHAT_WEBHOOK}' \
-H 'Content-Type: application/json' \
-d '{"msgtype":"text","text":{"content":"✅ 项目构建成功!\\n任务:${JOB_NAME}\\n编号:${BUILD_NUMBER}"}}'
"""
}
}
}
failure {
script {
node('jenkins-slave') {
sh """
curl '${WECHAT_WEBHOOK}' \
-H 'Content-Type: application/json' \
-d '{"msgtype":"text","text":{"content":"❌ 项目构建失败!\\n任务:${JOB_NAME}\\n编号:${BUILD_NUMBER}\\n请检查日志!"}}'
"""
}
}
}
}
}
只需要改 1 个地方
把环境变量里的 企业微信机器人 WebHook 地址 换成你自己的:
bash
WECHAT_WEBHOOK = '你的机器人地址'
验证

知识点整理
def WECHAT_WEBHOOK = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的key'这个变量为什么需要定义到pipeline外面?
因为如果将这个自定义变量定义到environment块中,那么这个WECHAT_WEBHOOK 变量在 post 阶段无法访问,因为 post 阶段运行在没有节点上下文的环境中,无法直接读取 environment 里的变量。所以jenkins会报错。所以两种处理方式:
ini
第一种是不用变量直接将webhook在命令中curl那里写死。
第二种就是笔记中的方式在 environment 里定义「全局变量」并通过 script 传递。可以在 pipeline 最外层用 def 定义,再在 post 里引用。
错误整理--知识点
-
agent none的含义 :在pipeline顶层设置agent none意味着整个流水线默认没有指定的执行节点(代理) 。任何需要执行器(Executor) 资源的步骤(如sh,bat,docker.build等)都必须在明确的节点上下文中运行。 -
Stage 为何能运行 :您的两个构建 Stage(
🚀 构建后端镜像和🚀 构建前端镜像)都各自定义了自己的agent,这为它们内部的步骤(git,sh,script等)提供了必要的节点上下文,所以它们能正常执行。 -
Post 阶段为何失败 :
post块不会继承 它之前任何一个 Stage 的agent配置。由于在post块内没有定义任何agent或node,当 Jenkins 尝试执行其中的sh步骤时,它找不到一个可用的节点来运行这个 Shell 命令,因此抛出异常:Attempted to execute a step that requires a node context while 'agent none' was specified.
解决方案
需要在 post阶段的 sh步骤外,包裹一个 node块,为其指定一个执行节点。需要注意的是post块只能包含特定的条件(always、changed、success、failure等),不能直接在post块中使用node块。因此需要如下编写:需要在每个 post条件内部使用 script块,然后在script块中使用node.
script块的作用:script块允许您在声明式流水线中嵌入脚本式语法,这样就可以使用node了
ini
post {
always {
script {
// 在 script 块内部使用 node
node('jenkins-slave') {
cleanWs()
}
}
}
success {
script {
node('jenkins-slave') {
sh """
curl '${WECHAT_WEBHOOK}' \
-H 'Content-Type: application/json' \
-d '{"msgtype":"text","text":{"content":"✅ 项目构建成功!\\n任务:${JOB_NAME}\\n编号:${BUILD_NUMBER}"}}'
"""
}
}
}
failure {
script {
node('jenkins-slave') {
sh """
curl '${WECHAT_WEBHOOK}' \
-H 'Content-Type: application/json' \
-d '{"msgtype":"text","text":{"content":"❌ 项目构建失败!\\n任务:${JOB_NAME}\\n编号:${BUILD_NUMBER}\\n请检查日志!"}}'
"""
}
}
}
}
发送钉钉通知
把 post 部分替换成下面这段即可:
或者将def WECHAT_WEBHOOK = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你企业微信的key'替换成钉钉的token
ini
post {
always {
script {
// 在 script 块内部使用 node
node('jenkins-slave') {
cleanWs()
}
}
}
success {
script {
node('jenkins-slave') {
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=你的钉钉token' \
-H 'Content-Type: application/json' \
-d '{"msgtype":"text","text":{"content":"✅ 项目构建成功!\\n任务:${JOB_NAME}\\n编号:${BUILD_NUMBER}"}}'
"""
}
}
}
failure {
script {
node('jenkins-slave') {
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=你的钉钉token' \
-H 'Content-Type: application/json' \
-d '{"msgtype":"text","text":{"content":"❌ 项目构建失败!\\n任务:${JOB_NAME}\\n编号:${BUILD_NUMBER}\\n请检查日志!"}}'
"""
}
}
}
}