228 行
7.8 KiB
Groovy
228 行
7.8 KiB
Groovy
// note-manager Jenkins Pipeline
|
|
// 项目:Go/Gin + SQLite(CGO),部署端口 9090
|
|
|
|
pipeline {
|
|
agent any
|
|
|
|
environment {
|
|
// ─── 基础配置 ───
|
|
APP_NAME = 'note-manager'
|
|
GO_VERSION = '1.21'
|
|
GIT_REPO = 'https://git.cnbugs.com/AI-Agent/note-manager.git'
|
|
GIT_BRANCH = 'main'
|
|
// ─── 部署配置(敏感信息用 Jenkins Credentials)───
|
|
DEPLOY_HOST = credentials('deploy-host')
|
|
DEPLOY_USER = credentials('deploy-user')
|
|
DEPLOY_PATH = '/vol1/Project/note-manager'
|
|
SERVICE_PORT = '9090'
|
|
// ─── 构建产物 ───
|
|
BUILD_DIR = 'dist'
|
|
}
|
|
|
|
options {
|
|
timestamps()
|
|
timeout(time: 15, unit: 'MINUTES')
|
|
disableConcurrentBuilds()
|
|
buildDiscarder(logRotator(numToKeepStr: '10'))
|
|
}
|
|
|
|
stages {
|
|
|
|
// ━━━━━━━━ 拉取代码 ━━━━━━━━
|
|
stage('Checkout') {
|
|
steps {
|
|
git branch: "${GIT_BRANCH}",
|
|
url: "${GIT_REPO}",
|
|
credentialsId: 'git-cnbugs-credentials'
|
|
sh 'echo "分支: ${GIT_BRANCH} | 提交: $(git rev-parse --short HEAD)"'
|
|
}
|
|
}
|
|
|
|
// ━━━━━━━━ 代码检查 ━━━━━━━━
|
|
stage('Lint') {
|
|
steps {
|
|
sh '''
|
|
docker run --rm \
|
|
-v "$PWD":/app \
|
|
-w /app \
|
|
golang:${GO_VERSION}-alpine \
|
|
sh -c "go fmt ./... && go vet ./..."
|
|
'''
|
|
}
|
|
}
|
|
|
|
// ━━━━━━━━ 单元测试 ━━━━━━━━
|
|
stage('Test') {
|
|
steps {
|
|
sh '''
|
|
docker run --rm \
|
|
-v "$PWD":/app \
|
|
-w /app \
|
|
-e CGO_ENABLED=1 \
|
|
golang:${GO_VERSION} \
|
|
go test -v -race -coverprofile=coverage.out ./...
|
|
'''
|
|
}
|
|
post {
|
|
always {
|
|
archiveArtifacts artifacts: 'coverage.out', allowEmptyArchive: true
|
|
}
|
|
}
|
|
}
|
|
|
|
// ━━━━━━━━ 编译构建 ━━━━━━━━
|
|
stage('Build') {
|
|
steps {
|
|
sh '''
|
|
rm -rf ${BUILD_DIR} && mkdir -p ${BUILD_DIR}
|
|
|
|
VERSION=$(git describe --tags --always --dirty 2>/dev/null || git rev-parse --short HEAD)
|
|
BUILD_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
COMMIT=$(git rev-parse --short HEAD)
|
|
|
|
echo "━━━ 构建信息 ━━━"
|
|
echo "版本: ${VERSION}"
|
|
echo "提交: ${COMMIT}"
|
|
echo "时间: ${BUILD_TIME}"
|
|
|
|
# go-sqlite3 需要 CGO_ENABLED=1,用完整 golang 镜像确保 gcc 可用
|
|
docker run --rm \
|
|
-v "$PWD":/app \
|
|
-w /app \
|
|
-e CGO_ENABLED=1 \
|
|
-e GOOS=linux \
|
|
-e GOARCH=amd64 \
|
|
golang:${GO_VERSION} \
|
|
go build \
|
|
-ldflags="-s -w \
|
|
-X main.Version=${VERSION} \
|
|
-X main.BuildTime=${BUILD_TIME} \
|
|
-X main.Commit=${COMMIT}" \
|
|
-o ${BUILD_DIR}/${APP_NAME} \
|
|
./...
|
|
|
|
file ${BUILD_DIR}/${APP_NAME}
|
|
ls -lh ${BUILD_DIR}/${APP_NAME}
|
|
'''
|
|
}
|
|
}
|
|
|
|
// ━━━━━━━━ 打包发布 ━━━━━━━━
|
|
stage('Package') {
|
|
steps {
|
|
sh '''
|
|
VERSION=$(git describe --tags --always --dirty 2>/dev/null || git rev-parse --short HEAD)
|
|
|
|
mkdir -p ${BUILD_DIR}/package
|
|
|
|
# 复制运行所需文件
|
|
cp ${BUILD_DIR}/${APP_NAME} ${BUILD_DIR}/package/
|
|
cp -r config ${BUILD_DIR}/package/
|
|
cp -r web ${BUILD_DIR}/package/
|
|
|
|
# 生成启动脚本
|
|
cat > ${BUILD_DIR}/package/start.sh << 'STARTSCRIPT'
|
|
#!/bin/bash
|
|
APP_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
cd "$APP_DIR"
|
|
|
|
export PORT=${SERVICE_PORT}
|
|
export DB_PATH=data/notes.db
|
|
export UPLOAD_DIR=uploads
|
|
export ADMIN_PASS=${ADMIN_PASS:-admin123}
|
|
|
|
mkdir -p data uploads
|
|
|
|
echo "启动 note-manager ..."
|
|
./note-manager
|
|
STARTSCRIPT
|
|
chmod +x ${BUILD_DIR}/package/start.sh
|
|
|
|
# 打 tar 包
|
|
cd ${BUILD_DIR}/package
|
|
tar czf ${WORKSPACE}/${APP_NAME}-${VERSION}-linux-amd64.tar.gz .
|
|
cd ${WORKSPACE}
|
|
|
|
echo "━━━ 发布包 ━━━"
|
|
ls -lh ${APP_NAME}-${VERSION}-linux-amd64.tar.gz
|
|
'''
|
|
}
|
|
post {
|
|
success {
|
|
archiveArtifacts artifacts: "${APP_NAME}-*-linux-amd64.tar.gz", fingerprint: true
|
|
}
|
|
}
|
|
}
|
|
|
|
// ━━━━━━━━ 部署(需手动确认)━━━━━━━━
|
|
stage('Deploy') {
|
|
when {
|
|
branch 'main'
|
|
}
|
|
input {
|
|
message '确认部署到生产环境?'
|
|
ok '部署'
|
|
}
|
|
steps {
|
|
sh '''
|
|
VERSION=$(git describe --tags --always --dirty 2>/dev/null || git rev-parse --short HEAD)
|
|
PACKAGE="${APP_NAME}-${VERSION}-linux-amd64.tar.gz"
|
|
|
|
echo "━━━ 部署到 ${DEPLOY_HOST} ━━━"
|
|
|
|
# 上传发布包
|
|
scp -o StrictHostKeyChecking=no \
|
|
${PACKAGE} \
|
|
${DEPLOY_USER}@${DEPLOY_HOST}:/tmp/${PACKAGE}
|
|
|
|
# 远程执行部署
|
|
ssh -o StrictHostKeyChecking=no ${DEPLOY_USER}@${DEPLOY_HOST} "bash -s" << REMOTE_DEPLOY
|
|
set -e
|
|
echo "停止旧服务..."
|
|
pkill -f 'note-manager' || true
|
|
sleep 1
|
|
|
|
echo "备份旧版本..."
|
|
if [ -f ${DEPLOY_PATH}/note-manager ]; then
|
|
cp ${DEPLOY_PATH}/note-manager ${DEPLOY_PATH}/note-manager.bak
|
|
fi
|
|
|
|
echo "解压新版本..."
|
|
mkdir -p ${DEPLOY_PATH}
|
|
cd ${DEPLOY_PATH}
|
|
tar xzf /tmp/${PACKAGE}
|
|
rm -f /tmp/${PACKAGE}
|
|
|
|
echo "启动服务..."
|
|
cd ${DEPLOY_PATH}
|
|
PORT=${SERVICE_PORT} nohup ./note-manager > ${DEPLOY_PATH}/app.log 2>&1 &
|
|
|
|
sleep 2
|
|
if curl -sf http://localhost:${SERVICE_PORT}/ > /dev/null 2>&1; then
|
|
echo "✅ 服务启动成功!端口: ${SERVICE_PORT}"
|
|
else
|
|
echo "❌ 服务启动失败,查看日志:"
|
|
tail -20 ${DEPLOY_PATH}/app.log
|
|
exit 1
|
|
fi
|
|
REMOTE_DEPLOY
|
|
|
|
echo "━━━ 部署完成 ━━━"
|
|
'''
|
|
}
|
|
}
|
|
}
|
|
|
|
post {
|
|
success {
|
|
echo '✅ Pipeline 执行成功'
|
|
}
|
|
failure {
|
|
echo '❌ Pipeline 执行失败'
|
|
}
|
|
always {
|
|
cleanWs()
|
|
}
|
|
}
|
|
}
|