Files
novalon-website/.woodpecker.yml
T
张翔 5f9c5c9962
ci/woodpecker/push/woodpecker Pipeline failed
fix: 修复 SSH 私钥处理导致的语法错误
- 使用 printf '%s\n' 替代 echo 处理 SSH 私钥
- 移除包含特殊字符变量的 echo 命令
- 简化 SSH 命令,避免引号嵌套问题
2026-03-31 18:07:52 +08:00

290 lines
9.3 KiB
YAML

variables:
- &node_image node:20-alpine
- &tools_image registry.f.novalon.cn/novalon/tools:1.0.0
steps:
install-deps:
image: *node_image
environment:
NODE_ENV: development
CI: true
commands:
- npm ci --cache /tmp/npm-cache --prefer-offline --legacy-peer-deps
volumes:
- /tmp/npm-cache:/root/.npm
- /tmp/node-modules-cache:/woodpecker/src/node_modules
when:
event:
- push
- pull_request
lint:
image: *node_image
environment:
NODE_ENV: development
depends_on:
- install-deps
commands:
- npm run lint
volumes:
- /tmp/npm-cache:/root/.npm
- /tmp/node-modules-cache:/woodpecker/src/node_modules
when:
event:
- push
- pull_request
type-check:
image: *node_image
environment:
NODE_ENV: development
depends_on:
- install-deps
commands:
- npm run type-check
volumes:
- /tmp/npm-cache:/root/.npm
- /tmp/node-modules-cache:/woodpecker/src/node_modules
when:
event:
- push
- pull_request
security-scan:
image: *node_image
environment:
NODE_ENV: production
HUSKY: 0
depends_on:
- install-deps
commands:
- npm audit --audit-level=high --omit=dev
volumes:
- /tmp/npm-cache:/root/.npm
- /tmp/node-modules-cache:/woodpecker/src/node_modules
when:
event:
- push
- pull_request
unit-tests:
image: *node_image
environment:
NODE_ENV: test
CI: true
depends_on:
- lint
- type-check
commands:
- npm run test:unit -- --coverage --coverageReporters=text-summary --forceExit 2>&1 | tee test-results.txt || true
- echo "Unit tests completed."
failure: ignore
volumes:
- /tmp/npm-cache:/root/.npm
- /tmp/node-modules-cache:/woodpecker/src/node_modules
when:
event:
- push
- pull_request
branch:
- dev
e2e-tests:
image: mcr.microsoft.com/playwright:v1.48.0-jammy
environment:
NODE_ENV: test
CI: true
BASE_URL: http://localhost:3000
TEST_TIER: standard
depends_on:
- unit-tests
commands:
- npm run build
- npx playwright install chromium --with-deps
- npm run test:e2e
failure: ignore
volumes:
- /tmp/npm-cache:/root/.npm
- /tmp/node-modules-cache:/woodpecker/src/node_modules
- /tmp/playwright-cache:/root/.cache/ms-playwright
when:
event:
- push
branch:
- dev
build-and-deploy:
image: *tools_image
environment:
NODE_ENV: production
NEXT_TELEMETRY_DISABLED: 1
SSH_PRIVATE_KEY:
from_secret: ssh_private_key
depends_on:
- install-deps
- lint
- type-check
commands:
- echo "=== 构建并部署到生产环境 ==="
- echo "当前容器信息:"
- 'echo "主机名: $(hostname)"'
- 'echo "IP地址: $(hostname -i)"'
- 'echo "可用工具: $(which ssh rsync git curl dig nc)"'
- echo ""
- echo "Building production artifacts"
- npm run build
- echo "Build completed"
- ls -la dist/
- echo "Deploying to production"
- mkdir -p ~/.ssh
- printf '%s\n' "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- echo "SSH key file created, checking permissions:"
- ls -la ~/.ssh/
- echo "Testing SSH connection..."
- ssh -o StrictHostKeyChecking=no root@139.155.109.62 "echo Server connection OK"
- ssh -o StrictHostKeyChecking=no root@139.155.109.62 "df -h / /home | head -3"
- 'echo "Syncing build artifacts to production server"'
- 'rsync -avz --delete -e "ssh -o StrictHostKeyChecking=no" dist/ root@139.155.109.62:/home/novalon/docker-app/novalon-website/dist/'
- 'rsync -avz -e "ssh -o StrictHostKeyChecking=no" public/ root@139.155.109.62:/home/novalon/docker-app/novalon-website/public/'
- 'rsync -avz -e "ssh -o StrictHostKeyChecking=no" package.json package-lock.json root@139.155.109.62:/home/novalon/docker-app/novalon-website/'
- 'rsync -avz -e "ssh -o StrictHostKeyChecking=no" Dockerfile.prod docker-compose.server.yml root@139.155.109.62:/home/novalon/docker-app/novalon-website/'
- rsync -avz -e "ssh -o StrictHostKeyChecking=no" scripts/deploy-production.sh root@139.155.109.62:/home/novalon/docker-app/novalon-website/scripts/
- rsync -avz -e "ssh -o StrictHostKeyChecking=no" .env.production root@139.155.109.62:/home/novalon/docker-app/novalon-website/ 2>/dev/null || echo "No .env.production file"
- ssh -o StrictHostKeyChecking=no root@139.155.109.62 'cd /home/novalon/docker-app/novalon-website && [ -f docker-compose.server.yml ] && mv docker-compose.server.yml docker-compose.yml; chmod +x scripts/deploy-production.sh && ./scripts/deploy-production.sh'
- 'echo "Production deployment completed"'
volumes:
- /tmp/npm-cache:/root/.npm
- /tmp/node-modules-cache:/woodpecker/src/node_modules
when:
event:
- push
branch:
- release
- release/**
archive-to-main:
image: *tools_image
environment:
SSH_PRIVATE_KEY:
from_secret: ssh_private_key
depends_on:
- build-and-deploy
commands:
- echo "=== Archiving to main branch (增强可靠性版本) ==="
- echo "当前容器信息:"
- 'echo "主机名: $(hostname)"'
- 'echo "IP地址: $(hostname -i)"'
- echo ""
- echo ""
- echo "2. 配置SSH环境"
- mkdir -p ~/.ssh
- printf '%s\n' "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- echo "✅ SSH私钥文件已创建"
- 'ls -la ~/.ssh/id_rsa'
- 'wc -c < ~/.ssh/id_rsa'
- echo ""
- echo "3. 配置Git服务器主机密钥"
- ssh-keyscan -H -p 22 git.f.novalon.cn >> ~/.ssh/known_hosts
- echo "✅ Git服务器主机密钥已添加"
- echo ""
- echo "4. 增强网络连接测试"
- echo "测试DNS解析:"
- 'dig +short git.f.novalon.cn || nslookup git.f.novalon.cn || echo "DNS解析测试完成"'
- echo "测试端口连通性:"
- 'timeout 10 nc -zv git.f.novalon.cn 22 && echo "✅ SSH端口可达" || echo "❌ SSH端口不可达"'
- echo ""
- echo "5. 增强SSH连接测试"
- echo "测试SSH连接到Git服务器..."
- 'timeout 15 ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 -o BatchMode=yes -T git@git.f.novalon.cn "echo \"✅ SSH连接成功\"" 2>&1 || echo "❌ SSH连接失败,但继续执行"'
- echo ""
- echo "6. 配置Git用户信息"
- git config --global user.email "ci@novalon.cn"
- git config --global user.name "Woodpecker CI"
- echo "✅ Git用户信息已配置"
- echo ""
- echo "7. 配置Git远程仓库"
- git remote set-url origin git@git.f.novalon.cn:novalon/novalon-website.git
- echo "✅ Git远程仓库已配置"
- echo ""
- echo "8. 增强Git远程访问测试"
- echo "测试Git远程仓库访问权限..."
- 'timeout 10 git ls-remote origin --heads 2>&1 | head -5 && echo "✅ Git远程访问成功" || echo "❌ Git远程访问失败,但继续执行"'
- echo ""
- echo "9. 执行归档操作(增强错误处理)"
- 'export CURRENT_BRANCH="${CI_COMMIT_BRANCH}"'
- 'echo "当前分支: $CURRENT_BRANCH"'
- 'echo "提交SHA: ${CI_COMMIT_SHA:0:7}"'
- echo ""
- echo "9.1 切换到main分支"
- 'git checkout main || { echo "❌ 切换到main分支失败"; exit 1; }'
- echo ""
- echo "9.2 拉取最新main分支"
- 'git pull origin main --no-rebase || { echo "❌ 拉取main分支失败"; exit 1; }'
- echo ""
- echo "9.3 合并当前分支到main"
- 'git merge "$CURRENT_BRANCH" --no-ff -m "archive: $CURRENT_BRANCH → main [CI]" || { echo "❌ 合并分支失败"; exit 1; }'
- echo ""
- echo "9.4 创建版本标签"
- 'export VERSION_TAG="v$(date +%Y.%m.%d)-${CI_COMMIT_SHA:0:7}"'
- 'git tag -a "$VERSION_TAG" -m "Release: $CURRENT_BRANCH → $VERSION_TAG [CI]" || { echo "❌ 创建标签失败"; exit 1; }'
- echo ""
- echo "9.5 推送到远程仓库"
- 'git push origin main || { echo "❌ 推送main分支失败"; exit 1; }'
- 'git push origin --tags || { echo "❌ 推送标签失败"; exit 1; }'
- echo ""
- 'echo "✅ 归档成功完成!版本: $VERSION_TAG"'
when:
event:
- push
branch:
- release
- release/**
notify-wechat-success:
image: curlimages/curl:latest
environment:
WECHAT_WEBHOOK:
from_secret: wechat_webhook
depends_on:
- archive-to-main
commands:
- sh scripts/notify-wechat.sh success
when:
event:
- push
branch:
- release
- release/**
notify-wechat-failure:
image: curlimages/curl:latest
environment:
WECHAT_WEBHOOK:
from_secret: wechat_webhook
depends_on:
- archive-to-main
commands:
- sh scripts/notify-wechat.sh failure
when:
event:
- push
branch:
- release
- release/**
status:
- failure
workspace:
base: /woodpecker
path: src
clone:
git:
image: woodpeckerci/plugin-git
settings:
depth: 1
partial: false
lfs: false