gateway/Jenkinsfile

212 lines
11 KiB
Groovy
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Groovy 辅助函数,用于发送钉钉通知。(保持不变)
@NonCPS
def sendDingTalkNotification(Map config) {
def message = config.get('message', '来自 Jenkins 的通知')
def webhookEnvVarName = config.get('webhookEnvVarName') // 存储 Webhook URL 的环境变量名称
def author = config.get('author', '未知用户')
def jobName = config.get('jobName', env.JOB_NAME ?: 'N/A')
def buildNumber = config.get('buildNumber', env.BUILD_NUMBER ?: 'N/A')
def enabled = config.get('enabled', false)
if (enabled && webhookEnvVarName) {
def webhookUrl = env[webhookEnvVarName]
if (!webhookUrl) {
echo "钉钉 Webhook URL 未通过环境变量 ${webhookEnvVarName} 找到。跳过通知。"
return
}
def finalMessage = "BZPT.发布 (${jobName}#${buildNumber}):\n${message}"
if (author && author != "未知用户" && author.trim() != "") {
finalMessage += "\n@${author.trim()}"
}
def payload = groovy.json.JsonOutput.toJson([msgtype: "text", text: [content: finalMessage]])
def curlResult = sh script: """
echo "正在发送钉钉通知..."
curl -X POST -H 'Content-Type: application/json' -d '${payload}' '${webhookUrl}' --silent --show-error --connect-timeout 10 --max-time 15
""", returnStatus: true
if (curlResult != 0) {
echo "警告:钉钉通知可能发送失败 (curl 退出码: ${curlResult})。"
} else {
echo "钉钉通知发送成功。"
}
} else {
echo "钉钉通知已跳过 (可能已禁用、未设置 Webhook 凭证或未找到 Webhook URL 的环境变量)。"
}
}
pipeline {
agent any
// triggers 块现在会使用在 Jenkins UI 中配置的 SCM 信息进行轮询
triggers {
pollSCM('H/5 * * * *')
}
parameters {
// Git 参数现在主要用于 UI 显示和分支选择,实际 SCM 配置在 Job UI 中
string(name: 'GIT_REPO_URL', defaultValue: 'http://111.230.114.47:3000/yidongliang/gateway.git', description: 'Git 仓库 URL (仅供参考实际配置在Job的SCM部分)')
string(name: 'GIT_BRANCH', defaultValue: 'stage', description: '要拉取的 Git 分支 (例如develop, stage, master)')
credentials(name: 'GIT_CREDENTIALS_ID', defaultValue: 'jenkins', description: 'Git 凭证 ID', required: true)
// Docker 构建参数 (保持不变)
string(name: 'DOCKERFILE_PATH_IN_REPO', defaultValue: 'Dockerfile', description: '仓库中 Dockerfile 的路径')
string(name: 'DOCKER_REGISTRY_URL', defaultValue: 'https://106.52.199.114:5000', description: 'Docker 镜像仓库 URL。留空则不推送。')
string(name: 'DOCKER_IMAGE_NAME', defaultValue: 'bzpt.gateway', description: 'Docker 镜像名称')
string(name: 'IMAGE_BASE_TAG', defaultValue: '1.0', description: '镜像标签的基础部分')
credentials(name: 'DOCKER_CREDENTIALS_ID', defaultValue: 'dockerregister', description: 'Docker 镜像仓库凭证 ID', required: false)
booleanParam(name: 'PUSH_LATEST_TAG', defaultValue: true, description: '是否同时创建并推送 "latest" 标签?')
// 钉钉通知参数 (保持不变)
booleanParam(name: 'SEND_DINGTALK_NOTIFICATIONS', defaultValue: true, description: '是否发送钉钉通知?')
credentials(name: 'DINGTALK_WEBHOOK_CREDENTIAL_ID', defaultValue: 'stage-publish-dingding', description: '存储钉钉 Webhook URL 的凭证 ID', required: false)
}
environment {
LAST_COMMIT_AUTHOR = "gateway-stage"
DINGTALK_WEBHOOK_ENV_VAR_NAME = 'DINGTALK_WEBHOOK_URL_FROM_CREDS'
}
stages {
// =========================================================================
// **核心改动:不再需要“拉取代码”阶段。**
// 代码已由 Jenkins 根据 UI 配置自动检出。
// 第一个阶段直接开始进行初始化。
// =========================================================================
stage('0. 初始化和准备') {
steps {
// 清理工作空间是好习惯,但注意它会删除所有文件,包括 Jenkins 自动检出的代码。
// 如果需要重新检出,可以使用 checkout scm。但通常在此场景下不需要 cleanWs。
// 我们暂时保留它,因为它在您的原始脚本中。
cleanWs()
// **重要**:由于 cleanWs 删除了所有内容,我们需要再次检出代码。
// `checkout scm` 是一个特殊的步骤,它会使用在 Jenkins UI 中配置的 SCM 信息。
echo "重新检出代码以确保工作空间内容最新..."
checkout scm
script {
echo "代码已检出。开始初始化构建环境..."
// 构造带 registry 的完整镜像名
def preparedImageNameWithRegistry = params.DOCKER_IMAGE_NAME
env.PREPARED_IMAGE_NAME = preparedImageNameWithRegistry
echo "构建的镜像全名 (不含标签): ${env.PREPARED_IMAGE_NAME}"
// 现在可以安全地执行 git 命令
def shortCommit = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()
env.IMAGE_TAG = "${params.IMAGE_BASE_TAG}.${BUILD_NUMBER}-${shortCommit}"
echo "生成的 IMAGE_TAG: ${env.IMAGE_TAG}"
try {
env.LAST_COMMIT_AUTHOR = sh(script: 'git log -1 --pretty=format:"%an"', returnStdout: true).trim()
} catch (e) {
echo "警告:无法获取最后提交的作者。 ${e.getMessage()}"
env.LAST_COMMIT_AUTHOR = "未知用户"
}
echo "最后提交的作者: ${env.LAST_COMMIT_AUTHOR}"
}
}
}
// 后续阶段保持不变,仅序号变更
stage('1. 构建 Docker 镜像') {
steps {
script {
def dockerfilePath = params.DOCKERFILE_PATH_IN_REPO
if (!fileExists(dockerfilePath)) {
error "在工作空间相对路径下未找到 Dockerfile: ${dockerfilePath}"
}
if (!env.PREPARED_IMAGE_NAME || !env.IMAGE_TAG) {
error "构建 Docker 镜像所需的 PREPARED_IMAGE_NAME 或 IMAGE_TAG 未设置。"
}
def fullImageNameWithTag = "${env.PREPARED_IMAGE_NAME}:${env.IMAGE_TAG}"
docker.build(fullImageNameWithTag, "-f \"${dockerfilePath}\" .")
echo "Docker 镜像 ${fullImageNameWithTag} 构建成功。"
if (params.PUSH_LATEST_TAG) {
def fullImageNameLatest = "${env.PREPARED_IMAGE_NAME}:latest"
sh "docker tag ${fullImageNameWithTag} ${fullImageNameLatest}"
echo "成功将镜像标记为: ${fullImageNameLatest}"
}
}
}
}
stage('2. 推送 Docker 镜像 (可选)') {
when { expression { params.DOCKER_REGISTRY_URL != "" } }
steps {
script {
def fullImageNameWithTag = "${env.PREPARED_IMAGE_NAME}:${env.IMAGE_TAG}"
def fullImageNameLatest = "${env.PREPARED_IMAGE_NAME}:latest"
docker.withRegistry(params.DOCKER_REGISTRY_URL, params.DOCKER_CREDENTIALS_ID) {
echo "正在推送镜像: ${fullImageNameWithTag}"
docker.image(fullImageNameWithTag).push()
echo "镜像 ${fullImageNameWithTag} 推送成功。"
if (params.PUSH_LATEST_TAG) {
echo "正在推送 latest 镜像: ${fullImageNameLatest}"
docker.image(fullImageNameLatest).push()
echo "镜像 ${fullImageNameLatest} 推送成功。"
}
}
}
}
}
}
// post 块定义无需任何修改,保持原样
post {
always {
echo "流水线结束。最终状态: ${currentBuild.result ?: 'IN PROGRESS'}"
}
success {
script {
if (params.SEND_DINGTALK_NOTIFICATIONS && params.DINGTALK_WEBHOOK_CREDENTIAL_ID) {
withCredentials([string(credentialsId: params.DINGTALK_WEBHOOK_CREDENTIAL_ID, variable: env.DINGTALK_WEBHOOK_ENV_VAR_NAME)]) {
sendDingTalkNotification(
message: "${params.DOCKER_IMAGE_NAME} 构建和推送成功。镜像: ${env.PREPARED_IMAGE_NAME}:${env.IMAGE_TAG}",
webhookEnvVarName: env.DINGTALK_WEBHOOK_ENV_VAR_NAME,
author: env.LAST_COMMIT_AUTHOR ?: '未知用户',
jobName: env.JOB_NAME,
buildNumber: env.BUILD_NUMBER,
enabled: params.SEND_DINGTALK_NOTIFICATIONS
)
}
}
}
}
failure {
script {
if (params.SEND_DINGTALK_NOTIFICATIONS && params.DINGTALK_WEBHOOK_CREDENTIAL_ID) {
withCredentials([string(credentialsId: params.DINGTALK_WEBHOOK_CREDENTIAL_ID, variable: env.DINGTALK_WEBHOOK_ENV_VAR_NAME)]) {
sendDingTalkNotification(
message: "${params.DOCKER_IMAGE_NAME} 构建失败。请检查控制台: ${env.BUILD_URL}console",
webhookEnvVarName: env.DINGTALK_WEBHOOK_ENV_VAR_NAME,
author: env.LAST_COMMIT_AUTHOR ?: '未知用户',
jobName: env.JOB_NAME,
buildNumber: env.BUILD_NUMBER,
enabled: params.SEND_DINGTALK_NOTIFICATIONS
)
}
}
}
}
aborted {
script {
if (params.SEND_DINGTALK_NOTIFICATIONS && params.DINGTALK_WEBHOOK_CREDENTIAL_ID) {
withCredentials([string(credentialsId: params.DINGTALK_WEBHOOK_CREDENTIAL_ID, variable: env.DINGTALK_WEBHOOK_ENV_VAR_NAME)]) {
sendDingTalkNotification(
message: "${params.DOCKER_IMAGE_NAME} 构建已中止。请检查控制台: ${env.BUILD_URL}console",
webhookEnvVarName: env.DINGTALK_WEBHOOK_ENV_VAR_NAME,
author: env.LAST_COMMIT_AUTHOR ?: '未知用户',
jobName: env.JOB_NAME,
buildNumber: env.BUILD_NUMBER,
enabled: params.SEND_DINGTALK_NOTIFICATIONS
)
}
}
}
}
}
}