优化
This commit is contained in:
Vendored
+23
-9
@@ -60,14 +60,15 @@ def databaseMigrationPaths = ['deploy/sql/']
|
|||||||
def downstreamResults = [:]
|
def downstreamResults = [:]
|
||||||
|
|
||||||
def parseAutoBuildState(String description, List<String> allowedServices) {
|
def parseAutoBuildState(String description, List<String> allowedServices) {
|
||||||
String marker = ' | RESULTS'
|
if (!description?.startsWith('AUTO ')) return null
|
||||||
if (!description?.startsWith('AUTO ') || !description.contains(marker)) return null
|
int markerIndex = description.indexOf(' | ')
|
||||||
int markerIndex = description.indexOf(marker)
|
if (markerIndex < 0) return null
|
||||||
String commit = description.substring('AUTO '.length(), markerIndex).trim()
|
String commit = description.substring('AUTO '.length(), markerIndex).trim()
|
||||||
if (!(commit ==~ /[0-9a-fA-F]{7,40}/)) return null
|
if (!(commit ==~ /[0-9a-fA-F]{7,40}/)) return null
|
||||||
String summary = description.substring(markerIndex + marker.length()).trim()
|
String state = description.substring(markerIndex + ' | '.length()).trim()
|
||||||
List<String> failedServices = []
|
List<String> failedServices = []
|
||||||
if (summary) {
|
if (state.startsWith('RESULTS')) {
|
||||||
|
String summary = state.substring('RESULTS'.length()).trim()
|
||||||
summary.split(',').collect { it.trim() }.findAll { it }.each { item ->
|
summary.split(',').collect { it.trim() }.findAll { it }.each { item ->
|
||||||
int separator = item.indexOf('=')
|
int separator = item.indexOf('=')
|
||||||
if (separator > 0) {
|
if (separator > 0) {
|
||||||
@@ -76,6 +77,17 @@ def parseAutoBuildState(String description, List<String> allowedServices) {
|
|||||||
if (allowedServices.contains(service) && result != 'SUCCESS') failedServices << service
|
if (allowedServices.contains(service) && result != 'SUCCESS') failedServices << service
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (state.startsWith('PENDING')) {
|
||||||
|
// 上一轮若在统一测试、排队或并行部署期间失败/取消,description 仍是 PENDING。
|
||||||
|
// 将该轮已选服务作为精确补跑范围,同时让 Git 基线前进到该轮提交,
|
||||||
|
// 避免回退到很早的成功构建后把历史公共文件再次解释成全量变更。
|
||||||
|
String selected = state.substring('PENDING'.length()).trim()
|
||||||
|
int suffixIndex = selected.indexOf(' | ')
|
||||||
|
if (suffixIndex >= 0) selected = selected.substring(0, suffixIndex).trim()
|
||||||
|
failedServices.addAll(selected.split(',').collect { it.trim() }
|
||||||
|
.findAll { allowedServices.contains(it) })
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
return [commit: commit, failedServices: failedServices.unique()]
|
return [commit: commit, failedServices: failedServices.unique()]
|
||||||
}
|
}
|
||||||
@@ -85,7 +97,8 @@ def previousAutoBuildState(def previousBuild, List<String> allowedServices) {
|
|||||||
int inspected = 0
|
int inspected = 0
|
||||||
while (candidate != null && inspected < 30) {
|
while (candidate != null && inspected < 30) {
|
||||||
def state = parseAutoBuildState(candidate.description, allowedServices)
|
def state = parseAutoBuildState(candidate.description, allowedServices)
|
||||||
if (state != null && ['SUCCESS', 'UNSTABLE'].contains(candidate.result)) return state
|
// 完成的 RESULTS 和中断留下的 PENDING 都能推进 AUTO 基线;PENDING 中的服务会被精确补跑。
|
||||||
|
if (state != null) return state
|
||||||
candidate = candidate.previousBuild
|
candidate = candidate.previousBuild
|
||||||
inspected++
|
inspected++
|
||||||
}
|
}
|
||||||
@@ -190,9 +203,10 @@ pipeline {
|
|||||||
String base = autoState?.commit?.trim()
|
String base = autoState?.commit?.trim()
|
||||||
List retryServices = autoState?.failedServices ?: []
|
List retryServices = autoState?.failedServices ?: []
|
||||||
if (!base) {
|
if (!base) {
|
||||||
// 首次启用新算法时兼容旧构建记录;后续只读取标记为 AUTO 的完成记录,
|
// 首次启用或旧构建记录已淘汰时,只比较当前提交的直接父提交。
|
||||||
// SELECT/ALL 不会推进 AUTO 基线。
|
// 需要初始化全部服务时应显式使用 ALL,不能因历史成功基线过旧而意外全量部署。
|
||||||
base = env.GIT_PREVIOUS_SUCCESSFUL_COMMIT?.trim()
|
base = sh(script: 'git rev-parse HEAD^ 2>/dev/null || true', returnStdout: true).trim()
|
||||||
|
if (base) echo "AUTO 未找到历史记录,本次使用直接父提交作为基线: ${base}"
|
||||||
}
|
}
|
||||||
if (!base || sh(script: "git cat-file -e ${base}^{commit} 2>/dev/null", returnStatus: true) != 0) {
|
if (!base || sh(script: "git cat-file -e ${base}^{commit} 2>/dev/null", returnStatus: true) != 0) {
|
||||||
selected = serviceModules
|
selected = serviceModules
|
||||||
|
|||||||
@@ -37,13 +37,17 @@ test('coordinator jobs present their own deployment environment as the default c
|
|||||||
assert.match(coordinatorPipeline, /downstreamJobPrefixForJob\(env\.JOB_BASE_NAME\)/)
|
assert.match(coordinatorPipeline, /downstreamJobPrefixForJob\(env\.JOB_BASE_NAME\)/)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('AUTO keeps its own baseline and retries only previously failed services', () => {
|
test('AUTO advances interrupted baselines and retries only their selected services', () => {
|
||||||
assert.match(coordinatorPipeline, /def parseAutoBuildState\(/)
|
assert.match(coordinatorPipeline, /def parseAutoBuildState\(/)
|
||||||
assert.match(coordinatorPipeline, /def previousAutoBuildState\(/)
|
assert.match(coordinatorPipeline, /def previousAutoBuildState\(/)
|
||||||
assert.match(coordinatorPipeline, /previousAutoBuildState\(currentBuild\.previousBuild, serviceModules\)/)
|
assert.match(coordinatorPipeline, /previousAutoBuildState\(currentBuild\.previousBuild, serviceModules\)/)
|
||||||
|
assert.match(coordinatorPipeline, /state\.startsWith\('PENDING'\)/)
|
||||||
|
assert.match(coordinatorPipeline, /failedServices\.addAll\(selected\.split\(','\)/)
|
||||||
|
assert.match(coordinatorPipeline, /git rev-parse HEAD\^/)
|
||||||
assert.match(coordinatorPipeline, /selected\.addAll\(retryServices\)/)
|
assert.match(coordinatorPipeline, /selected\.addAll\(retryServices\)/)
|
||||||
assert.match(coordinatorPipeline, /AUTO \$\{env\.IMAGE_TAG\} \| PENDING/)
|
assert.match(coordinatorPipeline, /AUTO \$\{env\.IMAGE_TAG\} \| PENDING/)
|
||||||
assert.match(coordinatorPipeline, /AUTO \$\{env\.IMAGE_TAG\} \| RESULTS/)
|
assert.match(coordinatorPipeline, /AUTO \$\{env\.IMAGE_TAG\} \| RESULTS/)
|
||||||
|
assert.doesNotMatch(coordinatorPipeline, /GIT_PREVIOUS_SUCCESSFUL_COMMIT/)
|
||||||
assert.doesNotMatch(coordinatorPipeline, /commonChanged \? serviceModules/)
|
assert.doesNotMatch(coordinatorPipeline, /commonChanged \? serviceModules/)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user