Files
baiyue-firstleg/scripts/test-environment-pipeline-contract.test.mjs
T

114 lines
6.4 KiB
JavaScript

import assert from 'node:assert/strict'
import { readFile } from 'node:fs/promises'
import test from 'node:test'
const pipeline = (await readFile(new URL('../Jenkinsfile.service', import.meta.url), 'utf8'))
.replaceAll('\r\n', '\n')
const coordinatorPipeline = (await readFile(new URL('../Jenkinsfile', import.meta.url), 'utf8'))
.replaceAll('\r\n', '\n')
const directDeployScript = (await readFile(new URL('../deploy/scripts/deploy-built-service.sh', import.meta.url), 'utf8'))
.replaceAll('\r\n', '\n')
const ciMavenSettings = (await readFile(new URL('../deploy/maven/settings-ci.xml', import.meta.url), 'utf8'))
.replaceAll('\r\n', '\n')
const serviceDockerfile = (await readFile(new URL('../deploy/docker/Dockerfile', import.meta.url), 'utf8'))
.replaceAll('\r\n', '\n')
test('test deployments compile packages without rerunning the full unit test suite', () => {
assert.match(pipeline, /params\.ENVIRONMENT == 'test' \|\| params\.SKIP_TESTS/)
assert.match(pipeline, /skipTestExecution \? '-DskipTests' : ''/)
assert.match(pipeline, /-pl \$\{env\.RESOLVED_SERVICE\} -am clean package/)
assert.doesNotMatch(pipeline, /-Dmaven\.test\.skip=true/)
})
test('coordinator jobs present their own deployment environment as the default choice', () => {
assert.match(coordinatorPipeline, /jobBaseName == 'backend-java-dev'/)
assert.match(coordinatorPipeline, /\? \['development', 'test', 'staging', 'production'\]/)
assert.match(coordinatorPipeline, /: \['test', 'development', 'staging', 'production'\]/)
assert.match(coordinatorPipeline, /environmentChoicesForJob\(env\.JOB_BASE_NAME\)/)
assert.match(coordinatorPipeline, /jobBaseName == 'backend-java-dev'[\s\S]*?'baiyue-firstleg-dev-'/)
assert.match(coordinatorPipeline, /downstreamJobPrefixForJob\(env\.JOB_BASE_NAME\)/)
})
test('production deployments cannot skip tests', () => {
assert.match(pipeline, /params\.ENVIRONMENT == 'production' && params\.SKIP_TESTS/)
assert.match(pipeline, /error\('生产环境禁止跳过测试'\)/)
})
test('Java builds use the shared builder pool and serialize incremental target deployments', () => {
assert.match(pipeline, /agent \{ label 'java-builder' \}/)
assert.match(pipeline, /\['development', 'test'\]\.contains\(params\.ENVIRONMENT\)/)
assert.match(pipeline, /params\.ENVIRONMENT == 'development' \? 'java-dev' : 'java-test'/)
assert.match(pipeline, /'TARGET_IS_LOCAL=true'/)
assert.match(pipeline, /String deployLock = "firstleg-\$\{params\.ENVIRONMENT\}-deploy"/)
assert.match(pipeline, /lock\(resource: deployLock, inversePrecedence: true\)/)
assert.match(pipeline, /deploy-built-service\.sh/)
assert.doesNotMatch(pipeline, /dev_deploy|test_deploy|TARGET_SSH_KEY/)
assert.match(directDeployScript, /docker pull "\$IMAGE"/)
assert.match(directDeployScript, /run_ssh docker pull "\$IMAGE"/)
assert.doesNotMatch(directDeployScript, /docker save "\$IMAGE"/)
assert.match(directDeployScript, /--pull never/)
})
test('parallel remote deployments keep env and compose assets isolated by project', () => {
assert.match(directDeployScript, /REMOTE_ENV_NAME="\.env\.\$PROJECT_NAME"/)
assert.match(directDeployScript, /REMOTE_COMPOSE_NAME="docker-compose\.\$PROJECT_NAME\.yml"/)
assert.match(directDeployScript, /REMOTE_ENV_TMP="\$REMOTE_DIR\/\$REMOTE_ENV_NAME\.\$SUFFIX\.tmp"/)
assert.match(directDeployScript, /REMOTE_COMPOSE_TMP="\$REMOTE_DIR\/\$REMOTE_COMPOSE_NAME\.\$SUFFIX\.tmp"/)
assert.match(directDeployScript, /env_target="\$3"/)
assert.match(directDeployScript, /compose_target="\$4"/)
assert.match(directDeployScript, /mv -f "\$env_tmp" "\$env_target"/)
assert.match(directDeployScript, /mv -f "\$compose_tmp" "\$compose_target"/)
assert.match(directDeployScript, /env_file="\$7"/)
assert.match(directDeployScript, /compose_file="\$8"/)
assert.match(directDeployScript, /--env-file "\$env_file"/)
assert.match(directDeployScript, /-f "\$compose_file"/)
assert.doesNotMatch(directDeployScript, /mv -f "\$env_tmp" "\$remote_dir\/\.env"/)
assert.doesNotMatch(directDeployScript, /mv -f "\$compose_tmp" "\$remote_dir\/docker-compose\.yml"/)
assert.doesNotMatch(directDeployScript, /--env-file \.env/)
assert.doesNotMatch(directDeployScript, /-f docker-compose\.yml/)
})
test('shared builders use a reachable public Maven mirror instead of the retired private proxy', () => {
assert.match(pipeline, /MAVEN_SETTINGS = 'deploy\/maven\/settings-ci\.xml'/)
assert.match(ciMavenSettings, /https:\/\/maven\.aliyun\.com\/repository\/public/)
assert.doesNotMatch(ciMavenSettings, /:18081/)
})
test('Java service images use the internal registry base image by default', () => {
const internalBaseImage = '172.31.198.7:10082/java-project/eclipse-temurin:17-jre-alpine'
assert.match(coordinatorPipeline, new RegExp(internalBaseImage.replaceAll('.', '\\.')))
assert.match(pipeline, new RegExp(internalBaseImage.replaceAll('.', '\\.')))
assert.match(serviceDockerfile, new RegExp(internalBaseImage.replaceAll('.', '\\.')))
assert.doesNotMatch(coordinatorPipeline, /docker\.m\.daocloud\.io\/library\/eclipse-temurin/)
assert.doesNotMatch(pipeline, /docker\.m\.daocloud\.io\/library\/eclipse-temurin/)
assert.doesNotMatch(serviceDockerfile, /docker\.m\.daocloud\.io\/library\/eclipse-temurin/)
})
test('source workspaces are preserved for incremental Git fetches', () => {
const buildStage = pipeline.slice(
pipeline.indexOf("stage('构建并发布单服务')"),
pipeline.indexOf("stage('部署开发或测试环境')")
)
const directDeployStage = pipeline.slice(
pipeline.indexOf("stage('部署开发或测试环境')"),
pipeline.indexOf("stage('部署单个服务')")
)
assert.match(pipeline, /checkout scm/)
assert.doesNotMatch(buildStage, /cleanWs\(/)
assert.match(directDeployStage, /cleanWs\(/)
assert.equal((pipeline.match(/cleanWs\(/g) ?? []).length, 2)
assert.doesNotMatch(coordinatorPipeline, /cleanWs\(/)
})
test('direct deployments wait for health and automatically restore the previous image', () => {
assert.match(directDeployScript, /HEALTH_TIMEOUT_SECONDS="\$\{DEPLOY_HEALTH_TIMEOUT_SECONDS:-240\}"/)
assert.match(directDeployScript, /previous_image="\$\(local_container_image \|\| true\)"/)
assert.match(directDeployScript, /if wait_for_local_health; then/)
assert.match(directDeployScript, /开始自动回滚到/)
assert.match(directDeployScript, /自动回滚成功/)
assert.match(directDeployScript, /自动回滚失败/)
assert.match(directDeployScript, /return 1/)
})