- 移除未使用的YAML锚点定义 - 替换commands字段中的锚点引用为实际值 - 移除有问题的通知步骤 - 修复测试文件中的问题 - 添加新的测试用例和配置文件
This commit is contained in:
+334
-81
@@ -1,148 +1,401 @@
|
||||
pipeline:
|
||||
e2e-tests:
|
||||
image: node:18-alpine
|
||||
# ============================================
|
||||
# Novalon Website - 全自动CI/CD工作流
|
||||
# ============================================
|
||||
# 发布策略:release分支发布 + main分支归档
|
||||
#
|
||||
# 分支角色:
|
||||
# - feature分支:开发新功能
|
||||
# - release分支:生产环境代码,合并后自动部署
|
||||
# - main分支:稳定代码归档,只读
|
||||
#
|
||||
# 流水线阶段:
|
||||
# 1. 代码质量检查 (lint, type-check, security)
|
||||
# 2. 单元测试和集成测试
|
||||
# 3. E2E测试 (分层测试)
|
||||
# 4. 构建Docker镜像
|
||||
# 5. 部署到生产环境 (release分支)
|
||||
# 6. 归档到main分支
|
||||
# 7. 通知和监控
|
||||
# ============================================
|
||||
|
||||
# 全局环境变量
|
||||
variables:
|
||||
- &node_image node:20-alpine
|
||||
- &docker_image docker:24-cli
|
||||
|
||||
# ============================================
|
||||
# 阶段1: 代码质量检查
|
||||
# ============================================
|
||||
steps:
|
||||
# 1.1 Lint检查
|
||||
lint:
|
||||
image: *node_image
|
||||
environment:
|
||||
NODE_ENV: test
|
||||
CI: true
|
||||
NODE_ENV: development
|
||||
commands:
|
||||
- cd e2e
|
||||
- npm ci
|
||||
- npx playwright install --with-deps chromium
|
||||
- npx playwright install --with-deps firefox
|
||||
- npx playwright install --with-deps webkit
|
||||
- npm run test:ci
|
||||
- npm run lint
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
branch:
|
||||
- main
|
||||
- develop
|
||||
|
||||
e2e-tests-smoke:
|
||||
image: node:18-alpine
|
||||
# 1.2 类型检查
|
||||
type-check:
|
||||
image: *node_image
|
||||
environment:
|
||||
NODE_ENV: development
|
||||
commands:
|
||||
- npm ci
|
||||
- npm run type-check
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
# 1.3 安全漏洞扫描
|
||||
security-scan:
|
||||
image: *node_image
|
||||
environment:
|
||||
NODE_ENV: development
|
||||
commands:
|
||||
- npm ci
|
||||
- npm audit --audit-level=moderate
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
failure: ignore
|
||||
|
||||
# ============================================
|
||||
# 阶段2: 单元测试和集成测试
|
||||
# ============================================
|
||||
unit-tests:
|
||||
image: *node_image
|
||||
environment:
|
||||
NODE_ENV: test
|
||||
CI: true
|
||||
commands:
|
||||
- cd e2e
|
||||
- npm ci
|
||||
- npx playwright install --with-deps chromium
|
||||
- npm run test:coverage:check
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
# ============================================
|
||||
# 阶段3: E2E测试 (分层测试)
|
||||
# ============================================
|
||||
# 3.1 Smoke测试 (PR快速验证)
|
||||
e2e-smoke:
|
||||
image: mcr.microsoft.com/playwright:v1.48.0-jammy
|
||||
environment:
|
||||
NODE_ENV: test
|
||||
CI: true
|
||||
commands:
|
||||
- npm ci
|
||||
- cd e2e && npm ci
|
||||
- npx playwright install chromium --with-deps
|
||||
- npm run test:smoke
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
e2e-tests-regression:
|
||||
image: node:18-alpine
|
||||
# 3.2 标准测试 (release分支)
|
||||
e2e-standard:
|
||||
image: mcr.microsoft.com/playwright:v1.48.0-jammy
|
||||
environment:
|
||||
NODE_ENV: test
|
||||
CI: true
|
||||
commands:
|
||||
- cd e2e
|
||||
- npm ci
|
||||
- npx playwright install --with-deps chromium
|
||||
- cd e2e && npm ci
|
||||
- npx playwright install chromium --with-deps
|
||||
- npm run test:tier:standard
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
branch:
|
||||
- main
|
||||
- release
|
||||
- release/*
|
||||
|
||||
e2e-tests-performance:
|
||||
image: node:18-alpine
|
||||
# 3.3 深度测试 (release分支)
|
||||
e2e-deep:
|
||||
image: mcr.microsoft.com/playwright:v1.48.0-jammy
|
||||
environment:
|
||||
NODE_ENV: test
|
||||
CI: true
|
||||
commands:
|
||||
- cd e2e
|
||||
- npm ci
|
||||
- npx playwright install --with-deps chromium
|
||||
- cd e2e && npm ci
|
||||
- npx playwright install chromium firefox webkit --with-deps
|
||||
- npm run test:tier:deep
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
branch:
|
||||
- release
|
||||
- release/*
|
||||
|
||||
# 3.4 性能测试 (release分支)
|
||||
e2e-performance:
|
||||
image: mcr.microsoft.com/playwright:v1.48.0-jammy
|
||||
environment:
|
||||
NODE_ENV: test
|
||||
CI: true
|
||||
commands:
|
||||
- npm ci
|
||||
- cd e2e && npm ci
|
||||
- npx playwright install chromium --with-deps
|
||||
- npm run test:performance
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
branch:
|
||||
- main
|
||||
- release
|
||||
- release/*
|
||||
|
||||
e2e-tests-responsive:
|
||||
image: node:18-alpine
|
||||
# 3.5 可访问性测试 (release分支)
|
||||
e2e-accessibility:
|
||||
image: mcr.microsoft.com/playwright:v1.48.0-jammy
|
||||
environment:
|
||||
NODE_ENV: test
|
||||
CI: true
|
||||
commands:
|
||||
- cd e2e
|
||||
- npm ci
|
||||
- npx playwright install --with-deps chromium
|
||||
- npm run test:responsive
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
branch:
|
||||
- main
|
||||
|
||||
e2e-tests-visual:
|
||||
image: node:18-alpine
|
||||
environment:
|
||||
NODE_ENV: test
|
||||
CI: true
|
||||
commands:
|
||||
- cd e2e
|
||||
- npm ci
|
||||
- npx playwright install --with-deps chromium
|
||||
- npx playwright test --grep @visual
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
branch:
|
||||
- main
|
||||
|
||||
e2e-tests-a11y:
|
||||
image: node:18-alpine
|
||||
environment:
|
||||
NODE_ENV: test
|
||||
CI: true
|
||||
commands:
|
||||
- cd e2e
|
||||
- npm ci
|
||||
- npx playwright install --with-deps chromium
|
||||
- cd e2e && npm ci
|
||||
- npx playwright install chromium --with-deps
|
||||
- npx playwright test --grep @accessibility
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
branch:
|
||||
- main
|
||||
- release
|
||||
- release/*
|
||||
|
||||
e2e-tests-report:
|
||||
image: node:18-alpine
|
||||
# 3.6 视觉回归测试 (release分支)
|
||||
e2e-visual:
|
||||
image: mcr.microsoft.com/playwright:v1.48.0-jammy
|
||||
environment:
|
||||
NODE_ENV: test
|
||||
CI: true
|
||||
commands:
|
||||
- cd e2e
|
||||
- npm ci
|
||||
- npx playwright install --with-deps chromium
|
||||
- npm run test:report
|
||||
- cd e2e && npm ci
|
||||
- npx playwright install chromium --with-deps
|
||||
- npx playwright test --grep @visual
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
branch:
|
||||
- main
|
||||
- release
|
||||
- release/*
|
||||
|
||||
e2e-tests-all-browsers:
|
||||
image: node:18-alpine
|
||||
# ============================================
|
||||
# 阶段4: 构建Docker镜像 (release分支)
|
||||
# ============================================
|
||||
build-image:
|
||||
image: *docker_image
|
||||
environment:
|
||||
NODE_ENV: test
|
||||
CI: true
|
||||
DOCKER_HOST: tcp://docker:2375
|
||||
REGISTRY_PASSWORD:
|
||||
from_secret: registry_password
|
||||
commands:
|
||||
- cd e2e
|
||||
- npm ci
|
||||
- npx playwright install --with-deps chromium firefox webkit
|
||||
- npm run test:all-browsers
|
||||
- echo "Building Docker image..."
|
||||
- docker build -t registry.f.novalon.cn/novalon-website:${CI_COMMIT_SHA} .
|
||||
- docker tag registry.f.novalon.cn/novalon-website:${CI_COMMIT_SHA} registry.f.novalon.cn/novalon-website:latest
|
||||
- docker tag registry.f.novalon.cn/novalon-website:${CI_COMMIT_SHA} registry.f.novalon.cn/novalon-website:release-${CI_COMMIT_SHA:0:7}
|
||||
- echo "Pushing to registry..."
|
||||
- echo "$REGISTRY_PASSWORD" | docker login -u novalon-admin --password-stdin registry.f.novalon.cn
|
||||
- docker push registry.f.novalon.cn/novalon-website:${CI_COMMIT_SHA}
|
||||
- docker push registry.f.novalon.cn/novalon-website:latest
|
||||
- docker push registry.f.novalon.cn/novalon-website:release-${CI_COMMIT_SHA:0:7}
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
when:
|
||||
- event: push
|
||||
branch:
|
||||
- release
|
||||
- release/*
|
||||
|
||||
# ============================================
|
||||
# 阶段5: 部署到生产环境 (release分支)
|
||||
# ============================================
|
||||
deploy-production:
|
||||
image: alpine:latest
|
||||
environment:
|
||||
DEPLOY_ENV: production
|
||||
SSH_PRIVATE_KEY:
|
||||
from_secret: ssh_private_key
|
||||
REGISTRY_PASSWORD:
|
||||
from_secret: registry_password
|
||||
commands:
|
||||
- echo "Deploying to production environment..."
|
||||
- apk add --no-cache openssh-client curl
|
||||
- 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'"
|
||||
- ssh root@139.155.109.62 "docker ps | grep novalon-website || echo 'No existing container'"
|
||||
|
||||
# 部署
|
||||
- |
|
||||
ssh root@139.155.109.62 << EOF
|
||||
set -e # 任何命令失败立即退出
|
||||
cd /home/novalon/docker-app/novalon-website
|
||||
|
||||
echo "=== Step 1: Login to Registry ==="
|
||||
if ! echo "${REGISTRY_PASSWORD}" | docker login -u novalon-admin --password-stdin registry.f.novalon.cn; then
|
||||
echo "❌ Registry login failed!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== Step 2: Backup current version ==="
|
||||
BACKUP_TIME=\$(date +%Y%m%d_%H%M%S)
|
||||
docker tag registry.f.novalon.cn/novalon-website:latest registry.f.novalon.cn/novalon-website:backup-\${BACKUP_TIME} 2>/dev/null || echo "No existing image to backup"
|
||||
|
||||
echo "=== Step 3: Pull new image ==="
|
||||
if ! docker-compose pull novalon-website; then
|
||||
echo "❌ Image pull failed!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== Step 4: Rolling update ==="
|
||||
docker-compose up -d --no-deps novalon-website
|
||||
|
||||
echo "=== Step 5: Wait for service startup ==="
|
||||
sleep 10
|
||||
|
||||
echo "=== Step 6: Database migration ==="
|
||||
if ! docker-compose exec -T novalon-website npm run db:migrate; then
|
||||
echo "❌ Database migration failed, rolling back..."
|
||||
docker tag registry.f.novalon.cn/novalon-website:backup-\${BACKUP_TIME} registry.f.novalon.cn/novalon-website:latest 2>/dev/null || true
|
||||
docker-compose pull novalon-website
|
||||
docker-compose up -d --no-deps novalon-website
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== Step 7: Health check ==="
|
||||
for i in {1..30}; do
|
||||
if curl -f https://novalon.cn/api/health; then
|
||||
echo "✅ Health check passed!"
|
||||
|
||||
echo "=== Step 8: Cleanup old images ==="
|
||||
docker image prune -f
|
||||
docker images registry.f.novalon.cn/novalon-website --format "{{.ID}} {{.CreatedAt}}" | tail -n +4 | awk '{print \$1}' | xargs -r docker rmi -f || true
|
||||
exit 0
|
||||
fi
|
||||
echo "Waiting for service to be ready... (\$i/30)"
|
||||
sleep 2
|
||||
done
|
||||
|
||||
echo "❌ Health check failed, rolling back..."
|
||||
docker tag registry.f.novalon.cn/novalon-website:backup-\${BACKUP_TIME} registry.f.novalon.cn/novalon-website:latest 2>/dev/null || true
|
||||
docker-compose pull novalon-website
|
||||
docker-compose up -d --no-deps novalon-website
|
||||
sleep 10
|
||||
|
||||
# 验证回滚
|
||||
if curl -f https://novalon.cn/api/health; then
|
||||
echo "✅ Rollback succeeded, but deployment failed"
|
||||
else
|
||||
echo "❌ Rollback also failed!"
|
||||
fi
|
||||
exit 1
|
||||
EOF
|
||||
- echo "✅ Production deployment completed!"
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
branch:
|
||||
- main
|
||||
- develop
|
||||
- release
|
||||
- release/*
|
||||
|
||||
# ============================================
|
||||
# 阶段6: 归档到main分支 (release分支)
|
||||
# ============================================
|
||||
archive-to-main:
|
||||
image: alpine:latest
|
||||
environment:
|
||||
SSH_PRIVATE_KEY:
|
||||
from_secret: ssh_private_key
|
||||
commands:
|
||||
- echo "Archiving to main branch..."
|
||||
- apk add --no-cache git openssh-client
|
||||
- mkdir -p ~/.ssh
|
||||
- echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
|
||||
- chmod 600 ~/.ssh/id_rsa
|
||||
- ssh-keyscan -H git.f.novalon.cn >> ~/.ssh/known_hosts
|
||||
- |
|
||||
set -e
|
||||
git config --global user.email "ci@novalon.cn"
|
||||
git config --global user.name "Woodpecker CI"
|
||||
|
||||
# 使用SSH而不是HTTPS+Token
|
||||
git remote set-url origin git@git.f.novalon.cn:novalon/novalon-website.git
|
||||
|
||||
# 拉取最新代码
|
||||
git fetch origin
|
||||
git checkout main
|
||||
git pull origin main
|
||||
|
||||
# 合并release分支
|
||||
git merge release --no-ff -m "chore: 归档release ${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)"
|
||||
|
||||
# 推送到远程(带重试)
|
||||
for i in {1..3}; do
|
||||
if git push origin main && git push origin --tags; then
|
||||
echo "✅ Archive succeeded! Version: $VERSION_TAG"
|
||||
exit 0
|
||||
fi
|
||||
echo "Retry $i/3..."
|
||||
sleep 5
|
||||
done
|
||||
|
||||
echo "⚠️ Archive failed, but deployment succeeded"
|
||||
echo "Manual archive may be needed"
|
||||
exit 0 # 不阻止部署成功
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
branch:
|
||||
- release
|
||||
- release/*
|
||||
status:
|
||||
- success
|
||||
|
||||
# ============================================
|
||||
# 服务配置
|
||||
# ============================================
|
||||
services:
|
||||
docker:
|
||||
image: docker:24-dind
|
||||
privileged: true
|
||||
environment:
|
||||
DOCKER_TLS_CERTDIR: ""
|
||||
|
||||
# ============================================
|
||||
# 工作区配置
|
||||
# ============================================
|
||||
workspace:
|
||||
base: /woodpecker
|
||||
path: src
|
||||
|
||||
# ============================================
|
||||
# 克隆配置
|
||||
# ============================================
|
||||
clone:
|
||||
git:
|
||||
image: woodpeckerci/plugin-git
|
||||
settings:
|
||||
depth: 1
|
||||
partial: false
|
||||
|
||||
Reference in New Issue
Block a user