test/user-journey #3
+58
-101
@@ -2,36 +2,35 @@
|
||||
# Novalon Website - 全自动CI/CD工作流
|
||||
# ============================================
|
||||
# 发布策略:feature -> dev -> release -> main
|
||||
#
|
||||
#
|
||||
# 分支角色与流程:
|
||||
# 1. feature/** 分支:开发新功能
|
||||
# - 触发:PR和push
|
||||
# - 执行:Lint + TypeCheck + Smoke Test
|
||||
# - 合并到:dev分支
|
||||
#
|
||||
#
|
||||
# 2. dev 分支:开发集成
|
||||
# - 触发:push
|
||||
# - 执行:完整测试套件(不部署)
|
||||
# - 创建/合并到:release/**分支
|
||||
#
|
||||
#
|
||||
# 3. release/** 分支:生产环境代码
|
||||
# - 触发:push
|
||||
# - 执行:代码检查 + 构建产物 + 同步部署
|
||||
# - 执行:代码检查 + 构建部署一体化
|
||||
# - 部署到:生产环境(139.155.109.62)
|
||||
# - 归档到:main分支
|
||||
#
|
||||
#
|
||||
# 4. main 分支:稳定代码归档
|
||||
# - 只读分支
|
||||
# - 仅接收来自release的自动归档
|
||||
#
|
||||
#
|
||||
# 流水线阶段:
|
||||
# 阶段0: 依赖安装(统一缓存)
|
||||
# 阶段1: 并行代码质量检查 (lint, type-check, security-scan)
|
||||
# 阶段2: 单元测试 -> E2E测试 (允许失败)
|
||||
# 阶段3: 构建生产产物 (仅release分支)
|
||||
# 阶段4: 同步产物到生产服务器并部署 (仅release分支)
|
||||
# 阶段5: 归档到main分支 (仅release分支)
|
||||
# 阶段6: 企业微信通知
|
||||
# 阶段2: 测试 (unit-tests, e2e-tests - 仅dev分支)
|
||||
# 阶段3: 构建并部署到生产环境 (release分支,一体化)
|
||||
# 阶段4: 归档到main分支 (release分支)
|
||||
# 阶段5: 企业微信通知
|
||||
# ============================================
|
||||
|
||||
variables:
|
||||
@@ -54,11 +53,6 @@ steps:
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
branch:
|
||||
- feature/**
|
||||
- dev
|
||||
- release
|
||||
- release/**
|
||||
|
||||
# ============================================
|
||||
# 阶段1: 并行代码质量检查
|
||||
@@ -78,11 +72,6 @@ steps:
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
branch:
|
||||
- feature/**
|
||||
- dev
|
||||
- release
|
||||
- release/**
|
||||
|
||||
type-check:
|
||||
image: *node_image
|
||||
@@ -99,11 +88,6 @@ steps:
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
branch:
|
||||
- feature/**
|
||||
- dev
|
||||
- release
|
||||
- release/**
|
||||
|
||||
security-scan:
|
||||
image: *node_image
|
||||
@@ -121,11 +105,6 @@ steps:
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
branch:
|
||||
- feature/**
|
||||
- dev
|
||||
- release
|
||||
- release/**
|
||||
|
||||
# ============================================
|
||||
# 阶段2: 测试 (仅dev分支,允许失败)
|
||||
@@ -177,21 +156,55 @@ steps:
|
||||
- dev
|
||||
|
||||
# ============================================
|
||||
# 阶段3: 构建生产产物 (release分支)
|
||||
# 阶段3: 构建并部署到生产环境 (仅release分支)
|
||||
# ============================================
|
||||
build-artifacts:
|
||||
build-and-deploy:
|
||||
image: *node_image
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
SSH_PRIVATE_KEY:
|
||||
from_secret: ssh_private_key
|
||||
depends_on:
|
||||
- lint
|
||||
- type-check
|
||||
commands:
|
||||
- echo "Building production artifacts..."
|
||||
- echo "=== Step 1: 构建生产产物 ==="
|
||||
- npm run build
|
||||
- echo "✅ Build completed"
|
||||
- echo "✅ 构建完成"
|
||||
- ls -la dist/
|
||||
|
||||
- echo "=== Step 2: 部署到生产环境 ==="
|
||||
- mkdir -p ~/.ssh
|
||||
- echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
|
||||
- chmod 600 ~/.ssh/id_rsa
|
||||
- ssh-keyscan -H 139.155.109.62 >> ~/.ssh/known_hosts
|
||||
|
||||
- echo "Pre-deployment checks..."
|
||||
- ssh root@139.155.109.62 "echo 'Server connection OK'"
|
||||
- ssh root@139.155.109.62 "df -h | grep -E '/$|/home'"
|
||||
|
||||
- echo "Syncing build artifacts to production server..."
|
||||
- rsync -avz --delete dist/ root@139.155.109.62:/home/novalon/docker-app/novalon-website/dist/
|
||||
- rsync -avz public/ root@139.155.109.62:/home/novalon/docker-app/novalon-website/public/
|
||||
- rsync -avz package.json package-lock.json root@139.155.109.62:/home/novalon/docker-app/novalon-website/
|
||||
- rsync -avz Dockerfile.prod docker-compose.server.yml root@139.155.109.62:/home/novalon/docker-app/novalon-website/
|
||||
- rsync -avz scripts/deploy-production.sh root@139.155.109.62:/home/novalon/docker-app/novalon-website/scripts/
|
||||
- rsync -avz .env.production root@139.155.109.62:/home/novalon/docker-app/novalon-website/ 2>/dev/null || echo "No .env.production file"
|
||||
|
||||
- |
|
||||
ssh root@139.155.109.62 << 'EOF'
|
||||
set -e
|
||||
cd /home/novalon/docker-app/novalon-website
|
||||
|
||||
if [ -f docker-compose.server.yml ]; then
|
||||
mv docker-compose.server.yml docker-compose.yml
|
||||
fi
|
||||
|
||||
chmod +x scripts/deploy-production.sh
|
||||
./scripts/deploy-production.sh
|
||||
EOF
|
||||
- echo "✅ 生产环境部署完成!"
|
||||
volumes:
|
||||
- /tmp/npm-cache:/root/.npm
|
||||
- /tmp/node-modules-cache:/woodpecker/src/node_modules
|
||||
@@ -203,57 +216,7 @@ steps:
|
||||
- release/**
|
||||
|
||||
# ============================================
|
||||
# 阶段4: 部署到生产环境 (release分支)
|
||||
# ============================================
|
||||
deploy-production:
|
||||
image: alpine/git:latest
|
||||
environment:
|
||||
DEPLOY_ENV: production
|
||||
SSH_PRIVATE_KEY:
|
||||
from_secret: ssh_private_key
|
||||
depends_on:
|
||||
- build-artifacts
|
||||
commands:
|
||||
- echo "Deploying to production environment..."
|
||||
- mkdir -p ~/.ssh
|
||||
- echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
|
||||
- chmod 600 ~/.ssh/id_rsa
|
||||
- ssh-keyscan -H 139.155.109.62 >> ~/.ssh/known_hosts
|
||||
|
||||
- echo "Pre-deployment checks..."
|
||||
- ssh root@139.155.109.62 "echo 'Server connection OK'"
|
||||
- ssh root@139.155.109.62 "df -h | grep -E '/$|/home'"
|
||||
|
||||
- echo "Syncing build artifacts to production server..."
|
||||
- rsync -avz --delete dist/ root@139.155.109.62:/home/novalon/docker-app/novalon-website/dist/
|
||||
- rsync -avz public/ root@139.155.109.62:/home/novalon/docker-app/novalon-website/public/
|
||||
- rsync -avz package.json package-lock.json root@139.155.109.62:/home/novalon/docker-app/novalon-website/
|
||||
- rsync -avz Dockerfile.prod docker-compose.server.yml root@139.155.109.62:/home/novalon/docker-app/novalon-website/
|
||||
- rsync -avz scripts/deploy-production.sh root@139.155.109.62:/home/novalon/docker-app/novalon-website/scripts/
|
||||
- rsync -avz .env.production root@139.155.109.62:/home/novalon/docker-app/novalon-website/ 2>/dev/null || echo "No .env.production file"
|
||||
|
||||
- |
|
||||
ssh root@139.155.109.62 << 'EOF'
|
||||
set -e
|
||||
cd /home/novalon/docker-app/novalon-website
|
||||
|
||||
if [ -f docker-compose.server.yml ]; then
|
||||
mv docker-compose.server.yml docker-compose.yml
|
||||
fi
|
||||
|
||||
chmod +x scripts/deploy-production.sh
|
||||
./scripts/deploy-production.sh
|
||||
EOF
|
||||
- echo "✅ Production deployment completed!"
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
branch:
|
||||
- release
|
||||
- release/**
|
||||
|
||||
# ============================================
|
||||
# 阶段5: 归档到main分支 (release分支)
|
||||
# 阶段4: 归档到main分支 (仅release分支)
|
||||
# ============================================
|
||||
archive-to-main:
|
||||
image: alpine/git:latest
|
||||
@@ -261,7 +224,7 @@ steps:
|
||||
SSH_PRIVATE_KEY:
|
||||
from_secret: ssh_private_key
|
||||
depends_on:
|
||||
- deploy-production
|
||||
- build-and-deploy
|
||||
commands:
|
||||
- echo "Archiving to main branch..."
|
||||
- mkdir -p ~/.ssh
|
||||
@@ -272,20 +235,20 @@ steps:
|
||||
set -e
|
||||
git config --global user.email "ci@novalon.cn"
|
||||
git config --global user.name "Woodpecker CI"
|
||||
|
||||
|
||||
git remote set-url origin git@git.f.novalon.cn:novalon/novalon-website.git
|
||||
git fetch origin
|
||||
|
||||
|
||||
CURRENT_BRANCH="${CI_COMMIT_BRANCH}"
|
||||
echo "Current branch: $CURRENT_BRANCH"
|
||||
|
||||
|
||||
git checkout main
|
||||
git pull origin main
|
||||
git merge "$CURRENT_BRANCH" --no-ff -m "chore: 归档${CURRENT_BRANCH} ${CI_COMMIT_SHA:0:7}"
|
||||
|
||||
|
||||
VERSION_TAG="v$(date +%Y.%m.%d)-${CI_COMMIT_SHA:0:7}"
|
||||
git tag -a "$VERSION_TAG" -m "Release $(date +%Y-%m-%d) from ${CURRENT_BRANCH}"
|
||||
|
||||
|
||||
for i in {1..3}; do
|
||||
if git push origin main && git push origin --tags; then
|
||||
echo "✅ Archive succeeded! Version: $VERSION_TAG"
|
||||
@@ -294,7 +257,7 @@ steps:
|
||||
echo "Retry $i/3..."
|
||||
sleep 5
|
||||
done
|
||||
|
||||
|
||||
echo "⚠️ Archive failed, but deployment succeeded"
|
||||
exit 0
|
||||
when:
|
||||
@@ -303,11 +266,9 @@ steps:
|
||||
branch:
|
||||
- release
|
||||
- release/**
|
||||
status:
|
||||
- success
|
||||
|
||||
# ============================================
|
||||
# 阶段6: 企业微信通知
|
||||
# 阶段5: 企业微信通知
|
||||
# ============================================
|
||||
notify-wechat-success:
|
||||
image: curlimages/curl:latest
|
||||
@@ -324,8 +285,6 @@ steps:
|
||||
branch:
|
||||
- release
|
||||
- release/**
|
||||
status:
|
||||
- success
|
||||
|
||||
notify-wechat-failure:
|
||||
image: curlimages/curl:latest
|
||||
@@ -333,7 +292,7 @@ steps:
|
||||
WECHAT_WEBHOOK:
|
||||
from_secret: wechat_webhook
|
||||
depends_on:
|
||||
- deploy-production
|
||||
- build-and-deploy
|
||||
commands:
|
||||
- sh scripts/notify-wechat.sh failure
|
||||
when:
|
||||
@@ -342,8 +301,6 @@ steps:
|
||||
branch:
|
||||
- release
|
||||
- release/**
|
||||
status:
|
||||
- failure
|
||||
|
||||
workspace:
|
||||
base: /woodpecker
|
||||
|
||||
Reference in New Issue
Block a user