diff --git a/Jenkinsfile b/Jenkinsfile index 4e4617a..2d03c6a 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,42 +1,7 @@ -// BuildFlow buildflow-api CI/CD - clean version -// ①拉取代码 -> ②编译打包 -> 推送Harbor -> ③部署 + 飞书通知 - -def feishuNotify = { String result, String failedStageName = "" -> - def dur = currentBuild.durationString.replace(" and counting", "") - def commit = "" - try { commit = sh(script: "git log -1 --pretty=format:%s", returnStdout: true).trim() } catch(ignored) {} - def isOk = (result == "SUCCESS") - def color = isOk ? "green" : "red" - def statusText = isOk ? "成功" : "失败" - def title = "CI/CD " + statusText + " " + 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" + statusText]] - ] - 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]]) - } - def burl = env.BUILD_URL - if (burl == null) { burl = "http://115.191.51.246:8080/job/" + env.JOB_NAME.replace("/", "/job/") + "/" } - elements.add([tag: "action", actions: [[tag: "button", text: [tag: "plain_text", content: "查看构建"], url: burl, type: isOk ? "primary" : "danger"]]]) - def card = [msg_type: "interactive", card: [header: [title: [tag: "plain_text", content: title], template: color], elements: elements]] - def ts = String.valueOf(System.currentTimeMillis() / 1000L as long) - def stringToSign = ts + "\n" + "${env.FEISHU_SIGN_SECRET}" - def mac = javax.crypto.Mac.getInstance("HmacSHA256") - mac.init(new javax.crypto.spec.SecretKeySpec(stringToSign.getBytes("UTF-8"), "HmacSHA256")) - def sign = mac.doFinal().encodeBase64().toString() - card.timestamp = ts - card.sign = sign - def jsonStr = groovy.json.JsonOutput.toJson(card) - writeFile file: "/tmp/feishu_msg.json", text: jsonStr - sh "curl -sS -X POST ${env.FEISHU_WEBHOOK_URL} -H \"Content-Type: application/json\" -d @/tmp/feishu_msg.json || true" - sh 'rm -f /tmp/feishu_msg.json' -} +// BuildFlow buildflow-api CI/CD +// 链路:①拉取代码 → ②编译打包(docker build) → 推送 Harbor → ③部署(cd-target SSH) → HealthCheck +// 注:飞书通知逻辑已移除(凭证未配齐);部署通过 ssh 直连 cd-target 执行。 +// api 运行依赖:PostgreSQL(5库) / Redis / MongoDB(im_system) / RabbitMQ / S3(RustFS) / 本地LLM(1234) / KKFileView(8012) pipeline { agent any @@ -44,9 +9,8 @@ pipeline { HARBOR = "43.134.235.58:58080" IMAGE = "${HARBOR}/buildflow/buildflow-api" TAG = "${env.BUILD_NUMBER}" - // 飞书通知签名密钥与 Webhook 地址从 Jenkins 凭证注入,禁止硬编码(已清除明文) - FEISHU_SIGN_SECRET = credentials('feishu-signature-key') - FEISHU_WEBHOOK_URL = credentials('feishu-webhook-url') + DEPLOY_HOST = "cd-target" + APP_PORT = "5667" } options { timeout(time: 30, unit: "MINUTES") @@ -81,31 +45,42 @@ pipeline { steps { script { try { - node("deploy-agent") { - sh ''' - docker pull $IMAGE:latest + sh """ + ssh -o StrictHostKeyChecking=accept-new ${DEPLOY_HOST} ' + 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 - ''' - } + docker run -d --name buildflow-api --restart unless-stopped -p ${APP_PORT}:${APP_PORT} ${IMAGE}:latest + ' + """ echo "部署完成" } catch (e) { - echo "部署节点暂不可用,跳过自动部署。镜像已推送 Harbor。api依赖PG/Mongo/Redis/RabbitMQ" + echo "警告:部署节点 ${DEPLOY_HOST} 暂不可用,跳过自动部署(镜像已推送 Harbor)。原因:${e.getMessage()}" + } + } + } + } + stage("HealthCheck") { + steps { + script { + try { + sh """ + sleep 8 + ssh -o StrictHostKeyChecking=accept-new ${DEPLOY_HOST} 'wget -q --spider http://127.0.0.1:${APP_PORT}/health || wget -q --spider http://127.0.0.1:${APP_PORT}/ && echo HEALTHCHECK_OK' + """ + echo "=== HealthCheck OK: api http://110.42.240.10:${APP_PORT} ===" + } catch (e) { + echo "警告:HealthCheck 探测失败(容器可能仍在启动,或依赖的 PG/Redis/Mongo 未就绪)。镜像已推送 Harbor,可手动检查。" } } } } } post { - success { - script { feishuNotify("SUCCESS") } - } - failure { - script { feishuNotify("FAILURE", "构建失败,请查看日志") } - } - always { + success { echo '=== buildflow-api CI/CD SUCCESS ===' } + failure { echo '=== buildflow-api CI/CD FAILED ===' } + always { sh "docker rmi ${IMAGE}:${TAG} ${IMAGE}:latest 2>/dev/null || true" deleteDir() } } -} \ No newline at end of file +}