fix(runner): classify harbor 110 repair waiting runs
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 33s
CD Pipeline / build-and-deploy (push) Failing after 2m37s
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 0s
CD Pipeline / post-deploy-checks (push) Has been skipped
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Has been cancelled
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 33s
CD Pipeline / build-and-deploy (push) Failing after 2m37s
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 0s
CD Pipeline / post-deploy-checks (push) Has been skipped
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Has been cancelled
This commit is contained in:
@@ -1,3 +1,17 @@
|
||||
## 2026-06-30 — 20:45 Harbor 110 repair waiting readback classifier
|
||||
|
||||
**照主線修正的問題**:
|
||||
- `ops/runner/read-public-gitea-actions-queue.py` 新增 `harbor-110-local-repair.yaml` 專用 readback:run id、status、kind、title、commit、waiting / running / blocked 與 no-matching runner label。
|
||||
- Rollups 新增 `harbor_110_repair_run_visible`、`harbor_110_repair_run_status`、`harbor_110_repair_waiting`、`harbor_110_repair_running`、`harbor_110_repair_blocked`,避免 110 local repair workflow 只藏在 `top_visible_runs` 靠人眼判讀。
|
||||
- Live readback 目前精準收斂:CD `#4061` failure,classifier=`harbor_registry_public_route_unavailable`、`registry_v2_status=502`、CD non110 self-heal skip=`not_110_host`;scheduled Harbor repair `#4060` visible 且 `Waiting`。
|
||||
|
||||
**驗證**:
|
||||
- `py_compile`、`ruff check`、`pytest ops/runner/test_read_public_gitea_actions_queue.py -q` 通過(`15 passed`)。
|
||||
- `read-public-gitea-actions-queue.py --json` 成功讀出 `latest_visible_harbor_110_repair_run_id=4060`、`latest_visible_harbor_110_repair_run_status=Waiting`。
|
||||
- `git diff --check` 通過。
|
||||
|
||||
**邊界**:只讀 public Gitea / 本機 source;未讀 secret / token / `.env` / raw sessions / SQLite / auth;未使用 GitHub / `gh` / GitHub API;未 workflow_dispatch;未 SSH / Docker / Nginx / K3s / DB / firewall runtime 寫入。
|
||||
|
||||
## 2026-06-30 — 20:29 Harbor self-heal skip reason classifier
|
||||
|
||||
**照主線修正的問題**:
|
||||
|
||||
@@ -182,6 +182,14 @@ def build_readback(
|
||||
(run for run in visible_runs if run.get("workflow") == "cd.yaml"),
|
||||
{},
|
||||
)
|
||||
latest_harbor_110_repair_run = next(
|
||||
(
|
||||
run
|
||||
for run in visible_runs
|
||||
if run.get("workflow") == "harbor-110-local-repair.yaml"
|
||||
),
|
||||
{},
|
||||
)
|
||||
cd_jobs = cd_jobs_payload if isinstance(cd_jobs_payload, dict) else {}
|
||||
actions_list = actions_list_payload if isinstance(actions_list_payload, dict) else {}
|
||||
actions_list_message = str(actions_list.get("message") or "")
|
||||
@@ -228,6 +236,10 @@ def build_readback(
|
||||
build_log_classifier = classify_cd_build_log(latest_cd_build_log_text)
|
||||
tests_log_classifier = classify_cd_tests_log(latest_cd_tests_log_text)
|
||||
latest_cd_visible_blocked = latest_cd_run.get("status", "") == "Blocked"
|
||||
harbor_110_repair_status = latest_harbor_110_repair_run.get("status", "")
|
||||
harbor_110_repair_waiting = harbor_110_repair_status == "Waiting"
|
||||
harbor_110_repair_running = harbor_110_repair_status == "Running"
|
||||
harbor_110_repair_blocked = harbor_110_repair_status == "Blocked"
|
||||
|
||||
readback = {
|
||||
"actions_page_visible_run_count": len(visible_runs),
|
||||
@@ -281,6 +293,25 @@ def build_readback(
|
||||
"harbor_public_route_blocked"
|
||||
],
|
||||
"latest_visible_cd_tests_log_http_status": latest_cd_tests_log_http_status,
|
||||
"latest_visible_harbor_110_repair_run_id": (
|
||||
latest_harbor_110_repair_run.get("run_id", "")
|
||||
),
|
||||
"latest_visible_harbor_110_repair_run_status": harbor_110_repair_status,
|
||||
"latest_visible_harbor_110_repair_run_kind": (
|
||||
latest_harbor_110_repair_run.get("kind", "")
|
||||
),
|
||||
"latest_visible_harbor_110_repair_run_title": (
|
||||
latest_harbor_110_repair_run.get("title", "")
|
||||
),
|
||||
"latest_visible_harbor_110_repair_run_commit_sha": (
|
||||
latest_harbor_110_repair_run.get("commit_sha", "")
|
||||
),
|
||||
"latest_visible_harbor_110_repair_no_matching_runner_label": (
|
||||
latest_harbor_110_repair_run.get("no_matching_runner_label", "")
|
||||
),
|
||||
"latest_visible_harbor_110_repair_waiting": harbor_110_repair_waiting,
|
||||
"latest_visible_harbor_110_repair_running": harbor_110_repair_running,
|
||||
"latest_visible_harbor_110_repair_blocked": harbor_110_repair_blocked,
|
||||
"latest_visible_cd_host_pressure_classifier": tests_log_classifier[
|
||||
"host_pressure_classifier"
|
||||
],
|
||||
@@ -316,6 +347,12 @@ def build_readback(
|
||||
if build_log_classifier["harbor_public_route_blocked"]
|
||||
else "blocked_host_web_build_pressure"
|
||||
if tests_log_classifier["host_pressure_blocked_or_waiting"]
|
||||
else "harbor_110_repair_waiting_for_runner_or_queue"
|
||||
if harbor_110_repair_waiting
|
||||
else "harbor_110_repair_running"
|
||||
if harbor_110_repair_running
|
||||
else "blocked_harbor_110_repair_run"
|
||||
if harbor_110_repair_blocked
|
||||
else "cd_jobs_stale_or_mismatched"
|
||||
if cd_jobs_stale_or_mismatched
|
||||
else "no_matching_runner_not_visible"
|
||||
@@ -351,6 +388,14 @@ def build_readback(
|
||||
"host_pressure_refused"
|
||||
],
|
||||
"no_matching_online_runner_visible": bool(no_matching),
|
||||
"harbor_110_repair_run_visible": bool(latest_harbor_110_repair_run),
|
||||
"harbor_110_repair_run_status": harbor_110_repair_status,
|
||||
"harbor_110_repair_waiting": harbor_110_repair_waiting,
|
||||
"harbor_110_repair_running": harbor_110_repair_running,
|
||||
"harbor_110_repair_blocked": harbor_110_repair_blocked,
|
||||
"harbor_110_repair_no_matching_runner_label": (
|
||||
latest_harbor_110_repair_run.get("no_matching_runner_label", "")
|
||||
),
|
||||
},
|
||||
"operation_boundaries": {
|
||||
"public_gitea_read_only": True,
|
||||
@@ -498,6 +543,18 @@ def _human_summary(payload: dict[str, Any]) -> str:
|
||||
"LATEST_VISIBLE_CD_HOST_PRESSURE_CLASSIFIER="
|
||||
f"{readback['latest_visible_cd_host_pressure_classifier']}"
|
||||
),
|
||||
(
|
||||
"LATEST_VISIBLE_HARBOR_110_REPAIR_RUN_ID="
|
||||
f"{readback['latest_visible_harbor_110_repair_run_id']}"
|
||||
),
|
||||
(
|
||||
"LATEST_VISIBLE_HARBOR_110_REPAIR_RUN_STATUS="
|
||||
f"{readback['latest_visible_harbor_110_repair_run_status']}"
|
||||
),
|
||||
(
|
||||
"LATEST_VISIBLE_HARBOR_110_REPAIR_NO_MATCHING_RUNNER_LABEL="
|
||||
f"{readback['latest_visible_harbor_110_repair_no_matching_runner_label']}"
|
||||
),
|
||||
"WRITE_PERFORMED=false",
|
||||
"TOKEN_COLLECTED=false",
|
||||
]
|
||||
|
||||
@@ -91,6 +91,40 @@ def _actions_html_single_cd_run() -> str:
|
||||
"""
|
||||
|
||||
|
||||
def _actions_html_cd_running_harbor_repair_waiting() -> str:
|
||||
return """
|
||||
<div class="flex-list run-list">
|
||||
<div class="flex-item tw-items-center">
|
||||
<div class="flex-item-leading">
|
||||
<span data-tooltip-content="Running"></span>
|
||||
</div>
|
||||
<div class="flex-item-main">
|
||||
<a class="flex-item-title" title="fix(cd): keep harbor repair workflow on controlled profile" href="/wooo/awoooi/actions/runs/4061">
|
||||
fix(cd): keep harbor repair workflow on controlled profile
|
||||
</a>
|
||||
<div class="flex-item-body">
|
||||
<span><b>cd.yaml #4061</b>:</span>Commit
|
||||
<a href="/wooo/awoooi/commit/49a9f73094592150f5d748e6be68a9e49ba1b7df">49a9f7309</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-item tw-items-center">
|
||||
<div class="flex-item-leading">
|
||||
<span data-tooltip-content="Waiting"></span>
|
||||
</div>
|
||||
<div class="flex-item-main">
|
||||
<a class="flex-item-title" title="fix(cd): schedule bounded 110 harbor repair" href="/wooo/awoooi/actions/runs/4060">
|
||||
fix(cd): schedule bounded 110 harbor repair
|
||||
</a>
|
||||
<div class="flex-item-body">
|
||||
<span><b>harbor-110-local-repair.yaml #4060</b>:</span>Scheduled
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
||||
|
||||
def _actions_html_failed_cd_run() -> str:
|
||||
return """
|
||||
<div class="flex-list run-list">
|
||||
@@ -190,6 +224,32 @@ def test_build_readback_reports_latest_visible_cd_run() -> None:
|
||||
assert payload["readback"]["cd_run_jobs_stale_or_mismatched"] is False
|
||||
|
||||
|
||||
def test_build_readback_surfaces_harbor_110_repair_waiting_run() -> None:
|
||||
module = _load_module()
|
||||
payload = module.build_readback(
|
||||
actions_html=_actions_html_cd_running_harbor_repair_waiting(),
|
||||
actions_list_http_status=401,
|
||||
actions_list_payload={"message": "token is required"},
|
||||
cd_jobs_http_status=200,
|
||||
cd_jobs_payload={"jobs": [], "total_count": 0},
|
||||
)
|
||||
|
||||
assert payload["status"] == "harbor_110_repair_waiting_for_runner_or_queue"
|
||||
assert payload["readback"]["latest_visible_cd_run_id"] == "4061"
|
||||
assert payload["readback"]["latest_visible_cd_run_status"] == "Running"
|
||||
assert payload["readback"]["latest_visible_harbor_110_repair_run_id"] == "4060"
|
||||
assert (
|
||||
payload["readback"]["latest_visible_harbor_110_repair_run_status"]
|
||||
== "Waiting"
|
||||
)
|
||||
assert payload["readback"]["latest_visible_harbor_110_repair_waiting"] is True
|
||||
assert payload["readback"]["latest_visible_harbor_110_repair_running"] is False
|
||||
assert payload["rollups"]["harbor_110_repair_run_visible"] is True
|
||||
assert payload["rollups"]["harbor_110_repair_waiting"] is True
|
||||
assert payload["rollups"]["harbor_110_repair_run_status"] == "Waiting"
|
||||
assert payload["operation_boundaries"]["workflow_dispatch_performed"] is False
|
||||
|
||||
|
||||
def test_build_readback_classifies_harbor_public_route_blocker() -> None:
|
||||
module = _load_module()
|
||||
payload = module.build_readback(
|
||||
|
||||
Reference in New Issue
Block a user