WROAD2 增加受控上线每日巡检

这个提交包含在:
2026-05-20 12:28:40 +08:00
父节点 123ebc9c95
当前提交 512a58d40e
共修改 15 个文件,包含 310 行新增和 71 行删除
+185
查看文件
@@ -0,0 +1,185 @@
#!/usr/bin/env bash
set -u -o pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
SERVER_DIR="$ROOT_DIR/server"
PUBLIC_BASE_URL="${LIVE_SMOKE_BASE_URL:-https://oa.hyinda.com}"
REPORT_DIR="${WROAD2_OPS_REPORT_DIR:-$ROOT_DIR/artifacts/qa-flow/wroad2-ops-$(date +%Y%m%d-%H%M%S)}"
SUMMARY_TXT="$REPORT_DIR/summary.txt"
STATUS=0
FINDING_COUNT=0
mkdir -p "$REPORT_DIR"
: >"$SUMMARY_TXT"
load_default_env() {
local env_file="${WROAD2_OPS_ENV_FILE:-$HOME/.hyb-oa/live-smoke.env}"
if [[ "${WROAD2_OPS_SKIP_ENV_FILE:-0}" == "1" || ! -f "$env_file" ]]; then
return 0
fi
set -a
# shellcheck disable=SC1090
source "$env_file"
set +a
PUBLIC_BASE_URL="${LIVE_SMOKE_BASE_URL:-$PUBLIC_BASE_URL}"
echo "[wroad2-ops] loaded masked env file" | tee -a "$SUMMARY_TXT"
}
run_step() {
local name="$1"
shift
local log_file="$REPORT_DIR/${name}.log"
echo ">>> [wroad2-ops] $name" | tee -a "$SUMMARY_TXT"
if "$@" > >(tee "$log_file") 2>&1; then
echo "[wroad2-ops][PASS] $name" | tee -a "$SUMMARY_TXT"
else
local code="$?"
echo "[wroad2-ops][FAIL] $name exit=$code" | tee -a "$SUMMARY_TXT"
STATUS=1
fi
}
run_finding_step() {
local name="$1"
shift
local log_file="$REPORT_DIR/${name}.log"
echo ">>> [wroad2-ops] $name" | tee -a "$SUMMARY_TXT"
if "$@" > >(tee "$log_file") 2>&1; then
echo "[wroad2-ops][PASS] $name" | tee -a "$SUMMARY_TXT"
else
local code="$?"
echo "[wroad2-ops][FINDING] $name exit=$code" | tee -a "$SUMMARY_TXT"
FINDING_COUNT=$((FINDING_COUNT + 1))
fi
}
run_shell_step() {
local name="$1"
local command="$2"
run_step "$name" bash -lc "$command"
}
run_shell_finding_step() {
local name="$1"
local command="$2"
run_finding_step "$name" bash -lc "$command"
}
write_summary_json() {
local status="PASS_CONTROLLED_OPS_READY"
local qa_status="PASS"
local notes="WROAD2+OPS Day 0/每日巡检通过:受控上线测试账号范围,归档补偿可写 OA 留存库,不写企业微信,不安装定时任务。"
if [[ "$STATUS" -ne 0 ]]; then
status="SKIP/BLOCKED_BY_EXTERNAL_CONFIG"
qa_status="SKIP"
notes="WROAD2+OPS 巡检存在失败:按真实 Secret、权限、可信 IP、可见范围、凭据或外部配置阻断处理,不伪造成 PASS。"
elif [[ "$FINDING_COUNT" -gt 0 ]]; then
status="PASS_WITH_FINDINGS"
qa_status="PASS_WITH_FINDINGS"
notes="WROAD2+OPS 巡检主链路通过,但存在可解释 finding;按事实源保留审计,不扩大范围。"
fi
QA_REPORT_DIR="$REPORT_DIR" \
QA_ISSUE_ID="WROAD2" \
QA_BASE_URL="$PUBLIC_BASE_URL" \
QA_MODE="wroad2-controlled-ops-daily" \
QA_STATUS="$qa_status" \
QA_SUMMARY_NOTES="$notes" \
node "$ROOT_DIR/scripts/qa/write-qa-summary.mjs" >/dev/null 2>&1 || true
node - "$REPORT_DIR" "$PUBLIC_BASE_URL" "$status" "$notes" "$FINDING_COUNT" <<'NODE' || true
const fs = require("node:fs");
const path = require("node:path");
const { execSync } = require("node:child_process");
const [reportDir, baseURL, initialStatus, initialNotes, findingCountInput] = process.argv.slice(2);
const findingCount = Number(findingCountInput || 0);
let commit = "unknown";
try {
commit = execSync("git rev-parse --short HEAD", { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
} catch {}
const childReports = {};
for (const [key, file] of Object.entries({
liveReadiness: "live-smoke-readiness/summary.json",
wecomRuntimeReady: "wecom-runtime-ready/summary.json",
approvalCompensation: "wecom-approval-compensation-poc/summary.json",
approvalArchive: "wecom-approval-archive/summary.json",
})) {
const fullPath = path.join(reportDir, file);
if (!fs.existsSync(fullPath)) continue;
try {
const json = JSON.parse(fs.readFileSync(fullPath, "utf8"));
childReports[key] = {
status: json.status || json.conclusion || "UNKNOWN",
conclusion: json.conclusion || null,
reportPath: fullPath,
};
} catch {
childReports[key] = { status: "UNREADABLE", reportPath: fullPath };
}
}
const childStatuses = Object.values(childReports).map((report) => report.status);
const status = initialStatus === "PASS_CONTROLLED_OPS_READY" && childStatuses.includes("PASS_WITH_FINDINGS")
? "PASS_WITH_FINDINGS"
: initialStatus;
const notes = status === "PASS_WITH_FINDINGS"
? "WROAD2+OPS 巡检主链路通过,但子报告存在可解释 finding;按事实源保留审计,不扩大范围。"
: initialNotes;
const summary = {
issueId: "WROAD2",
mode: "wroad2-controlled-ops-daily",
status,
baseURL,
commit,
checkedAt: new Date().toISOString(),
reportDir: path.resolve(reportDir),
pilot: {
scope: "test_accounts",
applicant: "SMOKE002",
approver: "SMOKE101",
reviewer: "wangshunli",
durationDays: 3,
schedule: "manual_daily_script",
},
boundaries: {
noWeComWrites: true,
noFixtureCreation: true,
noCronOrSystemdTimer: true,
archivePersistence: "OA_DB_only_with_process_level_WECOM_ARCHIVE_WRITE",
postponed: ["outing_overtime", "deep_mirror", "emergency_mode", "recovery_writeback", "ruleops", "large_P2_features"],
},
childReports,
findingCount,
privacy: "masked prefixes/counts/status summaries only; no phone/email/token/secret/full userid/full template_id/full sp_no/raw XML/ciphertext/form values/attachments/comments/raw payload",
notes,
};
fs.writeFileSync(path.join(reportDir, "summary.json"), `${JSON.stringify(summary, null, 2)}\n`, "utf8");
console.log(`[wroad2-ops] summary=${path.join(reportDir, "summary.json")}`);
NODE
}
finish() {
write_summary_json
echo "[wroad2-ops] report=$REPORT_DIR" | tee -a "$SUMMARY_TXT"
exit "$STATUS"
}
trap finish EXIT
load_default_env
run_shell_step "public-ready" "curl -fsS '$PUBLIC_BASE_URL/ready' >/dev/null"
run_shell_finding_step "live-smoke-readiness" "QA_ISSUE_ID='WROAD2' LIVE_SMOKE_BASE_URL='$PUBLIC_BASE_URL' LIVE_SMOKE_READINESS_DIR='$REPORT_DIR/live-smoke-readiness' bash '$ROOT_DIR/scripts/qa/run-live-smoke-readiness.sh'"
run_shell_finding_step "live-feature-flags" "LIVE_SMOKE_BASE_URL='$PUBLIC_BASE_URL' node '$ROOT_DIR/scripts/qa/check-live-feature-flags.mjs' --expect payment_batch_v1=force_on --expect erp_sync=force_off --expect attendance_v1=disabled --expect attendance_unified_v1=enabled --json"
run_shell_step "wecom-runtime-ready" "cd '$SERVER_DIR' && npm run check:wecom-runtime-ready -- --live --format=json --report-dir='$REPORT_DIR/wecom-runtime-ready'"
run_shell_step "approval-compensation-persist" "cd '$SERVER_DIR' && WECOM_ARCHIVE_WRITE=1 npm run check:wecom-approval-compensation-poc -- --live --format=json --discover-template-ids --persist-to-db --report-dir='$REPORT_DIR/wecom-approval-compensation-poc'"
run_shell_step "approval-archive-offline" "cd '$SERVER_DIR' && npm run check:wecom-approval-archive -- --offline --format=json --report-dir='$REPORT_DIR/wecom-approval-archive'"
run_shell_step "report-privacy-smoke" "if grep -RInE 'access_token=[A-Za-z0-9._-]{8,}|1[3-9][0-9]{9}|[[:alnum:]._%+-]+@[[:alnum:].-]+\\.[[:alpha:]]{2,}|-----BEGIN|BEGIN [A-Z ]*KEY' '$REPORT_DIR'; then exit 1; fi"