From 76071f21a811fe3c28998fa384e5beacd412c2f7 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 29 Jun 2026 09:38:21 +0800 Subject: [PATCH] feat(delivery): expose queue verifier contract --- .../services/delivery_closure_workbench.py | 39 +++++++++++++++++++ .../test_delivery_closure_workbench_api.py | 36 ++++++++++++++++- apps/web/src/lib/api-client.ts | 8 ++++ docs/LOGBOOK.md | 8 ++++ ...tion-deploy-readback-blocker.snapshot.json | 6 +-- 5 files changed, 93 insertions(+), 4 deletions(-) diff --git a/apps/api/src/services/delivery_closure_workbench.py b/apps/api/src/services/delivery_closure_workbench.py index cfb64759d..dcfaeec18 100644 --- a/apps/api/src/services/delivery_closure_workbench.py +++ b/apps/api/src/services/delivery_closure_workbench.py @@ -192,6 +192,12 @@ def build_delivery_closure_workbench( ) or "" ), + "latest_visible_waiting_runner_kind": str( + production_deploy_readback.get( + "latest_visible_waiting_runner_kind" + ) + or "" + ), "latest_visible_waiting_runner_status": str( production_deploy_readback.get( "latest_visible_waiting_runner_status" @@ -204,6 +210,18 @@ def build_delivery_closure_workbench( ) or "" ), + "public_actions_queue_readback_schema_version": str( + production_deploy_readback.get( + "public_actions_queue_readback_schema_version" + ) + or "" + ), + "public_actions_queue_readback_verifier": str( + production_deploy_readback.get( + "public_actions_queue_readback_verifier" + ) + or "" + ), "non110_runner_ready": production_deploy_readback.get( "non110_runner_ready" ) @@ -258,6 +276,10 @@ def build_delivery_closure_workbench( "non110_runner_ready_registration_count" ) ), + "non110_runner_safe_next_step": str( + production_deploy_readback.get("non110_runner_safe_next_step") + or "" + ), "non110_runner_remaining_blocker_count": len( _strings( production_deploy_readback.get( @@ -496,6 +518,10 @@ def build_delivery_closure_workbench( ) or "" ), + "production_deploy_latest_visible_waiting_runner_kind": str( + production_deploy_readback.get("latest_visible_waiting_runner_kind") + or "" + ), "production_deploy_latest_visible_waiting_runner_status": str( production_deploy_readback.get("latest_visible_waiting_runner_status") or "" @@ -504,6 +530,16 @@ def build_delivery_closure_workbench( production_deploy_readback.get("latest_visible_waiting_runner_label") or "" ), + "production_deploy_public_actions_queue_readback_schema_version": str( + production_deploy_readback.get( + "public_actions_queue_readback_schema_version" + ) + or "" + ), + "production_deploy_public_actions_queue_readback_verifier": str( + production_deploy_readback.get("public_actions_queue_readback_verifier") + or "" + ), "production_deploy_non110_runner_ready": production_deploy_readback.get( "non110_runner_ready" ) @@ -560,6 +596,9 @@ def build_delivery_closure_workbench( "non110_runner_ready_registration_count" ) ), + "production_deploy_non110_runner_safe_next_step": str( + production_deploy_readback.get("non110_runner_safe_next_step") or "" + ), "production_deploy_non110_runner_remaining_blocker_count": len( _strings( production_deploy_readback.get( diff --git a/apps/api/tests/test_delivery_closure_workbench_api.py b/apps/api/tests/test_delivery_closure_workbench_api.py index 8719db862..696461440 100644 --- a/apps/api/tests/test_delivery_closure_workbench_api.py +++ b/apps/api/tests/test_delivery_closure_workbench_api.py @@ -71,6 +71,10 @@ def test_delivery_closure_workbench_endpoint_returns_product_summary(): data["summary"]["production_deploy_latest_visible_waiting_runner_workflow"] == "ai-technology-watch.yaml" ) + assert ( + data["summary"]["production_deploy_latest_visible_waiting_runner_kind"] + == "Scheduled" + ) assert ( data["summary"]["production_deploy_latest_visible_waiting_runner_status"] == "No matching online runner with label: awoooi-non110-ubuntu" @@ -79,6 +83,16 @@ def test_delivery_closure_workbench_endpoint_returns_product_summary(): data["summary"]["production_deploy_latest_visible_waiting_runner_label"] == "awoooi-non110-ubuntu" ) + assert ( + data["summary"][ + "production_deploy_public_actions_queue_readback_schema_version" + ] + == "awoooi_public_gitea_actions_queue_readback_v1" + ) + assert ( + data["summary"]["production_deploy_public_actions_queue_readback_verifier"] + == "ops/runner/read-public-gitea-actions-queue.py --json" + ) assert data["summary"]["production_deploy_non110_runner_ready"] is False assert ( data["summary"][ @@ -130,6 +144,9 @@ def test_delivery_closure_workbench_endpoint_returns_product_summary(): data["summary"]["production_deploy_non110_runner_ready_registration_count"] == 0 ) + assert data["summary"]["production_deploy_non110_runner_safe_next_step"] == ( + "run_register_awoooi_non110_runner_script_without_printing_token_then_autostart_path_will_enable_service_and_rerun_this_verifier" + ) assert ( data["summary"]["production_deploy_non110_runner_remaining_blocker_count"] == 3 @@ -177,7 +194,7 @@ def test_delivery_closure_workbench_endpoint_returns_product_summary(): assert lanes["production_deploy"]["blocker_count"] == 4 assert lanes["production_deploy"]["metric"][ "observed_source_control_main_short_sha" - ] == "f84269453834" + ] == "c53cbca4a26d" assert lanes["production_deploy"]["metric"][ "production_image_tag_short_sha" ] == "af45811e87" @@ -235,6 +252,10 @@ def test_delivery_closure_workbench_endpoint_returns_product_summary(): ] == "ai-technology-watch.yaml" ) + assert ( + lanes["production_deploy"]["metric"]["latest_visible_waiting_runner_kind"] + == "Scheduled" + ) assert ( lanes["production_deploy"]["metric"][ "latest_visible_waiting_runner_status" @@ -245,6 +266,16 @@ def test_delivery_closure_workbench_endpoint_returns_product_summary(): lanes["production_deploy"]["metric"]["latest_visible_waiting_runner_label"] == "awoooi-non110-ubuntu" ) + assert ( + lanes["production_deploy"]["metric"][ + "public_actions_queue_readback_schema_version" + ] + == "awoooi_public_gitea_actions_queue_readback_v1" + ) + assert ( + lanes["production_deploy"]["metric"]["public_actions_queue_readback_verifier"] + == "ops/runner/read-public-gitea-actions-queue.py --json" + ) assert lanes["production_deploy"]["metric"]["non110_runner_ready"] is False assert ( lanes["production_deploy"]["metric"][ @@ -300,6 +331,9 @@ def test_delivery_closure_workbench_endpoint_returns_product_summary(): ] == 0 ) + assert lanes["production_deploy"]["metric"]["non110_runner_safe_next_step"] == ( + "run_register_awoooi_non110_runner_script_without_printing_token_then_autostart_path_will_enable_service_and_rerun_this_verifier" + ) assert ( lanes["production_deploy"]["metric"][ "non110_runner_remaining_blocker_count" diff --git a/apps/web/src/lib/api-client.ts b/apps/web/src/lib/api-client.ts index 1183da031..82830ab38 100644 --- a/apps/web/src/lib/api-client.ts +++ b/apps/web/src/lib/api-client.ts @@ -2560,8 +2560,11 @@ export interface DeliveryClosureWorkbenchSnapshot { production_deploy_gitea_actions_list_without_token_message: string production_deploy_latest_visible_waiting_runner_run_id: string production_deploy_latest_visible_waiting_runner_workflow: string + production_deploy_latest_visible_waiting_runner_kind: string production_deploy_latest_visible_waiting_runner_status: string production_deploy_latest_visible_waiting_runner_label: string + production_deploy_public_actions_queue_readback_schema_version: string + production_deploy_public_actions_queue_readback_verifier: string production_deploy_non110_runner_ready: boolean production_deploy_non110_runner_prepare_only_source_ready: boolean production_deploy_non110_runner_safe_registration_helper_ready: boolean @@ -2575,6 +2578,7 @@ export interface DeliveryClosureWorkbenchSnapshot { production_deploy_non110_runner_ready_config_count: number production_deploy_non110_runner_ready_service_count: number production_deploy_non110_runner_ready_registration_count: number + production_deploy_non110_runner_safe_next_step: string production_deploy_non110_runner_remaining_blocker_count: number github_write_channel_ready: boolean github_account_status: string @@ -2619,8 +2623,11 @@ export interface DeliveryClosureWorkbenchSnapshot { gitea_actions_list_without_token_message: string latest_visible_waiting_runner_run_id: string latest_visible_waiting_runner_workflow: string + latest_visible_waiting_runner_kind: string latest_visible_waiting_runner_status: string latest_visible_waiting_runner_label: string + public_actions_queue_readback_schema_version: string + public_actions_queue_readback_verifier: string non110_runner_ready: boolean non110_runner_prepare_only_source_ready: boolean non110_runner_safe_registration_helper_ready: boolean @@ -2634,6 +2641,7 @@ export interface DeliveryClosureWorkbenchSnapshot { non110_runner_ready_config_count: number non110_runner_ready_service_count: number non110_runner_ready_registration_count: number + non110_runner_safe_next_step: string non110_runner_remaining_blocker_count: number } | { diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index c1314205f..6d5659276 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -1,3 +1,11 @@ +## 2026-06-29 — 09:30 Delivery Workbench queue verifier contract 投影 + +**完成內容**: +- 將 `public_actions_queue_readback_schema_version`、`public_actions_queue_readback_verifier`、latest waiting runner kind 與 `non110_runner_safe_next_step` 投影到 Delivery Workbench summary / `production_deploy` lane metric / web API type。 +- 刷新 source readback 觀測 SHA 為 `c53cbca4a26d`;public queue verifier 仍讀回 `blocked_no_matching_online_runner`、actions list `401`、CD jobs `0`、label `awoooi-non110-ubuntu`。 + +**邊界**:只改 committed source / snapshot / API type / tests;未使用 GitHub;未讀 token / `.runner` 內容 / cookie / session / secret;未操作 host / Docker / K8s / runner service;未 workflow_dispatch。 + ## 2026-06-29 — 09:15 Delivery Workbench non-110 autostart watcher 投影 **完成內容**: diff --git a/docs/operations/awoooi-production-deploy-readback-blocker.snapshot.json b/docs/operations/awoooi-production-deploy-readback-blocker.snapshot.json index c0346bc6f..47b1a16c4 100644 --- a/docs/operations/awoooi-production-deploy-readback-blocker.snapshot.json +++ b/docs/operations/awoooi-production-deploy-readback-blocker.snapshot.json @@ -1,12 +1,12 @@ { "schema_version": "awoooi_production_deploy_readback_blocker_v1", - "generated_at": "2026-06-29T09:15:03+08:00", + "generated_at": "2026-06-29T09:30:31+08:00", "status": "blocked_waiting_authorized_gitea_workflow_dispatch_and_runner_queue", "priority": "P0", "scope": "awoooi_production_truth", "readback": { - "observed_source_control_main_sha": "f84269453834a123eb40c6974e941f806b175b42", - "observed_source_control_main_short_sha": "f84269453834", + "observed_source_control_main_sha": "c53cbca4a26d03e8b8a9cff38d7acfe698f7089d", + "observed_source_control_main_short_sha": "c53cbca4a26d", "governance_closure_merge_sha": "27b96f0450d0e3ca6651d6b5f274a341dd727ef2", "governance_closure_commit_sha": "9e3e7fbb6ba3ffd324b45abf3ad1e7b6ec826b22", "production_image_tag_sha": "af45811e876fda322ee63c036fbc39c9f07ffd76",