fix(acceptance): 完善跨版本验收状态收口
生产流量处于旧失败验收 Run 的 validation 状态时,允许新验收接管任意已验证的 Git 祖先 release,而非仅允许 release manifest 的直接 base;仍保留 Run 状态、镜像 digest、revision 与当前集群 release CAS 校验。\n\n允许 pending Run 在激活前异常时直接标记为 failed,避免验收工具在 CAS 或网络错误后遗留无法结束的 Run。新增祖先关系脚本测试及临时 PostgreSQL 集成验证。\n\n验证:Go 全量测试、go vet、临时 PostgreSQL 集成测试、bash -n、ShellCheck、manual-release-test。
This commit is contained in:
@@ -266,6 +266,11 @@ WHERE (
|
|||||||
id = $1::uuid
|
id = $1::uuid
|
||||||
AND status = 'running'
|
AND status = 'running'
|
||||||
)
|
)
|
||||||
|
OR (
|
||||||
|
id = $1::uuid
|
||||||
|
AND $2::text = 'failed'
|
||||||
|
AND status = 'pending'
|
||||||
|
)
|
||||||
OR (
|
OR (
|
||||||
id = $1::uuid
|
id = $1::uuid
|
||||||
AND $2::text = 'failed'
|
AND $2::text = 'failed'
|
||||||
|
|||||||
@@ -56,6 +56,11 @@ WHERE setting_key = $1`, SystemSettingGatewayTrafficMode)
|
|||||||
if strings.Contains(string(encoded), token) {
|
if strings.Contains(string(encoded), token) {
|
||||||
t.Fatal("acceptance run response exposed the raw token")
|
t.Fatal("acceptance run response exposed the raw token")
|
||||||
}
|
}
|
||||||
|
if failed, err := db.FinishAcceptanceRun(ctx, FinishAcceptanceRunInput{
|
||||||
|
RunID: run.ID, Passed: false, FailureReason: "pre-activation gate failed",
|
||||||
|
}); err != nil || failed.Status != "failed" {
|
||||||
|
t.Fatalf("finish pending acceptance run after pre-activation failure=%+v err=%v", failed, err)
|
||||||
|
}
|
||||||
mode, err := db.ActivateAcceptanceRun(ctx, run.ID)
|
mode, err := db.ActivateAcceptanceRun(ctx, run.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("activate acceptance run: %v", err)
|
t.Fatalf("activate acceptance run: %v", err)
|
||||||
|
|||||||
@@ -190,7 +190,6 @@ fi
|
|||||||
|
|
||||||
node "$cluster_root/scripts/release-manifest.mjs" validate "$release_manifest" >/dev/null
|
node "$cluster_root/scripts/release-manifest.mjs" validate "$release_manifest" >/dev/null
|
||||||
release_sha=$(node "$cluster_root/scripts/release-manifest.mjs" get "$release_manifest" sourceSha)
|
release_sha=$(node "$cluster_root/scripts/release-manifest.mjs" get "$release_manifest" sourceSha)
|
||||||
base_sha=$(node "$cluster_root/scripts/release-manifest.mjs" get "$release_manifest" baseReleaseSha)
|
|
||||||
api_image=$(node "$cluster_root/scripts/release-manifest.mjs" get "$release_manifest" images.api)
|
api_image=$(node "$cluster_root/scripts/release-manifest.mjs" get "$release_manifest" images.api)
|
||||||
[[ $release_sha =~ ^[0-9a-f]{40}$ && $api_image =~ @sha256:[0-9a-f]{64}$ ]] || {
|
[[ $release_sha =~ ^[0-9a-f]{40}$ && $api_image =~ @sha256:[0-9a-f]{64}$ ]] || {
|
||||||
echo 'release manifest is not full-SHA and digest pinned' >&2
|
echo 'release manifest is not full-SHA and digest pinned' >&2
|
||||||
@@ -1315,6 +1314,13 @@ deploy_protocol_emulator() {
|
|||||||
-n "$namespace" --timeout=300s
|
-n "$namespace" --timeout=300s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_release_ancestor() {
|
||||||
|
local ancestor=$1
|
||||||
|
local descendant=$2
|
||||||
|
[[ $ancestor =~ ^[0-9a-f]{40}$ && $descendant =~ ^[0-9a-f]{40}$ ]] &&
|
||||||
|
git -C "$cluster_root" merge-base --is-ancestor "$ancestor" "$descendant"
|
||||||
|
}
|
||||||
|
|
||||||
create_and_activate_run() {
|
create_and_activate_run() {
|
||||||
local create_response=$temporary_root/create-run.json
|
local create_response=$temporary_root/create-run.json
|
||||||
local activate_response=$temporary_root/activate-run.json
|
local activate_response=$temporary_root/activate-run.json
|
||||||
@@ -1393,8 +1399,8 @@ create_and_activate_run() {
|
|||||||
echo 'current-release validation mode has unexpected image digests' >&2
|
echo 'current-release validation mode has unexpected image digests' >&2
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
elif [[ -z $base_sha || $traffic_release != "$base_sha" ]]; then
|
elif ! is_release_ancestor "$traffic_release" "$release_sha"; then
|
||||||
echo 'refusing to replace validation mode outside the direct release base' >&2
|
echo 'refusing to replace validation mode owned by a non-ancestor release' >&2
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
body=$(jq -cn \
|
body=$(jq -cn \
|
||||||
|
|||||||
@@ -307,5 +307,6 @@ if grep -Fq 'archive_timeout: 60s' "$root/deploy/kubernetes/production/database.
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
"$root/tests/release/cluster-release-helper-test.sh" >/dev/null
|
"$root/tests/release/cluster-release-helper-test.sh" >/dev/null
|
||||||
|
"$root/tests/release/production-acceptance-script-test.sh" >/dev/null
|
||||||
|
|
||||||
echo 'manual_release_tests=PASS'
|
echo 'manual_release_tests=PASS'
|
||||||
|
|||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
root=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
|
||||||
|
tmp=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$tmp"' EXIT
|
||||||
|
|
||||||
|
script=$root/scripts/cluster/run-production-acceptance.sh
|
||||||
|
awk '
|
||||||
|
/^is_release_ancestor\(\)/ { capture = 1 }
|
||||||
|
capture && /^create_and_activate_run\(\)/ { exit }
|
||||||
|
capture { print }
|
||||||
|
' "$script" >"$tmp/is-release-ancestor.sh"
|
||||||
|
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "$tmp/is-release-ancestor.sh"
|
||||||
|
|
||||||
|
cluster_root=$tmp/repository
|
||||||
|
git init -q "$cluster_root"
|
||||||
|
git -C "$cluster_root" config user.name 'Acceptance Script Test'
|
||||||
|
git -C "$cluster_root" config user.email 'acceptance-script-test@example.invalid'
|
||||||
|
git -C "$cluster_root" commit --allow-empty -qm first
|
||||||
|
first=$(git -C "$cluster_root" rev-parse HEAD)
|
||||||
|
git -C "$cluster_root" commit --allow-empty -qm second
|
||||||
|
git -C "$cluster_root" commit --allow-empty -qm third
|
||||||
|
third=$(git -C "$cluster_root" rev-parse HEAD)
|
||||||
|
|
||||||
|
is_release_ancestor "$first" "$third"
|
||||||
|
if is_release_ancestor "$third" "$first"; then
|
||||||
|
echo 'descendant release was accepted as an ancestor' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if is_release_ancestor invalid "$third"; then
|
||||||
|
echo 'invalid release identifier was accepted as an ancestor' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo 'production_acceptance_script_tests=PASS'
|
||||||
Reference in New Issue
Block a user