WROAD2 增加受控上线每日巡检
这个提交包含在:
+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"
|
||||
在新工单中引用
屏蔽一个用户