186 lines
6.4 KiB
Groovy
186 lines
6.4 KiB
Groovy
// 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}"
|
||
}
|
||
}
|
||
}
|