diff --git a/Dockerfile.ci-deps b/Dockerfile.ci-deps new file mode 100644 index 0000000..c9b58e4 --- /dev/null +++ b/Dockerfile.ci-deps @@ -0,0 +1,8 @@ +ARG CI_IMAGE=mcr.microsoft.com/playwright:v1.51.1-jammy +FROM ${CI_IMAGE} + +ARG NPM_REGISTRY=https://registry.npmmirror.com +WORKDIR /workspace + +COPY package.json package-lock.json ./ +RUN npm config set registry ${NPM_REGISTRY} && npm ci --prefer-offline --no-audit --progress=false diff --git a/Jenkinsfile b/Jenkinsfile index 8f232d6..bd41954 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -12,9 +12,6 @@ pipeline { environment { APP_NAME = 'no-whatever' CI_IMAGE = 'mcr.microsoft.com/playwright:v1.51.1-jammy' - NPM_CACHE_VOLUME = 'no-whatever-npm-cache' - NODE_MODULES_VOLUME = 'no-whatever-node-modules' - NPM_LOCK_HASH_FILE = '/npm-cache/no-whatever-package-lock.sha256' NPM_REGISTRY = 'https://registry.npmmirror.com' } @@ -54,6 +51,31 @@ pipeline { } } + 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') @@ -64,22 +86,8 @@ pipeline { rm -rf playwright-report test-results cid=$(docker create --ipc=host \ -e HOME=/tmp \ - -e NPM_CONFIG_CACHE=/npm-cache \ - -e NPM_CONFIG_REGISTRY=${NPM_REGISTRY} \ - -e NPM_LOCK_HASH_FILE=${NPM_LOCK_HASH_FILE} \ - -v ${NPM_CACHE_VOLUME}:/npm-cache \ - -v ${NODE_MODULES_VOLUME}:/workspace/node_modules \ - ${CI_IMAGE} \ - sh -lc 'set -e; cd /workspace; \ - lock_hash=$(sha256sum package-lock.json | cut -d " " -f1); \ - cached_hash=$(cat "$NPM_LOCK_HASH_FILE" 2>/dev/null || true); \ - if [ "$lock_hash" = "$cached_hash" ] && [ -d node_modules ] && [ "$(ls -A node_modules 2>/dev/null)" ]; then \ - echo "node_modules cache hit, skip npm ci"; \ - else \ - npm ci --prefer-offline --no-audit --progress=false; \ - printf "%s" "$lock_hash" > "$NPM_LOCK_HASH_FILE"; \ - fi; \ - npm run lint; npx tsc --noEmit; npm run test:coverage; npm run test:e2e:smoke') + ${CI_DEPS_IMAGE} \ + sh -lc 'set -e; cd /workspace; npm run lint; npx tsc --noEmit; npm run test:coverage; npm run test:e2e:smoke') cleanup() { docker rm -f "$cid" >/dev/null 2>&1 || true } @@ -151,22 +159,8 @@ pipeline { rm -rf playwright-report-full test-results-full cid=$(docker create --ipc=host \ -e HOME=/tmp \ - -e NPM_CONFIG_CACHE=/npm-cache \ - -e NPM_CONFIG_REGISTRY=${NPM_REGISTRY} \ - -e NPM_LOCK_HASH_FILE=${NPM_LOCK_HASH_FILE} \ - -v ${NPM_CACHE_VOLUME}:/npm-cache \ - -v ${NODE_MODULES_VOLUME}:/workspace/node_modules \ - ${CI_IMAGE} \ - sh -lc 'set -e; cd /workspace; \ - lock_hash=$(sha256sum package-lock.json | cut -d " " -f1); \ - cached_hash=$(cat "$NPM_LOCK_HASH_FILE" 2>/dev/null || true); \ - if [ "$lock_hash" = "$cached_hash" ] && [ -d node_modules ] && [ "$(ls -A node_modules 2>/dev/null)" ]; then \ - echo "node_modules cache hit, skip npm ci"; \ - else \ - npm ci --prefer-offline --no-audit --progress=false; \ - printf "%s" "$lock_hash" > "$NPM_LOCK_HASH_FILE"; \ - fi; \ - npm run test:e2e') + ${CI_DEPS_IMAGE} \ + sh -lc 'set -e; cd /workspace; npm run test:e2e') cleanup() { docker rm -f "$cid" >/dev/null 2>&1 || true }