CI 提速:合并门禁容器执行并拆分 Smoke/全量 E2E
This commit is contained in:
Vendored
+62
-24
@@ -1,8 +1,18 @@
|
|||||||
pipeline {
|
pipeline {
|
||||||
agent any
|
agent any
|
||||||
|
|
||||||
|
options {
|
||||||
|
skipDefaultCheckout(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
parameters {
|
||||||
|
booleanParam(name: 'RUN_FULL_E2E', defaultValue: false, description: '是否在部署后额外执行全量 E2E(失败仅标记 UNSTABLE)')
|
||||||
|
}
|
||||||
|
|
||||||
environment {
|
environment {
|
||||||
APP_NAME = 'no-whatever'
|
APP_NAME = 'no-whatever'
|
||||||
|
CI_IMAGE = 'mcr.microsoft.com/playwright:v1.51.1-jammy'
|
||||||
|
NPM_CACHE_VOLUME = 'no-whatever-npm-cache'
|
||||||
}
|
}
|
||||||
|
|
||||||
triggers {
|
triggers {
|
||||||
@@ -31,42 +41,30 @@ pipeline {
|
|||||||
sh '''
|
sh '''
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
if docker image inspect node:20-bookworm >/dev/null 2>&1; then
|
if docker image inspect ${CI_IMAGE} >/dev/null 2>&1; then
|
||||||
echo "node:20-bookworm already exists, skip pull"
|
echo "${CI_IMAGE} already exists, skip pull"
|
||||||
else
|
else
|
||||||
docker pull node:20-bookworm
|
docker pull ${CI_IMAGE}
|
||||||
fi
|
|
||||||
|
|
||||||
if docker image inspect mcr.microsoft.com/playwright:v1.51.1-jammy >/dev/null 2>&1; then
|
|
||||||
echo "mcr.microsoft.com/playwright:v1.51.1-jammy already exists, skip pull"
|
|
||||||
else
|
|
||||||
docker pull mcr.microsoft.com/playwright:v1.51.1-jammy
|
|
||||||
fi
|
fi
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stage('Quality Gate') {
|
stage('CI Gate (Lint + TypeCheck + Unit + Smoke E2E)') {
|
||||||
steps {
|
|
||||||
sh '''
|
|
||||||
set -e
|
|
||||||
cid=$(docker create node:20-bookworm sh -lc "cd /workspace && npm ci && npm run lint && npx tsc --noEmit && npm run test:coverage")
|
|
||||||
trap 'docker rm -f "$cid" >/dev/null 2>&1 || true' EXIT
|
|
||||||
docker cp . "$cid":/workspace
|
|
||||||
docker start -a "$cid"
|
|
||||||
'''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('E2E Gate') {
|
|
||||||
options {
|
options {
|
||||||
timeout(time: 20, unit: 'MINUTES')
|
timeout(time: 30, unit: 'MINUTES')
|
||||||
}
|
}
|
||||||
steps {
|
steps {
|
||||||
sh '''
|
sh '''
|
||||||
set -e
|
set -e
|
||||||
cid=$(docker create --ipc=host mcr.microsoft.com/playwright:v1.51.1-jammy sh -lc "cd /workspace && npm ci && npm run test:e2e")
|
rm -rf playwright-report test-results
|
||||||
|
cid=$(docker create --ipc=host \
|
||||||
|
-e HOME=/tmp \
|
||||||
|
-e NPM_CONFIG_CACHE=/npm-cache \
|
||||||
|
-v ${NPM_CACHE_VOLUME}:/npm-cache \
|
||||||
|
${CI_IMAGE} \
|
||||||
|
sh -lc "cd /workspace && npm ci --prefer-offline --no-audit --progress=false && npm run lint && npx tsc --noEmit && npm run test:coverage && npm run test:e2e:smoke")
|
||||||
cleanup() {
|
cleanup() {
|
||||||
docker rm -f "$cid" >/dev/null 2>&1 || true
|
docker rm -f "$cid" >/dev/null 2>&1 || true
|
||||||
}
|
}
|
||||||
@@ -123,6 +121,46 @@ pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 \
|
||||||
|
-e NPM_CONFIG_CACHE=/npm-cache \
|
||||||
|
-v ${NPM_CACHE_VOLUME}:/npm-cache \
|
||||||
|
${CI_IMAGE} \
|
||||||
|
sh -lc "cd /workspace && npm ci --prefer-offline --no-audit --progress=false && npm run test:e2e")
|
||||||
|
cleanup() {
|
||||||
|
docker rm -f "$cid" >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
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 {
|
post {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { test, expect } from "@playwright/test";
|
import { test, expect } from "@playwright/test";
|
||||||
|
|
||||||
test("首页模式卡片可正确导航", async ({ page }) => {
|
test("@smoke 首页模式卡片可正确导航", async ({ page }) => {
|
||||||
await page.goto("/");
|
await page.goto("/");
|
||||||
await expect(page.getByRole("heading", { name: "NoWhatever" })).toBeVisible();
|
await expect(page.getByRole("heading", { name: "NoWhatever" })).toBeVisible();
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { test, expect } from "@playwright/test";
|
import { test, expect } from "@playwright/test";
|
||||||
|
|
||||||
test("Panic 手动加入房间会规范化房间号并发起 join 请求", async ({ page }) => {
|
test("@smoke Panic 手动加入房间会规范化房间号并发起 join 请求", async ({ page }) => {
|
||||||
const joinBodies: Array<{ userId?: string }> = [];
|
const joinBodies: Array<{ userId?: string }> = [];
|
||||||
|
|
||||||
await page.route("**/api/room/*/join", async (route) => {
|
await page.route("**/api/room/*/join", async (route) => {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
"test:watch": "vitest",
|
"test:watch": "vitest",
|
||||||
"test:coverage": "vitest run --coverage",
|
"test:coverage": "vitest run --coverage",
|
||||||
"test:e2e:install": "playwright install chromium",
|
"test:e2e:install": "playwright install chromium",
|
||||||
|
"test:e2e:smoke": "playwright test --grep @smoke",
|
||||||
"test:e2e": "playwright test",
|
"test:e2e": "playwright test",
|
||||||
"test:e2e:headed": "playwright test --headed"
|
"test:e2e:headed": "playwright test --headed"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user