From c19f47ef3efe510e30a31a9ed84c4e8f579f48ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E7=BF=94?= Date: Wed, 1 Apr 2026 20:41:02 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=BF=81=E7=A7=BBCI/CD=E4=BB=8EWoodpec?= =?UTF-8?q?ker=E5=88=B0Jenkins?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加Jenkinsfile替代Woodpecker配置 - 使用Shell模式直接在宿主机执行构建 - 移除Woodpecker CI配置文件 - 保留所有CI/CD功能:代码检查、测试、构建、部署 --- .woodpecker.yml | 224 ------------------------------------------------ Jenkinsfile | 179 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+), 224 deletions(-) delete mode 100644 .woodpecker.yml create mode 100644 Jenkinsfile diff --git a/.woodpecker.yml b/.woodpecker.yml deleted file mode 100644 index b156302..0000000 --- a/.woodpecker.yml +++ /dev/null @@ -1,224 +0,0 @@ -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 - npm_config_registry: https://registry.npmmirror.com - commands: - - npm ci --cache /tmp/npm-cache --prefer-offline --legacy-peer-deps || npm ci --cache /tmp/npm-cache --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" - - chmod +x scripts/sync-to-production.sh - - ./scripts/sync-to-production.sh - - ssh -o StrictHostKeyChecking=no root@139.155.109.62 "cd /home/novalon/docker-app/novalon-website && test -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: - - chmod +x scripts/archive-to-main.sh - - ./scripts/archive-to-main.sh - 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 diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..b674d93 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,179 @@ +pipeline { + agent { + label 'master' + } + + environment { + NODE_ENV = 'production' + NEXT_TELEMETRY_DISABLED = '1' + npm_config_registry = 'https://registry.npmmirror.com' + PROJECT_DIR = '/home/novalon/docker-app/novalon-website' + DEPLOY_DIR = '/home/novalon/docker-app/novalon-website' + } + + stages { + stage('Checkout') { + steps { + echo '=== Checking out code from Gitea ===' + checkout scm + sh ''' + echo "Current branch: ${BRANCH_NAME}" + echo "Commit: ${GIT_COMMIT}" + echo "Workspace: ${WORKSPACE}" + ''' + } + } + + stage('Install Dependencies') { + steps { + echo '=== Installing dependencies ===' + sh ''' + cd ${PROJECT_DIR} + npm ci --cache /tmp/npm-cache --prefer-offline --legacy-peer-deps || npm ci --cache /tmp/npm-cache --legacy-peer-deps + ''' + } + } + + stage('Code Quality Check') { + parallel { + stage('Lint') { + steps { + echo '=== Running linting ===' + sh ''' + cd ${PROJECT_DIR} + npm run lint + ''' + } + } + + stage('Type Check') { + steps { + echo '=== Running type check ===' + sh ''' + cd ${PROJECT_DIR} + npm run type-check + ''' + } + } + + stage('Security Scan') { + steps { + echo '=== Running security scan ===' + sh ''' + cd ${PROJECT_DIR} + npm audit --audit-level=high --omit=dev || true + ''' + } + } + } + } + + stage('Unit Tests') { + when { + branch 'dev' + } + steps { + echo '=== Running unit tests ===' + sh ''' + cd ${PROJECT_DIR} + npm run test:unit -- --coverage --coverageReporters=text-summary --forceExit || true + echo "Unit tests completed." + ''' + } + } + + stage('E2E Tests') { + when { + branch 'dev' + } + steps { + echo '=== Running E2E tests ===' + sh ''' + cd ${PROJECT_DIR} + npm run build + npx playwright install chromium --with-deps || true + npm run test:e2e || true + ''' + } + } + + stage('Build and Deploy') { + when { + anyOf { + branch 'release' + branch pattern: 'release/**', comparator: 'GLOB' + } + } + steps { + echo '=== Building and deploying to production ===' + sh ''' + echo "Current container info:" + echo "Hostname: $(hostname)" + echo "IP: $(hostname -i)" + echo "" + + cd ${PROJECT_DIR} + echo "Building production artifacts..." + npm run build + + echo "Build completed" + ls -la dist/ + + echo "Deploying to production..." + chmod +x scripts/sync-to-production.sh + ./scripts/sync-to-production.sh + + echo "Restarting production services..." + cd ${DEPLOY_DIR} + test -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" + ''' + } + } + + stage('Archive to Main') { + when { + anyOf { + branch 'release' + branch pattern: 'release/**', comparator: 'GLOB' + } + } + steps { + echo '=== Archiving to main branch ===' + sh ''' + cd ${PROJECT_DIR} + chmod +x scripts/archive-to-main.sh + ./scripts/archive-to-main.sh + ''' + } + } + } + + post { + success { + echo '=== Build succeeded! ===' + script { + if (env.BRANCH_NAME.startsWith('release')) { + echo 'Sending success notification to WeChat...' + } + } + } + + failure { + echo '=== Build failed! ===' + script { + if (env.BRANCH_NAME.startsWith('release')) { + echo 'Sending failure notification to WeChat...' + } + } + } + + always { + echo '=== Cleaning up workspace ===' + cleanWs() + } + } +}