build-flow.portal/Jenkinsfile
xiangning 501f70d489 feat(cicd): 接入自动触发 + docker compose 部署
- Jenkinsfile 加 GenericTrigger(token=buildflow-portal)
- 部署 stage 改 docker compose
- HealthCheck 改轮询,失败标 unstable
2026-07-17 15:22:51 +08:00

105 lines
4.1 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.

// BuildFlow buildflow-portal CI/CD
// 链路:①拉取代码 → ②编译打包(docker build) → 推送 Harbor → ③部署(cd-target docker compose) → HealthCheck
// 自动触发:Gitea push → Generic Webhook Trigger(token=buildflow-portal)
// Gitea webhook 指向:http://jenkins:8080/generic-webhook-trigger/invoke?token=buildflow-portal
pipeline {
agent any
triggers {
GenericTrigger(
token: 'buildflow-portal',
causeString: 'Gitea push 触发',
printContributedVariables: false,
printPostContent: false,
regexpFilterText: '',
regexpFilterExpression: ''
)
}
environment {
HARBOR = "43.134.235.58:58080"
IMAGE = "${HARBOR}/buildflow/buildflow-portal"
TAG = "${env.BUILD_NUMBER}"
// Jenkins 容器内无 ssh 别名,直接用 IP;ubuntu 用户 sudo 免密(NOPASSWD)
DEPLOY_HOST = "ubuntu@110.42.240.10"
APP_PORT = "5173"
DEPLOY_DIR = "/home/ubuntu/deploy"
SERVICE = "buildflow-portal"
}
options {
timeout(time: 30, unit: "MINUTES")
buildDiscarder(logRotator(numToKeepStr: "10"))
}
stages {
stage("① 拉取代码") {
steps {
checkout scm
sh "git log --oneline -3"
}
}
stage("② 编译打包") {
steps {
sh "docker build -t ${IMAGE}:${TAG} -t ${IMAGE}:latest ."
sh "docker images | grep ${IMAGE} | head -2"
}
}
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:latest
docker logout $HARBOR
'''
}
}
}
stage("③ 部署") {
steps {
withCredentials([usernamePassword(credentialsId: "harbor-credentials", usernameVariable: "HUSER", passwordVariable: "HPASS")]) {
sh """
ssh -o StrictHostKeyChecking=accept-new ${DEPLOY_HOST} "
cd ${DEPLOY_DIR}
echo '${HPASS}' | sudo docker login ${HARBOR} -u ${HUSER} --password-stdin
sudo docker compose pull ${SERVICE}
sudo docker compose up -d --no-deps ${SERVICE}
"
"""
}
echo "部署完成"
}
}
stage("HealthCheck") {
steps {
script {
def healthy = false
for (int i = 1; i <= 6; i++) {
sleep 5
try {
sh """
ssh -o StrictHostKeyChecking=accept-new ${DEPLOY_HOST} 'wget -q --spider http://127.0.0.1:${APP_PORT}/ && echo HEALTHCHECK_OK'
"""
healthy = true
echo "=== HealthCheck OK: portal http://110.42.240.10:${APP_PORT} ==="
break
} catch (e) {
echo "HealthCheck 第 ${i}/6 次探测未就绪,5s 后重试..."
}
}
if (!healthy) {
unstable("HealthCheck 30s 内未通过,查日志:ssh cd-target 'sudo docker logs ${SERVICE} --tail 50'")
}
}
}
}
}
post {
success { echo '=== buildflow-portal CI/CD SUCCESS ===' }
failure { echo '=== buildflow-portal CI/CD FAILED ===' }
always {
sh "docker rmi ${IMAGE}:${TAG} ${IMAGE}:latest 2>/dev/null || true"
deleteDir()
}
}
}