Files
no-whatever/Jenkinsfile
T

198 lines
7.2 KiB
Groovy
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
pipeline {
agent any
options {
skipDefaultCheckout(true)
}
parameters {
booleanParam(name: 'RUN_FULL_E2E', defaultValue: false, description: '是否在部署后额外执行全量 E2E(失败仅标记 UNSTABLE')
booleanParam(name: 'RUN_COVERAGE', defaultValue: false, description: '是否在主链路执行覆盖率测试(关闭可提速)')
}
environment {
APP_NAME = 'no-whatever'
CI_IMAGE = 'mcr.microsoft.com/playwright:v1.51.1-jammy'
NPM_REGISTRY = 'https://registry.npmmirror.com'
}
triggers {
GenericTrigger(tokenCredentialId: 'no-whatever-deploy-token')
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Runtime Check') {
steps {
sh 'docker --version'
}
}
stage('Prepare Test Images') {
options {
timeout(time: 15, unit: 'MINUTES')
}
steps {
retry(2) {
sh '''
set -e
if docker image inspect ${CI_IMAGE} >/dev/null 2>&1; then
echo "${CI_IMAGE} already exists, skip pull"
else
docker pull ${CI_IMAGE}
fi
'''
}
}
}
stage('Prepare CI Deps Image') {
options {
timeout(time: 20, unit: 'MINUTES')
}
steps {
script {
env.LOCK_HASH = sh(script: "sha256sum package-lock.json | cut -d ' ' -f1", returnStdout: true).trim()
env.CI_DEPS_IMAGE = "${APP_NAME}-ci-deps:${env.LOCK_HASH}"
}
sh '''
set -e
if docker image inspect "${CI_DEPS_IMAGE}" >/dev/null 2>&1; then
echo "deps image cache hit: ${CI_DEPS_IMAGE}"
else
echo "deps image cache miss, building: ${CI_DEPS_IMAGE}"
docker build \
--build-arg CI_IMAGE=${CI_IMAGE} \
--build-arg NPM_REGISTRY=${NPM_REGISTRY} \
-f Dockerfile.ci-deps \
-t "${CI_DEPS_IMAGE}" .
fi
'''
}
}
stage('CI Gate (Lint + TypeCheck + Unit + Smoke E2E)') {
options {
timeout(time: 30, unit: 'MINUTES')
}
steps {
sh '''
set -e
rm -rf playwright-report test-results
cid=$(docker create --ipc=host \
-e HOME=/tmp \
-e RUN_COVERAGE=${RUN_COVERAGE} \
${CI_DEPS_IMAGE} \
sh -lc 'set -e; cd /workspace; npx prisma generate; npm run lint; npx tsc --noEmit; if [ "$RUN_COVERAGE" = "true" ]; then npm run test:coverage; else npm run test; fi; npm run test:e2e:smoke')
cleanup() {
docker rm -f "$cid" >/dev/null 2>&1 || true
}
trap cleanup EXIT
git archive --format=tar HEAD | docker cp - "$cid":/workspace
set +e
docker start -a "$cid"
status=$?
set -e
docker cp "$cid":/workspace/playwright-report ./playwright-report 2>/dev/null || true
docker cp "$cid":/workspace/test-results ./test-results 2>/dev/null || true
exit $status
'''
}
post {
always {
archiveArtifacts artifacts: 'playwright-report/**,test-results/**', allowEmptyArchive: true
}
}
}
stage('Build Docker Image') {
steps {
withCredentials([
string(credentialsId: 'amap-api-key', variable: 'AMAP_KEY')
]) {
sh "docker build --build-arg NEXT_PUBLIC_AMAP_API_KEY=${AMAP_KEY} -t ${APP_NAME}:${BUILD_NUMBER} -t ${APP_NAME}:latest ."
}
}
}
stage('Deploy') {
steps {
withCredentials([
string(credentialsId: 'amap-api-key', variable: 'AMAP_KEY'),
string(credentialsId: 'deepseek-api-key', variable: 'DEEPSEEK_KEY')
]) {
sh """
docker stop ${APP_NAME} || true
docker rm ${APP_NAME} || true
mkdir -p /data/${APP_NAME}
chown 1001:1001 /data/${APP_NAME}
docker run -d \
--name ${APP_NAME} \
--network nginx \
-p 3721:3721 \
-v /data/${APP_NAME}:/app/data \
-e DATABASE_URL=file:/app/data/prod.db \
-e AMAP_API_KEY=${AMAP_KEY} \
-e DEEPSEEK_API_KEY=${DEEPSEEK_KEY} \
--restart unless-stopped \
${APP_NAME}:latest
"""
}
}
}
stage('Full E2E (Optional, Non-Blocking)') {
when {
expression { return params.RUN_FULL_E2E }
}
options {
timeout(time: 30, unit: 'MINUTES')
}
steps {
catchError(buildResult: 'UNSTABLE', stageResult: 'UNSTABLE') {
sh '''
set -e
rm -rf playwright-report-full test-results-full
cid=$(docker create --ipc=host \
-e HOME=/tmp \
${CI_DEPS_IMAGE} \
sh -lc 'set -e; cd /workspace; npx prisma generate; npm run test:e2e')
cleanup() {
docker rm -f "$cid" >/dev/null 2>&1 || true
}
trap cleanup EXIT
git archive --format=tar HEAD | docker cp - "$cid":/workspace
set +e
docker start -a "$cid"
status=$?
set -e
docker cp "$cid":/workspace/playwright-report ./playwright-report-full 2>/dev/null || true
docker cp "$cid":/workspace/test-results ./test-results-full 2>/dev/null || true
exit $status
'''
}
}
post {
always {
archiveArtifacts artifacts: 'playwright-report-full/**,test-results-full/**', allowEmptyArchive: true
}
}
}
}
post {
success {
echo "Deployed ${APP_NAME} build #${BUILD_NUMBER} successfully"
}
failure {
echo "Build #${BUILD_NUMBER} failed"
}
}
}