release: include latest TEST revision memory guard
This commit is contained in:
@@ -125,6 +125,14 @@ pipeline {
|
|||||||
git cat-file -e "${RESOLVED_SOURCE_COMMIT}^{commit}"
|
git cat-file -e "${RESOLVED_SOURCE_COMMIT}^{commit}"
|
||||||
git checkout --detach "${RESOLVED_SOURCE_COMMIT}"
|
git checkout --detach "${RESOLVED_SOURCE_COMMIT}"
|
||||||
test "$(git rev-parse HEAD)" = "$(git rev-parse "${RESOLVED_SOURCE_COMMIT}^{commit}")"
|
test "$(git rev-parse HEAD)" = "$(git rev-parse "${RESOLVED_SOURCE_COMMIT}^{commit}")"
|
||||||
|
# TEST 重发旧提交也须包含限额文件及部署入口,避免重建时恢复无限制容器。
|
||||||
|
if [ "$RESOLVED_ENVIRONMENT" = "test" ]; then
|
||||||
|
if ! git cat-file -e "${RESOLVED_SOURCE_COMMIT}:deploy/docker-compose.test-limits.yml" 2>/dev/null ||
|
||||||
|
! git grep -q -F 'docker-compose.test-limits.yml' "$RESOLVED_SOURCE_COMMIT" -- deploy/scripts/deploy-built-service.sh; then
|
||||||
|
echo "目标 TEST 提交缺少完整内存保护,请选择包含限额修复的 test 提交" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
if [ "$RESOLVED_ENVIRONMENT" = "production" ]; then
|
if [ "$RESOLVED_ENVIRONMENT" = "production" ]; then
|
||||||
git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main
|
git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main
|
||||||
git merge-base --is-ancestor "$RESOLVED_SOURCE_COMMIT" origin/main || {
|
git merge-base --is-ancestor "$RESOLVED_SOURCE_COMMIT" origin/main || {
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import assert from 'node:assert/strict'
|
import assert from 'node:assert/strict'
|
||||||
import { readFile } from 'node:fs/promises'
|
import { existsSync } from 'node:fs'
|
||||||
|
import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
|
||||||
|
import { spawnSync } from 'node:child_process'
|
||||||
|
import { tmpdir } from 'node:os'
|
||||||
|
import { dirname, join, resolve } from 'node:path'
|
||||||
import test from 'node:test'
|
import test from 'node:test'
|
||||||
|
|
||||||
const pipeline = (await readFile(new URL('../Jenkinsfile.service', import.meta.url), 'utf8'))
|
const pipeline = (await readFile(new URL('../Jenkinsfile.service', import.meta.url), 'utf8'))
|
||||||
@@ -15,6 +19,60 @@ const serviceDockerfile = (await readFile(new URL('../deploy/docker/Dockerfile',
|
|||||||
const serviceCompose = (await readFile(new URL('../deploy/docker-compose.yml', import.meta.url), 'utf8'))
|
const serviceCompose = (await readFile(new URL('../deploy/docker-compose.yml', import.meta.url), 'utf8'))
|
||||||
.replaceAll('\r\n', '\n')
|
.replaceAll('\r\n', '\n')
|
||||||
|
|
||||||
|
test('TEST rejects old source commits even when the workspace contains newer limits files', {
|
||||||
|
skip: process.platform === 'win32' && !existsSync('C:/Program Files/Git/bin/bash.exe')
|
||||||
|
}, async () => {
|
||||||
|
const directory = await mkdtemp(join(tmpdir(), 'test-memory-source-'))
|
||||||
|
const bash = process.platform === 'win32' ? 'C:/Program Files/Git/bin/bash.exe' : 'bash'
|
||||||
|
const guardStart = pipeline.indexOf('if [ "$RESOLVED_ENVIRONMENT" = "test" ]; then')
|
||||||
|
const guardEnd = pipeline.indexOf('if [ "$RESOLVED_ENVIRONMENT" = "production" ]; then', guardStart)
|
||||||
|
assert.ok(guardStart >= 0 && guardEnd > guardStart)
|
||||||
|
assert.ok(guardStart < pipeline.indexOf("stage('Maven 测试与打包')"))
|
||||||
|
const guard = pipeline.slice(guardStart, guardEnd)
|
||||||
|
// 在微型 Git 夹具中验证目标提交本身,避免工作区残留文件误放行旧版本。
|
||||||
|
const git = (...args) => {
|
||||||
|
const result = spawnSync('git', args, { cwd: directory, encoding: 'utf8' })
|
||||||
|
assert.equal(result.status, 0, result.stderr)
|
||||||
|
return result.stdout.trim()
|
||||||
|
}
|
||||||
|
// 构建提交沿用正常身份设置,但禁止夹具触发全局签名及提交钩子。
|
||||||
|
const commit = (message) => {
|
||||||
|
git('add', '.')
|
||||||
|
git('-c', 'user.name=Resource Contract', '-c', 'user.email=resource@example.invalid',
|
||||||
|
'-c', 'core.hooksPath=/dev/null', 'commit', '--no-gpg-sign', '-m', message)
|
||||||
|
return git('rev-parse', 'HEAD')
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
git('init')
|
||||||
|
await writeFile(join(directory, 'README.md'), 'Source guard fixture\n')
|
||||||
|
const oldCommit = commit('old source')
|
||||||
|
await mkdir(join(directory, 'deploy/scripts'), { recursive: true })
|
||||||
|
await writeFile(join(directory, 'deploy/docker-compose.test-limits.yml'), 'services: {}\n')
|
||||||
|
await writeFile(join(directory, 'deploy/scripts/deploy-built-service.sh'), '#!/bin/sh\nexit 0\n')
|
||||||
|
const incompleteCommit = commit('limits file without deployment integration')
|
||||||
|
await writeFile(join(directory, 'deploy/scripts/deploy-built-service.sh'), directDeployScript)
|
||||||
|
const protectedCommit = commit('complete memory protection')
|
||||||
|
git('checkout', '--detach', oldCommit)
|
||||||
|
await mkdir(join(directory, 'deploy/scripts'), { recursive: true })
|
||||||
|
await writeFile(join(directory, 'deploy/docker-compose.test-limits.yml'), 'services: {}\n')
|
||||||
|
await writeFile(join(directory, 'deploy/scripts/deploy-built-service.sh'), directDeployScript)
|
||||||
|
for (const [environment, sourceCommit, status] of [
|
||||||
|
['test', oldCommit, 1], ['test', incompleteCommit, 1],
|
||||||
|
['test', protectedCommit, 0], ['production', oldCommit, 0]
|
||||||
|
]) {
|
||||||
|
const result = spawnSync(bash, ['-c', guard], {
|
||||||
|
cwd: directory, encoding: 'utf8', timeout: 10000,
|
||||||
|
env: { ...process.env, RESOLVED_ENVIRONMENT: environment, RESOLVED_SOURCE_COMMIT: sourceCommit }
|
||||||
|
})
|
||||||
|
assert.equal(result.status, status, result.stderr)
|
||||||
|
if (status !== 0) assert.match(result.stderr, /目标 TEST 提交缺少完整内存保护/)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
assert.equal(dirname(resolve(directory)), resolve(tmpdir()))
|
||||||
|
await rm(directory, { recursive: true, force: true })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
test('both pipelines reject the placeholder registry from failed build 662 before Maven or Docker', () => {
|
test('both pipelines reject the placeholder registry from failed build 662 before Maven or Docker', () => {
|
||||||
for (const source of [coordinatorPipeline, pipeline]) {
|
for (const source of [coordinatorPipeline, pipeline]) {
|
||||||
assert.match(source, /string\(name: 'IMAGE_REPOSITORY', defaultValue: params\.IMAGE_REPOSITORY \?: ''/,
|
assert.match(source, /string\(name: 'IMAGE_REPOSITORY', defaultValue: params\.IMAGE_REPOSITORY \?: ''/,
|
||||||
|
|||||||
Reference in New Issue
Block a user