Files
2026-09-23 17:42:55 +08:00

186 lines
6.4 KiB
Groovy
Raw Permalink 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.
// live.fuhua91.com 部署流水线(基于 Jenkinsfile2 模板改造)
// 构建前后端镜像推送 Harbor(harbor.fuhua91.com/live),并 SSH 到宝塔服务器(192.168.2.226)
// 执行 /root/deploy.sh 拉取镜像更新容器。
//
// Jenkins 凭据要求:
// - harbor-live-push : Username with password,Harbor 项目 live 的 robot 账号
// (robot$live+live / harbor.json 中的 secret)
// - deploy-server-ssh-key: SSH Username with private key,可登录 root@192.168.2.226
//
// 服务器要求: /root/deploy.sh 已就位(见 deploy/deploy.sh),首次已手动跑通
pipeline {
agent any
options {
timestamps()
disableConcurrentBuilds()
}
parameters {
choice(
name: 'DEPLOY_MODE',
choices: ['BUILD_AND_DEPLOY', 'DEPLOY_ONLY'],
description: 'BUILD_AND_DEPLOY 构建新镜像并部署;DEPLOY_ONLY 部署 Harbor 中已有的镜像 tag(回滚用)'
)
string(
name: 'IMAGE_TAG',
defaultValue: '',
description: '要部署的镜像 tag。DEPLOY_ONLY 必填;BUILD_AND_DEPLOY 留空则使用当前 commit'
)
}
environment {
APP_NAME = 'live'
REGISTRY_HOST = 'harbor.fuhua91.com'
REGISTRY_NAMESPACE = 'live'
BACKEND_IMAGE = "${REGISTRY_HOST}/${REGISTRY_NAMESPACE}/backend"
FRONTEND_IMAGE = "${REGISTRY_HOST}/${REGISTRY_NAMESPACE}/frontend"
LIVEWEB_IMAGE = "${REGISTRY_HOST}/${REGISTRY_NAMESPACE}/live-web"
DEPLOY_HOST = 'root@192.168.2.226'
BIN_NAME = 'kratos-admin'
APP_BASE = 'live' // 前端 vite base 与 nginx 服务名前缀
PNPM_VERSION = '10.15.1'
DOCKER_BUILDKIT = '1'
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Prepare') {
steps {
script {
env.GIT_COMMIT_SHORT = sh(script: 'git rev-parse --short=12 HEAD', returnStdout: true).trim()
env.VERSION = sh(script: 'git describe --tags --always --dirty', returnStdout: true).trim()
if (params.DEPLOY_MODE == 'DEPLOY_ONLY') {
if (!params.IMAGE_TAG?.trim()) {
error('IMAGE_TAG is required when DEPLOY_MODE=DEPLOY_ONLY')
}
env.DEPLOY_IMAGE_TAG = params.IMAGE_TAG.trim()
} else {
env.DEPLOY_IMAGE_TAG = params.IMAGE_TAG?.trim() ? params.IMAGE_TAG.trim() : env.GIT_COMMIT_SHORT
}
echo "Deploy mode: ${params.DEPLOY_MODE}"
echo "Backend : ${env.BACKEND_IMAGE}:${env.DEPLOY_IMAGE_TAG}"
echo "Frontend: ${env.FRONTEND_IMAGE}:${env.DEPLOY_IMAGE_TAG}"
echo "LiveWeb : ${env.LIVEWEB_IMAGE}:${env.DEPLOY_IMAGE_TAG}"
}
}
}
stage('Test') {
when {
expression { params.DEPLOY_MODE == 'BUILD_AND_DEPLOY' }
}
steps {
sh '''
go env -w GOPROXY=https://goproxy.cn,direct
go test ./...
'''
}
}
stage('Build Frontend') {
when {
expression { params.DEPLOY_MODE == 'BUILD_AND_DEPLOY' }
}
steps {
// 容器内构建 dist(vite base 由 web/.env.production 的 VITE_APP_BASE=/admin/ 控制),
// 并渲染前端 nginx 配置(/api 转发到 live-backend:8000)
sh '''
docker run --rm \
-v "$PWD/web:/app" -w /app \
-e COREPACK_NPM_REGISTRY=https://registry.npmmirror.com \
-e npm_config_registry=https://registry.npmmirror.com \
-v kra-pnpm-store:/root/.local/share/pnpm/store \
docker.m.daocloud.io/node:20-slim \
bash -lc "corepack enable && corepack prepare pnpm@$PNPM_VERSION --activate && pnpm install --frozen-lockfile && pnpm build"
sed "s/\\${KRA_APP}/$APP_BASE/g" web/.docker-compose/nginx/conf.d/my.conf > web/nginx.k8s.conf
'''
}
}
stage('Build Live Web') {
when {
expression { params.DEPLOY_MODE == 'BUILD_AND_DEPLOY' }
}
steps {
// PC 直播用户端与后端同仓维护,确保当前提交中的接口与页面一起发布。
// HTTP/WS 均请求同源 /api,由站点 nginx 去前缀转发到后端。
sh '''
docker run --rm \
-v "$PWD/frontend:/app" -w /app \
-e npm_config_registry=https://registry.npmmirror.com \
docker.m.daocloud.io/node:20-slim \
bash -lc "npm ci --no-audit --no-fund && npm run build"
'''
}
}
stage('Build Images') {
when {
expression { params.DEPLOY_MODE == 'BUILD_AND_DEPLOY' }
}
steps {
sh '''
CGO_ENABLED=0 go build -ldflags "-X main.Version=${VERSION}" -o bin/${BIN_NAME} ./cmd
docker build \
--build-arg BIN_NAME=${BIN_NAME} \
--tag ${BACKEND_IMAGE}:${DEPLOY_IMAGE_TAG} \
--tag ${BACKEND_IMAGE}:latest \
.
docker build \
--tag ${FRONTEND_IMAGE}:${DEPLOY_IMAGE_TAG} \
--tag ${FRONTEND_IMAGE}:latest \
web
docker build \
--tag ${LIVEWEB_IMAGE}:${DEPLOY_IMAGE_TAG} \
--tag ${LIVEWEB_IMAGE}:latest \
frontend
'''
}
}
stage('Push Images') {
when {
expression { params.DEPLOY_MODE == 'BUILD_AND_DEPLOY' }
}
steps {
withCredentials([usernamePassword(credentialsId: 'harbor-live-push', usernameVariable: 'HARBOR_USER', passwordVariable: 'HARBOR_PASS')]) {
sh '''
echo "${HARBOR_PASS}" | docker login "${REGISTRY_HOST}" -u "${HARBOR_USER}" --password-stdin
docker push ${BACKEND_IMAGE}:${DEPLOY_IMAGE_TAG}
docker push ${BACKEND_IMAGE}:latest
docker push ${FRONTEND_IMAGE}:${DEPLOY_IMAGE_TAG}
docker push ${FRONTEND_IMAGE}:latest
docker push ${LIVEWEB_IMAGE}:${DEPLOY_IMAGE_TAG}
docker push ${LIVEWEB_IMAGE}:latest
docker logout "${REGISTRY_HOST}"
'''
}
}
}
stage('Deploy') {
steps {
sshagent(credentials: ['deploy-server-ssh-key']) {
sh '''
ssh -o StrictHostKeyChecking=no ${DEPLOY_HOST} "bash /root/deploy.sh ${DEPLOY_IMAGE_TAG}"
'''
}
}
}
}
post {
success {
echo "Deployed ${BACKEND_IMAGE}:${DEPLOY_IMAGE_TAG} / ${FRONTEND_IMAGE}:${DEPLOY_IMAGE_TAG} / ${LIVEWEB_IMAGE}:${DEPLOY_IMAGE_TAG}"
}
}
}