Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
69a104b6b5
99
Jenkinsfile
vendored
99
Jenkinsfile
vendored
@ -1,31 +1,67 @@
|
|||||||
// BuildFlow API CI/CD (.NET 10)
|
// BuildFlow api CI/CD 企业级流水线
|
||||||
// Checkout -> Build Image -> Push Harbor
|
// Stages: ①拉取代码 → ②编译打包 → 推送Harbor → ③部署
|
||||||
// 部署阶段预留: API 依赖 PG/Mongo/Redis/RabbitMQ, 待中间件就绪后启用 Deploy stage
|
// 构建成功/失败推送飞书交互卡片(绿/红)
|
||||||
|
// 飞书通知闭包(内联): 使用 Groovy JsonOutput 构造 JSON, 不依赖插件, 最稳妥
|
||||||
|
|
||||||
|
def feishuNotify = { String result, String failedStageName = '' ->
|
||||||
|
def dur = currentBuild.durationString.replace(' and counting', '')
|
||||||
|
def commit = sh(script: 'git log -1 --pretty=format:"%s (%an)"', returnStdout: true).trim()
|
||||||
|
def isOk = (result == 'SUCCESS')
|
||||||
|
def emoji = isOk ? '✅' : '❌'
|
||||||
|
def color = isOk ? 'green' : 'red'
|
||||||
|
def title = "${emoji} CI/CD ${isOk ? '成功' : '失败'} · ${env.JOB_NAME} #${env.BUILD_NUMBER}"
|
||||||
|
def fields = [
|
||||||
|
[is_short: true, text: [tag: 'lark_md', content: "**项目**\n${env.JOB_NAME}"]],
|
||||||
|
[is_short: true, text: [tag: 'lark_md', content: "**耗时**\n${dur}"]],
|
||||||
|
[is_short: true, text: [tag: 'lark_md', content: "**提交**\n${commit.take(50)}"]],
|
||||||
|
[is_short: true, text: [tag: 'lark_md', content: "**状态**\n${isOk ? '成功' : '失败'}"]]
|
||||||
|
]
|
||||||
|
def elements = [[tag: 'div', fields: fields], [tag: 'hr']]
|
||||||
|
if (isOk) {
|
||||||
|
elements.add([tag: 'div', text: [tag: 'lark_md', content: "📦 镜像地址\n`${env.IMAGE}:${env.TAG}`"]])
|
||||||
|
} else if (failedStageName) {
|
||||||
|
elements.add([tag: 'div', text: [tag: 'lark_md', content: "⚠️ 失败阶段\n${failedStageName}"]])
|
||||||
|
}
|
||||||
|
elements.add([tag: 'action', actions: [[tag: 'button', text: [tag: 'plain_text', content: '查看构建'], url: env.BUILD_URL ?: 'http://115.191.51.246:8080', type: isOk ? 'primary' : 'danger']]])
|
||||||
|
def card = [msg_type: 'interactive', card: [header: [title: [tag: 'plain_text', content: title], template: color], elements: elements]]
|
||||||
|
def jsonStr = groovy.json.JsonOutput.toJson(card)
|
||||||
|
writeFile file: '/tmp/feishu_msg.json', text: jsonStr
|
||||||
|
sh "curl -sS -X POST https://open.feishu.cn/open-apis/bot/v2/hook/d215e8ed-edea-4f07-a77c-2a0e5b52d9b9 -H 'Content-Type: application/json' -d @/tmp/feishu_msg.json || true"
|
||||||
|
sh "rm -f /tmp/feishu_msg.json"
|
||||||
|
}
|
||||||
|
|
||||||
pipeline {
|
pipeline {
|
||||||
agent any
|
agent any
|
||||||
environment {
|
environment {
|
||||||
HARBOR = "43.134.235.58:58080"
|
HARBOR = '43.134.235.58:58080'
|
||||||
IMAGE = "${HARBOR}/buildflow/buildflow-api"
|
IMAGE = "${HARBOR}/buildflow/buildflow-api"
|
||||||
TAG = "${env.BUILD_NUMBER}"
|
TAG = "${env.BUILD_NUMBER}"
|
||||||
}
|
}
|
||||||
options {
|
options {
|
||||||
timeout(time: 30, unit: "MINUTES")
|
timeout(time: 30, unit: 'MINUTES')
|
||||||
buildDiscarder(logRotator(numToKeepStr: "10"))
|
buildDiscarder(logRotator(numToKeepStr: '10'))
|
||||||
|
timestamps()
|
||||||
}
|
}
|
||||||
stages {
|
stages {
|
||||||
stage("Checkout") {
|
stage('① 拉取代码') {
|
||||||
steps { checkout scm }
|
|
||||||
}
|
|
||||||
stage("Build Image") {
|
|
||||||
steps {
|
steps {
|
||||||
sh "docker build -t ${IMAGE}:${TAG} -t ${IMAGE}:latest ."
|
checkout scm
|
||||||
|
sh 'git log --oneline -3'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage("Push Harbor") {
|
stage('② 编译打包') {
|
||||||
steps {
|
steps {
|
||||||
withCredentials([usernamePassword(credentialsId: "harbor-credentials", usernameVariable: "HUSER", passwordVariable: "HPASS")]) {
|
|
||||||
sh """
|
sh """
|
||||||
echo \$HPASS | docker login ${HARBOR} -u \$HUSER --password-stdin
|
docker build -t ${IMAGE}:${TAG} -t ${IMAGE}:latest .
|
||||||
|
docker images | grep ${IMAGE} | head
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('推送 Harbor') {
|
||||||
|
steps {
|
||||||
|
withCredentials([usernamePassword(credentialsId: 'harbor-credentials', usernameVariable: 'HUSER', passwordVariable: 'HPASS')]) {
|
||||||
|
sh """
|
||||||
|
echo $HPASS | docker login ${HARBOR} -u $HUSER --password-stdin
|
||||||
docker push ${IMAGE}:${TAG}
|
docker push ${IMAGE}:${TAG}
|
||||||
docker push ${IMAGE}:latest
|
docker push ${IMAGE}:latest
|
||||||
docker logout ${HARBOR}
|
docker logout ${HARBOR}
|
||||||
@ -33,17 +69,40 @@ pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage("Deploy") {
|
stage('③ 部署') {
|
||||||
// TODO: 等 PG/Mongo/Redis/RabbitMQ 中间件就绪后启用
|
|
||||||
// 由 deploy-agent 节点执行: docker pull + docker compose up
|
|
||||||
steps {
|
steps {
|
||||||
echo "Deploy stage 暂未启用: API 依赖中间件(PG/Mongo/Redis/RabbitMQ)尚未部署"
|
script {
|
||||||
|
try {
|
||||||
|
node('deploy-agent') {
|
||||||
|
sh """
|
||||||
|
docker pull ${IMAGE}:latest
|
||||||
|
docker rm -f buildflow-api 2>/dev/null || true
|
||||||
|
docker run -d --name buildflow-api --restart unless-stopped -p 5667:5667 ${IMAGE}:latest
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
echo "部署完成"
|
||||||
|
} catch (e) {
|
||||||
|
echo "⚠️ 部署节点(deploy-agent)暂不可用,跳过自动部署。镜像已推送 Harbor,可手动拉取部署。 API 依赖 PG/Mongo/Redis/RabbitMQ, 待中间件就绪后启用部署。"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
post {
|
post {
|
||||||
success { echo "BuildFlow API CI/CD SUCCESS: ${IMAGE}:${TAG}" }
|
success {
|
||||||
failure { echo "BuildFlow API CI/CD FAILED" }
|
script { feishuNotify('SUCCESS') }
|
||||||
|
}
|
||||||
|
failure {
|
||||||
|
script {
|
||||||
|
def stageName = '未知'
|
||||||
|
try {
|
||||||
|
def failedNodes = currentBuild.getRawBuild().getAction(org.jenkinsci.plugins.workflow.job.views.FlowGraphAction.class)?.getHeads()
|
||||||
|
if (failedNodes) { stageName = failedNodes.get(0).getDisplayNodeName() }
|
||||||
|
} catch (ignored) {}
|
||||||
|
feishuNotify('FAILURE', stageName)
|
||||||
|
}
|
||||||
|
}
|
||||||
always {
|
always {
|
||||||
sh "docker rmi ${IMAGE}:${TAG} ${IMAGE}:latest 2>/dev/null || true"
|
sh "docker rmi ${IMAGE}:${TAG} ${IMAGE}:latest 2>/dev/null || true"
|
||||||
deleteDir()
|
deleteDir()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user