fix(runner): prioritize harbor repair waiting readback
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 32s
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled

This commit is contained in:
Your Name
2026-06-30 20:53:59 +08:00
parent 01deee4a7d
commit 92d0290734
3 changed files with 56 additions and 0 deletions

View File

@@ -1,3 +1,17 @@
## 2026-06-30 — 20:52 Harbor 110 repair waiting status precedence
**照主線修正的問題**
- Public Gitea live readback 已同時看到 CD `#4062` failure`harbor_registry_public_route_unavailable``registry_v2_status=502`)與 `harbor-110-local-repair.yaml #4063` `Waiting`
- `ops/runner/read-public-gitea-actions-queue.py` 新增 `harbor_110_repair_waiting_after_cd_harbor_blocker`,當 CD 已證明 Harbor 502 且 110 local repair workflow 等 runner/queue 時,總狀態提升為 `blocked_harbor_110_repair_workflow_waiting`
- 這讓下一步優先順序直接指到 110-local repair lane 未接 job而不是重複停在泛化 Harbor 502。
**驗證**
- `pytest ops/runner/test_read_public_gitea_actions_queue.py -q` 通過(`16 passed`)。
- `py_compile``guard-gitea-runner-pressure.py``check-gitea-step-env-secrets.js``git diff --check` 通過。
- Live reader 回 `status=blocked_harbor_110_repair_workflow_waiting``latest_visible_harbor_110_repair_run_id=4063``latest_visible_harbor_110_repair_run_status=Waiting`
**邊界**:只讀 public Gitea / production HTTP 與本機 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:45 Harbor 110 repair waiting readback classifier
**照主線修正的問題**

View File

@@ -240,6 +240,10 @@ def build_readback(
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"
harbor_110_repair_waiting_after_cd_harbor_blocker = (
build_log_classifier["harbor_public_route_blocked"]
and harbor_110_repair_waiting
)
readback = {
"actions_page_visible_run_count": len(visible_runs),
@@ -312,6 +316,9 @@ def build_readback(
"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,
"harbor_110_repair_waiting_after_cd_harbor_blocker": (
harbor_110_repair_waiting_after_cd_harbor_blocker
),
"latest_visible_cd_host_pressure_classifier": tests_log_classifier[
"host_pressure_classifier"
],
@@ -343,6 +350,8 @@ def build_readback(
if no_matching
else "blocked_latest_visible_cd_run"
if latest_cd_visible_blocked
else "blocked_harbor_110_repair_workflow_waiting"
if harbor_110_repair_waiting_after_cd_harbor_blocker
else "blocked_harbor_public_route_unavailable"
if build_log_classifier["harbor_public_route_blocked"]
else "blocked_host_web_build_pressure"
@@ -393,6 +402,9 @@ def build_readback(
"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_waiting_after_cd_harbor_blocker": (
harbor_110_repair_waiting_after_cd_harbor_blocker
),
"harbor_110_repair_no_matching_runner_label": (
latest_harbor_110_repair_run.get("no_matching_runner_label", "")
),
@@ -555,6 +567,10 @@ def _human_summary(payload: dict[str, Any]) -> str:
"LATEST_VISIBLE_HARBOR_110_REPAIR_NO_MATCHING_RUNNER_LABEL="
f"{readback['latest_visible_harbor_110_repair_no_matching_runner_label']}"
),
(
"HARBOR_110_REPAIR_WAITING_AFTER_CD_HARBOR_BLOCKER="
f"{int(readback['harbor_110_repair_waiting_after_cd_harbor_blocker'])}"
),
"WRITE_PERFORMED=false",
"TOKEN_COLLECTED=false",
]

View File

@@ -434,6 +434,32 @@ def test_harbor_blocker_takes_status_precedence_over_stale_jobs_payload() -> Non
)
def test_harbor_repair_waiting_takes_actionable_precedence_after_harbor_blocker() -> 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},
latest_cd_build_log_http_status=200,
latest_cd_build_log_text=_harbor_blocked_log(),
)
assert payload["status"] == "blocked_harbor_110_repair_workflow_waiting"
assert payload["readback"]["latest_visible_harbor_110_repair_waiting"] is True
assert (
payload["readback"][
"harbor_110_repair_waiting_after_cd_harbor_blocker"
]
is True
)
assert (
payload["rollups"]["harbor_110_repair_waiting_after_cd_harbor_blocker"]
is True
)
def test_derive_jobs_api_url_tracks_latest_visible_run_id() -> None:
module = _load_module()