diff --git a/AGENTS.md b/AGENTS.md index 2f4c4aca..9019f2ea 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -42,6 +42,7 @@ UniDesk 以主 server 为统一入口。本文件只做自动加载的顶级索 ## P0: 配置、Secret 与 YAML-first - P0: UniDesk 自有配置优先使用 YAML;节点/lane、namespace、endpoint、版本、容量、退避窗口、Secret sourceRef 等可调项必须从 YAML 进入受控 CLI,不得写成隐藏默认。细则见 `docs/reference/yaml-first-ops.md` 和 `$unidesk-ymalops`。 +- P0: node/lane 必须作为 YAML 的变量值、selector、target key 或 CLI 参数参与渲染;禁止把具体 node/lane 写入 YAML 文件名、函数名、helper/module 名、长期 schema 名或隐藏默认。 - P0: Secret、API key、JWT/encryption key、`DATABASE_URL` 等凭据只能通过 YAML 声明 sourceRef/targetKey 和受控 CLI 下发;输出只披露对象名、key 名、presence、fingerprint 和摘要,不得打印完整凭据。 - P0: `hyueapi.com` / `.hyueapi.com` 是 Codex API 直连域名,必须保留在 `NO_PROXY` / `no_proxy` 中。 diff --git a/config/hwlab-fake-model-provider/d518-v03/fake-echo.yaml b/config/hwlab-fake-model-provider/d518-v03/fake-echo.yaml deleted file mode 100644 index f708d2dc..00000000 --- a/config/hwlab-fake-model-provider/d518-v03/fake-echo.yaml +++ /dev/null @@ -1,18 +0,0 @@ -version: 1 -kind: HwlabFakeModelProvider -metadata: - id: d518-v03-fake-echo - owner: UniDesk - issue: 1190 -provider: - id: fake-echo - enabled: true - mode: responses-echo - target: - node: D518 - lane: v03 - agentrunLane: d518-v02 - configRefs: - runtime: config/hwlab-fake-model-provider/runtime.d518-v03.yaml#provider.runtime - secrets: config/hwlab-fake-model-provider/secrets.d518-v03.yaml#provider.secrets - profile: config/hwlab-fake-model-provider/profile.fake-echo.d518-v03.yaml#provider.profile diff --git a/config/hwlab-fake-model-provider/fake-echo.yaml b/config/hwlab-fake-model-provider/fake-echo.yaml new file mode 100644 index 00000000..c7240137 --- /dev/null +++ b/config/hwlab-fake-model-provider/fake-echo.yaml @@ -0,0 +1,18 @@ +version: 1 +kind: HwlabFakeModelProvider +metadata: + id: fake-echo + owner: UniDesk + issue: 1190 +provider: + id: fake-echo + enabled: true + mode: responses-echo + target: + node: NC01 + lane: v03 + agentrunLane: nc01-v02 + configRefs: + runtime: config/hwlab-fake-model-provider/runtime.fake-echo.yaml#provider.runtime + secrets: config/hwlab-fake-model-provider/secrets.fake-echo.yaml#provider.secrets + profile: config/hwlab-fake-model-provider/profile.fake-echo.yaml#provider.profile diff --git a/config/hwlab-fake-model-provider/profile.fake-echo.d518-v03.yaml b/config/hwlab-fake-model-provider/profile.fake-echo.yaml similarity index 71% rename from config/hwlab-fake-model-provider/profile.fake-echo.d518-v03.yaml rename to config/hwlab-fake-model-provider/profile.fake-echo.yaml index 79d6d6b2..44c24ca8 100644 --- a/config/hwlab-fake-model-provider/profile.fake-echo.d518-v03.yaml +++ b/config/hwlab-fake-model-provider/profile.fake-echo.yaml @@ -1,24 +1,24 @@ version: 1 kind: HwlabFakeModelProviderProfile metadata: - id: d518-v03-fake-echo-profile + id: fake-echo-profile owner: UniDesk issue: 1190 provider: profile: name: fake-echo agentrun: - node: D518 - lane: d518-v02 - configRef: config/agentrun.yaml#controlPlane.lanes.d518-v02 + node: NC01 + lane: nc01-v02 + configRef: config/agentrun.yaml#controlPlane.lanes.nc01-v02 providerCredential: namespace: agentrun-v02 secretName: agentrun-v02-provider-fake-echo keys: - auth.json - config.toml - authJsonSourceRef: agentrun/d518-v02-provider-fake-echo-auth.json - configTomlSourceRef: agentrun/d518-v02-provider-fake-echo-config.toml + authJsonSourceRef: agentrun/nc01-v02-provider-fake-echo-auth.json + configTomlSourceRef: agentrun/nc01-v02-provider-fake-echo-config.toml codexConfig: model: fake-echo modelProvider: fake diff --git a/config/hwlab-fake-model-provider/runtime.d518-v03.yaml b/config/hwlab-fake-model-provider/runtime.fake-echo.yaml similarity index 93% rename from config/hwlab-fake-model-provider/runtime.d518-v03.yaml rename to config/hwlab-fake-model-provider/runtime.fake-echo.yaml index 1d89d0fe..8f794d2a 100644 --- a/config/hwlab-fake-model-provider/runtime.d518-v03.yaml +++ b/config/hwlab-fake-model-provider/runtime.fake-echo.yaml @@ -1,15 +1,15 @@ version: 1 kind: HwlabFakeModelProviderRuntime metadata: - id: d518-v03-fake-model-provider-runtime + id: fake-model-provider-runtime owner: UniDesk issue: 1190 provider: runtime: target: - node: D518 + node: NC01 lane: v03 - agentrunLane: d518-v02 + agentrunLane: nc01-v02 namespace: agentrun-v02 serviceAccountName: default deploymentName: hwlab-fake-model-provider diff --git a/config/hwlab-fake-model-provider/secrets.d518-v03.yaml b/config/hwlab-fake-model-provider/secrets.fake-echo.yaml similarity index 95% rename from config/hwlab-fake-model-provider/secrets.d518-v03.yaml rename to config/hwlab-fake-model-provider/secrets.fake-echo.yaml index e7e796ca..796a66c8 100644 --- a/config/hwlab-fake-model-provider/secrets.d518-v03.yaml +++ b/config/hwlab-fake-model-provider/secrets.fake-echo.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabFakeModelProviderSecrets metadata: - id: d518-v03-fake-model-provider-secrets + id: fake-model-provider-secrets owner: UniDesk issue: 1190 provider: diff --git a/config/hwlab-gateway/constart-71freq-d601-v03.yaml b/config/hwlab-gateway/constart-71freq.yaml similarity index 95% rename from config/hwlab-gateway/constart-71freq-d601-v03.yaml rename to config/hwlab-gateway/constart-71freq.yaml index 5c7d085c..2eee3b58 100644 --- a/config/hwlab-gateway/constart-71freq-d601-v03.yaml +++ b/config/hwlab-gateway/constart-71freq.yaml @@ -1,13 +1,13 @@ version: 1 kind: HwlabGatewayProfileConfig metadata: - name: constart-71freq-d601-v03 + name: constart-71freq spec: PJ2026-01010305 implementationRef: draft-2026-06-26-71freq-v03-hwpod-preinstall gateway: profile: - id: constart-71freq-d601-v03 + id: constart-71freq node: D601 lane: v03 cloudUrl: https://hwlab.pikapython.com diff --git a/config/hwlab-hwpod-preinstalls/constart-71freq-c.yaml b/config/hwlab-hwpod-preinstalls/constart-71freq-c.yaml index 75e26f80..54c910e6 100644 --- a/config/hwlab-hwpod-preinstalls/constart-71freq-c.yaml +++ b/config/hwlab-hwpod-preinstalls/constart-71freq-c.yaml @@ -48,7 +48,7 @@ hwpodPreinstall: endpoints: - id: hwpod-node-ops kind: hwpod-node-ops - endpointRef: config/hwlab-gateway/constart-71freq-d601-v03.yaml#gateway.profile.nodeOps.publicUrl + endpointRef: config/hwlab-gateway/constart-71freq.yaml#gateway.profile.nodeOps.publicUrl - id: freq71 kind: jsonrpc-tcp host: 192.168.0.154 @@ -113,7 +113,7 @@ hwpodPreinstall: endpoints: hwpod-node-ops: kind: hwpod-node-ops - endpointRef: config/hwlab-gateway/constart-71freq-d601-v03.yaml#gateway.profile.nodeOps.publicUrl + endpointRef: config/hwlab-gateway/constart-71freq.yaml#gateway.profile.nodeOps.publicUrl freq71: kind: jsonrpc-tcp host: 192.168.0.154 diff --git a/config/hwlab-project-management/constart-71freq-mdtodo.yaml b/config/hwlab-project-management/constart-71freq-mdtodo.yaml index aba96829..4951b79e 100644 --- a/config/hwlab-project-management/constart-71freq-mdtodo.yaml +++ b/config/hwlab-project-management/constart-71freq-mdtodo.yaml @@ -25,7 +25,7 @@ projectManagement: write: true reindex: true launchWorkbench: true - hwpodNodeOpsUrlConfigRef: config/hwlab-gateway/constart-71freq-d601-v03.yaml#gateway.profile.nodeOps.serviceUrl + hwpodNodeOpsUrlConfigRef: config/hwlab-gateway/constart-71freq.yaml#gateway.profile.nodeOps.serviceUrl runtimeEnv: envKey: HWLAB_PROJECT_MANAGEMENT_HWPOD_NODE_OPS_URL targetServiceId: hwlab-project-management diff --git a/config/hwlab-web-probe-sentinel/cicd.auth-session-switch.d601-v03.yaml b/config/hwlab-web-probe-sentinel/cicd.auth-session-switch.yaml similarity index 97% rename from config/hwlab-web-probe-sentinel/cicd.auth-session-switch.d601-v03.yaml rename to config/hwlab-web-probe-sentinel/cicd.auth-session-switch.yaml index 60c8cfde..f1b78ad6 100644 --- a/config/hwlab-web-probe-sentinel/cicd.auth-session-switch.d601-v03.yaml +++ b/config/hwlab-web-probe-sentinel/cicd.auth-session-switch.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelCicd metadata: - id: d601-v03-web-probe-sentinel-auth-session-switch-cicd + id: web-probe-sentinel-auth-session-switch-cicd owner: UniDesk specRef: PJ2026-01060508 sentinel: @@ -50,7 +50,7 @@ sentinel: repository: 127.0.0.1:5000/hwlab/web-probe-sentinel-auth-switch tagSource: source-commit baseImageRef: config/hwlab-node-control-plane.yaml#targets[0].tekton.toolsImage.output - envRecipeRef: config/hwlab-web-probe-sentinel/runtime.auth-session-switch.d601-v03.yaml#sentinel.runtime + envRecipeRef: config/hwlab-web-probe-sentinel/runtime.auth-session-switch.yaml#sentinel.runtime maintenance: startCommand: sentinel maintenance start stopCommand: sentinel maintenance stop diff --git a/config/hwlab-web-probe-sentinel/cicd.fake-echo.d518-v03.yaml b/config/hwlab-web-probe-sentinel/cicd.fake-echo.yaml similarity index 97% rename from config/hwlab-web-probe-sentinel/cicd.fake-echo.d518-v03.yaml rename to config/hwlab-web-probe-sentinel/cicd.fake-echo.yaml index 4a26d686..dea36379 100644 --- a/config/hwlab-web-probe-sentinel/cicd.fake-echo.d518-v03.yaml +++ b/config/hwlab-web-probe-sentinel/cicd.fake-echo.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelCicd metadata: - id: d518-v03-web-probe-sentinel-fake-echo-cicd + id: web-probe-sentinel-fake-echo-cicd owner: UniDesk specRef: PJ2026-01060508 issue: 1190 @@ -51,7 +51,7 @@ sentinel: repository: 127.0.0.1:5000/hwlab/web-probe-sentinel tagSource: source-commit baseImageRef: config/hwlab-node-control-plane.yaml#targets[1].tekton.toolsImage.output - envRecipeRef: config/hwlab-web-probe-sentinel/runtime.fake-echo.d518-v03.yaml#sentinel.runtime + envRecipeRef: config/hwlab-web-probe-sentinel/runtime.fake-echo.yaml#sentinel.runtime maintenance: startCommand: sentinel maintenance start stopCommand: sentinel maintenance stop diff --git a/config/hwlab-web-probe-sentinel/cicd.mdtodo.d601-v03.yaml b/config/hwlab-web-probe-sentinel/cicd.mdtodo.yaml similarity index 97% rename from config/hwlab-web-probe-sentinel/cicd.mdtodo.d601-v03.yaml rename to config/hwlab-web-probe-sentinel/cicd.mdtodo.yaml index e9291ce9..6b9573ea 100644 --- a/config/hwlab-web-probe-sentinel/cicd.mdtodo.d601-v03.yaml +++ b/config/hwlab-web-probe-sentinel/cicd.mdtodo.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelCicd metadata: - id: d601-v03-web-probe-sentinel-mdtodo-cicd + id: web-probe-sentinel-mdtodo-cicd owner: UniDesk specRef: PJ2026-01060508 sentinel: @@ -50,7 +50,7 @@ sentinel: repository: 127.0.0.1:5000/hwlab/web-probe-sentinel-mdtodo tagSource: source-commit baseImageRef: config/hwlab-node-control-plane.yaml#targets[0].tekton.toolsImage.output - envRecipeRef: config/hwlab-web-probe-sentinel/runtime.mdtodo.d601-v03.yaml#sentinel.runtime + envRecipeRef: config/hwlab-web-probe-sentinel/runtime.mdtodo.yaml#sentinel.runtime maintenance: startCommand: sentinel maintenance start stopCommand: sentinel maintenance stop diff --git a/config/hwlab-web-probe-sentinel/cicd.d518-v03.yaml b/config/hwlab-web-probe-sentinel/cicd.workbench-dsflash-go-secondary.yaml similarity index 95% rename from config/hwlab-web-probe-sentinel/cicd.d518-v03.yaml rename to config/hwlab-web-probe-sentinel/cicd.workbench-dsflash-go-secondary.yaml index 121cb967..1a965b42 100644 --- a/config/hwlab-web-probe-sentinel/cicd.d518-v03.yaml +++ b/config/hwlab-web-probe-sentinel/cicd.workbench-dsflash-go-secondary.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelCicd metadata: - id: d518-v03-web-probe-sentinel-cicd + id: web-probe-sentinel-workbench-dsflash-go-secondary-cicd owner: UniDesk specRef: PJ2026-01060508 sentinel: @@ -50,7 +50,7 @@ sentinel: repository: 127.0.0.1:5000/hwlab/web-probe-sentinel tagSource: source-commit baseImageRef: config/hwlab-node-control-plane.yaml#targets[1].tekton.toolsImage.output - envRecipeRef: config/hwlab-web-probe-sentinel/runtime.d518-v03.yaml#sentinel.runtime + envRecipeRef: config/hwlab-web-probe-sentinel/runtime.workbench-dsflash-go-secondary.yaml#sentinel.runtime maintenance: startCommand: sentinel maintenance start stopCommand: sentinel maintenance stop diff --git a/config/hwlab-web-probe-sentinel/cicd.d601-v03.yaml b/config/hwlab-web-probe-sentinel/cicd.workbench-dsflash-go.yaml similarity index 95% rename from config/hwlab-web-probe-sentinel/cicd.d601-v03.yaml rename to config/hwlab-web-probe-sentinel/cicd.workbench-dsflash-go.yaml index 70c49746..f97ae0cd 100644 --- a/config/hwlab-web-probe-sentinel/cicd.d601-v03.yaml +++ b/config/hwlab-web-probe-sentinel/cicd.workbench-dsflash-go.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelCicd metadata: - id: d601-v03-web-probe-sentinel-cicd + id: web-probe-sentinel-workbench-dsflash-go-cicd owner: UniDesk specRef: PJ2026-01060508 sentinel: @@ -50,7 +50,7 @@ sentinel: repository: 127.0.0.1:5000/hwlab/web-probe-sentinel tagSource: source-commit baseImageRef: config/hwlab-node-control-plane.yaml#targets[0].tekton.toolsImage.output - envRecipeRef: config/hwlab-web-probe-sentinel/runtime.d601-v03.yaml#sentinel.runtime + envRecipeRef: config/hwlab-web-probe-sentinel/runtime.workbench-dsflash-go.yaml#sentinel.runtime maintenance: startCommand: sentinel maintenance start stopCommand: sentinel maintenance stop diff --git a/config/hwlab-web-probe-sentinel/prompt-set.auth-session-switch.yaml b/config/hwlab-web-probe-sentinel/prompt-set.auth-session-switch.yaml index 402ccec2..147fdfa0 100644 --- a/config/hwlab-web-probe-sentinel/prompt-set.auth-session-switch.yaml +++ b/config/hwlab-web-probe-sentinel/prompt-set.auth-session-switch.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelPromptSet metadata: - id: d601-v03-web-probe-sentinel-auth-session-switch-prompt-set + id: web-probe-sentinel-auth-session-switch-prompt-set owner: UniDesk specRef: PJ2026-01060508 sentinel: diff --git a/config/hwlab-web-probe-sentinel/prompt-set.dsflash-go.yaml b/config/hwlab-web-probe-sentinel/prompt-set.dsflash-go.yaml index 8720d002..3087a075 100644 --- a/config/hwlab-web-probe-sentinel/prompt-set.dsflash-go.yaml +++ b/config/hwlab-web-probe-sentinel/prompt-set.dsflash-go.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelPromptSet metadata: - id: d601-v03-web-probe-sentinel-prompt-set + id: web-probe-sentinel-dsflash-go-prompt-set owner: UniDesk specRef: PJ2026-01060508 sentinel: diff --git a/config/hwlab-web-probe-sentinel/prompt-set.fake-echo.yaml b/config/hwlab-web-probe-sentinel/prompt-set.fake-echo.yaml index ab28be21..3770bbad 100644 --- a/config/hwlab-web-probe-sentinel/prompt-set.fake-echo.yaml +++ b/config/hwlab-web-probe-sentinel/prompt-set.fake-echo.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelPromptSet metadata: - id: d518-v03-web-probe-sentinel-fake-echo-prompt-set + id: web-probe-sentinel-fake-echo-prompt-set owner: UniDesk specRef: PJ2026-01060508 issue: 1190 diff --git a/config/hwlab-web-probe-sentinel/public-exposure.auth-session-switch.d601-v03.yaml b/config/hwlab-web-probe-sentinel/public-exposure.auth-session-switch.yaml similarity index 94% rename from config/hwlab-web-probe-sentinel/public-exposure.auth-session-switch.d601-v03.yaml rename to config/hwlab-web-probe-sentinel/public-exposure.auth-session-switch.yaml index 716a6744..5dcd741c 100644 --- a/config/hwlab-web-probe-sentinel/public-exposure.auth-session-switch.d601-v03.yaml +++ b/config/hwlab-web-probe-sentinel/public-exposure.auth-session-switch.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelPublicExposure metadata: - id: d601-v03-web-probe-sentinel-auth-session-switch-public-exposure + id: web-probe-sentinel-auth-session-switch-public-exposure owner: UniDesk specRef: PJ2026-01060508 sentinel: diff --git a/config/hwlab-web-probe-sentinel/public-exposure.fake-echo.d518-v03.yaml b/config/hwlab-web-probe-sentinel/public-exposure.fake-echo.yaml similarity index 95% rename from config/hwlab-web-probe-sentinel/public-exposure.fake-echo.d518-v03.yaml rename to config/hwlab-web-probe-sentinel/public-exposure.fake-echo.yaml index c4667df6..0c0320bf 100644 --- a/config/hwlab-web-probe-sentinel/public-exposure.fake-echo.d518-v03.yaml +++ b/config/hwlab-web-probe-sentinel/public-exposure.fake-echo.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelPublicExposure metadata: - id: d518-v03-web-probe-sentinel-fake-echo-public-exposure + id: web-probe-sentinel-fake-echo-public-exposure owner: UniDesk specRef: PJ2026-01060508 issue: 1190 diff --git a/config/hwlab-web-probe-sentinel/public-exposure.mdtodo.d601-v03.yaml b/config/hwlab-web-probe-sentinel/public-exposure.mdtodo.yaml similarity index 95% rename from config/hwlab-web-probe-sentinel/public-exposure.mdtodo.d601-v03.yaml rename to config/hwlab-web-probe-sentinel/public-exposure.mdtodo.yaml index 4df80c31..699ba549 100644 --- a/config/hwlab-web-probe-sentinel/public-exposure.mdtodo.d601-v03.yaml +++ b/config/hwlab-web-probe-sentinel/public-exposure.mdtodo.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelPublicExposure metadata: - id: d601-v03-web-probe-sentinel-mdtodo-public-exposure + id: web-probe-sentinel-mdtodo-public-exposure owner: UniDesk specRef: PJ2026-01060508 sentinel: diff --git a/config/hwlab-web-probe-sentinel/public-exposure.d518-v03.yaml b/config/hwlab-web-probe-sentinel/public-exposure.workbench-dsflash-go-secondary.yaml similarity index 94% rename from config/hwlab-web-probe-sentinel/public-exposure.d518-v03.yaml rename to config/hwlab-web-probe-sentinel/public-exposure.workbench-dsflash-go-secondary.yaml index 6d30ccb4..569a28a7 100644 --- a/config/hwlab-web-probe-sentinel/public-exposure.d518-v03.yaml +++ b/config/hwlab-web-probe-sentinel/public-exposure.workbench-dsflash-go-secondary.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelPublicExposure metadata: - id: d518-v03-web-probe-sentinel-public-exposure + id: web-probe-sentinel-workbench-dsflash-go-secondary-public-exposure owner: UniDesk specRef: PJ2026-01060508 sentinel: diff --git a/config/hwlab-web-probe-sentinel/public-exposure.d601-v03.yaml b/config/hwlab-web-probe-sentinel/public-exposure.workbench-dsflash-go.yaml similarity index 94% rename from config/hwlab-web-probe-sentinel/public-exposure.d601-v03.yaml rename to config/hwlab-web-probe-sentinel/public-exposure.workbench-dsflash-go.yaml index 2a2622f7..9b205f27 100644 --- a/config/hwlab-web-probe-sentinel/public-exposure.d601-v03.yaml +++ b/config/hwlab-web-probe-sentinel/public-exposure.workbench-dsflash-go.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelPublicExposure metadata: - id: d601-v03-web-probe-sentinel-public-exposure + id: web-probe-sentinel-workbench-dsflash-go-public-exposure owner: UniDesk specRef: PJ2026-01060508 sentinel: diff --git a/config/hwlab-web-probe-sentinel/report-views.auth-session-switch.yaml b/config/hwlab-web-probe-sentinel/report-views.auth-session-switch.yaml index 83b56c7b..e12551ed 100644 --- a/config/hwlab-web-probe-sentinel/report-views.auth-session-switch.yaml +++ b/config/hwlab-web-probe-sentinel/report-views.auth-session-switch.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelReportViews metadata: - id: d601-v03-web-probe-sentinel-auth-session-switch-report-views + id: web-probe-sentinel-auth-session-switch-report-views owner: UniDesk specRef: PJ2026-01060508 sentinel: diff --git a/config/hwlab-web-probe-sentinel/report-views.yaml b/config/hwlab-web-probe-sentinel/report-views.yaml index 70073c35..e3942342 100644 --- a/config/hwlab-web-probe-sentinel/report-views.yaml +++ b/config/hwlab-web-probe-sentinel/report-views.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelReportViews metadata: - id: d601-v03-web-probe-sentinel-report-views + id: web-probe-sentinel-report-views owner: UniDesk specRef: PJ2026-01060508 sentinel: diff --git a/config/hwlab-web-probe-sentinel/runtime.auth-session-switch.d601-v03.yaml b/config/hwlab-web-probe-sentinel/runtime.auth-session-switch.yaml similarity index 94% rename from config/hwlab-web-probe-sentinel/runtime.auth-session-switch.d601-v03.yaml rename to config/hwlab-web-probe-sentinel/runtime.auth-session-switch.yaml index 000ee70f..760c8f14 100644 --- a/config/hwlab-web-probe-sentinel/runtime.auth-session-switch.d601-v03.yaml +++ b/config/hwlab-web-probe-sentinel/runtime.auth-session-switch.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelRuntime metadata: - id: d601-v03-web-probe-sentinel-auth-session-switch-runtime + id: web-probe-sentinel-auth-session-switch-runtime owner: UniDesk specRef: PJ2026-01060508 sentinel: diff --git a/config/hwlab-web-probe-sentinel/runtime.fake-echo.d518-v03.yaml b/config/hwlab-web-probe-sentinel/runtime.fake-echo.yaml similarity index 95% rename from config/hwlab-web-probe-sentinel/runtime.fake-echo.d518-v03.yaml rename to config/hwlab-web-probe-sentinel/runtime.fake-echo.yaml index ad5538dc..b8521e7f 100644 --- a/config/hwlab-web-probe-sentinel/runtime.fake-echo.d518-v03.yaml +++ b/config/hwlab-web-probe-sentinel/runtime.fake-echo.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelRuntime metadata: - id: d518-v03-web-probe-sentinel-fake-echo-runtime + id: web-probe-sentinel-fake-echo-runtime owner: UniDesk specRef: PJ2026-01060508 issue: 1206 diff --git a/config/hwlab-web-probe-sentinel/runtime.mdtodo.d601-v03.yaml b/config/hwlab-web-probe-sentinel/runtime.mdtodo.yaml similarity index 95% rename from config/hwlab-web-probe-sentinel/runtime.mdtodo.d601-v03.yaml rename to config/hwlab-web-probe-sentinel/runtime.mdtodo.yaml index e5d3fee0..8b0e7429 100644 --- a/config/hwlab-web-probe-sentinel/runtime.mdtodo.d601-v03.yaml +++ b/config/hwlab-web-probe-sentinel/runtime.mdtodo.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelRuntime metadata: - id: d601-v03-web-probe-sentinel-mdtodo-runtime + id: web-probe-sentinel-mdtodo-runtime owner: UniDesk specRef: PJ2026-01060508 sentinel: diff --git a/config/hwlab-web-probe-sentinel/runtime.d518-v03.yaml b/config/hwlab-web-probe-sentinel/runtime.workbench-dsflash-go-secondary.yaml similarity index 94% rename from config/hwlab-web-probe-sentinel/runtime.d518-v03.yaml rename to config/hwlab-web-probe-sentinel/runtime.workbench-dsflash-go-secondary.yaml index d31a7986..a781fd5a 100644 --- a/config/hwlab-web-probe-sentinel/runtime.d518-v03.yaml +++ b/config/hwlab-web-probe-sentinel/runtime.workbench-dsflash-go-secondary.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelRuntime metadata: - id: d518-v03-web-probe-sentinel-dsflash-runtime + id: web-probe-sentinel-workbench-dsflash-go-secondary-runtime owner: UniDesk specRef: PJ2026-01060508 sentinel: diff --git a/config/hwlab-web-probe-sentinel/runtime.d601-v03.yaml b/config/hwlab-web-probe-sentinel/runtime.workbench-dsflash-go.yaml similarity index 95% rename from config/hwlab-web-probe-sentinel/runtime.d601-v03.yaml rename to config/hwlab-web-probe-sentinel/runtime.workbench-dsflash-go.yaml index d2d216b3..8eaa6c40 100644 --- a/config/hwlab-web-probe-sentinel/runtime.d601-v03.yaml +++ b/config/hwlab-web-probe-sentinel/runtime.workbench-dsflash-go.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelRuntime metadata: - id: d601-v03-web-probe-sentinel-runtime + id: web-probe-sentinel-workbench-dsflash-go-runtime owner: UniDesk specRef: PJ2026-01060508 sentinel: diff --git a/config/hwlab-web-probe-sentinel/scenarios.fake-echo.workbench.yaml b/config/hwlab-web-probe-sentinel/scenarios.fake-echo.workbench.yaml index 3e42e213..558fd505 100644 --- a/config/hwlab-web-probe-sentinel/scenarios.fake-echo.workbench.yaml +++ b/config/hwlab-web-probe-sentinel/scenarios.fake-echo.workbench.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelScenarios metadata: - id: d518-v03-web-probe-sentinel-fake-echo-scenarios + id: web-probe-sentinel-fake-echo-scenarios owner: UniDesk specRef: PJ2026-01060508 issue: 1190 diff --git a/config/hwlab-web-probe-sentinel/scenarios.mdtodo.yaml b/config/hwlab-web-probe-sentinel/scenarios.mdtodo.yaml index 46c6a780..16f6ccda 100644 --- a/config/hwlab-web-probe-sentinel/scenarios.mdtodo.yaml +++ b/config/hwlab-web-probe-sentinel/scenarios.mdtodo.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelScenarios metadata: - id: d601-v03-web-probe-sentinel-mdtodo-scenarios + id: web-probe-sentinel-mdtodo-scenarios owner: UniDesk specRef: PJ2026-01060508 sentinel: diff --git a/config/hwlab-web-probe-sentinel/scenarios.workbench.yaml b/config/hwlab-web-probe-sentinel/scenarios.workbench.yaml index 0b75196e..8926f68c 100644 --- a/config/hwlab-web-probe-sentinel/scenarios.workbench.yaml +++ b/config/hwlab-web-probe-sentinel/scenarios.workbench.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelScenarios metadata: - id: d601-v03-web-probe-sentinel-scenarios + id: web-probe-sentinel-workbench-scenarios owner: UniDesk specRef: PJ2026-01060508 sentinel: diff --git a/config/hwlab-web-probe-sentinel/secrets.auth-session-switch.d601-v03.yaml b/config/hwlab-web-probe-sentinel/secrets.auth-session-switch.yaml similarity index 95% rename from config/hwlab-web-probe-sentinel/secrets.auth-session-switch.d601-v03.yaml rename to config/hwlab-web-probe-sentinel/secrets.auth-session-switch.yaml index 07d5a733..b8160039 100644 --- a/config/hwlab-web-probe-sentinel/secrets.auth-session-switch.d601-v03.yaml +++ b/config/hwlab-web-probe-sentinel/secrets.auth-session-switch.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelSecrets metadata: - id: d601-v03-web-probe-sentinel-auth-session-switch-secrets + id: web-probe-sentinel-auth-session-switch-secrets owner: UniDesk specRef: PJ2026-01060508 sentinel: diff --git a/config/hwlab-web-probe-sentinel/secrets.fake-echo.d518-v03.yaml b/config/hwlab-web-probe-sentinel/secrets.fake-echo.yaml similarity index 95% rename from config/hwlab-web-probe-sentinel/secrets.fake-echo.d518-v03.yaml rename to config/hwlab-web-probe-sentinel/secrets.fake-echo.yaml index 12872f27..26943d91 100644 --- a/config/hwlab-web-probe-sentinel/secrets.fake-echo.d518-v03.yaml +++ b/config/hwlab-web-probe-sentinel/secrets.fake-echo.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelSecrets metadata: - id: d518-v03-web-probe-sentinel-fake-echo-secrets + id: web-probe-sentinel-fake-echo-secrets owner: UniDesk specRef: PJ2026-01060508 issue: 1190 diff --git a/config/hwlab-web-probe-sentinel/secrets.mdtodo.d601-v03.yaml b/config/hwlab-web-probe-sentinel/secrets.mdtodo.yaml similarity index 93% rename from config/hwlab-web-probe-sentinel/secrets.mdtodo.d601-v03.yaml rename to config/hwlab-web-probe-sentinel/secrets.mdtodo.yaml index 9827e485..a51ce981 100644 --- a/config/hwlab-web-probe-sentinel/secrets.mdtodo.d601-v03.yaml +++ b/config/hwlab-web-probe-sentinel/secrets.mdtodo.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelSecrets metadata: - id: d601-v03-web-probe-sentinel-mdtodo-secrets + id: web-probe-sentinel-mdtodo-secrets owner: UniDesk specRef: PJ2026-01060508 sentinel: diff --git a/config/hwlab-web-probe-sentinel/secrets.d518-v03.yaml b/config/hwlab-web-probe-sentinel/secrets.workbench-dsflash-go-secondary.yaml similarity index 94% rename from config/hwlab-web-probe-sentinel/secrets.d518-v03.yaml rename to config/hwlab-web-probe-sentinel/secrets.workbench-dsflash-go-secondary.yaml index 979d0814..45aa54e1 100644 --- a/config/hwlab-web-probe-sentinel/secrets.d518-v03.yaml +++ b/config/hwlab-web-probe-sentinel/secrets.workbench-dsflash-go-secondary.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelSecrets metadata: - id: d518-v03-web-probe-sentinel-secrets + id: web-probe-sentinel-workbench-dsflash-go-secondary-secrets owner: UniDesk specRef: PJ2026-01060508 sentinel: diff --git a/config/hwlab-web-probe-sentinel/secrets.d601-v03.yaml b/config/hwlab-web-probe-sentinel/secrets.workbench-dsflash-go.yaml similarity index 95% rename from config/hwlab-web-probe-sentinel/secrets.d601-v03.yaml rename to config/hwlab-web-probe-sentinel/secrets.workbench-dsflash-go.yaml index a02b804a..db57256b 100644 --- a/config/hwlab-web-probe-sentinel/secrets.d601-v03.yaml +++ b/config/hwlab-web-probe-sentinel/secrets.workbench-dsflash-go.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelSecrets metadata: - id: d601-v03-web-probe-sentinel-secrets + id: web-probe-sentinel-workbench-dsflash-go-secrets owner: UniDesk specRef: PJ2026-01060508 sentinel: diff --git a/config/hwlab-web-probe-sentinel/workflow.auth-session-switch.yaml b/config/hwlab-web-probe-sentinel/workflow.auth-session-switch.yaml index ec63e199..ffda42d5 100644 --- a/config/hwlab-web-probe-sentinel/workflow.auth-session-switch.yaml +++ b/config/hwlab-web-probe-sentinel/workflow.auth-session-switch.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinelWorkflow metadata: - id: d601-v03-web-probe-sentinel-auth-session-switch-workflow + id: web-probe-sentinel-auth-session-switch-workflow owner: UniDesk specRef: PJ2026-01060508 sentinel: diff --git a/config/hwlab-web-probe-sentinels/d601-v03/mdtodo-visual-regression.yaml b/config/hwlab-web-probe-sentinels/mdtodo-visual-regression.yaml similarity index 60% rename from config/hwlab-web-probe-sentinels/d601-v03/mdtodo-visual-regression.yaml rename to config/hwlab-web-probe-sentinels/mdtodo-visual-regression.yaml index 145da538..ce20d91a 100644 --- a/config/hwlab-web-probe-sentinels/d601-v03/mdtodo-visual-regression.yaml +++ b/config/hwlab-web-probe-sentinels/mdtodo-visual-regression.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinel metadata: - id: d601-v03-mdtodo-visual-regression + id: mdtodo-visual-regression owner: UniDesk specRef: PJ2026-01060508 sentinel: @@ -9,10 +9,10 @@ sentinel: enabled: true mode: web-probe-observe-wrapper configRefs: - runtime: config/hwlab-web-probe-sentinel/runtime.mdtodo.d601-v03.yaml#sentinel.runtime + runtime: config/hwlab-web-probe-sentinel/runtime.mdtodo.yaml#sentinel.runtime scenarios: config/hwlab-web-probe-sentinel/scenarios.mdtodo.yaml#sentinel.scenarios promptSet: config/hwlab-web-probe-sentinel/prompt-set.dsflash-go.yaml#sentinel.promptSet reportViews: config/hwlab-web-probe-sentinel/report-views.yaml#sentinel.reportViews - publicExposure: config/hwlab-web-probe-sentinel/public-exposure.mdtodo.d601-v03.yaml#sentinel.publicExposure - cicd: config/hwlab-web-probe-sentinel/cicd.mdtodo.d601-v03.yaml#sentinel.cicd - secrets: config/hwlab-web-probe-sentinel/secrets.mdtodo.d601-v03.yaml#sentinel.secrets + publicExposure: config/hwlab-web-probe-sentinel/public-exposure.mdtodo.yaml#sentinel.publicExposure + cicd: config/hwlab-web-probe-sentinel/cicd.mdtodo.yaml#sentinel.cicd + secrets: config/hwlab-web-probe-sentinel/secrets.mdtodo.yaml#sentinel.secrets diff --git a/config/hwlab-web-probe-sentinels/d601-v03/workbench-auth-session-switch-2users.yaml b/config/hwlab-web-probe-sentinels/workbench-auth-session-switch-2users.yaml similarity index 77% rename from config/hwlab-web-probe-sentinels/d601-v03/workbench-auth-session-switch-2users.yaml rename to config/hwlab-web-probe-sentinels/workbench-auth-session-switch-2users.yaml index e2188d3d..f5a0dbb5 100644 --- a/config/hwlab-web-probe-sentinels/d601-v03/workbench-auth-session-switch-2users.yaml +++ b/config/hwlab-web-probe-sentinels/workbench-auth-session-switch-2users.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinel metadata: - id: d601-v03-workbench-auth-session-switch-2users + id: workbench-auth-session-switch-2users owner: UniDesk specRef: PJ2026-01060508 sentinel: @@ -9,10 +9,10 @@ sentinel: enabled: true mode: web-probe-observe-wrapper configRefs: - runtime: config/hwlab-web-probe-sentinel/runtime.auth-session-switch.d601-v03.yaml#sentinel.runtime + runtime: config/hwlab-web-probe-sentinel/runtime.auth-session-switch.yaml#sentinel.runtime workflow: config/hwlab-web-probe-sentinel/workflow.auth-session-switch.yaml#sentinel.workflow promptSet: config/hwlab-web-probe-sentinel/prompt-set.auth-session-switch.yaml#sentinel.promptSet reportViews: config/hwlab-web-probe-sentinel/report-views.auth-session-switch.yaml#sentinel.reportViews - publicExposure: config/hwlab-web-probe-sentinel/public-exposure.auth-session-switch.d601-v03.yaml#sentinel.publicExposure - cicd: config/hwlab-web-probe-sentinel/cicd.auth-session-switch.d601-v03.yaml#sentinel.cicd - secrets: config/hwlab-web-probe-sentinel/secrets.auth-session-switch.d601-v03.yaml#sentinel.secrets + publicExposure: config/hwlab-web-probe-sentinel/public-exposure.auth-session-switch.yaml#sentinel.publicExposure + cicd: config/hwlab-web-probe-sentinel/cicd.auth-session-switch.yaml#sentinel.cicd + secrets: config/hwlab-web-probe-sentinel/secrets.auth-session-switch.yaml#sentinel.secrets diff --git a/config/hwlab-web-probe-sentinels/d601-v03/workbench-dsflash-go-tool-call-10x.yaml b/config/hwlab-web-probe-sentinels/workbench-dsflash-go-tool-call-10x-secondary.yaml similarity index 56% rename from config/hwlab-web-probe-sentinels/d601-v03/workbench-dsflash-go-tool-call-10x.yaml rename to config/hwlab-web-probe-sentinels/workbench-dsflash-go-tool-call-10x-secondary.yaml index 4f3d7c06..e3164057 100644 --- a/config/hwlab-web-probe-sentinels/d601-v03/workbench-dsflash-go-tool-call-10x.yaml +++ b/config/hwlab-web-probe-sentinels/workbench-dsflash-go-tool-call-10x-secondary.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinel metadata: - id: d601-v03-workbench-dsflash-go-tool-call-10x + id: workbench-dsflash-go-tool-call-10x-secondary owner: UniDesk specRef: PJ2026-01060508 sentinel: @@ -9,10 +9,10 @@ sentinel: enabled: true mode: web-probe-observe-wrapper configRefs: - runtime: config/hwlab-web-probe-sentinel/runtime.d601-v03.yaml#sentinel.runtime + runtime: config/hwlab-web-probe-sentinel/runtime.workbench-dsflash-go-secondary.yaml#sentinel.runtime scenarios: config/hwlab-web-probe-sentinel/scenarios.workbench.yaml#sentinel.scenarios promptSet: config/hwlab-web-probe-sentinel/prompt-set.dsflash-go.yaml#sentinel.promptSet reportViews: config/hwlab-web-probe-sentinel/report-views.yaml#sentinel.reportViews - publicExposure: config/hwlab-web-probe-sentinel/public-exposure.d601-v03.yaml#sentinel.publicExposure - cicd: config/hwlab-web-probe-sentinel/cicd.d601-v03.yaml#sentinel.cicd - secrets: config/hwlab-web-probe-sentinel/secrets.d601-v03.yaml#sentinel.secrets + publicExposure: config/hwlab-web-probe-sentinel/public-exposure.workbench-dsflash-go-secondary.yaml#sentinel.publicExposure + cicd: config/hwlab-web-probe-sentinel/cicd.workbench-dsflash-go-secondary.yaml#sentinel.cicd + secrets: config/hwlab-web-probe-sentinel/secrets.workbench-dsflash-go-secondary.yaml#sentinel.secrets diff --git a/config/hwlab-web-probe-sentinels/d518-v03/workbench-dsflash-go-tool-call-10x.yaml b/config/hwlab-web-probe-sentinels/workbench-dsflash-go-tool-call-10x.yaml similarity index 59% rename from config/hwlab-web-probe-sentinels/d518-v03/workbench-dsflash-go-tool-call-10x.yaml rename to config/hwlab-web-probe-sentinels/workbench-dsflash-go-tool-call-10x.yaml index 8076c855..9779bd87 100644 --- a/config/hwlab-web-probe-sentinels/d518-v03/workbench-dsflash-go-tool-call-10x.yaml +++ b/config/hwlab-web-probe-sentinels/workbench-dsflash-go-tool-call-10x.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinel metadata: - id: d518-v03-workbench-dsflash-go-tool-call-10x + id: workbench-dsflash-go-tool-call-10x owner: UniDesk specRef: PJ2026-01060508 sentinel: @@ -9,10 +9,10 @@ sentinel: enabled: true mode: web-probe-observe-wrapper configRefs: - runtime: config/hwlab-web-probe-sentinel/runtime.d518-v03.yaml#sentinel.runtime + runtime: config/hwlab-web-probe-sentinel/runtime.workbench-dsflash-go.yaml#sentinel.runtime scenarios: config/hwlab-web-probe-sentinel/scenarios.workbench.yaml#sentinel.scenarios promptSet: config/hwlab-web-probe-sentinel/prompt-set.dsflash-go.yaml#sentinel.promptSet reportViews: config/hwlab-web-probe-sentinel/report-views.yaml#sentinel.reportViews - publicExposure: config/hwlab-web-probe-sentinel/public-exposure.d518-v03.yaml#sentinel.publicExposure - cicd: config/hwlab-web-probe-sentinel/cicd.d518-v03.yaml#sentinel.cicd - secrets: config/hwlab-web-probe-sentinel/secrets.d518-v03.yaml#sentinel.secrets + publicExposure: config/hwlab-web-probe-sentinel/public-exposure.workbench-dsflash-go.yaml#sentinel.publicExposure + cicd: config/hwlab-web-probe-sentinel/cicd.workbench-dsflash-go.yaml#sentinel.cicd + secrets: config/hwlab-web-probe-sentinel/secrets.workbench-dsflash-go.yaml#sentinel.secrets diff --git a/config/hwlab-web-probe-sentinels/d518-v03/workbench-fake-echo-session-invariance-10x.yaml b/config/hwlab-web-probe-sentinels/workbench-fake-echo-session-invariance-10x.yaml similarity index 60% rename from config/hwlab-web-probe-sentinels/d518-v03/workbench-fake-echo-session-invariance-10x.yaml rename to config/hwlab-web-probe-sentinels/workbench-fake-echo-session-invariance-10x.yaml index b1d30bc4..ac24f5f1 100644 --- a/config/hwlab-web-probe-sentinels/d518-v03/workbench-fake-echo-session-invariance-10x.yaml +++ b/config/hwlab-web-probe-sentinels/workbench-fake-echo-session-invariance-10x.yaml @@ -1,7 +1,7 @@ version: 1 kind: HwlabWebProbeSentinel metadata: - id: d518-v03-workbench-fake-echo-session-invariance-10x + id: workbench-fake-echo-session-invariance-10x owner: UniDesk specRef: PJ2026-01060508 issue: 1190 @@ -10,10 +10,10 @@ sentinel: enabled: true mode: web-probe-observe-wrapper configRefs: - runtime: config/hwlab-web-probe-sentinel/runtime.fake-echo.d518-v03.yaml#sentinel.runtime + runtime: config/hwlab-web-probe-sentinel/runtime.fake-echo.yaml#sentinel.runtime scenarios: config/hwlab-web-probe-sentinel/scenarios.fake-echo.workbench.yaml#sentinel.scenarios promptSet: config/hwlab-web-probe-sentinel/prompt-set.fake-echo.yaml#sentinel.promptSet reportViews: config/hwlab-web-probe-sentinel/report-views.yaml#sentinel.reportViews - publicExposure: config/hwlab-web-probe-sentinel/public-exposure.fake-echo.d518-v03.yaml#sentinel.publicExposure - cicd: config/hwlab-web-probe-sentinel/cicd.fake-echo.d518-v03.yaml#sentinel.cicd - secrets: config/hwlab-web-probe-sentinel/secrets.fake-echo.d518-v03.yaml#sentinel.secrets + publicExposure: config/hwlab-web-probe-sentinel/public-exposure.fake-echo.yaml#sentinel.publicExposure + cicd: config/hwlab-web-probe-sentinel/cicd.fake-echo.yaml#sentinel.cicd + secrets: config/hwlab-web-probe-sentinel/secrets.fake-echo.yaml#sentinel.secrets diff --git a/project-management/PJ2026-01/specs/PJ2026-01010305-71freq-hwpod-v03-preinstall.md b/project-management/PJ2026-01/specs/PJ2026-01010305-71freq-hwpod-v03-preinstall.md index fd75561e..8799b135 100644 --- a/project-management/PJ2026-01/specs/PJ2026-01010305-71freq-hwpod-v03-preinstall.md +++ b/project-management/PJ2026-01/specs/PJ2026-01010305-71freq-hwpod-v03-preinstall.md @@ -133,7 +133,7 @@ flowchart LR PM --> Source[sourceId constart-71freq
sourceKind hwpod-workspace] PM --> Ops[HWLAB_PROJECT_MANAGEMENT_HWPOD_NODE_OPS_URL] PM --> OpsAuth[HWLAB_PROJECT_MANAGEMENT_HWPOD_NODE_OPS_API_KEY secretRef] - Lane --> GW[hwlab-gateway/constart-71freq-d601-v03.yaml] + Lane --> GW[hwlab-gateway/constart-71freq.yaml] GW --> SecretRefs[gateway/API Secret sourceRefs] ``` diff --git a/scripts/cli.ts b/scripts/cli.ts index c7656f11..a13ef752 100644 --- a/scripts/cli.ts +++ b/scripts/cli.ts @@ -392,8 +392,8 @@ async function main(): Promise { return; } if (sub === "g14") { - const { runHwlabG14Command } = await import("./src/hwlab-g14"); - const result = await runHwlabG14Command(readConfig(), args.slice(2)); + const { runHwlabLegacyRuntimeCommand } = await import("./src/hwlab-legacy-runtime"); + const result = await runHwlabLegacyRuntimeCommand(readConfig(), args.slice(2)); const ok = (result as { ok?: unknown }).ok !== false; emitJson(commandName, result, ok); if (!ok) process.exitCode = 1; diff --git a/scripts/src/artifact-registry/artifact-probe.ts b/scripts/src/artifact-registry/artifact-probe.ts index bf58d74e..713345ea 100644 --- a/scripts/src/artifact-registry/artifact-probe.ts +++ b/scripts/src/artifact-registry/artifact-probe.ts @@ -20,11 +20,11 @@ import { type DeployJsonExecutorMirror, type DeployJsonServiceContract, } from "../deploy-json-contract"; -import { d601K3sGuardShellLines } from "../d601-k3s-guard"; +import { k3sGuardShellLines } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import type { ArtifactConsumerSpec, ArtifactConsumerTarget, ArtifactRegistryOptions } from "./types"; -import { base64, d601K3sGuardScript, shellQuote } from "./bundle"; +import { base64, k3sTargetGuardScript, shellQuote } from "./bundle"; import { artifactImageRef, deployRefFor, sourceRepoFor } from "./consumer"; export function registryArtifactProbeScript(options: ArtifactRegistryOptions, spec: ArtifactConsumerSpec, commit: string): string { @@ -76,7 +76,7 @@ export function verifyLocalArtifactLabels( }; } -export function d601DevFrontendAuthPatchScript(config: UniDeskConfig): string { +export function devFrontendAuthPatchScript(config: UniDeskConfig): string { const sshClientToken = composeRuntimeEnvValue("UNIDESK_SSH_CLIENT_TOKEN"); if (sshClientToken === null) throw new Error("UNIDESK_SSH_CLIENT_TOKEN must be present in .state/docker-compose.env before deploying dev frontend"); const sshClientRouteAllowlist = composeRuntimeEnvValue("UNIDESK_SSH_CLIENT_ROUTE_ALLOWLIST") ?? "G14,G14:*,D601,D601:*"; @@ -91,7 +91,7 @@ export function d601DevFrontendAuthPatchScript(config: UniDeskConfig): string { UNIDESK_SSH_CLIENT_ROUTE_ALLOWLIST: sshClientRouteAllowlist, }; return [ - d601K3sGuardScript(), + k3sTargetGuardScript(), `secret_patch=${shellQuote(JSON.stringify({ data: secretData }))}`, `config_patch=${shellQuote(JSON.stringify({ data: configData }))}`, "kubectl -n unidesk-dev patch secret unidesk-dev-runtime-secrets --type merge -p \"$secret_patch\"", diff --git a/scripts/src/artifact-registry/bundle.ts b/scripts/src/artifact-registry/bundle.ts index 499b2ba3..1e46b78e 100644 --- a/scripts/src/artifact-registry/bundle.ts +++ b/scripts/src/artifact-registry/bundle.ts @@ -20,7 +20,7 @@ import { type DeployJsonExecutorMirror, type DeployJsonServiceContract, } from "../deploy-json-contract"; -import { d601K3sGuardShellLines } from "../d601-k3s-guard"; +import { k3sGuardShellLines } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import type { ArtifactRegistryOptions, RenderedBundle, RenderedFile } from "./types"; @@ -33,8 +33,8 @@ export function shellQuote(value: string): string { return `'${value.replace(/'/g, `'\\''`)}'`; } -export function d601K3sGuardScript(): string { - return d601K3sGuardShellLines().join("\n"); +export function k3sTargetGuardScript(): string { + return k3sGuardShellLines().join("\n"); } export function base64(value: string): string { diff --git a/scripts/src/artifact-registry/catalog.ts b/scripts/src/artifact-registry/catalog.ts index 7b499952..19f5926e 100644 --- a/scripts/src/artifact-registry/catalog.ts +++ b/scripts/src/artifact-registry/catalog.ts @@ -20,7 +20,7 @@ import { type DeployJsonExecutorMirror, type DeployJsonServiceContract, } from "../deploy-json-contract"; -import { d601K3sGuardShellLines } from "../d601-k3s-guard"; +import { k3sGuardShellLines } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import type { ArtifactConsumerSpec, AuthHealthGate, RuntimeSecretRequirement } from "./types"; diff --git a/scripts/src/artifact-registry/compose-deploy.ts b/scripts/src/artifact-registry/compose-deploy.ts index 26a5955a..94db7559 100644 --- a/scripts/src/artifact-registry/compose-deploy.ts +++ b/scripts/src/artifact-registry/compose-deploy.ts @@ -21,7 +21,7 @@ import { type DeployJsonExecutorMirror, type DeployJsonServiceContract, } from "../deploy-json-contract"; -import { d601K3sGuardShellLines } from "../d601-k3s-guard"; +import { k3sGuardShellLines } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import { artifactRegistryOptionsTargetSummary, type ArtifactConsumerSpec, type ArtifactConsumerTarget, type ArtifactRegistryOptions } from "./types"; @@ -33,7 +33,7 @@ import { composeLockScript } from "./install"; import { rollbackInfo } from "./k3s-deploy"; import { runReadonlyStatus } from "./readonly"; import { runRemoteScript } from "./remote"; -import { authHealthGateScript, composeArtifactRuntime, composeArtifactSecretPreflight, pullArtifactFromD601, runtimeSecretContractForComposeTarget, runtimeSecretRecommendedActionForService, upsertEnvFileValues } from "./runtime-secrets"; +import { authHealthGateScript, composeArtifactRuntime, composeArtifactSecretPreflight, pullArtifactFromRegistryTarget, runtimeSecretContractForComposeTarget, runtimeSecretRecommendedActionForService, upsertEnvFileValues } from "./runtime-secrets"; export async function deployComposeArtifactNow(options: ArtifactRegistryOptions, spec: ArtifactConsumerSpec, target: ArtifactConsumerTarget): Promise> { const commit = options.commit; @@ -85,7 +85,7 @@ export async function deployComposeArtifactNow(options: ArtifactRegistryOptions, registryProbe: commandTail(registryProbe), }; } - const pull = await pullArtifactFromD601(options, sourceImage); + const pull = await pullArtifactFromRegistryTarget(options, sourceImage); if (pull.exitCode !== 0 || pull.timedOut) { return { ok: false, @@ -211,7 +211,7 @@ export async function deployBackendCoreNow(options: ArtifactRegistryOptions): Pr return deployComposeArtifactNow(options, spec, target); } -export function d601ComposeArtifactDeployScript(options: ArtifactRegistryOptions, spec: ArtifactConsumerSpec, target: ArtifactConsumerTarget, commit: string): string { +export function composeTargetArtifactDeployScript(options: ArtifactRegistryOptions, spec: ArtifactConsumerSpec, target: ArtifactConsumerTarget, commit: string): string { if (target.compose === undefined) throw new Error(`${spec.serviceId} missing compose artifact consumer config`); const compose = target.compose; const sourceImage = artifactImageRef(options, spec, commit); @@ -313,7 +313,7 @@ export function d601ComposeArtifactDeployScript(options: ArtifactRegistryOptions ].join("\n"); } -export async function deployD601ComposeArtifactNow(options: ArtifactRegistryOptions, spec: ArtifactConsumerSpec, target: ArtifactConsumerTarget): Promise> { +export async function deployComposeTargetArtifactNow(options: ArtifactRegistryOptions, spec: ArtifactConsumerSpec, target: ArtifactConsumerTarget): Promise> { const environment = options.environment ?? "prod"; const commit = options.commit; if (commit === null) throw new Error("artifact-registry deploy-service requires --commit "); @@ -333,7 +333,7 @@ export async function deployD601ComposeArtifactNow(options: ArtifactRegistryOpti registryProbe: commandTail(registryProbe), }; } - const deploy = runRemoteScript(options, d601ComposeArtifactDeployScript(options, spec, target, commit), Math.max(options.timeoutMs, 420_000)); + const deploy = runRemoteScript(options, composeTargetArtifactDeployScript(options, spec, target, commit), Math.max(options.timeoutMs, 420_000)); if (deploy.exitCode !== 0 || deploy.timedOut) { return { ok: false, diff --git a/scripts/src/artifact-registry/consumer.ts b/scripts/src/artifact-registry/consumer.ts index 71d8a328..be4a83b2 100644 --- a/scripts/src/artifact-registry/consumer.ts +++ b/scripts/src/artifact-registry/consumer.ts @@ -20,7 +20,7 @@ import { type DeployJsonExecutorMirror, type DeployJsonServiceContract, } from "../deploy-json-contract"; -import { d601K3sGuardShellLines } from "../d601-k3s-guard"; +import { k3sGuardShellLines } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import type { ArtifactConsumerSpec, ArtifactConsumerTarget, ArtifactDeployEnvironment, ArtifactRegistryOptions, SupportedArtifactConsumerService } from "./types"; diff --git a/scripts/src/artifact-registry/entry.ts b/scripts/src/artifact-registry/entry.ts index eb854e25..3b1e917d 100644 --- a/scripts/src/artifact-registry/entry.ts +++ b/scripts/src/artifact-registry/entry.ts @@ -21,15 +21,15 @@ import { type DeployJsonExecutorMirror, type DeployJsonServiceContract, } from "../deploy-json-contract"; -import { d601K3sGuardShellLines } from "../d601-k3s-guard"; +import { k3sGuardShellLines } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import type { ArtifactRegistryAction, ArtifactRegistryCommandRuntime, ArtifactRegistryOptions } from "./types"; import { renderBundle } from "./bundle"; -import { deployBackendCoreJob, deployBackendCoreNow, deployComposeArtifactNow, deployD601ComposeArtifactNow, dryRunArtifactConsumerPlan, legacyDeployBackendCoreResult } from "./compose-deploy"; +import { deployBackendCoreJob, deployBackendCoreNow, deployComposeArtifactNow, deployComposeTargetArtifactNow, dryRunArtifactConsumerPlan, legacyDeployBackendCoreResult } from "./compose-deploy"; import { artifactConsumerLiveBlock, artifactConsumerSpec, artifactConsumerTarget, supportedArtifactConsumers, unsupportedEnvironment, unsupportedService } from "./consumer"; import { install, installDryRun } from "./install"; -import { deployD601K3sArtifactNow, rollbackInfo } from "./k3s-deploy"; +import { deployK3sTargetArtifactNow, rollbackInfo } from "./k3s-deploy"; import { isHelpArg, parseArtifactRegistryOptions } from "./options"; import { runReadonlyStatusWithRemoteFallback } from "./readonly"; import { plan } from "./status"; @@ -46,8 +46,8 @@ export async function deployServiceNow(options: ArtifactRegistryOptions): Promis const liveBlock = artifactConsumerLiveBlock(spec, options); if (liveBlock !== null) return liveBlock; if (spec.kind === "compose") return deployComposeArtifactNow(options, spec, target); - if (spec.kind === "d601-compose") return deployD601ComposeArtifactNow(options, spec, target); - return deployD601K3sArtifactNow(options, spec, target); + if (spec.kind === "d601-compose") return deployComposeTargetArtifactNow(options, spec, target); + return deployK3sTargetArtifactNow(options, spec, target); } export function deployServiceJob(args: string[], options: ArtifactRegistryOptions): Record { diff --git a/scripts/src/artifact-registry/install.ts b/scripts/src/artifact-registry/install.ts index f2272d58..4ad74ec3 100644 --- a/scripts/src/artifact-registry/install.ts +++ b/scripts/src/artifact-registry/install.ts @@ -20,7 +20,7 @@ import { type DeployJsonExecutorMirror, type DeployJsonServiceContract, } from "../deploy-json-contract"; -import { d601K3sGuardShellLines } from "../d601-k3s-guard"; +import { k3sGuardShellLines } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import type { ArtifactRegistryOptions, RenderedFile, RuntimeSecretPresence, RuntimeSecretRequirement } from "./types"; diff --git a/scripts/src/artifact-registry/k3s-deploy.ts b/scripts/src/artifact-registry/k3s-deploy.ts index 65961168..f3d0780c 100644 --- a/scripts/src/artifact-registry/k3s-deploy.ts +++ b/scripts/src/artifact-registry/k3s-deploy.ts @@ -20,12 +20,12 @@ import { type DeployJsonExecutorMirror, type DeployJsonServiceContract, } from "../deploy-json-contract"; -import { d601K3sGuardShellLines } from "../d601-k3s-guard"; +import { k3sGuardShellLines } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import type { ArtifactConsumerSpec, ArtifactConsumerTarget, ArtifactDeployEnvironment, ArtifactRegistryOptions } from "./types"; -import { d601DevFrontendAuthPatchScript, registryArtifactMissingMessage, registryArtifactProbeScript } from "./artifact-probe"; -import { d601K3sGuardScript, rootExecPrelude, shellQuote } from "./bundle"; +import { devFrontendAuthPatchScript, registryArtifactMissingMessage, registryArtifactProbeScript } from "./artifact-probe"; +import { k3sTargetGuardScript, rootExecPrelude, shellQuote } from "./bundle"; import { artifactImageRef, commandTail, deployRefFor, sourceRepoFor } from "./consumer"; import { runReadonlyStatus } from "./readonly"; import { runRemoteScript, runRemoteScriptBackground } from "./remote"; @@ -54,7 +54,7 @@ export function rollbackInfo(spec: ArtifactConsumerSpec, target: ArtifactConsume }; } -export function d601K3sArtifactDeployScript(options: ArtifactRegistryOptions, spec: ArtifactConsumerSpec, target: ArtifactConsumerTarget, commit: string): string { +export function k3sTargetArtifactDeployScript(options: ArtifactRegistryOptions, spec: ArtifactConsumerSpec, target: ArtifactConsumerTarget, commit: string): string { const environment = options.environment ?? "prod"; if (target.k3s === undefined) throw new Error(`${spec.serviceId} missing k3s artifact consumer config for ${environment}`); const manifestText = readFileSync(rootPath(target.k3s.manifestRepoPath), "utf8"); @@ -120,7 +120,7 @@ export function d601K3sArtifactDeployScript(options: ArtifactRegistryOptions, sp "command -v kubectl >/dev/null", "command -v ctr >/dev/null", "test -S /run/k3s/containerd/containerd.sock", - d601K3sGuardScript(), + k3sTargetGuardScript(), `curl -fsSI -H 'Accept: application/vnd.docker.distribution.manifest.v2+json' ${shellQuote(`http://127.0.0.1:${options.port}/v2/${spec.registryRepository}/manifests/${commit}`)} >/dev/null`, "docker pull -q \"$registry_image\" >/dev/null", "label_commit=$(docker image inspect \"$registry_image\" --format '{{ index .Config.Labels \"unidesk.ai/source-commit\" }}')", @@ -159,7 +159,7 @@ export function d601K3sArtifactDeployScript(options: ArtifactRegistryOptions, sp " raise SystemExit('manifest missing deployment(s): ' + ','.join(missing))", "PY", "if [ -n \"$apply_selector\" ]; then kubectl apply -f \"$manifest\" -l \"$apply_selector\"; else kubectl apply -f \"$manifest\"; fi", - ...(environment === "dev" && spec.serviceId === "frontend" ? [d601DevFrontendAuthPatchScript(readConfig())] : []), + ...(environment === "dev" && spec.serviceId === "frontend" ? [devFrontendAuthPatchScript(readConfig())] : []), "previous_commit=$(kubectl -n \"$namespace\" get deployment \"$deployment\" -o jsonpath='{.metadata.annotations.unidesk\\.ai/deploy-commit}' 2>/dev/null || true)", "python3 - \"$deployment_specs\" <<'PY' | while IFS=$'\\t' read -r rollout_deployment rollout_container; do", "import json, sys", @@ -264,7 +264,7 @@ export function d601K3sArtifactDeployScript(options: ArtifactRegistryOptions, sp ].join("\n"); } -export async function deployD601K3sArtifactNow(options: ArtifactRegistryOptions, spec: ArtifactConsumerSpec, target: ArtifactConsumerTarget): Promise> { +export async function deployK3sTargetArtifactNow(options: ArtifactRegistryOptions, spec: ArtifactConsumerSpec, target: ArtifactConsumerTarget): Promise> { const environment = options.environment ?? "prod"; const commit = options.commit; if (commit === null) throw new Error("artifact-registry deploy-service requires --commit "); @@ -283,7 +283,7 @@ export async function deployD601K3sArtifactNow(options: ArtifactRegistryOptions, registryProbe: commandTail(registryProbe), }; } - const deployScript = d601K3sArtifactDeployScript(options, spec, target, commit); + const deployScript = k3sTargetArtifactDeployScript(options, spec, target, commit); const deploy = await runRemoteScriptBackground(options, deployScript, Math.max(options.timeoutMs, 420_000), "d601-k3s-deploy"); if (deploy.exitCode !== 0 || deploy.timedOut) { return { diff --git a/scripts/src/artifact-registry/options.ts b/scripts/src/artifact-registry/options.ts index 8773ee15..a3840db0 100644 --- a/scripts/src/artifact-registry/options.ts +++ b/scripts/src/artifact-registry/options.ts @@ -21,7 +21,7 @@ import { type DeployJsonExecutorMirror, type DeployJsonServiceContract, } from "../deploy-json-contract"; -import { d601K3sGuardShellLines } from "../d601-k3s-guard"; +import { k3sGuardShellLines } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import type { ArtifactDeployEnvironment, ArtifactRegistryOptions } from "./types"; diff --git a/scripts/src/artifact-registry/readonly.ts b/scripts/src/artifact-registry/readonly.ts index 188f7e8d..dc644fb8 100644 --- a/scripts/src/artifact-registry/readonly.ts +++ b/scripts/src/artifact-registry/readonly.ts @@ -21,7 +21,7 @@ import { type DeployJsonExecutorMirror, type DeployJsonServiceContract, } from "../deploy-json-contract"; -import { d601K3sGuardShellLines } from "../d601-k3s-guard"; +import { k3sGuardShellLines } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import { artifactRegistryOptionsTargetSummary, type ArtifactRegistryCommandRuntime, type ArtifactRegistryOptions, type ArtifactRegistryReadonlyProbe } from "./types"; diff --git a/scripts/src/artifact-registry/remote.ts b/scripts/src/artifact-registry/remote.ts index e55d6ee0..2100ea40 100644 --- a/scripts/src/artifact-registry/remote.ts +++ b/scripts/src/artifact-registry/remote.ts @@ -21,7 +21,7 @@ import { type DeployJsonExecutorMirror, type DeployJsonServiceContract, } from "../deploy-json-contract"; -import { d601K3sGuardShellLines } from "../d601-k3s-guard"; +import { k3sGuardShellLines } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import type { ArtifactRegistryCommandRuntime, ArtifactRegistryOptions } from "./types"; diff --git a/scripts/src/artifact-registry/runtime-secrets.ts b/scripts/src/artifact-registry/runtime-secrets.ts index 8d9c4bdd..f70e6c77 100644 --- a/scripts/src/artifact-registry/runtime-secrets.ts +++ b/scripts/src/artifact-registry/runtime-secrets.ts @@ -20,7 +20,7 @@ import { type DeployJsonExecutorMirror, type DeployJsonServiceContract, } from "../deploy-json-contract"; -import { d601K3sGuardShellLines } from "../d601-k3s-guard"; +import { k3sGuardShellLines } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import type { ArtifactConsumerTarget, ArtifactDeployEnvironment, ArtifactRegistryOptions, AuthHealthGate, ComposeArtifactRuntime, RuntimeSecretContract, RuntimeSecretPresence, RuntimeSecretRequirement, RuntimeSecretSource } from "./types"; @@ -187,7 +187,7 @@ export function upsertEnvFileValues(path: string, values: Record writeFileSync(path, `${lines.join("\n")}\n`, "utf8"); } -export async function pullArtifactFromD601(options: ArtifactRegistryOptions, sourceImage: string): Promise { +export async function pullArtifactFromRegistryTarget(options: ArtifactRegistryOptions, sourceImage: string): Promise { const localArchive = `/tmp/unidesk-artifact-${safeName(options.serviceId ?? "service")}-${safeName(options.commit ?? "commit")}-${Date.now().toString(36)}.tar.gz`; const remoteArchive = `/tmp/unidesk-artifact-${safeName(options.serviceId ?? "service")}-${safeName(options.commit ?? "commit")}-${Date.now().toString(36)}.tar.gz`; const remoteScript = [ diff --git a/scripts/src/artifact-registry/status.ts b/scripts/src/artifact-registry/status.ts index 73ce55a5..b36f2aa8 100644 --- a/scripts/src/artifact-registry/status.ts +++ b/scripts/src/artifact-registry/status.ts @@ -21,7 +21,7 @@ import { type DeployJsonExecutorMirror, type DeployJsonServiceContract, } from "../deploy-json-contract"; -import { d601K3sGuardShellLines } from "../d601-k3s-guard"; +import { k3sGuardShellLines } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import { artifactRegistryOptionsTargetSummary, type ArtifactRegistryFailureClassification, type ArtifactRegistryOptions, type RenderedBundle } from "./types"; diff --git a/scripts/src/artifact-registry/types.ts b/scripts/src/artifact-registry/types.ts index 5b7e9685..b7e12ce5 100644 --- a/scripts/src/artifact-registry/types.ts +++ b/scripts/src/artifact-registry/types.ts @@ -21,7 +21,7 @@ import { type DeployJsonExecutorMirror, type DeployJsonServiceContract, } from "../deploy-json-contract"; -import { d601K3sGuardShellLines } from "../d601-k3s-guard"; +import { k3sGuardShellLines } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import { artifactRegistryTargetSummary, resolveArtifactRegistryTarget, type TargetConfigSource } from "../ops/targets"; diff --git a/scripts/src/check.ts b/scripts/src/check.ts index cbaaf668..b0cffc65 100644 --- a/scripts/src/check.ts +++ b/scripts/src/check.ts @@ -3,7 +3,7 @@ import { extname } from "node:path"; import { runCommandObserved, type CommandProgress } from "./command"; import { type UniDeskConfig, repoRoot, rootPath } from "./config"; import { composeConfig } from "./docker"; -import { compactD601RecoveryGuardrails, runD601RecoveryGuardrails } from "./recovery-guardrails"; +import { compactRecoveryGuardrails, runRecoveryGuardrails } from "./recovery-guardrails"; interface CheckItem { name: string; @@ -21,7 +21,7 @@ const syntaxFiles = [ "scripts/src/code-queue.ts", "scripts/src/code-queue-execution-plane.ts", "scripts/src/command.ts", - "scripts/src/d601-k3s-guard.ts", + "scripts/src/k3s-target-guard.ts", "scripts/src/hwlab-cd.ts", "scripts/src/decision-center.ts", "scripts/src/dev-env.ts", @@ -356,8 +356,8 @@ function skippedItem(name: string, reason: string, enableWith: string): CheckIte return { name, ok: true, detail: { skipped: true, reason, enableWith } }; } -export function runRecoveryGuardrailsCheck(config: UniDeskConfig): ReturnType { - return compactD601RecoveryGuardrails(runD601RecoveryGuardrails(config)); +export function runRecoveryGuardrailsCheck(config: UniDeskConfig): ReturnType { + return compactRecoveryGuardrails(runRecoveryGuardrails(config)); } export async function runChecks(config: UniDeskConfig, options: CheckOptions = defaultCheckOptions): Promise { diff --git a/scripts/src/ci/artifact-summary.ts b/scripts/src/ci/artifact-summary.ts index 19ad15df..efd7615e 100644 --- a/scripts/src/ci/artifact-summary.ts +++ b/scripts/src/ci/artifact-summary.ts @@ -18,7 +18,7 @@ import { parseArtifactRegistryOptions, type ArtifactRegistryReadonlyProbe, } from "../artifact-registry"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { runSshCommandCapture } from "../ssh"; import type { ArtifactSummary, ArtifactSummaryContext } from "./types"; diff --git a/scripts/src/ci/cleanup.ts b/scripts/src/ci/cleanup.ts index 7211b422..c2fcc554 100644 --- a/scripts/src/ci/cleanup.ts +++ b/scripts/src/ci/cleanup.ts @@ -19,7 +19,7 @@ import { parseArtifactRegistryOptions, type ArtifactRegistryReadonlyProbe, } from "../artifact-registry"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { runSshCommandCapture } from "../ssh"; import type { CiCleanupFailedPodsOptions, CiCleanupRunsOptions, CiTarget } from "./types"; diff --git a/scripts/src/ci/dev-e2e.ts b/scripts/src/ci/dev-e2e.ts index 5645ac73..85ee4d22 100644 --- a/scripts/src/ci/dev-e2e.ts +++ b/scripts/src/ci/dev-e2e.ts @@ -18,7 +18,7 @@ import { parseArtifactRegistryOptions, type ArtifactRegistryReadonlyProbe, } from "../artifact-registry"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { runSshCommandCapture } from "../ssh"; import type { CiDevE2EOptions, DeployDevManifestSummary, DispatchResult } from "./types"; diff --git a/scripts/src/ci/direct-docker.ts b/scripts/src/ci/direct-docker.ts index 9af24f85..0bb28d6b 100644 --- a/scripts/src/ci/direct-docker.ts +++ b/scripts/src/ci/direct-docker.ts @@ -18,7 +18,7 @@ import { parseArtifactRegistryOptions, type ArtifactRegistryReadonlyProbe, } from "../artifact-registry"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { runSshCommandCapture } from "../ssh"; import type { ArtifactSummary, ArtifactSummaryContext, CiPublishUserServiceArtifactOptions } from "./types"; diff --git a/scripts/src/ci/entry.ts b/scripts/src/ci/entry.ts index 3c36000f..46973840 100644 --- a/scripts/src/ci/entry.ts +++ b/scripts/src/ci/entry.ts @@ -19,7 +19,7 @@ import { parseArtifactRegistryOptions, type ArtifactRegistryReadonlyProbe, } from "../artifact-registry"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { runSshCommandCapture } from "../ssh"; import { cleanupFailedPods, cleanupRuns, status } from "./cleanup"; diff --git a/scripts/src/ci/help.ts b/scripts/src/ci/help.ts index 701ff089..0eb7efa7 100644 --- a/scripts/src/ci/help.ts +++ b/scripts/src/ci/help.ts @@ -19,7 +19,7 @@ import { parseArtifactRegistryOptions, type ArtifactRegistryReadonlyProbe, } from "../artifact-registry"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { runSshCommandCapture } from "../ssh"; import { g14CiPipelineManifest, tektonPipelineReleaseUrl, tektonPipelineVersion, tektonTriggersInterceptorsUrl, tektonTriggersReleaseUrl, tektonTriggersVersion } from "./types"; diff --git a/scripts/src/ci/install.ts b/scripts/src/ci/install.ts index 6b46bbfc..eadd5cbd 100644 --- a/scripts/src/ci/install.ts +++ b/scripts/src/ci/install.ts @@ -19,7 +19,7 @@ import { parseArtifactRegistryOptions, type ArtifactRegistryReadonlyProbe, } from "../artifact-registry"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { runSshCommandCapture } from "../ssh"; import type { CiInstallOptions } from "./types"; diff --git a/scripts/src/ci/logs.ts b/scripts/src/ci/logs.ts index 5f7372d4..f50147fb 100644 --- a/scripts/src/ci/logs.ts +++ b/scripts/src/ci/logs.ts @@ -19,7 +19,7 @@ import { parseArtifactRegistryOptions, type ArtifactRegistryReadonlyProbe, } from "../artifact-registry"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { runSshCommandCapture } from "../ssh"; import type { CiLogsOptions, CiTarget } from "./types"; diff --git a/scripts/src/ci/options.ts b/scripts/src/ci/options.ts index f67bbebb..e09ff001 100644 --- a/scripts/src/ci/options.ts +++ b/scripts/src/ci/options.ts @@ -18,11 +18,11 @@ import { parseArtifactRegistryOptions, type ArtifactRegistryReadonlyProbe, } from "../artifact-registry"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { runSshCommandCapture } from "../ssh"; import type { CiCleanupFailedPodsOptions, CiCleanupRunsOptions, CiLogsOptions, CiPublishTransport, CiTarget } from "./types"; -import { ciTarget, d601ProviderId, providerIdOption } from "./types"; +import { ciTarget, defaultCiProviderId, providerIdOption } from "./types"; export function stringOption(args: string[], name: string): string | null { const index = args.indexOf(name); @@ -171,8 +171,8 @@ export function shellQuote(value: string): string { } export function ciTargetGuardShellLines(target: CiTarget, options: { passOutput?: "stdout" | "stderr" | "quiet" } = {}): string[] { - if (target.providerId === d601ProviderId) { - return d601K3sGuardShellLines(target.kubeconfig, options); + if (target.providerId === defaultCiProviderId) { + return k3sGuardShellLines(target.kubeconfig, options); } const passOutput = options.passOutput ?? "stdout"; const labelSelector = target.requiredNodeLabel === undefined ? "" : `${target.requiredNodeLabel.key}=${target.requiredNodeLabel.value}`; @@ -320,11 +320,11 @@ export function userServicePublishBoundaryBlock( ): Record | null { const configService = config.microservices.find((item) => item.id === serviceId); if (configService === undefined) return null; - const isD601K3sService = configService.providerId === d601ProviderId - && configService.development.providerId === d601ProviderId + const isTargetK3sService = configService.providerId === defaultCiProviderId + && configService.development.providerId === defaultCiProviderId && configService.deployment.mode === "k3sctl-managed"; - const isD601DirectService = configService.providerId === d601ProviderId - && configService.development.providerId === d601ProviderId + const isTargetDirectService = configService.providerId === defaultCiProviderId + && configService.development.providerId === defaultCiProviderId && configService.deployment.mode === "unidesk-direct"; const isMainServerDirectService = configService.providerId === "main-server" && configService.development.providerId === "main-server" @@ -332,7 +332,7 @@ export function userServicePublishBoundaryBlock( const isMainServerInternalSidecar = configService.providerId === "main-server" && configService.development.providerId === "main-server" && configService.deployment.mode === "internal-sidecar"; - if (isD601K3sService || isD601DirectService || isMainServerDirectService || isMainServerInternalSidecar) return null; + if (isTargetK3sService || isTargetDirectService || isMainServerDirectService || isMainServerInternalSidecar) return null; return { ok: false, status: "blocked", diff --git a/scripts/src/ci/pipelinerun-runtime.ts b/scripts/src/ci/pipelinerun-runtime.ts index 716fc386..5f362d3b 100644 --- a/scripts/src/ci/pipelinerun-runtime.ts +++ b/scripts/src/ci/pipelinerun-runtime.ts @@ -18,7 +18,7 @@ import { parseArtifactRegistryOptions, type ArtifactRegistryReadonlyProbe, } from "../artifact-registry"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { runSshCommandCapture } from "../ssh"; import type { DispatchResult, PipelineRunCondition } from "./types"; diff --git a/scripts/src/ci/pipelinerun.ts b/scripts/src/ci/pipelinerun.ts index 63318b6b..a8f5f6e0 100644 --- a/scripts/src/ci/pipelinerun.ts +++ b/scripts/src/ci/pipelinerun.ts @@ -18,7 +18,7 @@ import { parseArtifactRegistryOptions, type ArtifactRegistryReadonlyProbe, } from "../artifact-registry"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { runSshCommandCapture } from "../ssh"; import type { CiOptions, CiPublishBackendCoreOptions, CiPublishUserServiceArtifactOptions } from "./types"; diff --git a/scripts/src/ci/preflight.ts b/scripts/src/ci/preflight.ts index 4c36daa6..a1c2fc98 100644 --- a/scripts/src/ci/preflight.ts +++ b/scripts/src/ci/preflight.ts @@ -18,12 +18,12 @@ import { parseArtifactRegistryOptions, type ArtifactRegistryReadonlyProbe, } from "../artifact-registry"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { runSshCommandCapture } from "../ssh"; import type { DispatchResult, PublishPreflight, PublishPreflightChannelProbe, PublishPreflightControlChannel, PublishPreflightControlChannelProbe, PublishPreflightDetailedChannel, PublishPreflightFailureClassification, PublishPreflightTransport } from "./types"; import { status } from "./cleanup"; -import { d601ProviderId } from "./types"; +import { defaultCiProviderId } from "./types"; export function chunks(value: string, size: number): string[] { const result: string[] = []; @@ -170,7 +170,7 @@ export function publishPreflightControlPlane( fallbackRunnerPath: "main-server-local-docker", remoteCommandShape, providerTunnel: { - providerId: d601ProviderId, + providerId: defaultCiProviderId, command: "host.ssh", requiredFor: ["provider-host-ssh", "artifact-registry"], }, diff --git a/scripts/src/ci/publish-preflight.ts b/scripts/src/ci/publish-preflight.ts index 135166f2..8bcfb84f 100644 --- a/scripts/src/ci/publish-preflight.ts +++ b/scripts/src/ci/publish-preflight.ts @@ -19,7 +19,7 @@ import { parseArtifactRegistryOptions, type ArtifactRegistryReadonlyProbe, } from "../artifact-registry"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { runSshCommandCapture } from "../ssh"; import type { ArtifactSummary, ArtifactSummaryContext, CiPublishBackendCoreOptions, CiPublishUserServiceArtifactOptions, PublishPreflight, PublishPreflightChannelProbe, PublishPreflightTransport } from "./types"; @@ -29,7 +29,7 @@ import { shellQuote } from "./options"; import { asRecord, asString, backendCoreUnavailable, channelProbe, classifyPublishPreflightFailure, coreBody, publishPreflightControlPlane, recommendedPublishPreflightAction, responseOk, summarizePublishControlChannels } from "./preflight"; import { runRemoteKubectlRaw } from "./remote"; import { backendCoreCiRunnerReady, backendCoreRemoteCommandShape, ciRunnerPreflightScript, commandResultFromDispatch, dispatchPreflightFailure } from "./runner-preflight"; -import { ciTarget, d601Kubeconfig, d601ProviderId } from "./types"; +import { ciTarget, defaultCiKubeconfig, defaultCiProviderId } from "./types"; export function assertArtifactSummaryComplete(artifact: ArtifactSummary, pipelineRun: string): void { const missing = missingArtifactSummaryFields(artifact); @@ -44,7 +44,7 @@ export async function publishUserServicePreflight( plannedArtifact: ArtifactSummary, transport: PublishPreflightTransport, ): Promise { - const providerId = d601ProviderId; + const providerId = defaultCiProviderId; const channels: PublishPreflightChannelProbe[] = []; const overview = await transport.coreFetch("/api/overview", { maxResponseBytes: 500_000 }); const overviewBody = coreBody(overview); @@ -66,7 +66,7 @@ export async function publishUserServicePreflight( const probeScript = [ "set -euo pipefail", - ...d601K3sGuardShellLines(d601Kubeconfig), + ...k3sGuardShellLines(defaultCiKubeconfig), "printf 'provider_host_ssh=ok\\n'", "command -v bash >/dev/null", "command -v docker >/dev/null", @@ -144,7 +144,7 @@ export async function publishBackendCorePreflight( plannedArtifact: ArtifactSummary, transport: PublishPreflightTransport, ): Promise { - const providerId = d601ProviderId; + const providerId = defaultCiProviderId; const channels: PublishPreflightChannelProbe[] = []; const overview = await transport.coreFetch("/api/overview", { maxResponseBytes: 500_000 }); const overviewBody = coreBody(overview); diff --git a/scripts/src/ci/publish.ts b/scripts/src/ci/publish.ts index 41309d26..3c3b5318 100644 --- a/scripts/src/ci/publish.ts +++ b/scripts/src/ci/publish.ts @@ -19,7 +19,7 @@ import { parseArtifactRegistryOptions, type ArtifactRegistryReadonlyProbe, } from "../artifact-registry"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { runSshCommandCapture } from "../ssh"; import type { ArtifactSummaryContext, CiOptions, CiPublishBackendCoreOptions, CiPublishUserServiceArtifactOptions, PublishPreflightTransport } from "./types"; @@ -33,7 +33,7 @@ import { assertArtifactSummaryComplete, publishBackendCorePreflight, publishUser import { localPublishPreflightTransport } from "./remote"; import { backendCoreArtifactRequirements, backendCoreDevApplyPath } from "./runner-preflight"; import { prepareBackendCoreArtifactSource, prepareClaudeqqArtifactSource, prepareUserServiceArtifactSource } from "./source-prepare"; -import { d601ProviderId, providerGatewayWsEgressProxyUrl } from "./types"; +import { defaultCiProviderId, providerGatewayWsEgressProxyUrl } from "./types"; export async function run(options: CiOptions): Promise> { const name = await remoteCreatePipelineRun(pipelineRunManifest(options), options.target); @@ -152,7 +152,7 @@ export async function publishUserServiceArtifact(config: UniDeskConfig, options: source: { ok: preflight.ok, mode: "planned-only", - providerId: d601ProviderId, + providerId: defaultCiProviderId, repoUrl: options.repoUrl, repoFetchUrl: plannedRepoFetchUrl, repoProbeUrl: repoConnectivityProbeUrl(plannedRepoFetchUrl), @@ -286,7 +286,7 @@ export async function runCiPublishUserServiceDryRunPreflight( source: { ok: preflight.ok, mode: "planned-only", - providerId: d601ProviderId, + providerId: defaultCiProviderId, repoUrl: options.repoUrl, repoFetchUrl: plannedRepoFetchUrl, repoProbeUrl: repoConnectivityProbeUrl(plannedRepoFetchUrl), @@ -357,9 +357,9 @@ export async function runCiPublishBackendCoreDryRunPreflight( targetCommit: options.commit, sourceRepo: options.repoUrl, serviceId: "backend-core", - providerId: d601ProviderId, + providerId: defaultCiProviderId, ciRunner: { - providerId: d601ProviderId, + providerId: defaultCiProviderId, environment: "D601", namespace: "unidesk-ci", pipeline: "unidesk-backend-core-artifact-publish", @@ -386,7 +386,7 @@ export async function runCiPublishBackendCoreDryRunPreflight( source: { ok: preflight.ok, mode: "planned-only", - providerId: d601ProviderId, + providerId: defaultCiProviderId, repoUrl: options.repoUrl, repoFetchUrl: plannedRepoFetchUrl, repoProbeUrl: repoConnectivityProbeUrl(plannedRepoFetchUrl), @@ -403,7 +403,7 @@ export async function runCiPublishBackendCoreDryRunPreflight( identityRequired: repoNeedsGithubSshIdentity(plannedRepoFetchUrl), }, d601Ci: { - providerId: d601ProviderId, + providerId: defaultCiProviderId, namespace: "unidesk-ci", pipeline: "unidesk-backend-core-artifact-publish", wouldBuildOnD601: true, diff --git a/scripts/src/ci/remote.ts b/scripts/src/ci/remote.ts index 7df798d6..649d57a2 100644 --- a/scripts/src/ci/remote.ts +++ b/scripts/src/ci/remote.ts @@ -18,7 +18,7 @@ import { parseArtifactRegistryOptions, type ArtifactRegistryReadonlyProbe, } from "../artifact-registry"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { runSshCommandCapture } from "../ssh"; import type { DispatchResult, PublishPreflightTransport } from "./types"; diff --git a/scripts/src/ci/runner-preflight.ts b/scripts/src/ci/runner-preflight.ts index d4a08708..c52691ff 100644 --- a/scripts/src/ci/runner-preflight.ts +++ b/scripts/src/ci/runner-preflight.ts @@ -18,19 +18,19 @@ import { parseArtifactRegistryOptions, type ArtifactRegistryReadonlyProbe, } from "../artifact-registry"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { runSshCommandCapture } from "../ssh"; import type { ArtifactSummary, CiPublishBackendCoreOptions, DispatchResult } from "./types"; import { shellQuote } from "./options"; import { backendCoreUnavailable } from "./preflight"; import { dispatchSsh } from "./remote"; -import { d601Kubeconfig } from "./types"; +import { defaultCiKubeconfig } from "./types"; export function ciRunnerPreflightScript(sourceHostPath: string): string { return [ "set -eu", - ...d601K3sGuardShellLines(d601Kubeconfig), + ...k3sGuardShellLines(defaultCiKubeconfig), "printf 'provider_host_ssh=ok\\n'", "printf 'kubectl='", "command -v kubectl >/dev/null && printf 'ok\\n' || { printf 'missing\\n'; exit 127; }", diff --git a/scripts/src/ci/source-prepare.ts b/scripts/src/ci/source-prepare.ts index ec7f56a3..14b530ab 100644 --- a/scripts/src/ci/source-prepare.ts +++ b/scripts/src/ci/source-prepare.ts @@ -18,20 +18,20 @@ import { parseArtifactRegistryOptions, type ArtifactRegistryReadonlyProbe, } from "../artifact-registry"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { runSshCommandCapture } from "../ssh"; import type { CiPublishBackendCoreOptions, CiPublishUserServiceArtifactOptions } from "./types"; import { repoConnectivityProbeUrl, repoNeedsGithubSshIdentity, repoSshUrl, requireRepoRelativePath, safePathToken, shellQuote } from "./options"; import { runRemoteBackground } from "./remote"; -import { d601ProviderId, providerGatewayWsEgressProxyUrl } from "./types"; +import { defaultCiProviderId, providerGatewayWsEgressProxyUrl } from "./types"; export async function prepareBackendCoreArtifactSource(config: UniDeskConfig, options: CiPublishBackendCoreOptions): Promise> { const sourceRoot = "/home/ubuntu/.unidesk/ci/backend-core-artifacts"; const sourceHostPath = options.sourceHostPath; const repoCache = "/home/ubuntu/.unidesk/ci/git/unidesk.git"; const repoFetchUrl = repoSshUrl(options.repoUrl); - const sshIdentity = repoNeedsGithubSshIdentity(repoFetchUrl) ? await ensureGithubSshIdentityForProvider(config, d601ProviderId) : null; + const sshIdentity = repoNeedsGithubSshIdentity(repoFetchUrl) ? await ensureGithubSshIdentityForProvider(config, defaultCiProviderId) : null; if (sshIdentity !== null && !sshIdentity.ok) throw new Error(sshIdentity.detail); const proxyPython = gitSshHttpConnectProxySource(); const dockerfile = requireRepoRelativePath(options.dockerfile, "CI.json.artifacts.backend-core.source.dockerfile"); @@ -82,7 +82,7 @@ export async function prepareBackendCoreArtifactSource(config: UniDeskConfig, op return { ok: true, mode: repoNeedsGithubSshIdentity(repoFetchUrl) ? "d601-host-git-ssh-export" : "d601-host-git-https-export", - providerId: d601ProviderId, + providerId: defaultCiProviderId, repoUrl: options.repoUrl, repoFetchUrl, commit: options.commit, @@ -102,7 +102,7 @@ export async function prepareUserServiceArtifactSource(config: UniDeskConfig, op const repoCache = `/home/ubuntu/.unidesk/ci/git/${safePathToken(options.serviceId)}.git`; const repoFetchUrl = repoSshUrl(options.repoUrl); const repoProbeUrl = repoConnectivityProbeUrl(repoFetchUrl); - const sshIdentity = repoNeedsGithubSshIdentity(repoFetchUrl) ? await ensureGithubSshIdentityForProvider(config, d601ProviderId) : null; + const sshIdentity = repoNeedsGithubSshIdentity(repoFetchUrl) ? await ensureGithubSshIdentityForProvider(config, defaultCiProviderId) : null; if (sshIdentity !== null && !sshIdentity.ok) throw new Error(sshIdentity.detail); const proxyPython = gitSshHttpConnectProxySource(); const script = [ @@ -156,7 +156,7 @@ export async function prepareUserServiceArtifactSource(config: UniDeskConfig, op return { ok: true, mode: repoNeedsGithubSshIdentity(repoFetchUrl) ? "d601-host-git-ssh-export" : "d601-host-git-https-export", - providerId: d601ProviderId, + providerId: defaultCiProviderId, repoUrl: options.repoUrl, repoFetchUrl, repoProbeUrl, @@ -246,7 +246,7 @@ export async function prepareClaudeqqArtifactSource(config: UniDeskConfig, optio return { ok: true, mode: "d601-host-gitee-https-export-with-unidesk-overlay", - providerId: d601ProviderId, + providerId: defaultCiProviderId, repoUrl: options.repoUrl, repoFetchUrl, commit: options.commit, diff --git a/scripts/src/ci/types.ts b/scripts/src/ci/types.ts index 5659d65a..95f1b8e8 100644 --- a/scripts/src/ci/types.ts +++ b/scripts/src/ci/types.ts @@ -19,19 +19,19 @@ import { parseArtifactRegistryOptions, type ArtifactRegistryReadonlyProbe, } from "../artifact-registry"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { runSshCommandCapture } from "../ssh"; import { cicdTargetSummary, resolveCicdTarget, type TargetConfigSource } from "../ops/targets"; import { status } from "./cleanup"; import { stringOption } from "./options"; -const d601YamlTarget = resolveCicdTarget("D601"); +const defaultCicdTarget = resolveCicdTarget(null); const g14YamlTarget = resolveCicdTarget("G14"); -export const d601ProviderId = d601YamlTarget.providerId; +export const defaultCiProviderId = defaultCicdTarget.providerId; -export const d601Kubeconfig = d601YamlTarget.kubeconfig; +export const defaultCiKubeconfig = defaultCicdTarget.kubeconfig; export const tektonPipelineVersion = "v1.12.0"; @@ -51,7 +51,7 @@ export const codeQueueDirectDockerBaseImage = "unidesk-code-queue:d601"; export const providerDispatchCompletionLagMs = 45_000; -export const defaultCiPipelineManifest = d601YamlTarget.pipelineManifest; +export const defaultCiPipelineManifest = defaultCicdTarget.pipelineManifest; export const g14CiPipelineManifest = g14YamlTarget.pipelineManifest; diff --git a/scripts/src/code-queue-execution-plane.ts b/scripts/src/code-queue-execution-plane.ts index 5d876470..8c230df5 100644 --- a/scripts/src/code-queue-execution-plane.ts +++ b/scripts/src/code-queue-execution-plane.ts @@ -1,6 +1,6 @@ import { runCommand, type CommandResult } from "./command"; import { repoRoot } from "./config"; -import { classifyD601K3sTarget, d601NativeKubeconfig, d601RequiredNodeName, type D601K3sGuardClassification } from "./d601-k3s-guard"; +import { classifyK3sTarget, defaultNativeKubeconfig, requiredNativeNodeName, type K3sGuardClassification } from "./k3s-target-guard"; type PlaneStatus = "ready" | "blocked" | "degraded"; type SignalSeverity = "blocker" | "warning"; @@ -113,7 +113,7 @@ export interface CodeQueueExecutionPlaneObservation { namespace: string; kubeconfig: string; worktreePath: string; - guard: D601K3sGuardClassification; + guard: K3sGuardClassification; deployments: DeploymentObservation[]; pods: PodObservation[]; services: ServiceObservation[]; @@ -185,7 +185,7 @@ function parseExecutionPlaneOptions(args: string[]): ExecutionPlaneOptions { const raw = hasFlag(args, "--raw"); return { namespace: optionValue(args, ["--namespace"]) ?? expectedNamespace, - kubeconfig: optionValue(args, ["--kubeconfig"]) ?? d601NativeKubeconfig, + kubeconfig: optionValue(args, ["--kubeconfig"]) ?? defaultNativeKubeconfig, worktreePath: optionValue(args, ["--worktree"]) ?? expectedWorktreePath, full: raw || hasFlag(args, "--full"), raw, @@ -246,14 +246,14 @@ function runKubectl(args: string[], options: ExecutionPlaneOptions): ProbeResult return runTran(["D601:k3s", "kubectl", ...args], options); } -function collectGuard(options: ExecutionPlaneOptions): { guard: D601K3sGuardClassification; diagnostics: Record } { +function collectGuard(options: ExecutionPlaneOptions): { guard: K3sGuardClassification; diagnostics: Record } { const context = runKubectl(["config", "current-context"], options); const server = runKubectl(["config", "view", "--minify", "-o", "jsonpath={.clusters[0].cluster.server}"], options); const nodes = runKubectl(["get", "nodes", "-o", "jsonpath={range .items[*]}{.metadata.name}{\"\\n\"}{end}"], options); const combinedText = [context.stdout, context.stderr, server.stdout, server.stderr, nodes.stdout, nodes.stderr].join("\n"); - const guard = classifyD601K3sTarget({ + const guard = classifyK3sTarget({ kubeconfig: options.kubeconfig, - expectedKubeconfig: d601NativeKubeconfig, + expectedKubeconfig: defaultNativeKubeconfig, currentContext: firstLine(context.stdout), apiServer: firstLine(server.stdout), nodeNames: lines(nodes.stdout), @@ -433,7 +433,7 @@ function collectWorktree(options: ExecutionPlaneOptions): WorktreeObservation { function collectResidual(): ResidualObservation { const remoteOptions: ExecutionPlaneOptions = { namespace: expectedNamespace, - kubeconfig: d601NativeKubeconfig, + kubeconfig: defaultNativeKubeconfig, worktreePath: expectedWorktreePath, full: false, raw: false, @@ -734,7 +734,7 @@ function evaluateObservation(observation: CodeQueueExecutionPlaneObservation, op code: "d601-k3s-guard-blocked", severity: "blocker", message: observation.guard.summary, - expected: { kubeconfig: d601NativeKubeconfig, node: d601RequiredNodeName }, + expected: { kubeconfig: defaultNativeKubeconfig, node: requiredNativeNodeName }, observed: { status: observation.guard.status, nodes: observation.guard.nodeNames }, }]; const signals = [...guardSignals, ...formalSignals, ...deploymentDriftSignals, ...deprecatedResidualSignals]; diff --git a/scripts/src/deploy/apply-service.ts b/scripts/src/deploy/apply-service.ts index 1432d18d..583d661a 100644 --- a/scripts/src/deploy/apply-service.ts +++ b/scripts/src/deploy/apply-service.ts @@ -13,7 +13,7 @@ import { baiduNetdiskRuntimeSecretRequirements, runtimeSecretContractFromEnvText import { startJob } from "../jobs"; import { coreInternalFetch } from "../microservices"; import { codeQueueSourceImportPreflight, codeQueueSourceSubdir } from "../code-queue-source-guard"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import { compareDeployJsonExecutorMirrors, @@ -34,7 +34,7 @@ import { asRecord, compactTail, elapsedMs, isUnideskRepo, nowIso, parseFullCommi import { dockerBuildTimeoutMs, targetExportDir, targetIsMain, targetWorkDir } from "./paths"; import { healthVerify, manifestEnvironmentForService, pushStep, readRuntimeState, step } from "./remote"; import { buildDirectImageScript, buildImageScript, codeQueueSourcePreflightScript, composeDeployScript, ensureNativeK3sScript, imageLabelVerifyScript, importK3sImageScript, patchDevK3sManifestScript, prepareSourceScript, syncDevFrontendAuthScript, syncK8sControlManifestsScript, syncSourceScript } from "./scripts"; -import { isD601MaintenanceDeployBlocked, isDevArtifactConsumerService, isDevK3sDeployService, isDirectComposeDeployMode, unsupportedReason } from "./service-plan"; +import { isTargetSideMaintenanceDeployBlocked, isDevArtifactConsumerService, isDevK3sDeployService, isDirectComposeDeployMode, unsupportedReason } from "./service-plan"; export async function ensureGithubSshIdentityStep(config: UniDeskConfig, service: UniDeskMicroserviceConfig): Promise { const startedAt = nowIso(); @@ -131,7 +131,7 @@ export async function applyOneService(config: UniDeskConfig, service: UniDeskMic if (options.dryRun) return { ok: true, serviceId: service.id, action: "would-deploy", before, steps }; - if (!options.dryRun && isD601MaintenanceDeployBlocked(service)) { + if (!options.dryRun && isTargetSideMaintenanceDeployBlocked(service)) { return { ok: false, serviceId: service.id, diff --git a/scripts/src/deploy/artifact-jobs.ts b/scripts/src/deploy/artifact-jobs.ts index 58b08e0c..2dec9f8a 100644 --- a/scripts/src/deploy/artifact-jobs.ts +++ b/scripts/src/deploy/artifact-jobs.ts @@ -13,7 +13,7 @@ import { baiduNetdiskRuntimeSecretRequirements, runtimeSecretContractFromEnvText import { startJob } from "../jobs"; import { coreInternalFetch } from "../microservices"; import { codeQueueSourceImportPreflight, codeQueueSourceSubdir } from "../code-queue-source-guard"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import { compareDeployJsonExecutorMirrors, diff --git a/scripts/src/deploy/check-plan.ts b/scripts/src/deploy/check-plan.ts index 4fe0a459..2ad48979 100644 --- a/scripts/src/deploy/check-plan.ts +++ b/scripts/src/deploy/check-plan.ts @@ -13,7 +13,7 @@ import { baiduNetdiskRuntimeSecretRequirements, runtimeSecretContractFromEnvText import { startJob } from "../jobs"; import { coreInternalFetch } from "../microservices"; import { codeQueueSourceImportPreflight, codeQueueSourceSubdir } from "../code-queue-source-guard"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import { compareDeployJsonExecutorMirrors, @@ -32,7 +32,7 @@ import type { DeployEnvironmentManifestSource, DeployManifest, DeployManifestSer import { readProdDeployManifestSnapshot } from "./manifest"; import { environmentPlanServiceConfig, redactedSecretContractForService } from "./paths"; import { readRuntimeState } from "./remote"; -import { artifactConsumerPlanKind, artifactConsumerPlanKindFromDeployJson, artifactConsumerPlanTarget, artifactConsumerPlanTargetFromDeployJson, artifactConsumerPlanValidation, codeQueueCiCdBoundary, codeQueueSelfBootstrapGuard, databaseFingerprint, deployJsonExecutorMirrors, deploymentPathForEnvironmentService, deploymentPathForEnvironmentServiceId, environmentTargetSummary, isD601MaintenanceDeployBlocked, selectServices, unsupportedEnvironmentPlanReason, unsupportedPlanTarget, unsupportedReason } from "./service-plan"; +import { artifactConsumerPlanKind, artifactConsumerPlanKindFromDeployJson, artifactConsumerPlanTarget, artifactConsumerPlanTargetFromDeployJson, artifactConsumerPlanValidation, codeQueueCiCdBoundary, codeQueueSelfBootstrapGuard, databaseFingerprint, deployJsonExecutorMirrors, deploymentPathForEnvironmentService, deploymentPathForEnvironmentServiceId, environmentTargetSummary, isTargetSideMaintenanceDeployBlocked, selectServices, unsupportedEnvironmentPlanReason, unsupportedPlanTarget, unsupportedReason } from "./service-plan"; import { artifactConsumerDryRunBlockedServiceIds, deployEnvironmentTargets, devApplySupportedServiceIds, devArtifactConsumerProdDesiredFallbackServiceIds, devArtifactConsumerServiceIds, devArtifactLiveApplyBlockedServiceIds, prodArtifactConsumerServiceIds, prodArtifactLiveApplyBlockedServiceIds } from "./types"; export async function checkOrPlan(config: UniDeskConfig, manifest: DeployManifest, options: DeployOptions, action: "check" | "plan"): Promise> { @@ -255,14 +255,14 @@ export function unsupportedDevApplyServices(manifest: DeployManifest, serviceId: return services.map((service) => service.id).filter((id) => !devApplySupportedServiceIds.has(id) && !devArtifactConsumerServiceIds.has(id)); } -export function blockedD601MaintenanceDeployServices(config: UniDeskConfig, manifest: DeployManifest, serviceId: string | null): string[] { +export function blockedTargetSideMaintenanceDeployServices(config: UniDeskConfig, manifest: DeployManifest, serviceId: string | null): string[] { return selectServices(config, manifest, serviceId) .map((item) => item.config) - .filter(isD601MaintenanceDeployBlocked) + .filter(isTargetSideMaintenanceDeployBlocked) .map((service) => service.id); } -export function d601MaintenanceDeployBlockMessage(blocked: string[]): string { +export function targetSideMaintenanceDeployBlockMessage(blocked: string[]): string { return `D601 target-side deployment is enabled only for k3sctl-adapter as a control-bridge maintenance path; artifact consumers must use registry CD. Blocked services: ${blocked.join(", ")}. Code Queue is dev-only through artifact-registry/deploy --env dev and has no production direct rollout path.`; } diff --git a/scripts/src/deploy/entry.ts b/scripts/src/deploy/entry.ts index 9d3636f0..632a533a 100644 --- a/scripts/src/deploy/entry.ts +++ b/scripts/src/deploy/entry.ts @@ -14,7 +14,7 @@ import { baiduNetdiskRuntimeSecretRequirements, runtimeSecretContractFromEnvText import { startJob } from "../jobs"; import { coreInternalFetch } from "../microservices"; import { codeQueueSourceImportPreflight, codeQueueSourceSubdir } from "../code-queue-source-guard"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import { compareDeployJsonExecutorMirrors, @@ -32,7 +32,7 @@ import { resolveArtifactRegistryTarget } from "../ops/targets"; import type { DeployAction } from "./types"; import { applyJob, devArtifactApplyJob, prodArtifactApplyJob, runApplyNow, runArtifactConsumerApplyNow, runProdArtifactApplyNow } from "./artifact-jobs"; -import { blockedD601MaintenanceDeployServices, checkOrPlan, commitOverrideArtifactConsumerError, d601MaintenanceDeployBlockMessage, devArtifactLiveApplyBlockedResult, environmentDryRunPlan, prodArtifactConsumerLocalManifestResult, prodArtifactUnsupportedResult, prodArtifactUnsupportedServices, selectedDevArtifactServicesWithProdFallback, selectedDevTargetServices, selectedEnvironmentServices, unsupportedDevApplyServices } from "./check-plan"; +import { blockedTargetSideMaintenanceDeployServices, checkOrPlan, commitOverrideArtifactConsumerError, targetSideMaintenanceDeployBlockMessage, devArtifactLiveApplyBlockedResult, environmentDryRunPlan, prodArtifactConsumerLocalManifestResult, prodArtifactUnsupportedResult, prodArtifactUnsupportedServices, selectedDevArtifactServicesWithProdFallback, selectedDevTargetServices, selectedEnvironmentServices, unsupportedDevApplyServices } from "./check-plan"; import { readDeployManifest, readEnvironmentDeployManifest } from "./manifest"; import { deployHelp, isHelpArg, optionValue, parseOptions, resolveManifestCommits } from "./options"; import { devArtifactLiveApplyBlockedServiceIds, prodForbiddenTargetSideBuildServiceIds } from "./types"; @@ -87,8 +87,8 @@ export async function runDeployCommand(config: UniDeskConfig | null, args: strin } if (config === null) throw new Error("deploy apply --env dev requires config.json"); if (!options.dryRun) { - const blocked = blockedD601MaintenanceDeployServices(config, manifest, options.serviceId).filter((serviceId) => serviceId !== "decision-center"); - if (blocked.length > 0) throw new Error(d601MaintenanceDeployBlockMessage(blocked)); + const blocked = blockedTargetSideMaintenanceDeployServices(config, manifest, options.serviceId).filter((serviceId) => serviceId !== "decision-center"); + if (blocked.length > 0) throw new Error(targetSideMaintenanceDeployBlockMessage(blocked)); } if (options.dryRun || options.runNow) return await runApplyNow(config, manifest, options); return applyJob(config, args, options); @@ -96,8 +96,8 @@ export async function runDeployCommand(config: UniDeskConfig | null, args: strin if (config === null) throw new Error("deploy local manifest mode requires config.json"); const rawManifest = await readDeployManifest(options.file); if (action === "apply") { - const blocked = blockedD601MaintenanceDeployServices(config, rawManifest, options.serviceId); - if (blocked.length > 0) throw new Error(d601MaintenanceDeployBlockMessage(blocked)); + const blocked = blockedTargetSideMaintenanceDeployServices(config, rawManifest, options.serviceId); + if (blocked.length > 0) throw new Error(targetSideMaintenanceDeployBlockMessage(blocked)); } const manifest = resolveManifestCommits(rawManifest, options.serviceId); if (action === "check" || action === "plan") return await checkOrPlan(config, manifest, options, action); diff --git a/scripts/src/deploy/health.ts b/scripts/src/deploy/health.ts index d8a0448b..a1a598f5 100644 --- a/scripts/src/deploy/health.ts +++ b/scripts/src/deploy/health.ts @@ -13,7 +13,7 @@ import { baiduNetdiskRuntimeSecretRequirements, runtimeSecretContractFromEnvText import { startJob } from "../jobs"; import { coreInternalFetch } from "../microservices"; import { codeQueueSourceImportPreflight, codeQueueSourceSubdir } from "../code-queue-source-guard"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import { compareDeployJsonExecutorMirrors, @@ -29,7 +29,7 @@ import { } from "../deploy-json-contract"; import type { DeployManifestService } from "./types"; -import { asRecord, asString, d601K3sGuardScript, parseJsonObjectFromText, shellQuote } from "./options"; +import { asRecord, asString, k3sTargetGuardScript, parseJsonObjectFromText, shellQuote } from "./options"; import { buildImageTag, k8sManifestPath, targetWorkDir } from "./paths"; import { runTargetCommand } from "./remote"; import { isCoreDeployService, isDevK3sDeployService } from "./service-plan"; @@ -84,7 +84,7 @@ export function applyK8sScript(service: UniDeskMicroserviceConfig): string { : ""; return [ "set -euo pipefail", - d601K3sGuardScript(), + k3sTargetGuardScript(), cleanup, `kubectl apply -f ${shellQuote(manifest)}`, ].filter(Boolean).join("\n"); diff --git a/scripts/src/deploy/manifest.ts b/scripts/src/deploy/manifest.ts index 0ffe7e2c..e9e55d1c 100644 --- a/scripts/src/deploy/manifest.ts +++ b/scripts/src/deploy/manifest.ts @@ -13,7 +13,7 @@ import { baiduNetdiskRuntimeSecretRequirements, runtimeSecretContractFromEnvText import { startJob } from "../jobs"; import { coreInternalFetch } from "../microservices"; import { codeQueueSourceImportPreflight, codeQueueSourceSubdir } from "../code-queue-source-guard"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import { compareDeployJsonExecutorMirrors, diff --git a/scripts/src/deploy/options.ts b/scripts/src/deploy/options.ts index 127c7000..a5e3823a 100644 --- a/scripts/src/deploy/options.ts +++ b/scripts/src/deploy/options.ts @@ -14,7 +14,7 @@ import { baiduNetdiskRuntimeSecretRequirements, runtimeSecretContractFromEnvText import { startJob } from "../jobs"; import { coreInternalFetch } from "../microservices"; import { codeQueueSourceImportPreflight, codeQueueSourceSubdir } from "../code-queue-source-guard"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import { compareDeployJsonExecutorMirrors, @@ -88,8 +88,8 @@ export function shellQuote(value: string): string { return `'${value.replace(/'/gu, `'\\''`)}'`; } -export function d601K3sGuardScript(): string { - return d601K3sGuardShellLines(k8sKubeconfig).join("\n"); +export function k3sTargetGuardScript(): string { + return k3sGuardShellLines(k8sKubeconfig).join("\n"); } export function compactTail(text: string, maxChars = 1600): string { diff --git a/scripts/src/deploy/paths.ts b/scripts/src/deploy/paths.ts index a32bbca4..fa036f16 100644 --- a/scripts/src/deploy/paths.ts +++ b/scripts/src/deploy/paths.ts @@ -13,7 +13,7 @@ import { baiduNetdiskRuntimeSecretRequirements, runtimeSecretContractFromEnvText import { startJob } from "../jobs"; import { coreInternalFetch } from "../microservices"; import { codeQueueSourceImportPreflight, codeQueueSourceSubdir } from "../code-queue-source-guard"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import { compareDeployJsonExecutorMirrors, diff --git a/scripts/src/deploy/remote.ts b/scripts/src/deploy/remote.ts index d7c7e8b1..7a69482a 100644 --- a/scripts/src/deploy/remote.ts +++ b/scripts/src/deploy/remote.ts @@ -13,7 +13,7 @@ import { baiduNetdiskRuntimeSecretRequirements, runtimeSecretContractFromEnvText import { startJob } from "../jobs"; import { coreInternalFetch } from "../microservices"; import { codeQueueSourceImportPreflight, codeQueueSourceSubdir } from "../code-queue-source-guard"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import { compareDeployJsonExecutorMirrors, diff --git a/scripts/src/deploy/scripts.ts b/scripts/src/deploy/scripts.ts index 935742f6..ea70f832 100644 --- a/scripts/src/deploy/scripts.ts +++ b/scripts/src/deploy/scripts.ts @@ -13,7 +13,7 @@ import { baiduNetdiskRuntimeSecretRequirements, runtimeSecretContractFromEnvText import { startJob } from "../jobs"; import { coreInternalFetch } from "../microservices"; import { codeQueueSourceImportPreflight, codeQueueSourceSubdir } from "../code-queue-source-guard"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import { compareDeployJsonExecutorMirrors, @@ -29,7 +29,7 @@ import { } from "../deploy-json-contract"; import type { DeployManifestService } from "./types"; -import { d601K3sGuardScript, isUnideskRepo, providerSourceRepoUrl, safeId, shellQuote } from "./options"; +import { k3sTargetGuardScript, isUnideskRepo, providerSourceRepoUrl, safeId, shellQuote } from "./options"; import { buildBaseImageFallbacks, buildCachePrelude, buildImageTag, devK3sPrepullImages, directBuildContextOverride, directComposeEnvFile, directComposeFile, directDockerfileOverride, k8sManifestPath, sourceBuildContext, sourceDockerfilePath, sourceFallbackWorktree, sourceProxyPrelude, sourceWorkDir, targetIsMain, targetRepoDir, targetWorkDir } from "./paths"; import { isDevK3sDeployService, isDirectComposeDeployMode } from "./service-plan"; import { k8sKubeconfig, nativeK3sCtrAddress, nativeK3sImage, nativeK3sInstallVersion, providerGatewayWsEgressProxyUrl } from "./types"; @@ -50,7 +50,7 @@ export function syncDevFrontendAuthScript(config: UniDeskConfig): string { }; return [ "set -euo pipefail", - d601K3sGuardScript(), + k3sTargetGuardScript(), `secret_patch=${shellQuote(JSON.stringify({ data }))}`, `config_patch=${shellQuote(JSON.stringify({ data: runtimeConfig }))}`, `kubectl -n unidesk-dev patch secret unidesk-dev-runtime-secrets --type merge -p "$secret_patch"`, @@ -657,7 +657,7 @@ export function ensureNativeK3sScript(): string { ` if KUBECONFIG=${shellQuote(k8sKubeconfig)} kubectl get nodes >/dev/null 2>&1; then break; fi`, " sleep 2", "done", - d601K3sGuardScript(), + k3sTargetGuardScript(), `KUBECONFIG=${shellQuote(k8sKubeconfig)} kubectl get nodes -l unidesk.ai/node-id=D601 --no-headers | grep -q .`, `KUBECONFIG=${shellQuote(k8sKubeconfig)} kubectl wait --for=condition=Ready node -l unidesk.ai/node-id=D601 --timeout=180s`, "install_system_images_from_legacy_k3s", diff --git a/scripts/src/deploy/service-plan.ts b/scripts/src/deploy/service-plan.ts index e40c891a..64e0a559 100644 --- a/scripts/src/deploy/service-plan.ts +++ b/scripts/src/deploy/service-plan.ts @@ -14,7 +14,7 @@ import { baiduNetdiskRuntimeSecretRequirements, runtimeSecretContractFromEnvText import { startJob } from "../jobs"; import { coreInternalFetch } from "../microservices"; import { codeQueueSourceImportPreflight, codeQueueSourceSubdir } from "../code-queue-source-guard"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import { compareDeployJsonExecutorMirrors, @@ -31,7 +31,7 @@ import { import type { ArtifactConsumerPlanKind, DeployEnvironment, DeployEnvironmentTarget, DeployManifest, DeployManifestService } from "./types"; import { targetIsMain, targetWorkDir } from "./paths"; -import { artifactConsumerDryRunBlockedServiceIds, d601DeployNodeId, d601DeployProviderId, d601MaintenanceDeployAllowedServiceIds, devApplySupportedServiceIds, devArtifactConsumerServiceIds, k8sNamespace, prodArtifactConsumerServiceIds, prodArtifactLiveApplyBlockedServiceIds, unideskRepoUrl } from "./types"; +import { artifactConsumerDryRunBlockedServiceIds, artifactDeployNodeId, artifactDeployProviderId, targetSideMaintenanceDeployAllowedServiceIds, devApplySupportedServiceIds, devArtifactConsumerServiceIds, k8sNamespace, prodArtifactConsumerServiceIds, prodArtifactLiveApplyBlockedServiceIds, unideskRepoUrl } from "./types"; export function frontendCoreDeployService(config: UniDeskConfig): UniDeskMicroserviceConfig { return { @@ -179,7 +179,7 @@ export function devK3sDeployService(id: string): UniDeskMicroserviceConfig | und return { id, name: spec.name, - providerId: d601DeployProviderId, + providerId: artifactDeployProviderId, description: spec.description, repository: { url: spec.repoUrl ?? unideskRepoUrl, @@ -206,11 +206,11 @@ export function devK3sDeployService(id: string): UniDeskMicroserviceConfig | und adapterServiceId: "k3sctl-adapter", k3sServiceId: spec.composeService, namespace: "unidesk-dev", - expectedNodeIds: [d601DeployNodeId], - activeNodeId: d601DeployNodeId, + expectedNodeIds: [artifactDeployNodeId], + activeNodeId: artifactDeployNodeId, }, development: { - providerId: d601DeployProviderId, + providerId: artifactDeployProviderId, sshPassthrough: true, worktreePath: id === "code-queue" ? "/home/ubuntu/unidesk-dev-code-queue-deploy/code-queue" @@ -243,10 +243,10 @@ export function isDevArtifactConsumerService(service: UniDeskMicroserviceConfig) && devArtifactConsumerServiceIds.has(service.id); } -export function isD601MaintenanceDeployBlocked(service: UniDeskMicroserviceConfig): boolean { +export function isTargetSideMaintenanceDeployBlocked(service: UniDeskMicroserviceConfig): boolean { if (targetIsMain(service)) return false; if (service.providerId !== "D601") return false; - return !d601MaintenanceDeployAllowedServiceIds.has(service.id); + return !targetSideMaintenanceDeployAllowedServiceIds.has(service.id); } export function isDirectComposeDeployMode(service: UniDeskMicroserviceConfig): boolean { @@ -279,7 +279,7 @@ export function selectServices(config: UniDeskConfig, manifest: DeployManifest, export function unsupportedReason(service: UniDeskMicroserviceConfig): string | null { if (service.repository.dockerfile.startsWith("docker.io/")) return "image-only service has no Dockerfile source artifact"; if (service.repository.composeFile.startsWith("docker run")) return "docker-run image-only service has no compose/k8s build path"; - if (isD601MaintenanceDeployBlocked(service)) return "D601 maintenance-channel deployment is not allowed for this service; use reviewed registry artifact consumers instead"; + if (isTargetSideMaintenanceDeployBlocked(service)) return "D601 maintenance-channel deployment is not allowed for this service; use reviewed registry artifact consumers instead"; if (service.repository.commitId === "local") return null; return null; } diff --git a/scripts/src/deploy/types.ts b/scripts/src/deploy/types.ts index 864f8cd7..ec72cbf5 100644 --- a/scripts/src/deploy/types.ts +++ b/scripts/src/deploy/types.ts @@ -14,7 +14,7 @@ import { baiduNetdiskRuntimeSecretRequirements, runtimeSecretContractFromEnvText import { startJob } from "../jobs"; import { coreInternalFetch } from "../microservices"; import { codeQueueSourceImportPreflight, codeQueueSourceSubdir } from "../code-queue-source-guard"; -import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard"; +import { k3sGuardShellLines, defaultNativeKubeconfig } from "../k3s-target-guard"; import { composeRuntimeEnvValue } from "../runtime-env"; import { resolveArtifactRegistryTarget } from "../ops/targets"; import { @@ -153,11 +153,11 @@ export const shortRemoteTimeoutMs = 20_000; export const providerDispatchCompletionLagMs = 45_000; -const d601ArtifactRegistryTarget = resolveArtifactRegistryTarget("D601"); +const defaultArtifactRegistryTarget = resolveArtifactRegistryTarget(null); -export const d601DeployProviderId = d601ArtifactRegistryTarget.providerId; +export const artifactDeployProviderId = defaultArtifactRegistryTarget.providerId; -export const d601DeployNodeId = d601ArtifactRegistryTarget.targetId; +export const artifactDeployNodeId = defaultArtifactRegistryTarget.targetId; export const pollIntervalMs = 5_000; @@ -165,7 +165,7 @@ export const remoteDeployRoot = "/home/ubuntu/.unidesk/deploy"; export const k8sNamespace = "unidesk"; -export const k8sKubeconfig = d601NativeKubeconfig; +export const k8sKubeconfig = defaultNativeKubeconfig; export // Production k3s hostPath repo. Code Queue production Pods mount this path as /app and /root/unidesk, // so deploy guards must validate this tree rather than config.json development.worktreePath. @@ -181,7 +181,7 @@ export const nativeK3sCtrAddress = "/run/k3s/containerd/containerd.sock"; export const unideskRepoUrl = "https://github.com/pikasTech/unidesk"; -export const d601MaintenanceDeployAllowedServiceIds = new Set(["k3sctl-adapter"]); +export const targetSideMaintenanceDeployAllowedServiceIds = new Set(["k3sctl-adapter"]); export const devApplySupportedServiceIds = new Set(); @@ -243,8 +243,8 @@ export const deployEnvironmentTargets: Record \"$DOCKER_CONFIG/config.json\"", diff --git a/scripts/src/docker.ts b/scripts/src/docker.ts index 19bcc5c5..6c246974 100644 --- a/scripts/src/docker.ts +++ b/scripts/src/docker.ts @@ -356,7 +356,7 @@ export function composeConfig(config: UniDeskConfig): { runtimeEnv: ComposeRunti export function startStack(config: UniDeskConfig): unknown { const containers = dockerContainers(config); - const deprecatedEntry = deprecatedD601HostComposeEntry(config, composeRuntimeEnvPreview(config), containers); + const deprecatedEntry = deprecatedHostComposeEntry(config, composeRuntimeEnvPreview(config), containers); if (deprecatedEntry !== null) return deprecatedEntry; const runtimeEnv = writeComposeEnv(config, true); const compose = resolveComposeCommand(config, runtimeEnv.envFile); @@ -663,7 +663,7 @@ function dockerExec(config: UniDeskConfig, container: string, command: string[]) export async function stackStatus(config: UniDeskConfig): Promise { const containers = dockerContainers(config); - const deprecatedEntry = deprecatedD601HostComposeEntry(config, composeRuntimeEnvPreview(config), containers); + const deprecatedEntry = deprecatedHostComposeEntry(config, composeRuntimeEnvPreview(config), containers); if (deprecatedEntry !== null) return deprecatedEntry; const runtimeEnv = writeComposeEnv(config, false); const runtimeRaw = existsSync(runtimeEnv.envFile) ? readFileSync(runtimeEnv.envFile, "utf8") : ""; @@ -739,16 +739,16 @@ export async function stackStatus(config: UniDeskConfig): Promise { }; } -export function deprecatedD601HostComposeEntryForTest(config: UniDeskConfig, runtimeEnv: ComposeRuntimeEnv, containers: ContainerStatus[], currentRoot: string): DeprecatedHostComposeEntry | null { - return deprecatedD601HostComposeEntry(config, runtimeEnv, containers, currentRoot); +export function deprecatedHostComposeEntryForTest(config: UniDeskConfig, runtimeEnv: ComposeRuntimeEnv, containers: ContainerStatus[], currentRoot: string): DeprecatedHostComposeEntry | null { + return deprecatedHostComposeEntry(config, runtimeEnv, containers, currentRoot); } -function deprecatedD601HostComposeEntry(config: UniDeskConfig, runtimeEnv: ComposeRuntimeEnv, containers: ContainerStatus[], currentRoot = repoRoot): DeprecatedHostComposeEntry | null { +function deprecatedHostComposeEntry(config: UniDeskConfig, runtimeEnv: ComposeRuntimeEnv, containers: ContainerStatus[], currentRoot = repoRoot): DeprecatedHostComposeEntry | null { const cwd = resolve(currentRoot); - const d601Workspaces = ["/home/ubuntu/unidesk", "/home/ubuntu/workspace/unidesk-dev", "/workspace/unidesk"]; - const cwdLooksD601 = d601Workspaces.some((workspace) => cwd === workspace || cwd.startsWith(`${workspace}/.worktree/`)); + const legacyHostWorkspaces = ["/home/ubuntu/unidesk", "/home/ubuntu/workspace/unidesk-dev", "/workspace/unidesk"]; + const cwdLooksLegacyHost = legacyHostWorkspaces.some((workspace) => cwd === workspace || cwd.startsWith(`${workspace}/.worktree/`)); const upgradeRootLooksMainServer = config.providerGateway.upgrade.hostProjectRoot === "/root/unidesk"; - if (!cwdLooksD601 || !upgradeRootLooksMainServer || containers.length > 0) return null; + if (!cwdLooksLegacyHost || !upgradeRootLooksMainServer || containers.length > 0) return null; const publicPorts = fixedPorts(config); const conflictingListeners = publicPorts .filter((item) => item.listening) diff --git a/scripts/src/e2e.ts b/scripts/src/e2e.ts index 82026040..26cdc9d9 100644 --- a/scripts/src/e2e.ts +++ b/scripts/src/e2e.ts @@ -2281,7 +2281,7 @@ async function serviceChecks(config: UniDeskConfig, urls: PublicUrls, checks: E2 : null; const filebrowserHealth = apiClient.getJson("/api/microservices/filebrowser/health"); const filebrowserWebui = apiClient.getJson("/api/microservices/filebrowser/proxy/"); - const filebrowserD601Health = apiClient.getJson("/api/microservices/filebrowser-d601/health"); + const filebrowserProviderHealth = apiClient.getJson("/api/microservices/filebrowser-d601/health"); const todoE2eName = `E2E Todo ${Date.now()}`; const todoNoteCreate = apiClient.getJson("/api/microservices/todo-note/proxy/api/instances", { method: "POST", body: { name: todoE2eName } }); const todoCreatedId = (todoNoteCreate as { body?: { id?: string } }).body?.id ?? ""; @@ -2332,7 +2332,7 @@ async function serviceChecks(config: UniDeskConfig, urls: PublicUrls, checks: E2 const codeQueue = microserviceList.find((service) => service.id === "code-queue"); const decisionCenter = microserviceList.find((service) => service.id === "decision-center"); const filebrowser = microserviceList.find((service) => service.id === "filebrowser"); - const filebrowserD601 = microserviceList.find((service) => service.id === "filebrowser-d601"); + const filebrowserProvider = microserviceList.find((service) => service.id === "filebrowser-d601"); const findjobSummaryBody = (findjobSummary as { body?: { totalJobs?: number; prioritizedJobs?: number } }).body; const findjobJobs = (findjobJobsPreview as { body?: { jobs?: unknown[]; _unidesk?: { arrayLimits?: { jobs?: { returnedLength?: number; originalLength?: number } } } } }).body; const todoNoteRows = (todoNoteInstances as { body?: { instances?: Array<{ id?: string; name?: string; todoCount?: number; completedCount?: number }> } }).body?.instances ?? []; @@ -2378,7 +2378,7 @@ async function serviceChecks(config: UniDeskConfig, urls: PublicUrls, checks: E2 const k3sctlClaudeqqService = k3sctlControlPlaneBody?.services?.find((service) => service.id === "claudeqq"); const k3sctlDecisionCenterService = k3sctlControlPlaneBody?.services?.find((service) => service.id === "decision-center"); const filebrowserHealthBody = (filebrowserHealth as { body?: { status?: string } }).body; - const filebrowserD601HealthBody = (filebrowserD601Health as { body?: { status?: string } }).body; + const filebrowserProviderHealthBody = (filebrowserProviderHealth as { body?: { status?: string } }).body; const filebrowserWebuiText = String((filebrowserWebui as { body?: { text?: string } }).body?.text || ""); const firstPipelineRun = Array.isArray(pipelineSnapshotBody?.runs) ? pipelineSnapshotBody.runs[0] as { runId?: string; pipelineId?: string; status?: string; updatedAt?: string } | undefined @@ -2493,11 +2493,11 @@ async function serviceChecks(config: UniDeskConfig, urls: PublicUrls, checks: E2 && filebrowser?.providerId === "D518" && filebrowser.backend?.public === false && filebrowser.runtime?.container?.name === "unidesk-filebrowser-d518" - && filebrowserD601?.providerId === "D601", - { filebrowser, filebrowserD601 }); + && filebrowserProvider?.providerId === "D601", + { filebrowser, filebrowserProvider }); addSelectedCheck(checks, options, "microservice:filebrowser-health", (filebrowserHealth as { ok?: boolean }).ok === true && filebrowserHealthBody?.status === "OK", filebrowserHealth); addSelectedCheck(checks, options, "microservice:filebrowser-webui", (filebrowserWebui as { ok?: boolean; status?: number }).ok === true && (filebrowserWebui as { status?: number }).status === 200 && filebrowserWebuiText.includes("File Browser"), { status: (filebrowserWebui as { status?: number }).status, textPreview: filebrowserWebuiText.slice(0, 600) }); - addSelectedCheck(checks, options, "microservice:filebrowser-d601-health", (filebrowserD601Health as { ok?: boolean }).ok === true && filebrowserD601HealthBody?.status === "OK", filebrowserD601Health); + addSelectedCheck(checks, options, "microservice:filebrowser-d601-health", (filebrowserProviderHealth as { ok?: boolean }).ok === true && filebrowserProviderHealthBody?.status === "OK", filebrowserProviderHealth); addSelectedCheck(checks, options, "microservice:findjob-status", (findjobStatus as { ok?: boolean }).ok === true && (findjobStatus as { body?: { microservice?: { id?: string; providerId?: string } } }).body?.microservice?.providerId === "D601", findjobStatus); addSelectedCheck(checks, options, "microservice:findjob-health", (findjobHealth as { ok?: boolean; body?: { ok?: boolean } }).ok === true && (findjobHealth as { body?: { ok?: boolean } }).body?.ok === true, findjobHealth); addSelectedCheck(checks, options, "microservice:findjob-summary", (findjobSummary as { ok?: boolean }).ok === true && Number.isFinite(findjobSummaryBody?.totalJobs) && Number.isFinite(findjobSummaryBody?.prioritizedJobs), findjobSummary); diff --git a/scripts/src/help.ts b/scripts/src/help.ts index 312924b2..160d74eb 100644 --- a/scripts/src/help.ts +++ b/scripts/src/help.ts @@ -760,7 +760,7 @@ function cicdHelpSummary(): unknown { }; } -function hwlabG14HelpSummary(): unknown { +function hwlabLegacyRuntimeHelpSummary(): unknown { return { command: "hwlab g14 retirement", output: "json", @@ -840,7 +840,7 @@ export async function staticNamespaceHelp(args: string[]): Promise (await import("./hwlab-node-hwpod-preinstall")).hwlabNodeHwpodPreinstallHelp(), hwlabNodeHelpSummary()); } if (top === "hwlab" && (sub === "node" || sub === "nodes")) return loadHelp(async () => (await import("./hwlab-node")).hwlabNodeHelp(), hwlabNodeHelpSummary()); - if (top === "hwlab" && sub === "g14") return loadHelp(async () => (await import("./hwlab-g14")).hwlabG14Help(), hwlabG14HelpSummary()); + if (top === "hwlab" && sub === "g14") return loadHelp(async () => (await import("./hwlab-legacy-runtime")).hwlabLegacyRuntimeHelp(), hwlabLegacyRuntimeHelpSummary()); if (top === "hwlab") return loadHelp(async () => (await import("./hwlab-cd")).hwlabHelp(), hwlabHelpSummary()); return null; } diff --git a/scripts/src/hwlab-cd.ts b/scripts/src/hwlab-cd.ts index 6f6aa5e9..7507224c 100644 --- a/scripts/src/hwlab-cd.ts +++ b/scripts/src/hwlab-cd.ts @@ -5,7 +5,7 @@ import { mkdir } from "node:fs/promises"; import { join } from "node:path"; import { gzipSync } from "node:zlib"; import { readConfig, repoRoot, rootPath, type UniDeskConfig } from "./config"; -import { d601NativeKubeconfig } from "./d601-k3s-guard"; +import { defaultNativeKubeconfig } from "./k3s-target-guard"; type HwlabCdAction = "status" | "preflight" | "audit" | "apply"; type HwlabCdEnvironment = "dev"; @@ -117,7 +117,7 @@ function parseOptions(args: string[]): HwlabCdOptions { environment: "dev", dryRun: false, repoPath: null, - kubeconfig: d601NativeKubeconfig, + kubeconfig: defaultNativeKubeconfig, providerId: defaultProviderId, transport: envTransport(), mainServerHost: process.env.UNIDESK_MAIN_SERVER_IP ?? process.env.UNIDESK_MAIN_SERVER_HOST ?? null, @@ -140,7 +140,7 @@ function parseOptions(args: string[]): HwlabCdOptions { index += 1; } else if (arg === "--kubeconfig") { const value = readOption(args, index + 1, arg); - if (value !== d601NativeKubeconfig) throw new Error(`hwlab cd requires the D601 native k3s kubeconfig: ${d601NativeKubeconfig}`); + if (value !== defaultNativeKubeconfig) throw new Error(`hwlab cd requires the D601 native k3s kubeconfig: ${defaultNativeKubeconfig}`); options.kubeconfig = value; index += 1; } else if (arg === "--provider-id") { @@ -783,7 +783,7 @@ export function hwlabHelp(): Record { ], description: "Bounded UniDesk wrapper for the HWLAB DEV CD path. The default transport uploads a small remote runner to D601 through short host.ssh commands, creates a one-run HWLAB clone owned by the host.ssh user, then calls HWLAB repo-owned scripts/dev-cd-apply.mjs from the D601 side.", boundary: [ - `KUBECONFIG is forced to ${d601NativeKubeconfig}`, + `KUBECONFIG is forced to ${defaultNativeKubeconfig}`, "docker-desktop, desktop-control-plane, and 127.0.0.1:11700 are refusal signals for the explicit D601 target", `default HWLAB CD repo is ${defaultHwlabCdRepoPath}, materialized from dedicated full bare cache ${defaultHwlabCdCachePath}; ${rejectedRunnerHistoryRepoPath} is rejected as runner history`, "deploy/deploy.json remains the authoritative desired-state source", diff --git a/scripts/src/hwlab-fake-model-provider.ts b/scripts/src/hwlab-fake-model-provider.ts index 2a157006..3e212d41 100644 --- a/scripts/src/hwlab-fake-model-provider.ts +++ b/scripts/src/hwlab-fake-model-provider.ts @@ -79,11 +79,11 @@ export function fakeModelProviderHelp(): Record { command: "hwlab nodes fake-model-provider", description: "YAML-first fake OpenAI-compatible Responses provider for HWLAB/AgentRun sentinel smoke.", examples: [ - "bun scripts/cli.ts hwlab nodes fake-model-provider plan --node D518 --lane v03 --provider fake-echo", - "bun scripts/cli.ts hwlab nodes fake-model-provider materialize --node D518 --lane v03 --provider fake-echo --confirm", - "bun scripts/cli.ts hwlab nodes fake-model-provider apply --node D518 --lane v03 --provider fake-echo --confirm", - "bun scripts/cli.ts hwlab nodes fake-model-provider status --node D518 --lane v03 --provider fake-echo", - "bun scripts/cli.ts hwlab nodes fake-model-provider smoke --node D518 --lane v03 --provider fake-echo", + "bun scripts/cli.ts hwlab nodes fake-model-provider plan --node NC01 --lane v03 --provider fake-echo", + "bun scripts/cli.ts hwlab nodes fake-model-provider materialize --node NC01 --lane v03 --provider fake-echo --confirm", + "bun scripts/cli.ts hwlab nodes fake-model-provider apply --node NC01 --lane v03 --provider fake-echo --confirm", + "bun scripts/cli.ts hwlab nodes fake-model-provider status --node NC01 --lane v03 --provider fake-echo", + "bun scripts/cli.ts hwlab nodes fake-model-provider smoke --node NC01 --lane v03 --provider fake-echo", ], actions: { plan: "Read YAML configRefs and show local source/materialization and target k3s objects without mutation.", @@ -147,7 +147,7 @@ function parseFakeModelProviderOptions(args: string[]): FakeModelProviderOptions throw new Error(`unsupported fake-model-provider option: ${arg}`); } const node = requiredOption(args, "--node"); - if (!/^[A-Z][A-Z0-9_-]*$/u.test(node)) throw new Error("--node must be a simple node id such as D518"); + if (!/^[A-Z][A-Z0-9_-]*$/u.test(node)) throw new Error("--node must be a simple node id such as NC01"); const laneRaw = requiredOption(args, "--lane"); if (!isHwlabRuntimeLane(laneRaw)) throw new Error(`--lane must be one of v02, v03; got ${laneRaw}`); const provider = optionValue(args, "--provider") ?? "fake-echo"; @@ -172,7 +172,7 @@ function parseFakeModelProviderOptions(args: string[]): FakeModelProviderOptions function readFakeModelProviderState(options: FakeModelProviderOptions): FakeModelProviderState { const spec = hwlabRuntimeLaneSpecForNode(options.lane, options.node); - const configPath = rootPath("config", "hwlab-fake-model-provider", `${options.node.toLowerCase()}-${options.lane}`, `${options.provider}.yaml`); + const configPath = rootPath("config", "hwlab-fake-model-provider", `${options.provider}.yaml`); if (!existsSync(configPath)) throw new Error(`fake provider config is missing: ${repoRelative(configPath)}`); const root = readYamlRecord(configPath, "HwlabFakeModelProvider"); const provider = record(root.provider, "provider"); @@ -249,7 +249,7 @@ function planFakeModelProvider(state: FakeModelProviderState): Record; - merge?: Record; - sourceCommit?: string | null; - pipelineRun?: string | null; - cd?: Record; - flush?: Record; - dryRun?: boolean; - message?: string; -} diff --git a/scripts/src/hwlab-legacy-runtime.ts b/scripts/src/hwlab-legacy-runtime.ts new file mode 100644 index 00000000..79daf178 --- /dev/null +++ b/scripts/src/hwlab-legacy-runtime.ts @@ -0,0 +1,2 @@ +// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. Thin compatibility entry for scripts/src/hwlab-legacy-runtime.ts. +export * from "./hwlab-legacy-runtime/index"; diff --git a/scripts/src/hwlab-g14/cd-trigger.ts b/scripts/src/hwlab-legacy-runtime/cd-trigger.ts similarity index 80% rename from scripts/src/hwlab-g14/cd-trigger.ts rename to scripts/src/hwlab-legacy-runtime/cd-trigger.ts index 7f35d30a..44636a64 100644 --- a/scripts/src/hwlab-g14/cd-trigger.ts +++ b/scripts/src/hwlab-legacy-runtime/cd-trigger.ts @@ -1,6 +1,6 @@ -// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. cd-trigger module for scripts/src/hwlab-g14.ts. +// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. cd-trigger module for scripts/src/hwlab-legacy-runtime.ts. -// Moved mechanically from scripts/src/hwlab-g14.ts:9508-10162 for #903. +// Moved mechanically from scripts/src/hwlab-legacy-runtime.ts:9508-10162 for #903. import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"; import { dirname, join } from "node:path"; @@ -10,15 +10,15 @@ import { runCommand } from "../command"; import { cancelJob, listJobs, readJob, startJob } from "../jobs"; import { hwlabRequiredNoProxyEntries, hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneIds, hwlabRuntimeLaneSpec, isHwlabRuntimeLane, type HwlabRuntimeLane, type HwlabRuntimeLaneSpec } from "../hwlab-node-lanes"; -import type { CommandJsonResult, G14MonitorOptions, OpenPullRequest } from "./types"; -import { runRuntimeLaneControlPlane, runV02ControlPlane, runtimeLaneControlPlaneStatus, v02ControlPlaneStatus } from "./control-plane"; -import { runG14GitMirror, runGitMirrorStatus } from "./git-mirror"; -import { activeV02PipelineRuns, commentRuntimeLanePullRequest, commentV02PullRequest, durationSeconds, reportRuntimeLaneAutomationIssue, runtimeLaneCdFailed, runtimeLaneCdPassed, sourceCommitFromMergeResult, summarizeRuntimeLaneCdStatus, summarizeV02CdStatus, v02CdFailed, v02CdPassed, v02PipelineSucceeded, waitForV02Head } from "./pr-monitor"; -import { commandData, compactCommandResult, isCommandSuccess, nested, printEvent, printRuntimeLanePrMonitorProgress, printV02PrMonitorProgress, record, sleep, stringOrNull } from "./remote"; -import { resolveRuntimeLaneHead, runtimeLanePipelineRunName, v02PipelineRunName } from "./source"; +import type { CommandJsonResult, LegacyRuntimeMonitorOptions, OpenPullRequest } from "./types"; +import { runRuntimeLaneControlPlane, runDefaultRuntimeLaneControlPlane, runtimeLaneControlPlaneStatus, defaultRuntimeLaneControlPlaneStatus } from "./control-plane"; +import { runLegacyRuntimeGitMirror, runGitMirrorStatus } from "./git-mirror"; +import { activeDefaultRuntimeLanePipelineRuns, commentRuntimeLanePullRequest, commentDefaultRuntimeLanePullRequest, durationSeconds, reportRuntimeLaneAutomationIssue, runtimeLaneCdFailed, runtimeLaneCdPassed, sourceCommitFromMergeResult, summarizeRuntimeLaneCdStatus, summarizeDefaultRuntimeLaneCdStatus, defaultRuntimeLaneCdFailed, defaultRuntimeLaneCdPassed, defaultRuntimeLanePipelineSucceeded, waitForDefaultRuntimeLaneHead } from "./pr-monitor"; +import { commandData, compactCommandResult, isCommandSuccess, nested, printEvent, printRuntimeLanePrMonitorProgress, printDefaultRuntimeLanePrMonitorProgress, record, sleep, stringOrNull } from "./remote"; +import { resolveRuntimeLaneHead, runtimeLanePipelineRunName, defaultRuntimeLanePipelineRunName } from "./source"; -export function triggerV02Current(timeoutSeconds: number): Record { - return runV02ControlPlane({ +export function triggerDefaultRuntimeLaneCurrent(timeoutSeconds: number): Record { + return runDefaultRuntimeLaneControlPlane({ action: "trigger-current", lane: "v02", dryRun: false, @@ -31,10 +31,10 @@ export function triggerV02Current(timeoutSeconds: number): Record, timeoutSeconds: number): Record { +export function flushDefaultRuntimeLaneGitMirrorIfNeeded(status: Record, timeoutSeconds: number): Record { const pendingFlush = nested(status, ["gitMirror", "summary", "pendingFlush"]); if (pendingFlush !== true) return { ok: true, skipped: true, reason: "git-mirror-already-flushed" }; - return runG14GitMirror({ + return runLegacyRuntimeGitMirror({ action: "flush", lane: "v02", confirm: true, @@ -81,7 +81,7 @@ export function runtimeLaneCdPassedWithMirror(spec: HwlabRuntimeLaneSpec, status export function flushRuntimeLaneGitMirrorIfNeeded(spec: HwlabRuntimeLaneSpec, status: Record, timeoutSeconds: number): Record { if (runtimeLaneGitopsSynced(spec, status)) return { ok: true, skipped: true, reason: `${spec.lane}-git-mirror-already-flushed` }; - return runG14GitMirror({ + return runLegacyRuntimeGitMirror({ action: "flush", lane: spec.lane, confirm: true, @@ -121,19 +121,19 @@ export async function waitForRuntimeLaneHead(spec: HwlabRuntimeLaneSpec, expecte return { ok: false, sourceCommit: head, expectedCommit, matched: false, waitedSeconds: Math.round((Date.now() - started) / 1000), degradedReason: `${spec.lane}-source-head-not-aligned-after-merge` }; } -export async function waitForV02Cd(sourceCommit: string, timeoutSeconds: number): Promise> { +export async function waitForDefaultRuntimeLaneCd(sourceCommit: string, timeoutSeconds: number): Promise> { const started = Date.now(); const startedAt = new Date(started).toISOString(); - const pipelineRun = v02PipelineRunName(sourceCommit); + const pipelineRun = defaultRuntimeLanePipelineRunName(sourceCommit); let lastStatus: Record = {}; let firstPassedAt: string | null = null; while (Date.now() - started < timeoutSeconds * 1000) { - lastStatus = v02ControlPlaneStatus({ sourceCommit, mode: "source-commit" }); - const summary = summarizeV02CdStatus(lastStatus); + lastStatus = defaultRuntimeLaneControlPlaneStatus({ sourceCommit, mode: "source-commit" }); + const summary = summarizeDefaultRuntimeLaneCdStatus(lastStatus); printEvent("v02.cd.status", { sourceCommit, pipelineRun, summary }); - printV02PrMonitorProgress({ stage: "cd-status", status: "running", sourceCommit, pipelineRun, targetValidationState: summary.targetValidationState ?? null, pipelineStatus: summary.pipelineStatus ?? null, pendingFlush: summary.pendingFlush ?? null }); - if (v02PipelineSucceeded(lastStatus) && summary.pendingFlush === true) { - const flush = flushV02GitMirrorIfNeeded(lastStatus, Math.min(timeoutSeconds, 600)); + printDefaultRuntimeLanePrMonitorProgress({ stage: "cd-status", status: "running", sourceCommit, pipelineRun, targetValidationState: summary.targetValidationState ?? null, pipelineStatus: summary.pipelineStatus ?? null, pendingFlush: summary.pendingFlush ?? null }); + if (defaultRuntimeLanePipelineSucceeded(lastStatus) && summary.pendingFlush === true) { + const flush = flushDefaultRuntimeLaneGitMirrorIfNeeded(lastStatus, Math.min(timeoutSeconds, 600)); if (record(flush).ok !== true) { return { ok: false, @@ -147,10 +147,10 @@ export async function waitForV02Cd(sourceCommit: string, timeoutSeconds: number) flush, }; } - const finalStatus = v02ControlPlaneStatus({ sourceCommit, mode: "source-commit" }); - const finalSummary = summarizeV02CdStatus(finalStatus); - if (v02CdPassed(finalStatus)) { - printV02PrMonitorProgress({ stage: "git-mirror-flush", status: "succeeded", sourceCommit, pipelineRun, pendingFlush: finalSummary.pendingFlush ?? null }); + const finalStatus = defaultRuntimeLaneControlPlaneStatus({ sourceCommit, mode: "source-commit" }); + const finalSummary = summarizeDefaultRuntimeLaneCdStatus(finalStatus); + if (defaultRuntimeLaneCdPassed(finalStatus)) { + printDefaultRuntimeLanePrMonitorProgress({ stage: "git-mirror-flush", status: "succeeded", sourceCommit, pipelineRun, pendingFlush: finalSummary.pendingFlush ?? null }); return { ok: true, phase: "cd-passed", @@ -165,27 +165,27 @@ export async function waitForV02Cd(sourceCommit: string, timeoutSeconds: number) } lastStatus = finalStatus; printEvent("v02.cd.after-flush", { sourceCommit, pipelineRun, flushOk: record(flush).ok, summary: finalSummary }); - printV02PrMonitorProgress({ stage: "git-mirror-flush", status: record(flush).ok === true ? "succeeded" : "failed", sourceCommit, pipelineRun, pendingFlush: finalSummary.pendingFlush ?? null }); + printDefaultRuntimeLanePrMonitorProgress({ stage: "git-mirror-flush", status: record(flush).ok === true ? "succeeded" : "failed", sourceCommit, pipelineRun, pendingFlush: finalSummary.pendingFlush ?? null }); } - if (v02CdPassed(lastStatus)) { + if (defaultRuntimeLaneCdPassed(lastStatus)) { firstPassedAt ??= new Date().toISOString(); - const flush = flushV02GitMirrorIfNeeded(lastStatus, Math.min(timeoutSeconds, 600)); - const finalStatus = v02ControlPlaneStatus({ sourceCommit, mode: "source-commit" }); - printV02PrMonitorProgress({ stage: "cd-status", status: v02CdPassed(finalStatus) ? "succeeded" : "failed", sourceCommit, pipelineRun, targetValidationState: nested(finalStatus, ["targetValidation", "state"]) ?? null }); + const flush = flushDefaultRuntimeLaneGitMirrorIfNeeded(lastStatus, Math.min(timeoutSeconds, 600)); + const finalStatus = defaultRuntimeLaneControlPlaneStatus({ sourceCommit, mode: "source-commit" }); + printDefaultRuntimeLanePrMonitorProgress({ stage: "cd-status", status: defaultRuntimeLaneCdPassed(finalStatus) ? "succeeded" : "failed", sourceCommit, pipelineRun, targetValidationState: nested(finalStatus, ["targetValidation", "state"]) ?? null }); return { - ok: v02CdPassed(finalStatus), - phase: v02CdPassed(finalStatus) ? "cd-passed" : "git-mirror-flush", + ok: defaultRuntimeLaneCdPassed(finalStatus), + phase: defaultRuntimeLaneCdPassed(finalStatus) ? "cd-passed" : "git-mirror-flush", startedAt, finishedAt: new Date().toISOString(), sourceCommit, pipelineRun, - status: summarizeV02CdStatus(finalStatus), + status: summarizeDefaultRuntimeLaneCdStatus(finalStatus), rawStatus: finalStatus, flush, }; } - if (v02CdFailed(lastStatus)) { - printV02PrMonitorProgress({ stage: "cd-status", status: "failed", sourceCommit, pipelineRun, pipelineStatus: summary.pipelineStatus ?? null, pipelineReason: summary.pipelineReason ?? null }); + if (defaultRuntimeLaneCdFailed(lastStatus)) { + printDefaultRuntimeLanePrMonitorProgress({ stage: "cd-status", status: "failed", sourceCommit, pipelineRun, pipelineStatus: summary.pipelineStatus ?? null, pipelineReason: summary.pipelineReason ?? null }); return { ok: false, phase: "cd-failed", @@ -208,7 +208,7 @@ export async function waitForV02Cd(sourceCommit: string, timeoutSeconds: number) pipelineRun, timeoutSeconds, firstPassedAt, - status: summarizeV02CdStatus(lastStatus), + status: summarizeDefaultRuntimeLaneCdStatus(lastStatus), rawStatus: lastStatus, }; } @@ -302,11 +302,11 @@ export async function waitForRuntimeLaneCd(spec: HwlabRuntimeLaneSpec, sourceCom }; } -export async function runV02PrAutoCd(pr: OpenPullRequest, preflight: Record, merge: CommandJsonResult, options: G14MonitorOptions, startedAt: string): Promise> { +export async function runDefaultRuntimeLanePrAutoCd(pr: OpenPullRequest, preflight: Record, merge: CommandJsonResult, options: LegacyRuntimeMonitorOptions, startedAt: string): Promise> { const mergeRaceState = isCommandSuccess(merge) ? null : mergeCommandRaceState(merge); if (!isCommandSuccess(merge) && mergeRaceState !== "merged") { - printV02PrMonitorProgress({ stage: "merge", status: "failed", pr: pr.number, mergeRaceState }); - const comment = commentV02PullRequest({ + printDefaultRuntimeLanePrMonitorProgress({ stage: "merge", status: "failed", pr: pr.number, mergeRaceState }); + const comment = commentDefaultRuntimeLanePullRequest({ pr, phase: "merge", state: "merge-failed", @@ -324,8 +324,8 @@ export async function runV02PrAutoCd(pr: OpenPullRequest, preflight: Record 0) { printEvent("v02.cd.active-runs-observed", { pr: pr.number, sourceCommit, pipelineRun, activeCount: activeRuns.length, activeRuns: activeRuns.slice(0, 5), latestOnlyPolicy: "do-not-wait-or-cancel-old-runs" }); } - const trigger = v02CdPassed(before) ? { ok: true, skipped: true, reason: "source-commit-already-deployed" } : triggerV02Current(Math.min(options.timeoutSeconds, 600)); + const trigger = defaultRuntimeLaneCdPassed(before) ? { ok: true, skipped: true, reason: "source-commit-already-deployed" } : triggerDefaultRuntimeLaneCurrent(Math.min(options.timeoutSeconds, 600)); printEvent("v02.cd.trigger", { pr: pr.number, sourceCommit, pipelineRun, ok: record(trigger).ok, skipped: record(trigger).skipped ?? false, degradedReason: record(trigger).degradedReason ?? null }); - printV02PrMonitorProgress({ stage: "cd-trigger", status: record(trigger).ok === true ? "succeeded" : "failed", pr: pr.number, sourceCommit, pipelineRun, activeCount: activeRuns.length, skipped: record(trigger).skipped ?? false, degradedReason: record(trigger).degradedReason ?? null }); + printDefaultRuntimeLanePrMonitorProgress({ stage: "cd-trigger", status: record(trigger).ok === true ? "succeeded" : "failed", pr: pr.number, sourceCommit, pipelineRun, activeCount: activeRuns.length, skipped: record(trigger).skipped ?? false, degradedReason: record(trigger).degradedReason ?? null }); if (record(trigger).ok !== true) { - const comment = commentV02PullRequest({ + const comment = commentDefaultRuntimeLanePullRequest({ pr, phase: "cd-trigger", state: "cd-failed", @@ -412,13 +412,13 @@ export async function runV02PrAutoCd(pr: OpenPullRequest, preflight: Record, merge: CommandJsonResult, options: G14MonitorOptions, startedAt: string): Promise> { +export async function runRuntimeLanePrAutoCd(spec: HwlabRuntimeLaneSpec, pr: OpenPullRequest, preflight: Record, merge: CommandJsonResult, options: LegacyRuntimeMonitorOptions, startedAt: string): Promise> { const mergeRaceState = isCommandSuccess(merge) ? null : mergeCommandRaceState(merge); if (!isCommandSuccess(merge) && mergeRaceState !== "merged") { printRuntimeLanePrMonitorProgress(spec, { stage: "merge", status: "failed", pr: pr.number, mergeRaceState }); diff --git a/scripts/src/hwlab-g14/cleanup.ts b/scripts/src/hwlab-legacy-runtime/cleanup.ts similarity index 92% rename from scripts/src/hwlab-g14/cleanup.ts rename to scripts/src/hwlab-legacy-runtime/cleanup.ts index eff83f5b..bab9537d 100644 --- a/scripts/src/hwlab-g14/cleanup.ts +++ b/scripts/src/hwlab-legacy-runtime/cleanup.ts @@ -1,6 +1,6 @@ -// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. cleanup module for scripts/src/hwlab-g14.ts. +// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. cleanup module for scripts/src/hwlab-legacy-runtime.ts. -// Moved mechanically from scripts/src/hwlab-g14.ts:2788-3345 for #903. +// Moved mechanically from scripts/src/hwlab-legacy-runtime.ts:2788-3345 for #903. import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"; import { dirname, join } from "node:path"; @@ -10,11 +10,11 @@ import { runCommand } from "../command"; import { cancelJob, listJobs, readJob, startJob } from "../jobs"; import { hwlabRequiredNoProxyEntries, hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneIds, hwlabRuntimeLaneSpec, isHwlabRuntimeLane, type HwlabRuntimeLane, type HwlabRuntimeLaneSpec } from "../hwlab-node-lanes"; -import type { CommandJsonResult, G14ControlPlaneOptions } from "./types"; -import { g14HostScript } from "./images"; +import type { CommandJsonResult, LegacyRuntimeControlPlaneOptions } from "./types"; +import { legacyRuntimeHostScript } from "./images"; import { statusText } from "./pr-monitor"; -import { g14K3s, isCommandSuccess, nested, shellQuote, shortSha, stringOrNull } from "./remote"; -import { runtimeLanePipelineRunName, v02PipelineRunName } from "./source"; +import { legacyRuntimeK3s, isCommandSuccess, nested, shellQuote, shortSha, stringOrNull } from "./remote"; +import { runtimeLanePipelineRunName, defaultRuntimeLanePipelineRunName } from "./source"; import { CI_NAMESPACE } from "./types"; export interface CleanupPipelineRunRow { @@ -25,7 +25,7 @@ export interface CleanupPipelineRunRow { reason: string | null; } -export function pipelinePrefixesForLane(lane: G14ControlPlaneOptions["lane"]): string[] { +export function pipelinePrefixesForLane(lane: LegacyRuntimeControlPlaneOptions["lane"]): string[] { if (isHwlabRuntimeLane(lane)) return [`${hwlabRuntimeLaneSpec(lane).pipelineRunPrefix}-`]; if (lane === "g14") return ["hwlab-g14-ci-poll-"]; return [...hwlabRuntimeLaneIds().map((runtimeLane) => `${hwlabRuntimeLaneSpec(runtimeLane).pipelineRunPrefix}-`), "hwlab-g14-ci-poll-"]; @@ -100,7 +100,7 @@ export function remoteStoragePathEstimates(paths: Array[] { +export function listCleanupPipelineRuns(options: LegacyRuntimeControlPlaneOptions): Record[] { if (options.lane !== "g14" && options.lane !== "all" && !isHwlabRuntimeLane(options.lane)) { throw new Error("control-plane cleanup-runs requires --lane v02|v03|g14|all"); } @@ -199,10 +199,10 @@ export function listCleanupPipelineRuns(options: G14ControlPlaneOptions): Record ? undefined : isHwlabRuntimeLane(options.lane) ? runtimeLanePipelineRunName(hwlabRuntimeLaneSpec(options.lane), options.sourceCommit) - : v02PipelineRunName(options.sourceCommit)); + : defaultRuntimeLanePipelineRunName(options.sourceCommit)); const now = Date.now(); if (targetPipelineRun !== undefined) { - const targetResult = g14K3s([ + const targetResult = legacyRuntimeK3s([ "kubectl", "get", "pipelinerun", @@ -222,7 +222,7 @@ export function listCleanupPipelineRuns(options: G14ControlPlaneOptions): Record nowMs: now, })]; } - const result = g14K3s([ + const result = legacyRuntimeK3s([ "kubectl", "get", "pipelinerun", @@ -267,7 +267,7 @@ export function listOwnedWorkspacePvcs(pipelineRunNames: string[]): Record[] { - const result = g14K3s([ +export function listReleasedCiWorkspacePvs(options: LegacyRuntimeControlPlaneOptions): Record[] { + const result = legacyRuntimeK3s([ "kubectl", "get", "pv", @@ -416,10 +416,10 @@ export function deletePersistentVolumes(names: string[], timeoutMs: number): Com parsed: null, }; } - return g14K3s(["kubectl", "delete", "pv", ...names, "--ignore-not-found=true"], timeoutMs); + return legacyRuntimeK3s(["kubectl", "delete", "pv", ...names, "--ignore-not-found=true"], timeoutMs); } -export function runControlPlaneReleasedPvCleanup(options: G14ControlPlaneOptions): Record { +export function runControlPlaneReleasedPvCleanup(options: LegacyRuntimeControlPlaneOptions): Record { const candidates = listReleasedCiWorkspacePvs(options); const candidateNames = candidates.map((item) => String(item.name)); const estimatedReclaimBytes = sumEstimatedBytes(candidates); @@ -460,7 +460,7 @@ export function runControlPlaneReleasedPvCleanup(options: G14ControlPlaneOptions }; } -export function runV02RuntimeMigration(options: G14ControlPlaneOptions, sourceCommit: string): Record { +export function runDefaultRuntimeLaneRuntimeMigration(options: LegacyRuntimeControlPlaneOptions, sourceCommit: string): Record { const reportPath = `/tmp/hwlab-v02-runtime-migration-${shortSha(sourceCommit)}.json`; const migrationArgs = options.dryRun ? [ @@ -487,7 +487,7 @@ export function runV02RuntimeMigration(options: G14ControlPlaneOptions, sourceCo "cmd/hwlab-cloud-api/migrate.ts", ...migrationArgs, ]; - const result = g14K3s(["kubectl", ...command], options.timeoutSeconds * 1000); + const result = legacyRuntimeK3s(["kubectl", ...command], options.timeoutSeconds * 1000); const ok = isCommandSuccess(result); return { ok, @@ -513,7 +513,7 @@ export function runV02RuntimeMigration(options: G14ControlPlaneOptions, sourceCo }; } -export function runControlPlaneCleanup(options: G14ControlPlaneOptions): Record { +export function runControlPlaneCleanup(options: LegacyRuntimeControlPlaneOptions): Record { const candidates = listCleanupPipelineRuns(options); const candidateNames = candidates .filter((item) => item.selected !== false) diff --git a/scripts/src/hwlab-g14/control-plane.ts b/scripts/src/hwlab-legacy-runtime/control-plane.ts similarity index 85% rename from scripts/src/hwlab-g14/control-plane.ts rename to scripts/src/hwlab-legacy-runtime/control-plane.ts index a1613fc8..c8867f36 100644 --- a/scripts/src/hwlab-g14/control-plane.ts +++ b/scripts/src/hwlab-legacy-runtime/control-plane.ts @@ -1,6 +1,6 @@ -// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. control-plane module for scripts/src/hwlab-g14.ts. +// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. control-plane module for scripts/src/hwlab-legacy-runtime.ts. -// Moved mechanically from scripts/src/hwlab-g14.ts:3737-5054 for #903. +// Moved mechanically from scripts/src/hwlab-legacy-runtime.ts:3737-5054 for #903. import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"; import { dirname, join } from "node:path"; @@ -10,16 +10,16 @@ import { runCommand } from "../command"; import { cancelJob, listJobs, readJob, startJob } from "../jobs"; import { hwlabRequiredNoProxyEntries, hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneIds, hwlabRuntimeLaneSpec, isHwlabRuntimeLane, type HwlabRuntimeLane, type HwlabRuntimeLaneSpec } from "../hwlab-node-lanes"; -import type { CommandJsonResult, G14ControlPlaneOptions, V02ControlPlaneStatusTarget, V02StatusTargetMode } from "./types"; +import type { CommandJsonResult, LegacyRuntimeControlPlaneOptions, DefaultRuntimeLaneControlPlaneStatusTarget, DefaultRuntimeLaneStatusTargetMode } from "./types"; import { runtimeLaneCdPassedWithMirror, runtimeLaneStatusWithGitMirror } from "./cd-trigger"; -import { runControlPlaneCleanup, runControlPlaneReleasedPvCleanup, runV02RuntimeMigration } from "./cleanup"; -import { compactGitMirrorSync, gitMirrorStatusSummary, preSyncV02GitMirror, runGitMirrorStatus, runGitMirrorSync, runtimeLaneGitMirrorSourceInSync } from "./git-mirror"; -import { statusText, summarizeRuntimeLaneCdStatus, v02ControlPlaneCloseout } from "./pr-monitor"; -import { compactCommandResult, compactControlPlaneRefresh, compactTriggerCommandResult, g14K3s, isCommandSuccess, nested, printProgressEvent, printRuntimeLaneTriggerProgress, record, shellQuote, stringOrNull } from "./remote"; -import { applyRuntimeLaneControlPlaneFiles, applyV02ControlPlaneFiles, cleanupRuntimeLaneRenderDir, cleanupV02RenderDir, deleteV02ObsoleteCronJobs, refreshV02ControlPlaneBeforeTrigger, runRuntimeLaneRenderToTemp, runV02RenderToTemp } from "./render"; -import { resolveRuntimeLaneHead, resolveRuntimeLaneLatestRemoteHead, resolveV02Head, resolveV02LatestRemoteHead, runtimeLanePipelineRunName, runtimeLaneRerunPipelineRunName, v02PipelineRunName } from "./source"; -import { ARGO_NAMESPACE, CI_NAMESPACE, V02_APP, V02_CICD_REPO, V02_LANE_SPEC, V02_PIPELINE, V02_SOURCE_BRANCH, V02_WORKSPACE } from "./types"; -import { getPipelineRunCompact, getV02TriggerSnapshot, keyValueLinesFromText, listV02PipelineRunsCompactFromText, numericField, parsePipelineRunRows, parseShellSections, pipelineRunCompactFromText, pipelineRunRowsJsonPath, runtimeLaneTaskRunDiagnosticsFromText, runtimeLaneTaskRunDiagnosticsScript, shellSectionOk, taskRunsCompactFromText, timestampMs, v02CloseoutVerdict, v02CommitAlignment, v02ControlPlaneStatusBundle, v02ExistingPipelineRunReuseDecision, v02FalseGreenGuard, v02LatestOnlyTargetValidation, v02PlanArtifactsFromText, v02RuntimeWorkloadsFromText, v02SourceHeadsFromText, v02TargetValidation, v02WebAssetsFromText } from "./v02-status"; +import { runControlPlaneCleanup, runControlPlaneReleasedPvCleanup, runDefaultRuntimeLaneRuntimeMigration } from "./cleanup"; +import { compactGitMirrorSync, gitMirrorStatusSummary, preSyncDefaultRuntimeLaneGitMirror, runGitMirrorStatus, runGitMirrorSync, runtimeLaneGitMirrorSourceInSync } from "./git-mirror"; +import { statusText, summarizeRuntimeLaneCdStatus, defaultRuntimeLaneControlPlaneCloseout } from "./pr-monitor"; +import { compactCommandResult, compactControlPlaneRefresh, compactTriggerCommandResult, legacyRuntimeK3s, isCommandSuccess, nested, printProgressEvent, printRuntimeLaneTriggerProgress, record, shellQuote, stringOrNull } from "./remote"; +import { applyRuntimeLaneControlPlaneFiles, applyDefaultRuntimeLaneControlPlaneFiles, cleanupRuntimeLaneRenderDir, cleanupDefaultRuntimeLaneRenderDir, deleteDefaultRuntimeLaneObsoleteCronJobs, refreshDefaultRuntimeLaneControlPlaneBeforeTrigger, runRuntimeLaneRenderToTemp, runDefaultRuntimeLaneRenderToTemp } from "./render"; +import { resolveRuntimeLaneHead, resolveRuntimeLaneLatestRemoteHead, resolveDefaultRuntimeLaneHead, resolveDefaultRuntimeLaneLatestRemoteHead, runtimeLanePipelineRunName, runtimeLaneRerunPipelineRunName, defaultRuntimeLanePipelineRunName } from "./source"; +import { ARGO_NAMESPACE, CI_NAMESPACE, DEFAULT_RUNTIME_LANE_APP, DEFAULT_RUNTIME_LANE_CICD_REPO, DEFAULT_RUNTIME_LANE_LANE_SPEC, DEFAULT_RUNTIME_LANE_PIPELINE, DEFAULT_RUNTIME_LANE_SOURCE_BRANCH, DEFAULT_RUNTIME_LANE_WORKSPACE } from "./types"; +import { getPipelineRunCompact, getDefaultRuntimeLaneTriggerSnapshot, keyValueLinesFromText, listDefaultRuntimeLanePipelineRunsCompactFromText, numericField, parsePipelineRunRows, parseShellSections, pipelineRunCompactFromText, pipelineRunRowsJsonPath, runtimeLaneTaskRunDiagnosticsFromText, runtimeLaneTaskRunDiagnosticsScript, shellSectionOk, taskRunsCompactFromText, timestampMs, defaultRuntimeLaneCloseoutVerdict, defaultRuntimeLaneCommitAlignment, defaultRuntimeLaneControlPlaneStatusBundle, defaultRuntimeLaneExistingPipelineRunReuseDecision, defaultRuntimeLaneFalseGreenGuard, defaultRuntimeLaneLatestOnlyTargetValidation, defaultRuntimeLanePlanArtifactsFromText, defaultRuntimeLaneRuntimeWorkloadsFromText, defaultRuntimeLaneSourceHeadsFromText, defaultRuntimeLaneTargetValidation, defaultRuntimeLaneWebAssetsFromText } from "./runtime-status"; export function runtimeLanePipelineRunManifest(spec: HwlabRuntimeLaneSpec, sourceCommit: string, pipelineRun = runtimeLanePipelineRunName(spec, sourceCommit)): Record { return { @@ -76,8 +76,8 @@ export function runtimeLanePipelineRunManifest(spec: HwlabRuntimeLaneSpec, sourc }; } -export function v02PipelineRunManifest(sourceCommit: string): Record { - return runtimeLanePipelineRunManifest(V02_LANE_SPEC, sourceCommit); +export function defaultRuntimeLanePipelineRunManifest(sourceCommit: string): Record { + return runtimeLanePipelineRunManifest(DEFAULT_RUNTIME_LANE_LANE_SPEC, sourceCommit); } export function createRuntimeLanePipelineRun(spec: HwlabRuntimeLaneSpec, sourceCommit: string, timeoutSeconds: number, pipelineRun = runtimeLanePipelineRunName(spec, sourceCommit)): CommandJsonResult { @@ -100,22 +100,22 @@ export function createRuntimeLanePipelineRun(spec: HwlabRuntimeLaneSpec, sourceC "fi", `kubectl get pipelinerun -n ${shellQuote(CI_NAMESPACE)} ${shellQuote(pipelineRun)} -o jsonpath='{.metadata.name}{\"\\n\"}{.metadata.labels.hwlab\\.pikastech\\.local/source-commit}{\"\\n\"}{.status.conditions[0].status}{\"\\n\"}{.status.conditions[0].reason}{\"\\n\"}'`, ].join("\n"); - return g14K3s(["sh", "--", script], timeoutSeconds * 1000); + return legacyRuntimeK3s(["sh", "--", script], timeoutSeconds * 1000); } -export function createV02PipelineRun(sourceCommit: string, timeoutSeconds: number): CommandJsonResult { - return createRuntimeLanePipelineRun(V02_LANE_SPEC, sourceCommit, timeoutSeconds); +export function createDefaultRuntimeLanePipelineRun(sourceCommit: string, timeoutSeconds: number): CommandJsonResult { + return createRuntimeLanePipelineRun(DEFAULT_RUNTIME_LANE_LANE_SPEC, sourceCommit, timeoutSeconds); } -export function v02ControlPlaneStatus(target: V02ControlPlaneStatusTarget = {}): Record { - const targetMode: V02StatusTargetMode = target.mode +export function defaultRuntimeLaneControlPlaneStatus(target: DefaultRuntimeLaneControlPlaneStatusTarget = {}): Record { + const targetMode: DefaultRuntimeLaneStatusTargetMode = target.mode ?? (target.pipelineRun !== undefined && target.pipelineRun !== null ? "pipeline-run" : target.sourceCommit !== undefined ? "source-commit" : "latest-source-head"); const includeHistory = target.includeHistory === true; const strictHeadAlignment = targetMode === "latest-source-head"; - const bundle = v02ControlPlaneStatusBundle({ ...target, mode: targetMode }); + const bundle = defaultRuntimeLaneControlPlaneStatusBundle({ ...target, mode: targetMode }); const sections = parseShellSections(statusText(bundle)); const sourceCommit = stringOrNull(sections.sourceCommit?.stdout) ?? null; - const pipelineRun = stringOrNull(sections.pipelineRunName?.stdout) ?? (sourceCommit === null ? null : v02PipelineRunName(sourceCommit)); + const pipelineRun = stringOrNull(sections.pipelineRunName?.stdout) ?? (sourceCommit === null ? null : defaultRuntimeLanePipelineRunName(sourceCommit)); const statusTargetFields = keyValueLinesFromText(sections.statusTarget?.stdout ?? ""); const queryNowMs = timestampMs(sections.queryNow?.stdout) ?? Date.now(); const sourceHeadsSection = sections.sourceHeads; @@ -128,7 +128,7 @@ export function v02ControlPlaneStatus(target: V02ControlPlaneStatusTarget = {}): const runtimeWorkloadsSection = sections.runtimeWorkloads; const gitMirrorCacheSection = sections.gitMirrorCache; const webAssetsSection = sections.webAssets; - const recentPipelineRuns = listV02PipelineRunsCompactFromText( + const recentPipelineRuns = listDefaultRuntimeLanePipelineRunsCompactFromText( sections.recentPipelineRuns?.stdout ?? "", shellSectionOk(sections.recentPipelineRuns), "kubectl get pipelinerun -n hwlab-ci -l hwlab.pikastech.local/gitops-target=v02 -o jsonpath=", @@ -139,7 +139,7 @@ export function v02ControlPlaneStatus(target: V02ControlPlaneStatusTarget = {}): ); const activePipelineRuns = Array.isArray(recentPipelineRuns.activeItems) ? recentPipelineRuns.activeItems : []; const [targetRevision = "", path = "", syncRevision = "", syncStatus = "", health = ""] = String(argo?.stdout ?? "").split(/\r?\n/u); - const sourceHeads = v02SourceHeadsFromText( + const sourceHeads = defaultRuntimeLaneSourceHeadsFromText( sourceHeadsSection?.stdout ?? "", shellSectionOk(sourceHeadsSection), sourceHeadsSection?.exitCode ?? null, @@ -162,20 +162,20 @@ export function v02ControlPlaneStatus(target: V02ControlPlaneStatusTarget = {}): taskRunsSection?.exitCode ?? null, bundle.stderr, ); - const planArtifacts = v02PlanArtifactsFromText( + const planArtifacts = defaultRuntimeLanePlanArtifactsFromText( planArtifactsSection?.stdout ?? "", shellSectionOk(planArtifactsSection), pipelineRun, planArtifactsSection?.exitCode ?? null, bundle.stderr, ); - const runtimeWorkloads = v02RuntimeWorkloadsFromText( + const runtimeWorkloads = defaultRuntimeLaneRuntimeWorkloadsFromText( runtimeWorkloadsSection?.stdout ?? "", shellSectionOk(runtimeWorkloadsSection), runtimeWorkloadsSection?.exitCode ?? null, bundle.stderr, ); - const webAssets = v02WebAssetsFromText( + const webAssets = defaultRuntimeLaneWebAssetsFromText( webAssetsSection?.stdout ?? "", shellSectionOk(webAssetsSection), sourceCommit, @@ -191,7 +191,7 @@ export function v02ControlPlaneStatus(target: V02ControlPlaneStatusTarget = {}): exitCode: gitMirrorCacheSection?.exitCode ?? null, stderr: shellSectionOk(gitMirrorCacheSection) ? "" : bundle.stderr.trim().slice(0, 2000), }; - const commitAlignment = v02CommitAlignment({ + const commitAlignment = defaultRuntimeLaneCommitAlignment({ expectedSourceHead: sourceCommit, sourceHeads, gitMirrorSummary: record(gitMirror.summary), @@ -201,7 +201,7 @@ export function v02ControlPlaneStatus(target: V02ControlPlaneStatusTarget = {}): runtimeWorkloads, webAssets, }); - const targetValidationBase = v02TargetValidation({ + const targetValidationBase = defaultRuntimeLaneTargetValidation({ targetMode, sourceCommit, pipelineRun: pipelineRunInfo, @@ -215,7 +215,7 @@ export function v02ControlPlaneStatus(target: V02ControlPlaneStatusTarget = {}): gitMirror, recentPipelineRuns, }); - const targetValidation = v02LatestOnlyTargetValidation({ + const targetValidation = defaultRuntimeLaneLatestOnlyTargetValidation({ targetMode, sourceCommit, pipelineRun: pipelineRunInfo, @@ -233,7 +233,7 @@ export function v02ControlPlaneStatus(target: V02ControlPlaneStatusTarget = {}): newerSucceededRuns: targetValidation.newerSucceededRuns ?? [], supersededRuntimeServices: targetValidation.supersededRuntimeServices ?? [], } - : v02FalseGreenGuard({ sourceCommit, pipelineRun: pipelineRunInfo, taskRuns, planArtifacts, runtimeWorkloads }); + : defaultRuntimeLaneFalseGreenGuard({ sourceCommit, pipelineRun: pipelineRunInfo, taskRuns, planArtifacts, runtimeWorkloads }); const baseOk = sourceCommit !== null && isCommandSuccess(bundle) && shellSectionOk(controlPlane) && shellSectionOk(argo); const targetPipelineRunOk = strictHeadAlignment ? true @@ -269,15 +269,15 @@ export function v02ControlPlaneStatus(target: V02ControlPlaneStatusTarget = {}): sourceCommit, sourceCommitSource, expected: { - sourceRepo: V02_CICD_REPO, - workspace: V02_WORKSPACE, + sourceRepo: DEFAULT_RUNTIME_LANE_CICD_REPO, + workspace: DEFAULT_RUNTIME_LANE_WORKSPACE, workspaceIsolation: "workspace dirty/stale state must not select CI/CD source commits", - branch: V02_SOURCE_BRANCH, + branch: DEFAULT_RUNTIME_LANE_SOURCE_BRANCH, namespace: CI_NAMESPACE, runtimeNamespace: "hwlab-v02", - pipeline: V02_PIPELINE, + pipeline: DEFAULT_RUNTIME_LANE_PIPELINE, trigger: "manual UniDesk CLI PipelineRun creation", - argoApplication: V02_APP, + argoApplication: DEFAULT_RUNTIME_LANE_APP, }, commitAlignment, targetValidation, @@ -329,12 +329,12 @@ export function v02ControlPlaneStatus(target: V02ControlPlaneStatusTarget = {}): }; return { ...status, - closeout: v02CloseoutVerdict(status), + closeout: defaultRuntimeLaneCloseoutVerdict(status), }; } -export function runtimeLaneControlPlaneStatusBundle(spec: HwlabRuntimeLaneSpec, target: V02ControlPlaneStatusTarget = {}): CommandJsonResult { - const targetMode: V02StatusTargetMode = target.mode +export function runtimeLaneControlPlaneStatusBundle(spec: HwlabRuntimeLaneSpec, target: DefaultRuntimeLaneControlPlaneStatusTarget = {}): CommandJsonResult { + const targetMode: DefaultRuntimeLaneStatusTargetMode = target.mode ?? (target.pipelineRun !== undefined && target.pipelineRun !== null ? "pipeline-run" : target.sourceCommit !== undefined ? "source-commit" : "latest-source-head"); const targetInit = target.pipelineRun !== undefined && target.pipelineRun !== null ? [ @@ -386,7 +386,7 @@ export function runtimeLaneControlPlaneStatusBundle(spec: HwlabRuntimeLaneSpec, shellQuote(pipelineRunRowsJsonPath()), ].join(" "), ].join("\n"); - return g14K3s(["sh", "--", script], 120_000); + return legacyRuntimeK3s(["sh", "--", script], 120_000); } export function runtimeLanePublicProbeScript(spec: HwlabRuntimeLaneSpec): string { @@ -423,8 +423,8 @@ export function runtimeLanePublicProbeScript(spec: HwlabRuntimeLaneSpec): string ].join("\n"); } -export function runtimeLaneControlPlaneStatus(spec: HwlabRuntimeLaneSpec, target: V02ControlPlaneStatusTarget = {}): Record { - const targetMode: V02StatusTargetMode = target.mode +export function runtimeLaneControlPlaneStatus(spec: HwlabRuntimeLaneSpec, target: DefaultRuntimeLaneControlPlaneStatusTarget = {}): Record { + const targetMode: DefaultRuntimeLaneStatusTargetMode = target.mode ?? (target.pipelineRun !== undefined && target.pipelineRun !== null ? "pipeline-run" : target.sourceCommit !== undefined ? "source-commit" : "latest-source-head"); const bundle = runtimeLaneControlPlaneStatusBundle(spec, target); const sections = parseShellSections(statusText(bundle)); @@ -638,8 +638,8 @@ export function runtimeLaneArgoRefreshScript(spec: HwlabRuntimeLaneSpec, dryRun: ].join("\n"); } -export function refreshRuntimeLaneArgoApplication(spec: HwlabRuntimeLaneSpec, options: G14ControlPlaneOptions): Record { - const result = g14K3s(["sh", "--", runtimeLaneArgoRefreshScript(spec, options.dryRun)], options.timeoutSeconds * 1000); +export function refreshRuntimeLaneArgoApplication(spec: HwlabRuntimeLaneSpec, options: LegacyRuntimeControlPlaneOptions): Record { + const result = legacyRuntimeK3s(["sh", "--", runtimeLaneArgoRefreshScript(spec, options.dryRun)], options.timeoutSeconds * 1000); const fields = keyValueLinesFromText(statusText(result)); const ok = isCommandSuccess(result); return { @@ -692,7 +692,7 @@ export function refreshRuntimeLaneArgoApplication(spec: HwlabRuntimeLaneSpec, op }; } -export function runRuntimeLaneControlPlane(spec: HwlabRuntimeLaneSpec, options: G14ControlPlaneOptions): Record { +export function runRuntimeLaneControlPlane(spec: HwlabRuntimeLaneSpec, options: LegacyRuntimeControlPlaneOptions): Record { if (options.action === "cleanup-runs") return runControlPlaneCleanup(options); if (options.action === "closeout" || options.action === "runtime-migration" || options.action === "cleanup-released-pvs") { return { @@ -1054,33 +1054,33 @@ export function runRuntimeLaneControlPlane(spec: HwlabRuntimeLaneSpec, options: }; } -export function runV02ControlPlane(options: G14ControlPlaneOptions): Record { +export function runDefaultRuntimeLaneControlPlane(options: LegacyRuntimeControlPlaneOptions): Record { if (options.action === "cleanup-runs") return runControlPlaneCleanup(options); if (options.action === "cleanup-released-pvs") return runControlPlaneReleasedPvCleanup(options); if ((options.action === "status" || options.action === "closeout") && options.pipelineRun !== undefined) { - const status = v02ControlPlaneStatus({ pipelineRun: options.pipelineRun, mode: "pipeline-run", includeHistory: options.history }); - if (options.action === "closeout") return v02ControlPlaneCloseout(status); + const status = defaultRuntimeLaneControlPlaneStatus({ pipelineRun: options.pipelineRun, mode: "pipeline-run", includeHistory: options.history }); + if (options.action === "closeout") return defaultRuntimeLaneControlPlaneCloseout(status); return status; } if ((options.action === "status" || options.action === "closeout") && options.sourceCommit !== undefined) { - const status = v02ControlPlaneStatus({ sourceCommit: options.sourceCommit, mode: "source-commit", includeHistory: options.history }); - if (options.action === "closeout") return v02ControlPlaneCloseout(status); + const status = defaultRuntimeLaneControlPlaneStatus({ sourceCommit: options.sourceCommit, mode: "source-commit", includeHistory: options.history }); + if (options.action === "closeout") return defaultRuntimeLaneControlPlaneCloseout(status); return status; } if (options.action === "closeout") { - const status = v02ControlPlaneStatus({ includeHistory: options.history }); - return v02ControlPlaneCloseout(status); + const status = defaultRuntimeLaneControlPlaneStatus({ includeHistory: options.history }); + return defaultRuntimeLaneControlPlaneCloseout(status); } - const snapshot = options.action === "trigger-current" ? getV02TriggerSnapshot() : null; - const latestHead = options.action === "trigger-current" ? resolveV02LatestRemoteHead() : null; + const snapshot = options.action === "trigger-current" ? getDefaultRuntimeLaneTriggerSnapshot() : null; + const latestHead = options.action === "trigger-current" ? resolveDefaultRuntimeLaneLatestRemoteHead() : null; const head = snapshot === null - ? resolveV02Head() + ? resolveDefaultRuntimeLaneHead() : snapshot.sourceCommit === null - ? resolveV02Head() + ? resolveDefaultRuntimeLaneHead() : { sourceCommit: snapshot.sourceCommit, result: snapshot.result }; let sourceCommit = head.sourceCommit; if (options.action === "trigger-current" && latestHead !== null && latestHead.sourceCommit !== null && latestHead.sourceCommit !== sourceCommit) { - const refreshedHead = resolveV02Head(); + const refreshedHead = resolveDefaultRuntimeLaneHead(); sourceCommit = refreshedHead.sourceCommit; if (sourceCommit !== latestHead.sourceCommit) { return { @@ -1100,13 +1100,13 @@ export function runV02ControlPlane(options: G14ControlPlaneOptions): Record> { - if (args.length === 0 || args.includes("--help") || args.includes("-h")) return { ok: true, ...hwlabG14Help() }; +export async function runHwlabLegacyRuntimeCommand(_config: Config, args: string[]): Promise> { + if (args.length === 0 || args.includes("--help") || args.includes("-h")) return { ok: true, ...hwlabLegacyRuntimeHelp() }; const [action] = args; if (action === "record-rollout") { - return legacyG14RecordRolloutRetired(); + return legacyLegacyRuntimeRecordRolloutRetired(); } if (action === "control-plane") { const options = parseControlPlaneOptions(args.slice(1)); @@ -36,34 +36,34 @@ export async function runHwlabG14Command(_config: Config, args: string[]): Promi if (isHwlabRuntimeLane(options.lane) && options.lane !== "v02") { return runRuntimeLaneControlPlane(hwlabRuntimeLaneSpec(options.lane), options); } - return runV02ControlPlane(options); + return runDefaultRuntimeLaneControlPlane(options); } if (action === "retirement") { const options = parseLegacyRetirementOptions(args.slice(1)); - return runLegacyG14Retirement(options); + return runLegacyLegacyRuntimeRetirement(options); } if (action === "secret") { const options = parseSecretOptions(args.slice(1)); - return runG14Secret(options); + return runLegacyRuntimeSecret(options); } if (action === "tools-image") { const options = parseToolsImageOptions(args.slice(1)); - return runG14ToolsImage(options); + return runLegacyRuntimeToolsImage(options); } if (action === "upstream-image") { const options = parseUpstreamImageOptions(args.slice(1)); - return runG14UpstreamImage(options); + return runLegacyRuntimeUpstreamImage(options); } if (action === "git-mirror") { const options = parseGitMirrorOptions(args.slice(1)); if ((options.action === "sync" || options.action === "flush") && options.confirm && !options.dryRun && !options.wait) { return startGitMirrorJob(options); } - return runG14GitMirror(options); + return runLegacyRuntimeGitMirror(options); } if (action === "observability") { const options = parseObservabilityOptions(args.slice(1)); - return runG14Observability(options); + return runLegacyRuntimeObservability(options); } if (action !== "monitor-prs") { return { ok: false, command: `hwlab g14 ${action ?? ""}`.trim(), degradedReason: "unsupported-command", message: "supported commands: hwlab g14 monitor-prs, hwlab g14 retirement, hwlab g14 control-plane, hwlab g14 secret, hwlab g14 git-mirror, hwlab g14 observability, hwlab g14 tools-image, hwlab g14 upstream-image" }; @@ -71,7 +71,7 @@ export async function runHwlabG14Command(_config: Config, args: string[]): Promi const options = parseOptions(args.slice(1)); if (options.worker) return runMonitorWorker(options); if (args.includes("--status")) return monitorStatus(options); - const retirement = options.lane === "g14" ? legacyG14RetirementBlocksMonitor() : null; + const retirement = options.lane === "g14" ? legacyLegacyRuntimeRetirementBlocksMonitor() : null; if (retirement !== null) { return { ok: false, @@ -83,7 +83,7 @@ export async function runHwlabG14Command(_config: Config, args: string[]): Promi retirement, next: { retirementStatus: "bun scripts/cli.ts hwlab g14 retirement status", - v02Monitor: "bun scripts/cli.ts hwlab g14 monitor-prs --lane v02", + defaultRuntimeLaneMonitor: "bun scripts/cli.ts hwlab g14 monitor-prs --lane v02", v03Monitor: "bun scripts/cli.ts hwlab g14 monitor-prs --lane v03", }, }; @@ -91,14 +91,14 @@ export async function runHwlabG14Command(_config: Config, args: string[]): Promi const command = ["bun", "scripts/cli.ts", "hwlab", "g14", "monitor-prs", "--worker", "--lane", options.lane, "--interval-seconds", String(options.intervalSeconds), "--timeout-seconds", String(options.timeoutSeconds), ...(options.once ? ["--once"] : []), ...(options.dryRun ? ["--dry-run"] : []), ...(options.maxCycles > 0 ? ["--max-cycles", String(options.maxCycles)] : [])]; const jobName = options.lane === "g14" ? "hwlab_g14_pr_monitor" : `hwlab_g14_${options.lane}_pr_monitor`; const jobNote = options.lane === "g14" - ? `Monitor ${HWLAB_REPO} PRs targeting ${G14_SOURCE_BRANCH} and roll merged changes to G14 DEV` + ? `Monitor ${HWLAB_REPO} PRs targeting ${LEGACY_RUNTIME_SOURCE_BRANCH} and roll merged changes to G14 DEV` : `Monitor ${HWLAB_REPO} PRs targeting ${monitorBaseBranch(options.lane)}, merge ready PRs, trigger ${hwlabRuntimeLaneSpec(options.lane).version} CD, comment PR progress, and file failure issues`; const job = startJob(jobName, command, jobNote); const statusCommand = `bun scripts/cli.ts job status ${job.id} --tail-bytes 30000`; const stateDir = rootPath(".state", "hwlab-g14"); mkdirSync(stateDir, { recursive: true }); - const stateFileName = hwlabG14MonitorStateFileName(options); - const stateFileRole = hwlabG14MonitorStateRole(options); + const stateFileName = hwlabLegacyRuntimeMonitorStateFileName(options); + const stateFileRole = hwlabLegacyRuntimeMonitorStateRole(options); const latestPath = join(stateDir, stateFileName); const previousLatest = existsSync(latestPath) ? readFileSync(latestPath, "utf8") : null; writeFileSync(latestPath, `${JSON.stringify({ jobId: job.id, createdAt: job.createdAt, statusCommand, role: stateFileRole, lane: options.lane, baseBranch: monitorBaseBranch(options.lane) }, null, 2)}\n`, "utf8"); diff --git a/scripts/src/hwlab-g14/git-mirror.ts b/scripts/src/hwlab-legacy-runtime/git-mirror.ts similarity index 80% rename from scripts/src/hwlab-g14/git-mirror.ts rename to scripts/src/hwlab-legacy-runtime/git-mirror.ts index ac472cc5..a355a18f 100644 --- a/scripts/src/hwlab-g14/git-mirror.ts +++ b/scripts/src/hwlab-legacy-runtime/git-mirror.ts @@ -1,6 +1,6 @@ -// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. git-mirror module for scripts/src/hwlab-g14.ts. +// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. git-mirror module for scripts/src/hwlab-legacy-runtime.ts. -// Moved mechanically from scripts/src/hwlab-g14.ts:5846-6777 for #903. +// Moved mechanically from scripts/src/hwlab-legacy-runtime.ts:5846-6777 for #903. import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"; import { dirname, join } from "node:path"; @@ -10,17 +10,17 @@ import { runCommand } from "../command"; import { cancelJob, listJobs, readJob, startJob } from "../jobs"; import { hwlabRequiredNoProxyEntries, hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneIds, hwlabRuntimeLaneSpec, isHwlabRuntimeLane, type HwlabRuntimeLane, type HwlabRuntimeLaneSpec } from "../hwlab-node-lanes"; -import type { CommandJsonResult, G14ControlPlaneOptions, G14GitMirrorOptions } from "./types"; +import type { CommandJsonResult, LegacyRuntimeControlPlaneOptions, LegacyRuntimeGitMirrorOptions } from "./types"; import { tailText } from "./cleanup"; import { statusText } from "./pr-monitor"; -import { compactCommandResult, g14K3s, isCommandSuccess, nested, printProgressEvent, record, shellQuote, shortSha, stringOrNull } from "./remote"; +import { compactCommandResult, legacyRuntimeK3s, isCommandSuccess, nested, printProgressEvent, record, shellQuote, shortSha, stringOrNull } from "./remote"; import { cleanupRuntimeLaneRenderDir, runRuntimeLaneRenderToTemp } from "./render"; import { resolveRuntimeLaneHead } from "./source"; -import { GIT_MIRROR_LEGACY_CRONJOB, GIT_MIRROR_MANIFEST_FIELD_MANAGER, GIT_MIRROR_NAMESPACE, GIT_MIRROR_SYNC_JOB_PREFIX, V02_GIT_MIRROR_PRESYNC_LOCK_STALE_MS, V02_GIT_MIRROR_PRESYNC_MAX_WAIT_MS, V02_GIT_MIRROR_PRESYNC_POLL_MS, V02_GIT_READ_URL, V02_GIT_WRITE_URL } from "./types"; -import { parseShellSections, shellSectionOk, timestampMs } from "./v02-status"; +import { GIT_MIRROR_LEGACY_CRONJOB, GIT_MIRROR_MANIFEST_FIELD_MANAGER, GIT_MIRROR_NAMESPACE, GIT_MIRROR_SYNC_JOB_PREFIX, DEFAULT_RUNTIME_LANE_GIT_MIRROR_PRESYNC_LOCK_STALE_MS, DEFAULT_RUNTIME_LANE_GIT_MIRROR_PRESYNC_MAX_WAIT_MS, DEFAULT_RUNTIME_LANE_GIT_MIRROR_PRESYNC_POLL_MS, DEFAULT_RUNTIME_LANE_GIT_READ_URL, DEFAULT_RUNTIME_LANE_GIT_WRITE_URL } from "./types"; +import { parseShellSections, shellSectionOk, timestampMs } from "./runtime-status"; export function deleteLegacyGitMirrorCronJob(dryRun: boolean): CommandJsonResult { - return g14K3s([ + return legacyRuntimeK3s([ "kubectl", "delete", "cronjob", @@ -33,7 +33,7 @@ export function deleteLegacyGitMirrorCronJob(dryRun: boolean): CommandJsonResult } export function applyGitMirrorManifestFile(renderDir: string, dryRun: boolean, timeoutSeconds: number): CommandJsonResult { - return g14K3s([ + return legacyRuntimeK3s([ "kubectl", "apply", "--server-side", @@ -131,10 +131,10 @@ export function parseGitMirrorStatusRefs(raw: string): { refs: Record { const lastSync = parseLabeledJsonLine(raw, "lastSync"); const lastWrite = parseLabeledJsonLine(raw, "lastWrite"); const lastFlush = parseLabeledJsonLine(raw, "lastFlush"); - const localV02 = refs.refs.localV02 ?? null; - const githubV02 = refs.refs.githubV02 ?? null; + const localDefaultRuntimeLane = refs.refs.localDefaultRuntimeLane ?? null; + const githubDefaultRuntimeLane = refs.refs.githubDefaultRuntimeLane ?? null; const localGitops = refs.refs.localGitops ?? null; const githubGitops = refs.refs.githubGitops ?? null; const localV03 = refs.refs.localV03 ?? null; const githubV03 = refs.refs.githubV03 ?? null; const localV03Gitops = refs.refs.localV03Gitops ?? null; const githubV03Gitops = refs.refs.githubV03Gitops ?? null; - const sourceInSync = Boolean(localV02 && githubV02 && localV02 === githubV02); + const sourceInSync = Boolean(localDefaultRuntimeLane && githubDefaultRuntimeLane && localDefaultRuntimeLane === githubDefaultRuntimeLane); const gitopsInSync = Boolean(localGitops && githubGitops && localGitops === githubGitops); const runtimeLanes = Object.fromEntries(hwlabRuntimeLaneIds().map((lane) => { const normalized = lane.slice(0, 1).toUpperCase() + lane.slice(1).toLowerCase(); @@ -196,12 +196,12 @@ export function gitMirrorStatusSummary(raw: string): Record { return laneSummary.sourceInSync === true && laneSummary.gitopsInSync === true; }); return { - localV02, - githubV02, + localDefaultRuntimeLane, + githubDefaultRuntimeLane, localV03, githubV03, - localG14: refs.refs.localG14 ?? null, - githubG14: refs.refs.githubG14 ?? null, + localLegacyRuntime: refs.refs.localLegacyRuntime ?? null, + githubLegacyRuntime: refs.refs.githubLegacyRuntime ?? null, localGitops, githubGitops, localV03Gitops, @@ -234,21 +234,21 @@ export function gitMirrorStatusSummary(raw: string): Record { }; } -export function gitMirrorV02SyncRequirement(sourceCommit: string, rawStatus: string): Record { +export function gitMirrorDefaultRuntimeLaneSyncRequirement(sourceCommit: string, rawStatus: string): Record { const parsed = parseGitMirrorStatusRefs(rawStatus); - const localV02 = parsed.refs.localV02 ?? null; + const localDefaultRuntimeLane = parsed.refs.localDefaultRuntimeLane ?? null; return { - required: localV02 !== sourceCommit, + required: localDefaultRuntimeLane !== sourceCommit, sourceCommit, - localV02, + localDefaultRuntimeLane, pendingFlush: parsed.pendingFlush, refs: parsed.refs, - reason: localV02 === sourceCommit ? "local-v02-current" : localV02 === null ? "local-v02-unresolved" : "local-v02-stale", + reason: localDefaultRuntimeLane === sourceCommit ? "local-v02-current" : localDefaultRuntimeLane === null ? "local-v02-unresolved" : "local-v02-stale", }; } export function runtimeLaneGitMirrorSourceInSyncForTest(lane: string, sourceCommit: string, summary: Record): boolean { - const localKey = lane === "v02" ? "localV02" : lane === "v03" ? "localV03" : null; + const localKey = lane === "v02" ? "localDefaultRuntimeLane" : lane === "v03" ? "localV03" : null; return localKey !== null && typeof summary[localKey] === "string" && summary[localKey] === sourceCommit; } @@ -261,19 +261,19 @@ export function runtimeLaneGitMirrorSourceInSync(spec: HwlabRuntimeLaneSpec, sou } export function compactGitMirrorStatus(status: Record, sourceCommit: string): Record { - const requirement = gitMirrorV02SyncRequirement(sourceCommit, gitMirrorStatusCacheRaw(status)); + const requirement = gitMirrorDefaultRuntimeLaneSyncRequirement(sourceCommit, gitMirrorStatusCacheRaw(status)); return { ok: status.ok === true, - readUrl: status.readUrl ?? V02_GIT_READ_URL, - writeUrl: status.writeUrl ?? V02_GIT_WRITE_URL, + readUrl: status.readUrl ?? DEFAULT_RUNTIME_LANE_GIT_READ_URL, + writeUrl: status.writeUrl ?? DEFAULT_RUNTIME_LANE_GIT_WRITE_URL, elapsedMs: status.elapsedMs ?? null, legacyCronJobExists: nested(status, ["legacyCronJob", "exists"]) === true, required: requirement.required, sourceCommit, - localV02: requirement.localV02 ?? null, - githubV02: requirement.refs.githubV02 ?? null, + localDefaultRuntimeLane: requirement.localDefaultRuntimeLane ?? null, + githubDefaultRuntimeLane: requirement.refs.githubDefaultRuntimeLane ?? null, pendingFlush: requirement.pendingFlush ?? null, - sourceInSync: Boolean(requirement.refs.localV02 && requirement.refs.githubV02 && requirement.refs.localV02 === requirement.refs.githubV02), + sourceInSync: Boolean(requirement.refs.localDefaultRuntimeLane && requirement.refs.githubDefaultRuntimeLane && requirement.refs.localDefaultRuntimeLane === requirement.refs.githubDefaultRuntimeLane), reason: requirement.reason, cacheOk: nested(status, ["cache", "ok"]) === true, cacheStderr: tailText(nested(status, ["cache", "stderr"]), 1000), @@ -299,74 +299,74 @@ export function compactGitMirrorSync(sync: Record): Record V02_GIT_MIRROR_PRESYNC_MAX_WAIT_MS) return null; + if (syncedAtMs === null || nowMs - syncedAtMs > DEFAULT_RUNTIME_LANE_GIT_MIRROR_PRESYNC_MAX_WAIT_MS) return null; if (syncedAtMs < minSyncedAtMs) return null; return candidate; } -export function readV02GitMirrorPreSyncMarker(sourceCommit: string, nowMs = Date.now(), minSyncedAtMs = 0): V02GitMirrorPreSyncMarker | null { - const path = v02GitMirrorPreSyncMarkerPath(sourceCommit); +export function readDefaultRuntimeLaneGitMirrorPreSyncMarker(sourceCommit: string, nowMs = Date.now(), minSyncedAtMs = 0): DefaultRuntimeLaneGitMirrorPreSyncMarker | null { + const path = defaultRuntimeLaneGitMirrorPreSyncMarkerPath(sourceCommit); if (!existsSync(path)) return null; try { - return v02ReusableGitMirrorPreSyncMarker(JSON.parse(readFileSync(path, "utf8")) as unknown, sourceCommit, nowMs, minSyncedAtMs); + return defaultRuntimeLaneReusableGitMirrorPreSyncMarker(JSON.parse(readFileSync(path, "utf8")) as unknown, sourceCommit, nowMs, minSyncedAtMs); } catch { return null; } } -export function writeV02GitMirrorPreSyncMarker(sourceCommit: string, summary: Record): V02GitMirrorPreSyncMarker { +export function writeDefaultRuntimeLaneGitMirrorPreSyncMarker(sourceCommit: string, summary: Record): DefaultRuntimeLaneGitMirrorPreSyncMarker { const marker = { ok: true, sourceCommit, syncedAt: new Date().toISOString(), - localV02: stringOrNull(summary.localV02), - githubV02: stringOrNull(summary.githubV02), + localDefaultRuntimeLane: stringOrNull(summary.localDefaultRuntimeLane), + githubDefaultRuntimeLane: stringOrNull(summary.githubDefaultRuntimeLane), reason: stringOrNull(summary.reason), }; - const dir = v02GitMirrorPreSyncStateDir(); + const dir = defaultRuntimeLaneGitMirrorPreSyncStateDir(); mkdirSync(dir, { recursive: true }); - writeFileSync(v02GitMirrorPreSyncMarkerPath(sourceCommit), `${JSON.stringify(marker, null, 2)}\n`, "utf8"); + writeFileSync(defaultRuntimeLaneGitMirrorPreSyncMarkerPath(sourceCommit), `${JSON.stringify(marker, null, 2)}\n`, "utf8"); return marker; } -export function acquireV02GitMirrorPreSyncLock(sourceCommit: string, waitMs: number, minSyncedAtMs = 0): { acquired: boolean; lockDir: string; waitedMs: number; marker?: V02GitMirrorPreSyncMarker } { - const stateDir = v02GitMirrorPreSyncStateDir(); +export function acquireDefaultRuntimeLaneGitMirrorPreSyncLock(sourceCommit: string, waitMs: number, minSyncedAtMs = 0): { acquired: boolean; lockDir: string; waitedMs: number; marker?: DefaultRuntimeLaneGitMirrorPreSyncMarker } { + const stateDir = defaultRuntimeLaneGitMirrorPreSyncStateDir(); mkdirSync(stateDir, { recursive: true }); - const lockDir = v02GitMirrorPreSyncLockDir(sourceCommit); + const lockDir = defaultRuntimeLaneGitMirrorPreSyncLockDir(sourceCommit); const startedAtMs = Date.now(); for (;;) { - const marker = readV02GitMirrorPreSyncMarker(sourceCommit, Date.now(), minSyncedAtMs); + const marker = readDefaultRuntimeLaneGitMirrorPreSyncMarker(sourceCommit, Date.now(), minSyncedAtMs); if (marker !== null) return { acquired: false, lockDir, waitedMs: Date.now() - startedAtMs, marker }; try { mkdirSync(lockDir); @@ -380,7 +380,7 @@ export function acquireV02GitMirrorPreSyncLock(sourceCommit: string, waitMs: num return 0; } })(); - if (ageMs > V02_GIT_MIRROR_PRESYNC_LOCK_STALE_MS) { + if (ageMs > DEFAULT_RUNTIME_LANE_GIT_MIRROR_PRESYNC_LOCK_STALE_MS) { try { rmSync(lockDir, { recursive: true, force: true }); continue; @@ -395,7 +395,7 @@ export function acquireV02GitMirrorPreSyncLock(sourceCommit: string, waitMs: num } } -export function releaseV02GitMirrorPreSyncLock(lockDir: string): void { +export function releaseDefaultRuntimeLaneGitMirrorPreSyncLock(lockDir: string): void { try { rmSync(lockDir, { recursive: true, force: true }); } catch { @@ -403,7 +403,7 @@ export function releaseV02GitMirrorPreSyncLock(lockDir: string): void { } } -export function waitForV02GitMirrorPreSync(sourceCommit: string, waitMs: number): Record { +export function waitForDefaultRuntimeLaneGitMirrorPreSync(sourceCommit: string, waitMs: number): Record { const startedAtMs = Date.now(); const observations: Record[] = []; let attempt = 0; @@ -425,8 +425,8 @@ export function waitForV02GitMirrorPreSync(sourceCommit: string, waitMs: number) statusElapsedMs: Date.now() - statusStartMs, ok: summary.ok, required: summary.required, - localV02: summary.localV02, - githubV02: summary.githubV02, + localDefaultRuntimeLane: summary.localDefaultRuntimeLane, + githubDefaultRuntimeLane: summary.githubDefaultRuntimeLane, pendingFlush: summary.pendingFlush, reason: summary.reason, }); @@ -438,8 +438,8 @@ export function waitForV02GitMirrorPreSync(sourceCommit: string, waitMs: number) elapsedMs: Date.now() - startedAtMs, statusElapsedMs: Date.now() - statusStartMs, required: summary.required, - localV02: summary.localV02, - githubV02: summary.githubV02, + localDefaultRuntimeLane: summary.localDefaultRuntimeLane, + githubDefaultRuntimeLane: summary.githubDefaultRuntimeLane, pendingFlush: summary.pendingFlush, reason: summary.reason, }); @@ -465,7 +465,7 @@ export function waitForV02GitMirrorPreSync(sourceCommit: string, waitMs: number) }; } const remainingMs = waitMs - (Date.now() - startedAtMs); - const sleepMs = Math.max(500, Math.min(V02_GIT_MIRROR_PRESYNC_POLL_MS, remainingMs)); + const sleepMs = Math.max(500, Math.min(DEFAULT_RUNTIME_LANE_GIT_MIRROR_PRESYNC_POLL_MS, remainingMs)); const wait = runCommand(["sleep", String(Math.ceil(sleepMs / 1000))], repoRoot, { timeoutMs: sleepMs + 2_000 }); if (wait.exitCode !== 0 && wait.timedOut) { return { @@ -515,14 +515,14 @@ export function gitMirrorCacheProbeScript(): string { " refs['local' + normalized + 'Gitops'] = localGitops;", " refs['github' + normalized + 'Gitops'] = githubGitops;", " if (spec.lane === 'v02') {", - " refs.localV02 = localSource;", - " refs.githubV02 = githubSource;", + " refs.localDefaultRuntimeLane = localSource;", + " refs.githubDefaultRuntimeLane = githubSource;", " refs.localGitops = localGitops;", " refs.githubGitops = githubGitops;", " }", "}", - "refs.localG14 = rev('refs/heads/G14');", - "refs.githubG14 = rev('refs/mirror-stage/heads/G14');", + "refs.localLegacyRuntime = rev('refs/heads/G14');", + "refs.githubLegacyRuntime = rev('refs/mirror-stage/heads/G14');", "const pendingFlush = runtimeLanes.some((spec) => {", " const localGitops = rev('refs/heads/' + spec.gitopsBranch);", " const githubGitops = rev('refs/mirror-stage/heads/' + spec.gitopsBranch);", @@ -533,8 +533,8 @@ export function gitMirrorCacheProbeScript(): string { ].join("\n"); } -export function preSyncV02GitMirror(sourceCommit: string, options: Pick): Record { - const waitMs = v02GitMirrorPreSyncWaitMs(options.timeoutSeconds); +export function preSyncDefaultRuntimeLaneGitMirror(sourceCommit: string, options: Pick): Record { + const waitMs = defaultRuntimeLaneGitMirrorPreSyncWaitMs(options.timeoutSeconds); const statusStartMs = Date.now(); printProgressEvent("hwlab.v02.trigger.progress", { stage: "git-mirror-pre-sync-status", status: "started", sourceCommit }); const before = runGitMirrorStatus(); @@ -545,7 +545,7 @@ export function preSyncV02GitMirror(sourceCommit: string, options: Pick { +export function runGitMirrorApply(options: LegacyRuntimeGitMirrorOptions): Record { const spec = hwlabRuntimeLaneSpec(options.lane); const head = resolveRuntimeLaneHead(spec); const sourceCommit = head.sourceCommit; @@ -835,7 +835,7 @@ export function runGitMirrorApply(options: G14GitMirrorOptions): Record { +export function runGitMirrorSync(options: LegacyRuntimeGitMirrorOptions): Record { const startedAtMs = Date.now(); const spec = hwlabRuntimeLaneSpec(options.lane); const jobName = gitMirrorSyncJobName(); @@ -872,7 +872,7 @@ export function runGitMirrorSync(options: G14GitMirrorOptions): Record/dev/null || true; printf "\\n"; git --git-dir=/cache/pikasTech/HWLAB.git rev-parse refs/heads/${spec.sourceBranch} refs/mirror-stage/heads/${spec.sourceBranch} refs/heads/${spec.gitopsBranch} refs/mirror-stage/heads/${spec.gitopsBranch} 2>/dev/null || true`)}`, ].join("\n"), ].join("\n"); - const result = g14K3s(["sh", "--", script], options.timeoutSeconds * 1000 + 30_000); + const result = legacyRuntimeK3s(["sh", "--", script], options.timeoutSeconds * 1000 + 30_000); const syncCommand = spec.lane === "v02" ? "bun scripts/cli.ts hwlab g14 git-mirror sync --lane v02 --confirm" : `bun scripts/cli.ts hwlab nodes git-mirror sync --node ${spec.nodeId} --lane ${spec.lane} --confirm`; @@ -893,7 +893,7 @@ export function runGitMirrorSync(options: G14GitMirrorOptions): Record { +export function runGitMirrorFlush(options: LegacyRuntimeGitMirrorOptions): Record { const jobName = gitMirrorFlushJobName(); const manifest = gitMirrorFlushJobManifest(jobName); const manifestB64 = Buffer.from(JSON.stringify(manifest), "utf8").toString("base64"); @@ -928,7 +928,7 @@ export function runGitMirrorFlush(options: G14GitMirrorOptions): Record/dev/null || true; printf "\\n"; git --git-dir=/cache/pikasTech/HWLAB.git rev-parse refs/heads/${options.lane === "v02" ? "v0.2-gitops" : hwlabRuntimeLaneSpec(options.lane).gitopsBranch} refs/mirror-stage/heads/${options.lane === "v02" ? "v0.2-gitops" : hwlabRuntimeLaneSpec(options.lane).gitopsBranch} 2>/dev/null || true`)}`, ].join("\n"), ].join("\n"); - const result = g14K3s(["sh", "--", script], options.timeoutSeconds * 1000 + 30_000); + const result = legacyRuntimeK3s(["sh", "--", script], options.timeoutSeconds * 1000 + 30_000); return { ok: isCommandSuccess(result), command: "hwlab g14 git-mirror flush", @@ -944,7 +944,7 @@ export function runGitMirrorFlush(options: G14GitMirrorOptions): Record { +export function runLegacyRuntimeGitMirror(options: LegacyRuntimeGitMirrorOptions): Record { if (options.action === "status") return runGitMirrorStatus(options.lane); if (options.action === "apply") return runGitMirrorApply(options); if (options.action === "flush") return runGitMirrorFlush(options); diff --git a/scripts/src/hwlab-g14/help.ts b/scripts/src/hwlab-legacy-runtime/help.ts similarity index 82% rename from scripts/src/hwlab-g14/help.ts rename to scripts/src/hwlab-legacy-runtime/help.ts index 105aeb04..621c467c 100644 --- a/scripts/src/hwlab-g14/help.ts +++ b/scripts/src/hwlab-legacy-runtime/help.ts @@ -1,6 +1,6 @@ -// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. help module for scripts/src/hwlab-g14.ts. +// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. help module for scripts/src/hwlab-legacy-runtime.ts. -// Moved mechanically from scripts/src/hwlab-g14.ts:10421-10618 for #903. +// Moved mechanically from scripts/src/hwlab-legacy-runtime.ts:10421-10618 for #903. import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"; import { dirname, join } from "node:path"; @@ -10,13 +10,13 @@ import { runCommand } from "../command"; import { cancelJob, listJobs, readJob, startJob } from "../jobs"; import { hwlabRequiredNoProxyEntries, hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneIds, hwlabRuntimeLaneSpec, isHwlabRuntimeLane, type HwlabRuntimeLane, type HwlabRuntimeLaneSpec } from "../hwlab-node-lanes"; -import type { G14MonitorOptions } from "./types"; -import { hwlabG14MonitorStateFileName, hwlabG14MonitorStateRole } from "./options"; +import type { LegacyRuntimeMonitorOptions } from "./types"; +import { hwlabLegacyRuntimeMonitorStateFileName, hwlabLegacyRuntimeMonitorStateRole } from "./options"; import { monitorBaseBranch, record } from "./remote"; -import { legacyG14RetirementBlocksMonitor, legacyG14RetirementStatePath } from "./retirement"; -import { DEFAULT_INTERVAL_SECONDS, DEV_APP, G14_BRIEF_INDEX_ISSUE, G14_CI_TOOLS_IMAGE_REPO, G14_OBSERVABILITY_NAMESPACE, G14_PROMETHEUS_OPERATOR_VERSION, G14_PROMETHEUS_VERSION, G14_PROVIDER, G14_SOURCE_BRANCH, G14_WORKSPACE, HWLAB_REPO, PROD_APP, V02_APP, V02_OBSERVABILITY_EXPECTED_TARGET_COUNT, V02_SOURCE_BRANCH, V02_WORKSPACE } from "./types"; +import { legacyLegacyRuntimeRetirementBlocksMonitor, legacyLegacyRuntimeRetirementStatePath } from "./retirement"; +import { DEFAULT_INTERVAL_SECONDS, DEV_APP, LEGACY_RUNTIME_BRIEF_INDEX_ISSUE, LEGACY_RUNTIME_CI_TOOLS_IMAGE_REPO, LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE, LEGACY_RUNTIME_PROMETHEUS_OPERATOR_VERSION, LEGACY_RUNTIME_PROMETHEUS_VERSION, LEGACY_RUNTIME_PROVIDER, LEGACY_RUNTIME_SOURCE_BRANCH, LEGACY_RUNTIME_WORKSPACE, HWLAB_REPO, PROD_APP, DEFAULT_RUNTIME_LANE_APP, DEFAULT_RUNTIME_LANE_OBSERVABILITY_EXPECTED_TARGET_COUNT, DEFAULT_RUNTIME_LANE_SOURCE_BRANCH, DEFAULT_RUNTIME_LANE_WORKSPACE } from "./types"; -export function hwlabG14Help(): Record { +export function hwlabLegacyRuntimeHelp(): Record { return { command: "hwlab g14", output: "json", @@ -88,9 +88,9 @@ export function hwlabG14Help(): Record { "bun scripts/cli.ts hwlab g14 observability status", "bun scripts/cli.ts hwlab g14 observability apply --dry-run", "bun scripts/cli.ts hwlab g14 observability apply --confirm", - `bun scripts/cli.ts hwlab g14 observability query --promql 'up{namespace=\"hwlab-v02\"}' --expect-count ${V02_OBSERVABILITY_EXPECTED_TARGET_COUNT} --expect-value 1`, - `bun scripts/cli.ts hwlab g14 observability query --promql 'hwlab_service_up{namespace=\"hwlab-v02\"}' --expect-count ${V02_OBSERVABILITY_EXPECTED_TARGET_COUNT} --expect-value 1`, - `bun scripts/cli.ts hwlab g14 observability query --promql 'hwlab_service_health_probe_success{namespace=\"hwlab-v02\"}' --expect-count ${V02_OBSERVABILITY_EXPECTED_TARGET_COUNT} --expect-value 1`, + `bun scripts/cli.ts hwlab g14 observability query --promql 'up{namespace=\"hwlab-v02\"}' --expect-count ${DEFAULT_RUNTIME_LANE_OBSERVABILITY_EXPECTED_TARGET_COUNT} --expect-value 1`, + `bun scripts/cli.ts hwlab g14 observability query --promql 'hwlab_service_up{namespace=\"hwlab-v02\"}' --expect-count ${DEFAULT_RUNTIME_LANE_OBSERVABILITY_EXPECTED_TARGET_COUNT} --expect-value 1`, + `bun scripts/cli.ts hwlab g14 observability query --promql 'hwlab_service_health_probe_success{namespace=\"hwlab-v02\"}' --expect-count ${DEFAULT_RUNTIME_LANE_OBSERVABILITY_EXPECTED_TARGET_COUNT} --expect-value 1`, "bun scripts/cli.ts hwlab g14 observability targets --lane v02", "bun scripts/cli.ts hwlab g14 observability boundary --lane v02", "bun scripts/cli.ts hwlab g14 observability closeout --lane v02", @@ -104,40 +104,40 @@ export function hwlabG14Help(): Record { description: "G14 HWLAB PR monitor, legacy DEV/PROD retirement status/plan/execute command, bounded v0.2 control-plane bootstrap/cleanup/runtime-migration helper, node-scoped runtime lane v03 control-plane apply/status/refresh/trigger entry, runtime lane SecretRef bootstrap, devops-infra git mirror and observability maintenance, controlled CI tools image build/status entry, and allowlisted upstream image mirroring. The legacy base=G14 monitor is blocked by the retirement contract; the local retirement marker records live execution evidence. `--lane v02` monitors base=v0.2 PRs, waits for GitHub preflight/CI readiness, automatically merges ready PRs without waiting for other active v0.2 PipelineRuns, triggers v0.2 CD with latest-only GitOps writeback, flushes the git mirror when needed, and posts deduplicated PR comments for pending, blocked/conflict, success, superseded, failure, or timeout states. `--lane v03` monitors base=v0.3 PRs through the runtime lane control-plane, waits for GitHub preflight/CI readiness, auto-merges ready non-conflicting PRs, triggers v0.3 CD, verifies PipelineRun/Argo/runtime public probes/Git mirror flush, posts deduplicated PR comments, and creates or updates failure issues for failed checks, conflicts, merge blockers, CD failures, and timeouts. confirmed control-plane trigger-current and git-mirror sync/flush also return async jobs by default, with --wait reserved for explicit synchronous debugging. control-plane v02 keeps the full closeout/cleanup/runtime-migration verdict path; v03+ is advertised through `hwlab nodes ... --node --lane vNN` so node identity remains configuration data instead of a command family. secret status/ensure is the standard runtime lane SecretRef bootstrap path for OpenFGA, cloud-api DB, master admin API key, and code-agent provider refs; it never reads or prints secret values. upstream-image status/ensure only mirrors allowlisted upstream runtime images into the G14 local registry. git-mirror status/apply/sync/flush is the manual devops-infra mirror/relay control path and does not install a CronJob. observability status/apply/query/targets/boundary/closeout owns the shared Prometheus Operator and Prometheus instance in devops-infra, adds bounded PromQL assertions and semantic closeout summaries, while HWLAB lane manifests own only ServiceMonitor and PrometheusRule objects.", defaults: { repo: HWLAB_REPO, - legacyBase: G14_SOURCE_BRANCH, - v02Base: V02_SOURCE_BRANCH, + legacyBase: LEGACY_RUNTIME_SOURCE_BRANCH, + defaultRuntimeLaneBase: DEFAULT_RUNTIME_LANE_SOURCE_BRANCH, runtimeLaneConfig: hwlabRuntimeLaneConfigPath(), runtimeLanes: hwlabRuntimeLaneIds(), - provider: G14_PROVIDER, - legacyWorkspace: G14_WORKSPACE, - v02Workspace: V02_WORKSPACE, + provider: LEGACY_RUNTIME_PROVIDER, + legacyWorkspace: LEGACY_RUNTIME_WORKSPACE, + defaultRuntimeLaneWorkspace: DEFAULT_RUNTIME_LANE_WORKSPACE, v03Workspace: hwlabRuntimeLaneSpec("v03").workspace, - ciToolsImageRepo: G14_CI_TOOLS_IMAGE_REPO, + ciToolsImageRepo: LEGACY_RUNTIME_CI_TOOLS_IMAGE_REPO, intervalSeconds: DEFAULT_INTERVAL_SECONDS, devApplication: DEV_APP, prodApplication: PROD_APP, - legacyRetirementState: legacyG14RetirementStatePath(), - v02Application: V02_APP, + legacyRetirementState: legacyLegacyRuntimeRetirementStatePath(), + defaultRuntimeLaneApplication: DEFAULT_RUNTIME_LANE_APP, v03Application: hwlabRuntimeLaneSpec("v03").app, v03Node: hwlabRuntimeLaneSpec("v03").nodeId, v03NetworkProfile: hwlabRuntimeLaneSpec("v03").networkProfileId, v03DownloadProfile: hwlabRuntimeLaneSpec("v03").downloadProfileId, requiredNoProxy: hwlabRequiredNoProxyEntries(), - briefIndexIssue: G14_BRIEF_INDEX_ISSUE, - observabilityNamespace: G14_OBSERVABILITY_NAMESPACE, - prometheusOperatorVersion: G14_PROMETHEUS_OPERATOR_VERSION, - prometheusVersion: G14_PROMETHEUS_VERSION, + briefIndexIssue: LEGACY_RUNTIME_BRIEF_INDEX_ISSUE, + observabilityNamespace: LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE, + prometheusOperatorVersion: LEGACY_RUNTIME_PROMETHEUS_OPERATOR_VERSION, + prometheusVersion: LEGACY_RUNTIME_PROMETHEUS_VERSION, }, stateFiles: { monitor: ".state/hwlab-g14/latest-monitor-job.json", once: ".state/hwlab-g14/latest-once-job.json", dryRun: ".state/hwlab-g14/latest-dry-run-job.json", onceDryRun: ".state/hwlab-g14/latest-once-dry-run-job.json", - v02Monitor: ".state/hwlab-g14/latest-v02-monitor-job.json", - v02Once: ".state/hwlab-g14/latest-v02-once-job.json", - v02DryRun: ".state/hwlab-g14/latest-v02-dry-run-job.json", - v02OnceDryRun: ".state/hwlab-g14/latest-v02-once-dry-run-job.json", - v02PrCommentSignatures: ".state/hwlab-g14/v02-pr-comment-signatures.json", + defaultRuntimeLaneMonitor: ".state/hwlab-g14/latest-v02-monitor-job.json", + defaultRuntimeLaneOnce: ".state/hwlab-g14/latest-v02-once-job.json", + defaultRuntimeLaneDryRun: ".state/hwlab-g14/latest-v02-dry-run-job.json", + defaultRuntimeLaneOnceDryRun: ".state/hwlab-g14/latest-v02-once-dry-run-job.json", + defaultRuntimeLanePrCommentSignatures: ".state/hwlab-g14/v02-pr-comment-signatures.json", v03Monitor: ".state/hwlab-g14/latest-v03-monitor-job.json", v03Once: ".state/hwlab-g14/latest-v03-once-job.json", v03DryRun: ".state/hwlab-g14/latest-v03-dry-run-job.json", @@ -147,12 +147,12 @@ export function hwlabG14Help(): Record { }; } -export function monitorStatus(options: G14MonitorOptions): Record { +export function monitorStatus(options: LegacyRuntimeMonitorOptions): Record { const stateDir = rootPath(".state", "hwlab-g14"); - const stateFileName = hwlabG14MonitorStateFileName(options); - const stateFileRole = hwlabG14MonitorStateRole(options); + const stateFileName = hwlabLegacyRuntimeMonitorStateFileName(options); + const stateFileRole = hwlabLegacyRuntimeMonitorStateRole(options); const latestPath = join(stateDir, stateFileName); - const retirement = options.lane === "g14" ? legacyG14RetirementBlocksMonitor() : null; + const retirement = options.lane === "g14" ? legacyLegacyRuntimeRetirementBlocksMonitor() : null; const exists = existsSync(latestPath); let latest: Record | null = null; let job: Record | null = null; @@ -204,7 +204,7 @@ export function monitorStatus(options: G14MonitorOptions): Record { +export function startAsyncHwlabLegacyRuntimeJob(name: string, command: string[], note: string): Record { const job = startJob(name, command, note); const statusCommand = `bun scripts/cli.ts job status ${job.id} --tail-bytes 12000`; return { @@ -31,7 +31,7 @@ export function startAsyncHwlabG14Job(name: string, command: string[], note: str }; } -export function startControlPlaneTriggerJob(options: G14ControlPlaneOptions): Record { +export function startControlPlaneTriggerJob(options: LegacyRuntimeControlPlaneOptions): Record { const command = [ "bun", "scripts/cli.ts", @@ -52,7 +52,7 @@ export function startControlPlaneTriggerJob(options: G14ControlPlaneOptions): Re lane: options.lane, reason: "confirmed trigger can spend tens of seconds syncing git mirror and creating PipelineRun; default is fire-and-forget to avoid silent blocking", waitCommand: command.join(" "), - ...startAsyncHwlabG14Job( + ...startAsyncHwlabLegacyRuntimeJob( `hwlab_g14_${options.lane}_trigger_current`, command, `Trigger HWLAB ${options.lane} current commit PipelineRun with git mirror pre-sync through G14 control-plane`, @@ -60,7 +60,7 @@ export function startControlPlaneTriggerJob(options: G14ControlPlaneOptions): Re }; } -export function startGitMirrorJob(options: G14GitMirrorOptions): Record { +export function startGitMirrorJob(options: LegacyRuntimeGitMirrorOptions): Record { const command = [ "bun", "scripts/cli.ts", @@ -81,7 +81,7 @@ export function startGitMirrorJob(options: G14GitMirrorOptions): Record { - const image = g14CiToolsImage(options.tag); +export function runLegacyRuntimeToolsImageStatus(options: LegacyRuntimeToolsImageOptions): Record { + const image = legacyRuntimeCiToolsImage(options.tag); const script = [ "set -u", `image=${shellQuote(image)}`, @@ -149,7 +149,7 @@ export function runG14ToolsImageStatus(options: G14ToolsImageOptions): Record 0) { @@ -169,11 +169,11 @@ export function runG14ToolsImageStatus(options: G14ToolsImageOptions): Record { - const image = g14CiToolsImage(options.tag); +export function runLegacyRuntimeToolsImageBuild(options: LegacyRuntimeToolsImageOptions): Record { + const image = legacyRuntimeCiToolsImage(options.tag); const script = [ "set -eu", - `cd ${shellQuote(V02_WORKSPACE)}`, + `cd ${shellQuote(DEFAULT_RUNTIME_LANE_WORKSPACE)}`, "git fetch origin v0.2 --prune", "git checkout v0.2 >/dev/null 2>&1 || true", "git merge --ff-only origin/v0.2", @@ -196,42 +196,42 @@ export function runG14ToolsImageBuild(options: G14ToolsImageOptions): Record { - if (options.action === "status") return runG14ToolsImageStatus(options); - return runG14ToolsImageBuild(options); +export function runLegacyRuntimeToolsImage(options: LegacyRuntimeToolsImageOptions): Record { + if (options.action === "status") return runLegacyRuntimeToolsImageStatus(options); + return runLegacyRuntimeToolsImageBuild(options); } -export function g14UpstreamImageTarget(options: G14UpstreamImageOptions): string { - return `${V02_REGISTRY_PREFIX}/${options.name}:${options.tag}`; +export function legacyRuntimeUpstreamImageTarget(options: LegacyRuntimeUpstreamImageOptions): string { + return `${DEFAULT_RUNTIME_LANE_REGISTRY_PREFIX}/${options.name}:${options.tag}`; } -export function g14UpstreamImageSource(options: G14UpstreamImageOptions): string { +export function legacyRuntimeUpstreamImageSource(options: LegacyRuntimeUpstreamImageOptions): string { if (options.name === "openfga") return `docker.io/openfga/openfga:${options.tag}`; return `${options.name}:${options.tag}`; } -export function runG14UpstreamImageStatus(options: G14UpstreamImageOptions): Record { - const sourceImage = g14UpstreamImageSource(options); - const targetImage = g14UpstreamImageTarget(options); +export function runLegacyRuntimeUpstreamImageStatus(options: LegacyRuntimeUpstreamImageOptions): Record { + const sourceImage = legacyRuntimeUpstreamImageSource(options); + const targetImage = legacyRuntimeUpstreamImageTarget(options); const script = [ "set +e", `source_image=${shellQuote(sourceImage)}`, @@ -257,7 +257,7 @@ export function runG14UpstreamImageStatus(options: G14UpstreamImageOptions): Rec "}, null, 2));", "NODE", ].join("\n"); - const result = g14HostScript(script, 120_000); + const result = legacyRuntimeHostScript(script, 120_000); let parsedStatus: unknown = null; const text = statusText(result); if (text.length > 0) { @@ -279,9 +279,9 @@ export function runG14UpstreamImageStatus(options: G14UpstreamImageOptions): Rec }; } -export function runG14UpstreamImageEnsure(options: G14UpstreamImageOptions): Record { - const sourceImage = g14UpstreamImageSource(options); - const targetImage = g14UpstreamImageTarget(options); +export function runLegacyRuntimeUpstreamImageEnsure(options: LegacyRuntimeUpstreamImageOptions): Record { + const sourceImage = legacyRuntimeUpstreamImageSource(options); + const targetImage = legacyRuntimeUpstreamImageTarget(options); if (options.dryRun) { return { ok: true, @@ -310,8 +310,8 @@ export function runG14UpstreamImageEnsure(options: G14UpstreamImageOptions): Rec "digest=$(docker image inspect \"$target_image\" --format '{{index .RepoDigests 0}}' 2>/dev/null || true)", "echo \"{\\\"phase\\\":\\\"published\\\",\\\"targetImage\\\":\\\"$target_image\\\",\\\"digest\\\":\\\"$digest\\\"}\"", ].join("\n"); - const result = g14HostScript(script, options.timeoutSeconds * 1000); - const status = runG14UpstreamImageStatus(options); + const result = legacyRuntimeHostScript(script, options.timeoutSeconds * 1000); + const status = runLegacyRuntimeUpstreamImageStatus(options); return { ok: isCommandSuccess(result) && status.ok === true, command: "hwlab g14 upstream-image ensure --name openfga", @@ -326,7 +326,7 @@ export function runG14UpstreamImageEnsure(options: G14UpstreamImageOptions): Rec }; } -export function runG14UpstreamImage(options: G14UpstreamImageOptions): Record { - if (options.action === "status") return runG14UpstreamImageStatus(options); - return runG14UpstreamImageEnsure(options); +export function runLegacyRuntimeUpstreamImage(options: LegacyRuntimeUpstreamImageOptions): Record { + if (options.action === "status") return runLegacyRuntimeUpstreamImageStatus(options); + return runLegacyRuntimeUpstreamImageEnsure(options); } diff --git a/scripts/src/hwlab-g14/index.ts b/scripts/src/hwlab-legacy-runtime/index.ts similarity index 85% rename from scripts/src/hwlab-g14/index.ts rename to scripts/src/hwlab-legacy-runtime/index.ts index e5dba783..e54ca93a 100644 --- a/scripts/src/hwlab-g14/index.ts +++ b/scripts/src/hwlab-legacy-runtime/index.ts @@ -1,9 +1,9 @@ -// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. Domain barrel for scripts/src/hwlab-g14.ts. +// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. Domain barrel for scripts/src/hwlab-legacy-runtime.ts. export * from "./types"; export * from "./options"; export * from "./remote"; export * from "./source"; -export * from "./v02-status"; +export * from "./runtime-status"; export * from "./cleanup"; export * from "./render"; export * from "./control-plane"; diff --git a/scripts/src/hwlab-g14/monitor.ts b/scripts/src/hwlab-legacy-runtime/monitor.ts similarity index 79% rename from scripts/src/hwlab-g14/monitor.ts rename to scripts/src/hwlab-legacy-runtime/monitor.ts index 3879009e..1c15ff28 100644 --- a/scripts/src/hwlab-g14/monitor.ts +++ b/scripts/src/hwlab-legacy-runtime/monitor.ts @@ -1,6 +1,6 @@ -// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. monitor module for scripts/src/hwlab-g14.ts. +// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. monitor module for scripts/src/hwlab-legacy-runtime.ts. -// Moved mechanically from scripts/src/hwlab-g14.ts:10163-10420 for #903. +// Moved mechanically from scripts/src/hwlab-legacy-runtime.ts:10163-10420 for #903. import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"; import { dirname, join } from "node:path"; @@ -10,14 +10,14 @@ import { runCommand } from "../command"; import { cancelJob, listJobs, readJob, startJob } from "../jobs"; import { hwlabRequiredNoProxyEntries, hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneIds, hwlabRuntimeLaneSpec, isHwlabRuntimeLane, type HwlabRuntimeLane, type HwlabRuntimeLaneSpec } from "../hwlab-node-lanes"; -import type { CommandJsonResult, G14MonitorOptions } from "./types"; -import { runRuntimeLanePrAutoCd, runV02PrAutoCd } from "./cd-trigger"; -import { appendRolloutBrief, collectPipelineMetrics, commentRuntimeLanePullRequest, commentV02PullRequest, durationSeconds, getArgoStatus, getDevWorkloads, getG14Head, getLiveHealth, getPipelineStatus, listOpenG14PullRequests, mergePullRequest, preflightPullRequest, preflightSummary, refreshArgoDev, reportRuntimeLaneAutomationIssue, statusText, v02PrConflictState, workloadReadiness } from "./pr-monitor"; -import { commandData, compactCommandResult, extractPullRequests, isCommandSuccess, nested, precheckWorkspace, printEvent, printRuntimeLanePrMonitorProgress, printV02PrMonitorProgress, record, shortSha, sleep } from "./remote"; -import { legacyG14RetirementBlocksMonitor } from "./retirement"; -import { V02_SOURCE_BRANCH } from "./types"; +import type { CommandJsonResult, LegacyRuntimeMonitorOptions } from "./types"; +import { runRuntimeLanePrAutoCd, runDefaultRuntimeLanePrAutoCd } from "./cd-trigger"; +import { appendRolloutBrief, collectPipelineMetrics, commentRuntimeLanePullRequest, commentDefaultRuntimeLanePullRequest, durationSeconds, getArgoStatus, getDevWorkloads, getLegacyRuntimeHead, getLiveHealth, getPipelineStatus, listOpenLegacyRuntimePullRequests, mergePullRequest, preflightPullRequest, preflightSummary, refreshArgoDev, reportRuntimeLaneAutomationIssue, statusText, defaultRuntimeLanePrConflictState, workloadReadiness } from "./pr-monitor"; +import { commandData, compactCommandResult, extractPullRequests, isCommandSuccess, nested, precheckWorkspace, printEvent, printRuntimeLanePrMonitorProgress, printDefaultRuntimeLanePrMonitorProgress, record, shortSha, sleep } from "./remote"; +import { legacyLegacyRuntimeRetirementBlocksMonitor } from "./retirement"; +import { DEFAULT_RUNTIME_LANE_SOURCE_BRANCH } from "./types"; -export async function waitForG14Dev(sourceCommit: string, timeoutSeconds: number): Promise> { +export async function waitForLegacyRuntimeDev(sourceCommit: string, timeoutSeconds: number): Promise> { const started = Date.now(); const startedAt = new Date(started).toISOString(); let pipelineText = ""; @@ -59,15 +59,15 @@ export async function waitForG14Dev(sourceCommit: string, timeoutSeconds: number return { ok: false, phase: "timeout", sourceCommit, pipelineText, argoText, startedAt, pipelineSucceededAt, workloadsReady, healthOk, timeoutSeconds }; } -export async function monitorV02Cycle(options: G14MonitorOptions, cycle: number): Promise> { +export async function monitorDefaultRuntimeLaneCycle(options: LegacyRuntimeMonitorOptions, cycle: number): Promise> { printEvent("v02.monitor.cycle.start", { cycle, dryRun: options.dryRun }); - printV02PrMonitorProgress({ stage: "cycle", status: "started", cycle, dryRun: options.dryRun }); - const listed = listOpenG14PullRequests(); + printDefaultRuntimeLanePrMonitorProgress({ stage: "cycle", status: "started", cycle, dryRun: options.dryRun }); + const listed = listOpenLegacyRuntimePullRequests(); if (!isCommandSuccess(listed)) return { ok: false, cycle, phase: "list-prs", listed }; - const prs = extractPullRequests(listed, V02_SOURCE_BRANCH); + const prs = extractPullRequests(listed, DEFAULT_RUNTIME_LANE_SOURCE_BRANCH); printEvent("v02.monitor.prs", { cycle, count: prs.length, pullRequests: prs }); if (prs.length === 0) { - printV02PrMonitorProgress({ stage: "idle", status: "waiting", cycle, pullRequests: 0, intervalSeconds: options.intervalSeconds }); + printDefaultRuntimeLanePrMonitorProgress({ stage: "idle", status: "waiting", cycle, pullRequests: 0, intervalSeconds: options.intervalSeconds }); return { ok: true, cycle, action: "none", lane: "v02", pullRequests: [] }; } const observations: unknown[] = []; @@ -81,19 +81,19 @@ export async function monitorV02Cycle(options: G14MonitorOptions, cycle: number) ok: isCommandSuccess(preflightResult), conclusion: preflight.conclusion, readyForCommanderMerge: preflight.readyForCommanderMerge, - conflict: v02PrConflictState(preflight), + conflict: defaultRuntimeLanePrConflictState(preflight), }); - printV02PrMonitorProgress({ + printDefaultRuntimeLanePrMonitorProgress({ stage: "preflight", status: preflight.readyForCommanderMerge === true ? "succeeded" : "running", pr: pr.number, conclusion: preflight.conclusion, - conflict: v02PrConflictState(preflight), + conflict: defaultRuntimeLanePrConflictState(preflight), }); if (!isCommandSuccess(preflightResult) || preflight.readyForCommanderMerge !== true) { const conclusion = String(preflight.conclusion ?? "unknown"); - const blocked = conclusion === "blocked" || v02PrConflictState(preflight) === "conflict" || !isCommandSuccess(preflightResult); - const comment = commentV02PullRequest({ + const blocked = conclusion === "blocked" || defaultRuntimeLanePrConflictState(preflight) === "conflict" || !isCommandSuccess(preflightResult); + const comment = commentDefaultRuntimeLanePullRequest({ pr, phase: "preflight", state: blocked ? "blocked" : "waiting-ci", @@ -107,14 +107,14 @@ export async function monitorV02Cycle(options: G14MonitorOptions, cycle: number) : "v0.2 自动化正在等待 GitHub CI / mergeability 收敛;CI 通过且无冲突后会自动合并并触发 CD。", }); observations.push({ pullRequest: pr, preflight, comment }); - printV02PrMonitorProgress({ stage: "pr-comment", status: record(comment).ok === true ? "succeeded" : "failed", pr: pr.number, conclusion: preflight.conclusion }); + printDefaultRuntimeLanePrMonitorProgress({ stage: "pr-comment", status: record(comment).ok === true ? "succeeded" : "failed", pr: pr.number, conclusion: preflight.conclusion }); if (record(comment).ok !== true) return { ok: false, cycle, lane: "v02", phase: "pr-comment", pullRequest: pr, preflight, comment, observations }; continue; } const merge = mergePullRequest(pr.number, options.dryRun); printEvent("v02.pr.merge", { cycle, number: pr.number, dryRun: options.dryRun, ok: isCommandSuccess(merge) }); - printV02PrMonitorProgress({ stage: "merge", status: isCommandSuccess(merge) ? "succeeded" : "running", pr: pr.number, dryRun: options.dryRun }); - const result = await runV02PrAutoCd(pr, preflight, merge, options, startedAt); + printDefaultRuntimeLanePrMonitorProgress({ stage: "merge", status: isCommandSuccess(merge) ? "succeeded" : "running", pr: pr.number, dryRun: options.dryRun }); + const result = await runDefaultRuntimeLanePrAutoCd(pr, preflight, merge, options, startedAt); observations.push(result); if (record(result).ok !== true) return { ok: false, cycle, lane: "v02", phase: record(result).phase ?? "v02-auto-cd", pullRequest: pr, result, observations }; return { ok: true, cycle, lane: "v02", action: record(result).action ?? (options.dryRun ? "dry-run-merge" : "merged-and-rolled-v02"), result, observations }; @@ -127,7 +127,7 @@ export function runtimeLanePreflightBlocked(preflightResult: CommandJsonResult, const pending = Array.isArray(preflight.pending) ? preflight.pending : []; const conclusion = String(preflight.conclusion ?? "unknown").toLowerCase(); return !isCommandSuccess(preflightResult) - || v02PrConflictState(preflight) === "conflict" + || defaultRuntimeLanePrConflictState(preflight) === "conflict" || conclusion === "blocked" || conclusion === "failed" || conclusion === "failure" @@ -135,10 +135,10 @@ export function runtimeLanePreflightBlocked(preflightResult: CommandJsonResult, || (blockers.length > 0 && pending.length === 0); } -export async function monitorRuntimeLaneCycle(spec: HwlabRuntimeLaneSpec, options: G14MonitorOptions, cycle: number): Promise> { +export async function monitorRuntimeLaneCycle(spec: HwlabRuntimeLaneSpec, options: LegacyRuntimeMonitorOptions, cycle: number): Promise> { printEvent(`${spec.lane}.monitor.cycle.start`, { cycle, dryRun: options.dryRun }); printRuntimeLanePrMonitorProgress(spec, { stage: "cycle", status: "started", cycle, dryRun: options.dryRun }); - const listed = listOpenG14PullRequests(); + const listed = listOpenLegacyRuntimePullRequests(); if (!isCommandSuccess(listed)) return { ok: false, cycle, lane: spec.lane, phase: "list-prs", listed }; const prs = extractPullRequests(listed, spec.sourceBranch); printEvent(`${spec.lane}.monitor.prs`, { cycle, count: prs.length, pullRequests: prs }); @@ -157,14 +157,14 @@ export async function monitorRuntimeLaneCycle(spec: HwlabRuntimeLaneSpec, option ok: isCommandSuccess(preflightResult), conclusion: preflight.conclusion, readyForCommanderMerge: preflight.readyForCommanderMerge, - conflict: v02PrConflictState(preflight), + conflict: defaultRuntimeLanePrConflictState(preflight), }); printRuntimeLanePrMonitorProgress(spec, { stage: "preflight", status: preflight.readyForCommanderMerge === true ? "succeeded" : "running", pr: pr.number, conclusion: preflight.conclusion, - conflict: v02PrConflictState(preflight), + conflict: defaultRuntimeLanePrConflictState(preflight), }); if (!isCommandSuccess(preflightResult) || preflight.readyForCommanderMerge !== true) { const blocked = runtimeLanePreflightBlocked(preflightResult, preflight); @@ -211,10 +211,10 @@ export async function monitorRuntimeLaneCycle(spec: HwlabRuntimeLaneSpec, option return { ok: true, cycle, lane: spec.lane, action: "none", observations }; } -export async function monitorCycle(options: G14MonitorOptions, cycle: number): Promise> { - if (options.lane === "v02") return monitorV02Cycle(options, cycle); +export async function monitorCycle(options: LegacyRuntimeMonitorOptions, cycle: number): Promise> { + if (options.lane === "v02") return monitorDefaultRuntimeLaneCycle(options, cycle); if (options.lane !== "g14") return monitorRuntimeLaneCycle(hwlabRuntimeLaneSpec(options.lane), options, cycle); - const retirement = legacyG14RetirementBlocksMonitor(); + const retirement = legacyLegacyRuntimeRetirementBlocksMonitor(); if (retirement !== null) { return { ok: false, @@ -222,13 +222,13 @@ export async function monitorCycle(options: G14MonitorOptions, cycle: number): P phase: "retired", degradedReason: "legacy-g14-dev-prod-retired", retirement, - next: { status: "bun scripts/cli.ts hwlab g14 retirement status", v02Monitor: "bun scripts/cli.ts hwlab g14 monitor-prs --lane v02" }, + next: { status: "bun scripts/cli.ts hwlab g14 retirement status", defaultRuntimeLaneMonitor: "bun scripts/cli.ts hwlab g14 monitor-prs --lane v02" }, }; } printEvent("g14.monitor.cycle.start", { cycle, dryRun: options.dryRun }); const precheck = precheckWorkspace(); if (!isCommandSuccess(precheck)) return { ok: false, cycle, phase: "workspace-precheck", precheck }; - const listed = listOpenG14PullRequests(); + const listed = listOpenLegacyRuntimePullRequests(); if (!isCommandSuccess(listed)) return { ok: false, cycle, phase: "list-prs", listed }; const prs = extractPullRequests(listed); printEvent("g14.monitor.prs", { cycle, count: prs.length, pullRequests: prs }); @@ -243,8 +243,8 @@ export async function monitorCycle(options: G14MonitorOptions, cycle: number): P const merge = mergePullRequest(pr.number, options.dryRun); printEvent("g14.pr.merge", { cycle, number: pr.number, dryRun: options.dryRun, ok: isCommandSuccess(merge) }); if (!isCommandSuccess(merge)) return { ok: false, cycle, phase: "pr-merge", pullRequest: pr, merge }; - const sourceCommit = getG14Head(); - const rollout = options.dryRun || sourceCommit === null ? { skipped: true, dryRun: options.dryRun, sourceCommit } : await waitForG14Dev(sourceCommit, options.timeoutSeconds); + const sourceCommit = getLegacyRuntimeHead(); + const rollout = options.dryRun || sourceCommit === null ? { skipped: true, dryRun: options.dryRun, sourceCommit } : await waitForLegacyRuntimeDev(sourceCommit, options.timeoutSeconds); const brief = options.dryRun || sourceCommit === null || record(rollout).ok !== true ? { skipped: true, dryRun: options.dryRun } : appendRolloutBrief({ prNumber: pr.number, sourceCommit, dryRun: false }, rollout); @@ -256,7 +256,7 @@ export async function monitorCycle(options: G14MonitorOptions, cycle: number): P return { ok: true, cycle, action: options.dryRun ? "dry-run-merge" : "merged-and-rolled-dev", merged }; } -export async function runMonitorWorker(options: G14MonitorOptions): Promise> { +export async function runMonitorWorker(options: LegacyRuntimeMonitorOptions): Promise> { const maxCycles = options.once ? 1 : options.maxCycles; let cycle = 0; const results: unknown[] = []; @@ -268,7 +268,7 @@ export async function runMonitorWorker(options: G14MonitorOptions): Promise { return { @@ -31,7 +31,7 @@ export function observabilityNamespaceLabel(): Record { }; } -export function g14PrometheusManifest(): Record { +export function legacyRuntimePrometheusManifest(): Record { const namespaceSelector = { matchLabels: observabilityNamespaceLabel() }; const monitorSelector = { matchLabels: { "hwlab.pikastech.local/monitoring": "enabled" } }; return { @@ -42,7 +42,7 @@ export function g14PrometheusManifest(): Record { apiVersion: "v1", kind: "Namespace", metadata: { - name: G14_OBSERVABILITY_NAMESPACE, + name: LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE, labels: { ...observabilityNamespaceLabel(), ...observabilityLabels("namespace"), @@ -53,7 +53,7 @@ export function g14PrometheusManifest(): Record { apiVersion: "v1", kind: "Namespace", metadata: { - name: V02_RUNTIME_NAMESPACE, + name: DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE, labels: observabilityNamespaceLabel(), }, }, @@ -61,8 +61,8 @@ export function g14PrometheusManifest(): Record { apiVersion: "v1", kind: "ServiceAccount", metadata: { - name: G14_PROMETHEUS_SERVICE_ACCOUNT, - namespace: G14_OBSERVABILITY_NAMESPACE, + name: LEGACY_RUNTIME_PROMETHEUS_SERVICE_ACCOUNT, + namespace: LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE, labels: observabilityLabels("prometheus"), }, }, @@ -70,7 +70,7 @@ export function g14PrometheusManifest(): Record { apiVersion: "rbac.authorization.k8s.io/v1", kind: "ClusterRole", metadata: { - name: G14_PROMETHEUS_SERVICE_ACCOUNT, + name: LEGACY_RUNTIME_PROMETHEUS_SERVICE_ACCOUNT, labels: observabilityLabels("prometheus"), }, rules: [ @@ -99,32 +99,32 @@ export function g14PrometheusManifest(): Record { apiVersion: "rbac.authorization.k8s.io/v1", kind: "ClusterRoleBinding", metadata: { - name: G14_PROMETHEUS_SERVICE_ACCOUNT, + name: LEGACY_RUNTIME_PROMETHEUS_SERVICE_ACCOUNT, labels: observabilityLabels("prometheus"), }, roleRef: { apiGroup: "rbac.authorization.k8s.io", kind: "ClusterRole", - name: G14_PROMETHEUS_SERVICE_ACCOUNT, + name: LEGACY_RUNTIME_PROMETHEUS_SERVICE_ACCOUNT, }, subjects: [{ kind: "ServiceAccount", - name: G14_PROMETHEUS_SERVICE_ACCOUNT, - namespace: G14_OBSERVABILITY_NAMESPACE, + name: LEGACY_RUNTIME_PROMETHEUS_SERVICE_ACCOUNT, + namespace: LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE, }], }, { apiVersion: "monitoring.coreos.com/v1", kind: "Prometheus", metadata: { - name: G14_PROMETHEUS_NAME, - namespace: G14_OBSERVABILITY_NAMESPACE, + name: LEGACY_RUNTIME_PROMETHEUS_NAME, + namespace: LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE, labels: observabilityLabels("prometheus"), }, spec: { replicas: 1, - version: G14_PROMETHEUS_VERSION, - serviceAccountName: G14_PROMETHEUS_SERVICE_ACCOUNT, + version: LEGACY_RUNTIME_PROMETHEUS_VERSION, + serviceAccountName: LEGACY_RUNTIME_PROMETHEUS_SERVICE_ACCOUNT, scrapeInterval: "30s", evaluationInterval: "30s", retention: "7d", @@ -155,14 +155,14 @@ export function g14PrometheusManifest(): Record { apiVersion: "v1", kind: "Service", metadata: { - name: G14_PROMETHEUS_SERVICE, - namespace: G14_OBSERVABILITY_NAMESPACE, + name: LEGACY_RUNTIME_PROMETHEUS_SERVICE, + namespace: LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE, labels: observabilityLabels("query"), }, spec: { type: "ClusterIP", selector: { - prometheus: G14_PROMETHEUS_NAME, + prometheus: LEGACY_RUNTIME_PROMETHEUS_NAME, }, ports: [{ name: "web", @@ -240,7 +240,7 @@ export function prometheusReady(prometheus: Record): boolean { } export function observabilityQueryPath(promql: string): string { - return `/api/v1/namespaces/${G14_OBSERVABILITY_NAMESPACE}/services/http:${G14_PROMETHEUS_SERVICE}:9090/proxy/api/v1/query?query=${encodeURIComponent(promql)}`; + return `/api/v1/namespaces/${LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE}/services/http:${LEGACY_RUNTIME_PROMETHEUS_SERVICE}:9090/proxy/api/v1/query?query=${encodeURIComponent(promql)}`; } export function arrayRecords(value: unknown): Record[] { @@ -339,7 +339,7 @@ export function metricValueMatches(actual: string | null, expected: string): boo return Number.isFinite(actualNumber) && Number.isFinite(expectedNumber) && actualNumber === expectedNumber; } -export function g14ObservabilityQueryAssertion(parsed: unknown, expectedCount?: number, expectedValue?: string): Record | null { +export function legacyRuntimeObservabilityQueryAssertion(parsed: unknown, expectedCount?: number, expectedValue?: string): Record | null { if (expectedCount === undefined && expectedValue === undefined) return null; const series = prometheusResultItems(parsed); const actualCount = series.length; @@ -368,9 +368,9 @@ export function g14ObservabilityQueryAssertion(parsed: unknown, expectedCount?: } export function observabilitySemanticName(promql: string): string | null { - if (promql === V02_OBSERVABILITY_QUERIES.scrapeReachable) return "scrapeReachable"; - if (promql === V02_OBSERVABILITY_QUERIES.sidecarServing) return "sidecarServing"; - if (promql === V02_OBSERVABILITY_QUERIES.businessHealthProbe) return "businessHealthProbe"; + if (promql === DEFAULT_RUNTIME_LANE_OBSERVABILITY_QUERIES.scrapeReachable) return "scrapeReachable"; + if (promql === DEFAULT_RUNTIME_LANE_OBSERVABILITY_QUERIES.sidecarServing) return "sidecarServing"; + if (promql === DEFAULT_RUNTIME_LANE_OBSERVABILITY_QUERIES.businessHealthProbe) return "businessHealthProbe"; return null; } @@ -546,7 +546,7 @@ export function buildObservabilityLevelSummary(targets: Record[ const scrapeDurations = observedTargets.map((target) => targetMetricValue(target, "scrapeDurationSeconds")).filter((item): item is number => item !== null); const samplesScraped = observedTargets.map((target) => targetMetricValue(target, "scrapeSamplesScraped")).filter((item): item is number => item !== null); const resourceSnapshots = observedTargets.map((target) => record(target.resource)).filter((item) => Object.keys(item).length > 0); - const resourceVisible = resourceSnapshots.length === V02_OBSERVABILITY_EXPECTED_TARGET_COUNT; + const resourceVisible = resourceSnapshots.length === DEFAULT_RUNTIME_LANE_OBSERVABILITY_EXPECTED_TARGET_COUNT; const resourceValue = (snapshot: Record, path: string[]): number | null => numericValue(nested(snapshot, path)); const resourceTotals = { totalCpuMillicores: resourceSnapshots.map((item) => resourceValue(item, ["total", "cpuMillicores"])).filter((item): item is number => item !== null), @@ -584,7 +584,7 @@ export function buildObservabilityLevelSummary(targets: Record[ ]; return { observedTargetCount: observedTargets.length, - expectedTargetCount: V02_OBSERVABILITY_EXPECTED_TARGET_COUNT, + expectedTargetCount: DEFAULT_RUNTIME_LANE_OBSERVABILITY_EXPECTED_TARGET_COUNT, healthProbeDuration: secondsStats(healthDurations), scrapeDuration: secondsStats(scrapeDurations), scrapeSamplesScraped: { @@ -596,7 +596,7 @@ export function buildObservabilityLevelSummary(targets: Record[ resourceUsage: { source: "metrics.k8s.io/v1beta1", observedTargetCount: resourceSnapshots.length, - expectedTargetCount: V02_OBSERVABILITY_EXPECTED_TARGET_COUNT, + expectedTargetCount: DEFAULT_RUNTIME_LANE_OBSERVABILITY_EXPECTED_TARGET_COUNT, totalCpuMillicores: numberStats(resourceTotals.totalCpuMillicores), totalMemoryMiB: numberStats(resourceTotals.totalMemoryMiB), businessCpuMillicores: numberStats(resourceTotals.businessCpuMillicores), @@ -756,9 +756,9 @@ export function looksLikePrometheusText(body: string, contentType: string): bool return type.includes("text/plain") || type.length === 0; } -export function g14ObservabilityStatus(): Record { +export function legacyRuntimeObservabilityStatus(): Record { const startedAtMs = Date.now(); - const queryPath = `/api/v1/namespaces/${G14_OBSERVABILITY_NAMESPACE}/services/http:${G14_PROMETHEUS_SERVICE}:9090/proxy/api/v1/query?query=${encodeURIComponent("up")}`; + const queryPath = `/api/v1/namespaces/${LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE}/services/http:${LEGACY_RUNTIME_PROMETHEUS_SERVICE}:9090/proxy/api/v1/query?query=${encodeURIComponent("up")}`; const crds = [ "servicemonitors.monitoring.coreos.com", "podmonitors.monitoring.coreos.com", @@ -776,18 +776,18 @@ export function g14ObservabilityStatus(): Record { " code=$?", " printf '\\n__UNIDESK_SECTION_END__ %s exit=%s\\n' \"$name\" \"$code\"", "}", - `section namespace kubectl get namespace ${shellQuote(G14_OBSERVABILITY_NAMESPACE)} -o json`, - `section discoveryNamespace kubectl get namespace ${shellQuote(V02_RUNTIME_NAMESPACE)} -o json`, + `section namespace kubectl get namespace ${shellQuote(LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE)} -o json`, + `section discoveryNamespace kubectl get namespace ${shellQuote(DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE)} -o json`, `section crds kubectl get crd ${crds.map(shellQuote).join(" ")} -o 'jsonpath={range .items[*]}{.metadata.name}{"\\n"}{end}'`, - `section operator kubectl get deploy -n ${shellQuote(G14_OBSERVABILITY_NAMESPACE)} prometheus-operator -o json`, - `section operatorPods kubectl get pods -n ${shellQuote(G14_OBSERVABILITY_NAMESPACE)} -l app.kubernetes.io/name=prometheus-operator -o 'jsonpath={range .items[*]}{.metadata.name}{"\\t"}{.status.phase}{"\\t"}{range .status.containerStatuses[*]}{.ready}{","}{end}{"\\n"}{end}'`, - `section prometheus kubectl get prometheus -n ${shellQuote(G14_OBSERVABILITY_NAMESPACE)} ${shellQuote(G14_PROMETHEUS_NAME)} -o json`, - `section prometheusPods kubectl get pods -n ${shellQuote(G14_OBSERVABILITY_NAMESPACE)} -l prometheus=${shellQuote(G14_PROMETHEUS_NAME)} -o 'jsonpath={range .items[*]}{.metadata.name}{"\\t"}{.status.phase}{"\\t"}{range .status.containerStatuses[*]}{.ready}{","}{end}{"\\n"}{end}'`, - `section prometheusService kubectl get service -n ${shellQuote(G14_OBSERVABILITY_NAMESPACE)} ${shellQuote(G14_PROMETHEUS_SERVICE)} -o json`, - `section workloadMonitors kubectl get servicemonitor,prometheusrule -n ${shellQuote(V02_RUNTIME_NAMESPACE)} -l hwlab.pikastech.local/monitoring=enabled -o json`, + `section operator kubectl get deploy -n ${shellQuote(LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE)} prometheus-operator -o json`, + `section operatorPods kubectl get pods -n ${shellQuote(LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE)} -l app.kubernetes.io/name=prometheus-operator -o 'jsonpath={range .items[*]}{.metadata.name}{"\\t"}{.status.phase}{"\\t"}{range .status.containerStatuses[*]}{.ready}{","}{end}{"\\n"}{end}'`, + `section prometheus kubectl get prometheus -n ${shellQuote(LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE)} ${shellQuote(LEGACY_RUNTIME_PROMETHEUS_NAME)} -o json`, + `section prometheusPods kubectl get pods -n ${shellQuote(LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE)} -l prometheus=${shellQuote(LEGACY_RUNTIME_PROMETHEUS_NAME)} -o 'jsonpath={range .items[*]}{.metadata.name}{"\\t"}{.status.phase}{"\\t"}{range .status.containerStatuses[*]}{.ready}{","}{end}{"\\n"}{end}'`, + `section prometheusService kubectl get service -n ${shellQuote(LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE)} ${shellQuote(LEGACY_RUNTIME_PROMETHEUS_SERVICE)} -o json`, + `section workloadMonitors kubectl get servicemonitor,prometheusrule -n ${shellQuote(DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE)} -l hwlab.pikastech.local/monitoring=enabled -o json`, `section query kubectl get --raw ${shellQuote(queryPath)}`, ].join("\n"); - const bundle = g14K3s(["sh", "--", script], 120_000); + const bundle = legacyRuntimeK3s(["sh", "--", script], 120_000); const sections = parseShellSections(statusText(bundle)); const namespace = parseSectionJson(sections.namespace); const discoveryNamespace = parseSectionJson(sections.discoveryNamespace); @@ -813,17 +813,17 @@ export function g14ObservabilityStatus(): Record { return { ok, command: "hwlab g14 observability status", - namespace: G14_OBSERVABILITY_NAMESPACE, + namespace: LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE, mode: "status", elapsedMs: Date.now() - startedAtMs, versions: { - prometheusOperator: G14_PROMETHEUS_OPERATOR_VERSION, - prometheus: G14_PROMETHEUS_VERSION, - operatorBundle: G14_PROMETHEUS_OPERATOR_RELEASE_ASSET, + prometheusOperator: LEGACY_RUNTIME_PROMETHEUS_OPERATOR_VERSION, + prometheus: LEGACY_RUNTIME_PROMETHEUS_VERSION, + operatorBundle: LEGACY_RUNTIME_PROMETHEUS_OPERATOR_RELEASE_ASSET, }, discovery: { namespaceLabel, - workloadNamespace: V02_RUNTIME_NAMESPACE, + workloadNamespace: DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE, workloadNamespaceLabel, selectorLabel: "hwlab.pikastech.local/monitoring=enabled", }, @@ -849,8 +849,8 @@ export function g14ObservabilityStatus(): Record { }, prometheus: { ok: prometheusExists && prometheusIsReady, - name: G14_PROMETHEUS_NAME, - service: G14_PROMETHEUS_SERVICE, + name: LEGACY_RUNTIME_PROMETHEUS_NAME, + service: LEGACY_RUNTIME_PROMETHEUS_SERVICE, serviceExists: Object.keys(prometheusService).length > 0, ready: prometheusIsReady, conditions: Array.isArray(record(prometheus.status).conditions) ? record(prometheus.status).conditions : [], @@ -863,7 +863,7 @@ export function g14ObservabilityStatus(): Record { }, workloadMonitors: { ok: shellSectionOk(sections.workloadMonitors), - namespace: V02_RUNTIME_NAMESPACE, + namespace: DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE, count: workloadMonitorItems.length, items: workloadMonitorItems.map((item) => ({ kind: item.kind ?? null, @@ -888,7 +888,7 @@ export function g14ObservabilityStatus(): Record { }; } -export function g14ObservabilityApplyScript(options: G14ObservabilityOptions, manifestB64: string): string { +export function legacyRuntimeObservabilityApplyScript(options: LegacyRuntimeObservabilityOptions, manifestB64: string): string { const dryRunArg = options.dryRun ? "--dry-run=server" : ""; const stackDryRunCommand = options.dryRun ? [ @@ -904,22 +904,22 @@ export function g14ObservabilityApplyScript(options: G14ObservabilityOptions, ma "kubectl apply --dry-run=client --validate=false -f \"$core_stack_path\"", "echo prometheus_cr_dry_run=skipped_until_monitoring_crds_are_installed", ].join("\n") - : `kubectl apply --server-side --force-conflicts --field-manager=${shellQuote(G14_OBSERVABILITY_FIELD_MANAGER)} -f "$stack_path"`; + : `kubectl apply --server-side --force-conflicts --field-manager=${shellQuote(LEGACY_RUNTIME_OBSERVABILITY_FIELD_MANAGER)} -f "$stack_path"`; const preStackWaitCommands = options.dryRun ? "echo observability_wait=skipped_dry_run" : [ "kubectl wait --for=condition=Established --timeout=45s crd/servicemonitors.monitoring.coreos.com crd/podmonitors.monitoring.coreos.com crd/prometheusrules.monitoring.coreos.com crd/prometheuses.monitoring.coreos.com", - `kubectl -n ${shellQuote(G14_OBSERVABILITY_NAMESPACE)} get deploy/prometheus-operator -o name`, + `kubectl -n ${shellQuote(LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE)} get deploy/prometheus-operator -o name`, ].join("\n"); const postStackWaitCommands = options.dryRun ? "echo prometheus_wait=skipped_dry_run" : "echo prometheus_wait=deferred_to_status_command"; return [ "set -eu", - `namespace=${shellQuote(G14_OBSERVABILITY_NAMESPACE)}`, - `bundle_url=${shellQuote(G14_PROMETHEUS_OPERATOR_RELEASE_ASSET)}`, - `operator_version=${shellQuote(G14_PROMETHEUS_OPERATOR_VERSION)}`, - `prometheus_version=${shellQuote(G14_PROMETHEUS_VERSION)}`, + `namespace=${shellQuote(LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE)}`, + `bundle_url=${shellQuote(LEGACY_RUNTIME_PROMETHEUS_OPERATOR_RELEASE_ASSET)}`, + `operator_version=${shellQuote(LEGACY_RUNTIME_PROMETHEUS_OPERATOR_VERSION)}`, + `prometheus_version=${shellQuote(LEGACY_RUNTIME_PROMETHEUS_VERSION)}`, `stack_b64=${shellQuote(manifestB64)}`, "tmpdir=$(mktemp -d /tmp/g14-observability-XXXXXX)", "cleanup() { rm -rf \"$tmpdir\"; }", @@ -938,14 +938,14 @@ export function g14ObservabilityApplyScript(options: G14ObservabilityOptions, ma "cat > \"$tmpdir/kustomization.yaml\" <<'YAML'", "apiVersion: kustomize.config.k8s.io/v1beta1", "kind: Kustomization", - `namespace: ${G14_OBSERVABILITY_NAMESPACE}`, + `namespace: ${LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE}`, "resources:", "- operator-bundle.yaml", "YAML", "kubectl kustomize \"$tmpdir\" > \"$operator_path\"", "grep -q 'namespace: devops-infra' \"$operator_path\"", - `kubectl create namespace ${shellQuote(G14_OBSERVABILITY_NAMESPACE)} --dry-run=client -o yaml | kubectl apply --server-side --force-conflicts --field-manager=${shellQuote(G14_OBSERVABILITY_FIELD_MANAGER)} ${dryRunArg} -f -`, - `kubectl apply --server-side --force-conflicts --field-manager=${shellQuote(G14_OBSERVABILITY_FIELD_MANAGER)} ${dryRunArg} -f "$operator_path"`, + `kubectl create namespace ${shellQuote(LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE)} --dry-run=client -o yaml | kubectl apply --server-side --force-conflicts --field-manager=${shellQuote(LEGACY_RUNTIME_OBSERVABILITY_FIELD_MANAGER)} ${dryRunArg} -f -`, + `kubectl apply --server-side --force-conflicts --field-manager=${shellQuote(LEGACY_RUNTIME_OBSERVABILITY_FIELD_MANAGER)} ${dryRunArg} -f "$operator_path"`, preStackWaitCommands, stackDryRunCommand, postStackWaitCommands, @@ -953,36 +953,36 @@ export function g14ObservabilityApplyScript(options: G14ObservabilityOptions, ma ].join("\n"); } -export function runG14ObservabilityApply(options: G14ObservabilityOptions): Record { +export function runLegacyRuntimeObservabilityApply(options: LegacyRuntimeObservabilityOptions): Record { const startedAtMs = Date.now(); - const manifest = g14PrometheusManifest(); + const manifest = legacyRuntimePrometheusManifest(); const manifestB64 = Buffer.from(JSON.stringify(manifest), "utf8").toString("base64"); - const script = g14ObservabilityApplyScript(options, manifestB64); - const result = g14K3s(["sh", "--", script], options.timeoutSeconds * 1000 + 90_000); + const script = legacyRuntimeObservabilityApplyScript(options, manifestB64); + const result = legacyRuntimeK3s(["sh", "--", script], options.timeoutSeconds * 1000 + 90_000); const ok = isCommandSuccess(result); return { ok, command: "hwlab g14 observability apply", mode: options.dryRun ? "dry-run" : "confirmed-apply", - namespace: G14_OBSERVABILITY_NAMESPACE, + namespace: LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE, versions: { - prometheusOperator: G14_PROMETHEUS_OPERATOR_VERSION, - prometheus: G14_PROMETHEUS_VERSION, - operatorBundle: G14_PROMETHEUS_OPERATOR_RELEASE_ASSET, + prometheusOperator: LEGACY_RUNTIME_PROMETHEUS_OPERATOR_VERSION, + prometheus: LEGACY_RUNTIME_PROMETHEUS_VERSION, + operatorBundle: LEGACY_RUNTIME_PROMETHEUS_OPERATOR_RELEASE_ASSET, }, manifest: options.dryRun ? manifest : undefined, elapsedMs: Date.now() - startedAtMs, result: compactCommandResult(result), - status: ok && !options.dryRun ? g14ObservabilityStatus() : undefined, + status: ok && !options.dryRun ? legacyRuntimeObservabilityStatus() : undefined, next: options.dryRun ? { apply: "bun scripts/cli.ts hwlab g14 observability apply --confirm" } : { status: "bun scripts/cli.ts hwlab g14 observability status", query: 'bun scripts/cli.ts hwlab g14 observability query --promql \'up{namespace="hwlab-v02"}\'' }, }; } -export function g14PrometheusQuery(promql: string, timeoutMs: number): { serviceProxyPath: string; result: CommandJsonResult; parsed: Record; ok: boolean } { +export function legacyRuntimePrometheusQuery(promql: string, timeoutMs: number): { serviceProxyPath: string; result: CommandJsonResult; parsed: Record; ok: boolean } { const serviceProxyPath = observabilityQueryPath(promql); - const result = g14K3s(["kubectl", "get", "--raw", serviceProxyPath], timeoutMs); + const result = legacyRuntimeK3s(["kubectl", "get", "--raw", serviceProxyPath], timeoutMs); const parsed = (() => { try { return record(JSON.parse(statusText(result)) as unknown); @@ -993,9 +993,9 @@ export function g14PrometheusQuery(promql: string, timeoutMs: number): { service return { serviceProxyPath, result, parsed, ok: isCommandSuccess(result) && parsed.status === "success" }; } -export function runG14ObservabilityQuery(options: G14ObservabilityOptions): Record { - const query = g14PrometheusQuery(options.query, options.timeoutSeconds * 1000); - const assertion = g14ObservabilityQueryAssertion(query.parsed, options.expectCount, options.expectValue); +export function runLegacyRuntimeObservabilityQuery(options: LegacyRuntimeObservabilityOptions): Record { + const query = legacyRuntimePrometheusQuery(options.query, options.timeoutSeconds * 1000); + const assertion = legacyRuntimeObservabilityQueryAssertion(query.parsed, options.expectCount, options.expectValue); const semantic = observabilitySemanticName(options.query); const resultCount = prometheusResultItems(query.parsed).length; const hasAssertion = options.expectCount !== undefined || options.expectValue !== undefined; @@ -1004,8 +1004,8 @@ export function runG14ObservabilityQuery(options: G14ObservabilityOptions): Reco return { ok, command: "hwlab g14 observability query", - namespace: G14_OBSERVABILITY_NAMESPACE, - service: G14_PROMETHEUS_SERVICE, + namespace: LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE, + service: LEGACY_RUNTIME_PROMETHEUS_SERVICE, promql: options.query, semantic, serviceProxyPath: query.serviceProxyPath, @@ -1031,9 +1031,9 @@ export function runG14ObservabilityQuery(options: G14ObservabilityOptions): Reco }; } -export function runG14ObservabilityTargets(options: G14ObservabilityOptions): Record { +export function runLegacyRuntimeObservabilityTargets(options: LegacyRuntimeObservabilityOptions): Record { const startedAtMs = Date.now(); - const queryCommands = Object.entries(V02_OBSERVABILITY_QUERIES).map(([name, promql]) => `section query_${name} kubectl get --raw ${shellQuote(observabilityQueryPath(promql))}`); + const queryCommands = Object.entries(DEFAULT_RUNTIME_LANE_OBSERVABILITY_QUERIES).map(([name, promql]) => `section query_${name} kubectl get --raw ${shellQuote(observabilityQueryPath(promql))}`); const script = [ "set +e", "section() {", @@ -1044,23 +1044,23 @@ export function runG14ObservabilityTargets(options: G14ObservabilityOptions): Re " code=$?", " printf '\\n__UNIDESK_SECTION_END__ %s exit=%s\\n' \"$name\" \"$code\"", "}", - `section pods kubectl get pods -n ${shellQuote(V02_RUNTIME_NAMESPACE)} -o json`, - `section monitors kubectl get servicemonitor,podmonitor,prometheusrule -n ${shellQuote(V02_RUNTIME_NAMESPACE)} -l hwlab.pikastech.local/monitoring=enabled -o json`, - `section podResourceMetrics kubectl get --raw ${shellQuote(`/apis/metrics.k8s.io/v1beta1/namespaces/${V02_RUNTIME_NAMESPACE}/pods`)}`, + `section pods kubectl get pods -n ${shellQuote(DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE)} -o json`, + `section monitors kubectl get servicemonitor,podmonitor,prometheusrule -n ${shellQuote(DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE)} -l hwlab.pikastech.local/monitoring=enabled -o json`, + `section podResourceMetrics kubectl get --raw ${shellQuote(`/apis/metrics.k8s.io/v1beta1/namespaces/${DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE}/pods`)}`, ...queryCommands, ].join("\n"); - const bundle = g14K3s(["sh", "--", script], options.timeoutSeconds * 1000); + const bundle = legacyRuntimeK3s(["sh", "--", script], options.timeoutSeconds * 1000); const sections = parseShellSections(statusText(bundle)); const pods = k8sItems(parseSectionJson(sections.pods)); const monitors = k8sItems(parseSectionJson(sections.monitors)); const podResourceMetrics = k8sItems(parseSectionJson(sections.podResourceMetrics)).map(podResourceMetricSummary); - const parsedQueries = Object.fromEntries(Object.entries(V02_OBSERVABILITY_QUERIES).map(([name]) => [name, parseSectionJson(sections[`query_${name}`])])); + const parsedQueries = Object.fromEntries(Object.entries(DEFAULT_RUNTIME_LANE_OBSERVABILITY_QUERIES).map(([name]) => [name, parseSectionJson(sections[`query_${name}`])])); const metricSeries = Object.fromEntries(Object.entries(parsedQueries).map(([name, parsed]) => [name, prometheusResultItems(parsed)])); - const booleanQueryNames = new Set(V02_OBSERVABILITY_BOOLEAN_QUERY_NAMES); - const closeoutQueryNames = new Set(V02_OBSERVABILITY_CLOSEOUT_QUERY_NAMES); + const booleanQueryNames = new Set(DEFAULT_RUNTIME_LANE_OBSERVABILITY_BOOLEAN_QUERY_NAMES); + const closeoutQueryNames = new Set(DEFAULT_RUNTIME_LANE_OBSERVABILITY_CLOSEOUT_QUERY_NAMES); const assertions = Object.fromEntries(Object.entries(parsedQueries).map(([name, parsed]) => [ name, - g14ObservabilityQueryAssertion(parsed, V02_OBSERVABILITY_EXPECTED_TARGET_COUNT, booleanQueryNames.has(name) ? "1" : undefined), + legacyRuntimeObservabilityQueryAssertion(parsed, DEFAULT_RUNTIME_LANE_OBSERVABILITY_EXPECTED_TARGET_COUNT, booleanQueryNames.has(name) ? "1" : undefined), ])); const targets = attachResourceMetricsToTargets(mergeObservabilityTargets(pods, monitors, metricSeries), podResourceMetrics); const compactTargets = targets.map(compactObservabilityTarget); @@ -1070,24 +1070,24 @@ export function runG14ObservabilityTargets(options: G14ObservabilityOptions): Re .filter((sidecar) => Object.keys(sidecar).length > 0); const notReadySidecars = sidecars.filter((sidecar) => sidecar.sidecarReady !== true || sidecar.podReady !== true); const restartProblems = sidecars.filter((sidecar) => (numericValue(sidecar.restartCount) ?? 0) > 0); - const queryOk = V02_OBSERVABILITY_CLOSEOUT_QUERY_NAMES.every((name) => record(assertions[name]).ok === true); - const sidecarOk = targets.length === V02_OBSERVABILITY_EXPECTED_TARGET_COUNT - && sidecars.length === V02_OBSERVABILITY_EXPECTED_TARGET_COUNT + const queryOk = DEFAULT_RUNTIME_LANE_OBSERVABILITY_CLOSEOUT_QUERY_NAMES.every((name) => record(assertions[name]).ok === true); + const sidecarOk = targets.length === DEFAULT_RUNTIME_LANE_OBSERVABILITY_EXPECTED_TARGET_COUNT + && sidecars.length === DEFAULT_RUNTIME_LANE_OBSERVABILITY_EXPECTED_TARGET_COUNT && notReadySidecars.length === 0; const monitorsOk = shellSectionOk(sections.monitors) && monitors.length > 0; const resourceOk = shellSectionOk(sections.podResourceMetrics) && podResourceMetrics.filter((item) => { const serviceId = stringOrNull(item.serviceId); - return serviceId !== null && V02_OBSERVABILITY_SERVICE_IDS.includes(serviceId); - }).length === V02_OBSERVABILITY_EXPECTED_TARGET_COUNT; + return serviceId !== null && DEFAULT_RUNTIME_LANE_OBSERVABILITY_SERVICE_IDS.includes(serviceId); + }).length === DEFAULT_RUNTIME_LANE_OBSERVABILITY_EXPECTED_TARGET_COUNT; const ok = isCommandSuccess(bundle) && shellSectionOk(sections.pods) && monitorsOk && queryOk && sidecarOk && resourceOk; return { ok, command: "hwlab g14 observability targets", lane: options.lane, - namespace: V02_RUNTIME_NAMESPACE, + namespace: DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE, elapsedMs: Date.now() - startedAtMs, - expectedTargetCount: V02_OBSERVABILITY_EXPECTED_TARGET_COUNT, + expectedTargetCount: DEFAULT_RUNTIME_LANE_OBSERVABILITY_EXPECTED_TARGET_COUNT, targetCount: targets.length, levelSummary, targets: compactTargets, @@ -1109,14 +1109,14 @@ export function runG14ObservabilityTargets(options: G14ObservabilityOptions): Re source: "metrics.k8s.io/v1beta1", observedTargetCount: podResourceMetrics.filter((item) => { const serviceId = stringOrNull(item.serviceId); - return serviceId !== null && V02_OBSERVABILITY_SERVICE_IDS.includes(serviceId); + return serviceId !== null && DEFAULT_RUNTIME_LANE_OBSERVABILITY_SERVICE_IDS.includes(serviceId); }).length, - expectedTargetCount: V02_OBSERVABILITY_EXPECTED_TARGET_COUNT, + expectedTargetCount: DEFAULT_RUNTIME_LANE_OBSERVABILITY_EXPECTED_TARGET_COUNT, sectionOk: shellSectionOk(sections.podResourceMetrics), stderr: shellSectionOk(sections.podResourceMetrics) ? "" : commandErrorSummary(bundle), }, queries: Object.fromEntries(Object.entries(parsedQueries).map(([name, parsed]) => [name, { - promql: record(V02_OBSERVABILITY_QUERIES)[name], + promql: record(DEFAULT_RUNTIME_LANE_OBSERVABILITY_QUERIES)[name], resultType: nested(parsed, ["data", "resultType"]) ?? null, resultCount: prometheusResultItems(parsed).length, assertion: assertions[name], @@ -1124,7 +1124,7 @@ export function runG14ObservabilityTargets(options: G14ObservabilityOptions): Re reason: closeoutQueryNames.has(name) ? "target-summary-uses-assertion-and-target-rows" : "auxiliary-metric-summarized-in-levelSummary", summaryField: closeoutQueryNames.has(name) ? "targets" : "levelSummary", drillDownCommand: closeoutQueryNames.has(name) - ? `bun scripts/cli.ts hwlab g14 observability query --promql ${shellQuote(String(record(V02_OBSERVABILITY_QUERIES)[name]))} --expect-count ${V02_OBSERVABILITY_EXPECTED_TARGET_COUNT} --expect-value 1` + ? `bun scripts/cli.ts hwlab g14 observability query --promql ${shellQuote(String(record(DEFAULT_RUNTIME_LANE_OBSERVABILITY_QUERIES)[name]))} --expect-count ${DEFAULT_RUNTIME_LANE_OBSERVABILITY_EXPECTED_TARGET_COUNT} --expect-value 1` : undefined, }, sectionOk: shellSectionOk(sections[`query_${name}`]), @@ -1135,7 +1135,7 @@ export function runG14ObservabilityTargets(options: G14ObservabilityOptions): Re }; } -export function runG14ObservabilityBoundary(options: G14ObservabilityOptions): Record { +export function runLegacyRuntimeObservabilityBoundary(options: LegacyRuntimeObservabilityOptions): Record { const startedAtMs = Date.now(); const script = [ "set +e", @@ -1147,20 +1147,20 @@ export function runG14ObservabilityBoundary(options: G14ObservabilityOptions): R " code=$?", " printf '\\n__UNIDESK_SECTION_END__ %s exit=%s\\n' \"$name\" \"$code\"", "}", - `section workloadMonitoring kubectl get servicemonitor,podmonitor,prometheusrule,prometheus,alertmanager -n ${shellQuote(V02_RUNTIME_NAMESPACE)} -o json`, - `section infraControlPlane kubectl get prometheus,alertmanager -n ${shellQuote(G14_OBSERVABILITY_NAMESPACE)} -o json`, + `section workloadMonitoring kubectl get servicemonitor,podmonitor,prometheusrule,prometheus,alertmanager -n ${shellQuote(DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE)} -o json`, + `section infraControlPlane kubectl get prometheus,alertmanager -n ${shellQuote(LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE)} -o json`, ].join("\n"); - const bundle = g14K3s(["sh", "--", script], options.timeoutSeconds * 1000); + const bundle = legacyRuntimeK3s(["sh", "--", script], options.timeoutSeconds * 1000); const sections = parseShellSections(statusText(bundle)); const workloadItems = k8sItems(parseSectionJson(sections.workloadMonitoring)); const infraItems = k8sItems(parseSectionJson(sections.infraControlPlane)); const forbiddenWorkloadControlPlane = workloadItems.filter((item) => item.kind === "Prometheus" || item.kind === "Alertmanager"); const allowedWorkloadDeclarations = workloadItems.filter((item) => item.kind === "ServiceMonitor" || item.kind === "PodMonitor" || item.kind === "PrometheusRule"); const namespaceBoundaryOk = shellSectionOk(sections.workloadMonitoring) && forbiddenWorkloadControlPlane.length === 0; - const infraControlPlaneOk = shellSectionOk(sections.infraControlPlane) && infraItems.some((item) => item.kind === "Prometheus" && k8sMetadataName(item) === G14_PROMETHEUS_NAME); + const infraControlPlaneOk = shellSectionOk(sections.infraControlPlane) && infraItems.some((item) => item.kind === "Prometheus" && k8sMetadataName(item) === LEGACY_RUNTIME_PROMETHEUS_NAME); const publicProbes = [ - publicMetricsProbe("hwlab-v02-cloud-web", `${V02_CLOUD_WEB_URL}/metrics`), - publicMetricsProbe("hwlab-v02-cloud-api", `${V02_CLOUD_API_URL}/metrics`), + publicMetricsProbe("hwlab-v02-cloud-web", `${DEFAULT_RUNTIME_LANE_CLOUD_WEB_URL}/metrics`), + publicMetricsProbe("hwlab-v02-cloud-api", `${DEFAULT_RUNTIME_LANE_CLOUD_API_URL}/metrics`), ]; const publicMetricsExposureOk = publicProbes.every((probe) => probe.ok === true && probe.exposed !== true); const ok = isCommandSuccess(bundle) && namespaceBoundaryOk && infraControlPlaneOk && publicMetricsExposureOk; @@ -1171,7 +1171,7 @@ export function runG14ObservabilityBoundary(options: G14ObservabilityOptions): R elapsedMs: Date.now() - startedAtMs, namespaceBoundary: { ok: namespaceBoundaryOk, - workloadNamespace: V02_RUNTIME_NAMESPACE, + workloadNamespace: DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE, allowedKinds: ["ServiceMonitor", "PodMonitor", "PrometheusRule"], allowedDeclarationCount: allowedWorkloadDeclarations.length, allowedDeclarations: monitorSummaries(allowedWorkloadDeclarations), @@ -1182,7 +1182,7 @@ export function runG14ObservabilityBoundary(options: G14ObservabilityOptions): R }, infraControlPlane: { ok: infraControlPlaneOk, - namespace: G14_OBSERVABILITY_NAMESPACE, + namespace: LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE, items: infraItems.map((item) => ({ kind: item.kind, name: k8sMetadataName(item) })), sectionOk: shellSectionOk(sections.infraControlPlane), }, @@ -1213,11 +1213,11 @@ export function closeoutAdvice(summary: Record): string[] { return advice; } -export function runG14ObservabilityCloseout(options: G14ObservabilityOptions): Record { +export function runLegacyRuntimeObservabilityCloseout(options: LegacyRuntimeObservabilityOptions): Record { const startedAtMs = Date.now(); - const status = g14ObservabilityStatus(); - const targets = runG14ObservabilityTargets(options); - const boundary = runG14ObservabilityBoundary(options); + const status = legacyRuntimeObservabilityStatus(); + const targets = runLegacyRuntimeObservabilityTargets(options); + const boundary = runLegacyRuntimeObservabilityBoundary(options); const targetQueries = record(targets.queries); const queryOk = (name: string): boolean => record(record(targetQueries[name]).assertion).ok === true; const sidecarsOk = record(record(targets.sidecars)).ok === true; @@ -1241,7 +1241,7 @@ export function runG14ObservabilityCloseout(options: G14ObservabilityOptions): R const ok = Object.entries(summary).every(([key, value]) => key === "workloadMonitorCount" ? numericValue(value) !== null && Number(value) > 0 : key === "observedTargetCount" - ? numericValue(value) === V02_OBSERVABILITY_EXPECTED_TARGET_COUNT + ? numericValue(value) === DEFAULT_RUNTIME_LANE_OBSERVABILITY_EXPECTED_TARGET_COUNT : key === "publicMetricsExposureState" ? value === "denied" : value === "pass"); @@ -1291,9 +1291,9 @@ export function runG14ObservabilityCloseout(options: G14ObservabilityOptions): R status: "bun scripts/cli.ts hwlab g14 observability status", targets: "bun scripts/cli.ts hwlab g14 observability targets --lane v02", boundary: "bun scripts/cli.ts hwlab g14 observability boundary --lane v02", - scrapeReachable: `bun scripts/cli.ts hwlab g14 observability query --promql 'up{namespace=\"hwlab-v02\"}' --expect-count ${V02_OBSERVABILITY_EXPECTED_TARGET_COUNT} --expect-value 1`, - sidecarServing: `bun scripts/cli.ts hwlab g14 observability query --promql 'hwlab_service_up{namespace=\"hwlab-v02\"}' --expect-count ${V02_OBSERVABILITY_EXPECTED_TARGET_COUNT} --expect-value 1`, - businessHealthProbe: `bun scripts/cli.ts hwlab g14 observability query --promql 'hwlab_service_health_probe_success{namespace=\"hwlab-v02\"}' --expect-count ${V02_OBSERVABILITY_EXPECTED_TARGET_COUNT} --expect-value 1`, + scrapeReachable: `bun scripts/cli.ts hwlab g14 observability query --promql 'up{namespace=\"hwlab-v02\"}' --expect-count ${DEFAULT_RUNTIME_LANE_OBSERVABILITY_EXPECTED_TARGET_COUNT} --expect-value 1`, + sidecarServing: `bun scripts/cli.ts hwlab g14 observability query --promql 'hwlab_service_up{namespace=\"hwlab-v02\"}' --expect-count ${DEFAULT_RUNTIME_LANE_OBSERVABILITY_EXPECTED_TARGET_COUNT} --expect-value 1`, + businessHealthProbe: `bun scripts/cli.ts hwlab g14 observability query --promql 'hwlab_service_health_probe_success{namespace=\"hwlab-v02\"}' --expect-count ${DEFAULT_RUNTIME_LANE_OBSERVABILITY_EXPECTED_TARGET_COUNT} --expect-value 1`, }, }, degradedReason: ok ? undefined : "observability-closeout-failed", @@ -1305,11 +1305,11 @@ export function runG14ObservabilityCloseout(options: G14ObservabilityOptions): R }; } -export function runG14Observability(options: G14ObservabilityOptions): Record { - if (options.action === "status") return g14ObservabilityStatus(); - if (options.action === "query") return runG14ObservabilityQuery(options); - if (options.action === "targets") return runG14ObservabilityTargets(options); - if (options.action === "boundary") return runG14ObservabilityBoundary(options); - if (options.action === "closeout") return runG14ObservabilityCloseout(options); - return runG14ObservabilityApply(options); +export function runLegacyRuntimeObservability(options: LegacyRuntimeObservabilityOptions): Record { + if (options.action === "status") return legacyRuntimeObservabilityStatus(); + if (options.action === "query") return runLegacyRuntimeObservabilityQuery(options); + if (options.action === "targets") return runLegacyRuntimeObservabilityTargets(options); + if (options.action === "boundary") return runLegacyRuntimeObservabilityBoundary(options); + if (options.action === "closeout") return runLegacyRuntimeObservabilityCloseout(options); + return runLegacyRuntimeObservabilityApply(options); } diff --git a/scripts/src/hwlab-g14/options.ts b/scripts/src/hwlab-legacy-runtime/options.ts similarity index 83% rename from scripts/src/hwlab-g14/options.ts rename to scripts/src/hwlab-legacy-runtime/options.ts index b8538632..5c649f78 100644 --- a/scripts/src/hwlab-g14/options.ts +++ b/scripts/src/hwlab-legacy-runtime/options.ts @@ -1,6 +1,6 @@ -// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. options module for scripts/src/hwlab-g14.ts. +// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. options module for scripts/src/hwlab-legacy-runtime.ts. -// Moved mechanically from scripts/src/hwlab-g14.ts:289-638 for #903. +// Moved mechanically from scripts/src/hwlab-legacy-runtime.ts:289-638 for #903. import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"; import { dirname, join } from "node:path"; @@ -10,11 +10,11 @@ import { runCommand } from "../command"; import { cancelJob, listJobs, readJob, startJob } from "../jobs"; import { hwlabRequiredNoProxyEntries, hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneIds, hwlabRuntimeLaneSpec, isHwlabRuntimeLane, type HwlabRuntimeLane, type HwlabRuntimeLaneSpec } from "../hwlab-node-lanes"; -import type { G14ControlPlaneOptions, G14GitMirrorOptions, G14LegacyRetirementOptions, G14MonitorLane, G14MonitorOptions, G14ObservabilityOptions, G14RecordRolloutOptions, G14SecretOptions, G14ToolsImageOptions, G14UpstreamImageOptions } from "./types"; +import type { LegacyRuntimeControlPlaneOptions, LegacyRuntimeGitMirrorOptions, LegacyRuntimeLegacyRetirementOptions, LegacyRuntimeMonitorLane, LegacyRuntimeMonitorOptions, LegacyRuntimeObservabilityOptions, LegacyRuntimeRecordRolloutOptions, LegacyRuntimeSecretOptions, LegacyRuntimeToolsImageOptions, LegacyRuntimeUpstreamImageOptions } from "./types"; import { positiveIntegerOption, runtimeLaneMasterAdminApiKeySecretName, runtimeLaneOpenFgaSecretName } from "./remote"; -import { DEFAULT_INTERVAL_SECONDS, DEFAULT_MAX_CYCLES, DEFAULT_TIMEOUT_SECONDS, G14_CI_TOOLS_BASE_TAG, V02_MASTER_ADMIN_API_KEY_SECRET, V02_MASTER_ADMIN_API_KEY_SECRET_KEY, V02_OPENFGA_AUTHN_SECRET_KEY, V02_OPENFGA_DATASTORE_URI_SECRET_KEY, V02_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY, V02_OPENFGA_SECRET } from "./types"; +import { DEFAULT_INTERVAL_SECONDS, DEFAULT_MAX_CYCLES, DEFAULT_TIMEOUT_SECONDS, LEGACY_RUNTIME_CI_TOOLS_BASE_TAG, DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_SECRET, DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_SECRET_KEY, DEFAULT_RUNTIME_LANE_OPENFGA_AUTHN_SECRET_KEY, DEFAULT_RUNTIME_LANE_OPENFGA_DATASTORE_URI_SECRET_KEY, DEFAULT_RUNTIME_LANE_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY, DEFAULT_RUNTIME_LANE_OPENFGA_SECRET } from "./types"; -export function hwlabG14MonitorStateFileName(options: Pick & { lane?: G14MonitorLane }): string { +export function hwlabLegacyRuntimeMonitorStateFileName(options: Pick & { lane?: LegacyRuntimeMonitorLane }): string { const prefix = options.lane !== undefined && options.lane !== "g14" ? `latest-${options.lane}-` : "latest-"; if (options.once && options.dryRun) return `${prefix}once-dry-run-job.json`; if (options.once) return `${prefix}once-job.json`; @@ -22,7 +22,7 @@ export function hwlabG14MonitorStateFileName(options: Pick & { lane?: G14MonitorLane }): string { +export function hwlabLegacyRuntimeMonitorStateRole(options: Pick & { lane?: LegacyRuntimeMonitorLane }): string { const lanePrefix = options.lane !== undefined && options.lane !== "g14" ? `${options.lane}-` : ""; if (options.once && options.dryRun) return `${lanePrefix}once-dry-run`; if (options.once) return `${lanePrefix}once`; @@ -30,13 +30,13 @@ export function hwlabG14MonitorStateRole(options: Pick PipelineRun name"); return value.toLowerCase(); } @@ -75,7 +75,7 @@ export function validateRuntimeLanePipelineRunOption(lane: HwlabRuntimeLane, val return value.toLowerCase(); } -export function parseRecordRolloutOptions(args: string[]): G14RecordRolloutOptions { +export function parseRecordRolloutOptions(args: string[]): LegacyRuntimeRecordRolloutOptions { const prRaw = optionValue(args, "--pr") ?? optionValue(args, "--number"); const prNumber = Number(prRaw); if (!Number.isInteger(prNumber) || prNumber <= 0) throw new Error("record-rollout requires --pr "); @@ -91,7 +91,7 @@ export function parseRecordRolloutOptions(args: string[]): G14RecordRolloutOptio }; } -export function parseControlPlaneOptions(args: string[]): G14ControlPlaneOptions { +export function parseControlPlaneOptions(args: string[]): LegacyRuntimeControlPlaneOptions { const [rawAction] = args; const actionRaw = rawAction === "rerun-current" ? "trigger-current" : rawAction; if ( @@ -107,7 +107,7 @@ export function parseControlPlaneOptions(args: string[]): G14ControlPlaneOptions throw new Error("control-plane usage: status|apply|trigger-current|refresh --lane v02|v03 | closeout|runtime-migration --lane v02 | cleanup-runs --lane v02|v03|g14|all | cleanup-released-pvs --lane all [--dry-run|--confirm]"); } const laneRaw = optionValue(args, "--lane") ?? (actionRaw === "cleanup-released-pvs" ? "all" : "v02"); - let lane: G14ControlPlaneOptions["lane"]; + let lane: LegacyRuntimeControlPlaneOptions["lane"]; if (actionRaw === "cleanup-runs") { if (laneRaw !== "g14" && laneRaw !== "all" && !isHwlabRuntimeLane(laneRaw)) throw new Error("control-plane cleanup-runs requires --lane v02|v03|g14|all"); lane = laneRaw; @@ -153,12 +153,12 @@ export function parseControlPlaneOptions(args: string[]): G14ControlPlaneOptions ? undefined : isHwlabRuntimeLane(lane) ? validateRuntimeLanePipelineRunOption(lane, pipelineRunRaw) - : validateV02PipelineRunOption(pipelineRunRaw), + : validateDefaultRuntimeLanePipelineRunOption(pipelineRunRaw), history: args.includes("--history"), }; } -export function parseLegacyRetirementOptions(args: string[]): G14LegacyRetirementOptions { +export function parseLegacyRetirementOptions(args: string[]): LegacyRuntimeLegacyRetirementOptions { const [actionRaw = "status"] = args; if (actionRaw !== "status" && actionRaw !== "plan" && actionRaw !== "execute") { throw new Error("retirement usage: status|plan|execute [--dry-run|--confirm] [--wait] [--reason text] [--timeout-seconds N]"); @@ -180,14 +180,14 @@ export function parseLegacyRetirementOptions(args: string[]): G14LegacyRetiremen }; } -export function parseToolsImageOptions(args: string[]): G14ToolsImageOptions { +export function parseToolsImageOptions(args: string[]): LegacyRuntimeToolsImageOptions { const [actionRaw] = args; if (actionRaw !== "status" && actionRaw !== "build") { throw new Error("tools-image usage: status|build --name ci-node-tools --tag [--dockerfile path] [--dry-run|--confirm]"); } const name = optionValue(args, "--name") ?? "ci-node-tools"; if (name !== "ci-node-tools") throw new Error("tools-image currently supports --name ci-node-tools"); - const tag = optionValue(args, "--tag") ?? G14_CI_TOOLS_BASE_TAG; + const tag = optionValue(args, "--tag") ?? LEGACY_RUNTIME_CI_TOOLS_BASE_TAG; if (!/^[A-Za-z0-9_.-]+$/u.test(tag)) throw new Error("--tag may only contain letters, numbers, dot, underscore, and dash"); const dockerfile = optionValue(args, "--dockerfile") ?? "deploy/ci/hwlab-ci-node-tools.Dockerfile"; if (dockerfile.startsWith("/") || dockerfile.includes("..")) throw new Error("--dockerfile must be a repo-relative path without '..'"); @@ -205,7 +205,7 @@ export function parseToolsImageOptions(args: string[]): G14ToolsImageOptions { }; } -export function parseUpstreamImageOptions(args: string[]): G14UpstreamImageOptions { +export function parseUpstreamImageOptions(args: string[]): LegacyRuntimeUpstreamImageOptions { const [actionRaw] = args; if (actionRaw !== "status" && actionRaw !== "ensure") { throw new Error("upstream-image usage: status|ensure --name openfga --tag v1.17.0 [--dry-run|--confirm]"); @@ -227,7 +227,7 @@ export function parseUpstreamImageOptions(args: string[]): G14UpstreamImageOptio }; } -export function parseGitMirrorOptions(args: string[]): G14GitMirrorOptions { +export function parseGitMirrorOptions(args: string[]): LegacyRuntimeGitMirrorOptions { const [actionRaw] = args; if (actionRaw !== "status" && actionRaw !== "apply" && actionRaw !== "sync" && actionRaw !== "flush") { throw new Error("git-mirror usage: status|apply|sync|flush [--lane v02|v03] [--dry-run|--confirm]"); @@ -247,7 +247,7 @@ export function parseGitMirrorOptions(args: string[]): G14GitMirrorOptions { }; } -export function parseObservabilityOptions(args: string[]): G14ObservabilityOptions { +export function parseObservabilityOptions(args: string[]): LegacyRuntimeObservabilityOptions { const [actionRaw] = args; if ( actionRaw !== "status" && @@ -301,7 +301,7 @@ export function parseObservabilityOptions(args: string[]): G14ObservabilityOptio }; } -export function parseSecretOptions(args: string[]): G14SecretOptions { +export function parseSecretOptions(args: string[]): LegacyRuntimeSecretOptions { const [actionRaw] = args; if (actionRaw !== "status" && actionRaw !== "ensure" && actionRaw !== "delete") { throw new Error("secret usage: status|ensure --lane v02|v03 --name hwlab-v0x-openfga|hwlab-v0x-master-server-admin-api-key [--dry-run|--confirm] | delete --lane v02 --name [--dry-run|--confirm]"); @@ -321,7 +321,7 @@ export function parseSecretOptions(args: string[]): G14SecretOptions { if (lane !== "v02") throw new Error("secret delete is currently limited to --lane v02 obsolete cleanup"); if (key !== undefined) throw new Error("secret delete does not accept --key; it deletes a whole obsolete Secret object"); if (!/^hwlab-v02-[a-z0-9-]+$/u.test(name)) throw new Error("secret delete requires a hwlab-v02-* Secret name"); - if (name === V02_OPENFGA_SECRET || name === V02_MASTER_ADMIN_API_KEY_SECRET || name === "hwlab-v02-postgres") throw new Error(`secret delete refuses required v0.2 Secret ${name}`); + if (name === DEFAULT_RUNTIME_LANE_OPENFGA_SECRET || name === DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_SECRET || name === "hwlab-v02-postgres") throw new Error(`secret delete refuses required v0.2 Secret ${name}`); return { action: actionRaw, lane, @@ -333,14 +333,14 @@ export function parseSecretOptions(args: string[]): G14SecretOptions { }; } if (name === masterAdminSecret) { - if (key !== undefined && key !== V02_MASTER_ADMIN_API_KEY_SECRET_KEY) throw new Error(`secret ${masterAdminSecret} supports only key ${V02_MASTER_ADMIN_API_KEY_SECRET_KEY}`); + if (key !== undefined && key !== DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_SECRET_KEY) throw new Error(`secret ${masterAdminSecret} supports only key ${DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_SECRET_KEY}`); return { action: actionRaw, lane, confirm, dryRun: actionRaw === "status" ? true : explicitDryRun || !confirm, name, - key: key ?? V02_MASTER_ADMIN_API_KEY_SECRET_KEY, + key: key ?? DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_SECRET_KEY, preset: "master-server-admin-api-key", timeoutSeconds: positiveIntegerOption(args, "--timeout-seconds", 120, 600), }; @@ -348,10 +348,10 @@ export function parseSecretOptions(args: string[]): G14SecretOptions { if (name !== openFgaSecret) { throw new Error(`secret status/ensure currently supports only --name ${openFgaSecret} or ${masterAdminSecret} for --lane ${lane}; use secret delete for obsolete v02 Secret objects`); } - if (key !== undefined && key !== V02_OPENFGA_AUTHN_SECRET_KEY && key !== V02_OPENFGA_DATASTORE_URI_SECRET_KEY && key !== V02_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY) { - throw new Error(`secret ${openFgaSecret} supports keys ${V02_OPENFGA_AUTHN_SECRET_KEY}, ${V02_OPENFGA_DATASTORE_URI_SECRET_KEY}, and ${V02_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY}`); + if (key !== undefined && key !== DEFAULT_RUNTIME_LANE_OPENFGA_AUTHN_SECRET_KEY && key !== DEFAULT_RUNTIME_LANE_OPENFGA_DATASTORE_URI_SECRET_KEY && key !== DEFAULT_RUNTIME_LANE_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY) { + throw new Error(`secret ${openFgaSecret} supports keys ${DEFAULT_RUNTIME_LANE_OPENFGA_AUTHN_SECRET_KEY}, ${DEFAULT_RUNTIME_LANE_OPENFGA_DATASTORE_URI_SECRET_KEY}, and ${DEFAULT_RUNTIME_LANE_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY}`); } - if (lane !== "v02" && key === V02_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY) throw new Error(`${openFgaSecret}/${V02_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY} is derived from ${postgresSecret}/POSTGRES_PASSWORD`); + if (lane !== "v02" && key === DEFAULT_RUNTIME_LANE_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY) throw new Error(`${openFgaSecret}/${DEFAULT_RUNTIME_LANE_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY} is derived from ${postgresSecret}/POSTGRES_PASSWORD`); return { action: actionRaw, lane, diff --git a/scripts/src/hwlab-g14/pr-monitor.ts b/scripts/src/hwlab-legacy-runtime/pr-monitor.ts similarity index 90% rename from scripts/src/hwlab-g14/pr-monitor.ts rename to scripts/src/hwlab-legacy-runtime/pr-monitor.ts index d43ae01e..fb834a2e 100644 --- a/scripts/src/hwlab-g14/pr-monitor.ts +++ b/scripts/src/hwlab-legacy-runtime/pr-monitor.ts @@ -1,6 +1,6 @@ -// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. pr-monitor module for scripts/src/hwlab-g14.ts. +// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. pr-monitor module for scripts/src/hwlab-legacy-runtime.ts. -// Moved mechanically from scripts/src/hwlab-g14.ts:8387-9507 for #903. +// Moved mechanically from scripts/src/hwlab-legacy-runtime.ts:8387-9507 for #903. import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"; import { dirname, join } from "node:path"; @@ -10,12 +10,12 @@ import { runCommand } from "../command"; import { cancelJob, listJobs, readJob, startJob } from "../jobs"; import { hwlabRequiredNoProxyEntries, hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneIds, hwlabRuntimeLaneSpec, isHwlabRuntimeLane, type HwlabRuntimeLane, type HwlabRuntimeLaneSpec } from "../hwlab-node-lanes"; -import type { CiPipelineMetrics, CiServiceMetric, CommandJsonResult, G14RecordRolloutOptions, OpenPullRequest, V02PrCommentInput } from "./types"; +import type { CiPipelineMetrics, CiServiceMetric, CommandJsonResult, LegacyRuntimeRecordRolloutOptions, OpenPullRequest, DefaultRuntimeLanePrCommentInput } from "./types"; import { cliJson, commandData, commandJson, isCommandSuccess, nested, printEvent, record, shortSha, sleep, stringOrNull, textHash } from "./remote"; -import { getV02Head } from "./source"; -import { ARGO_NAMESPACE, BEIJING_OFFSET_MS, CI_NAMESPACE, DEV_APP, DEV_NAMESPACE, G14_BRIEF_INDEX_ISSUE, G14_PROVIDER, G14_WORKSPACE, HWLAB_REPO, V02_SOURCE_BRANCH } from "./types"; +import { getDefaultRuntimeLaneHead } from "./source"; +import { ARGO_NAMESPACE, BEIJING_OFFSET_MS, CI_NAMESPACE, DEV_APP, DEV_NAMESPACE, LEGACY_RUNTIME_BRIEF_INDEX_ISSUE, LEGACY_RUNTIME_PROVIDER, LEGACY_RUNTIME_WORKSPACE, HWLAB_REPO, DEFAULT_RUNTIME_LANE_SOURCE_BRANCH } from "./types"; -export function listOpenG14PullRequests(): CommandJsonResult { +export function listOpenLegacyRuntimePullRequests(): CommandJsonResult { return cliJson(["gh", "pr", "list", "--repo", HWLAB_REPO, "--state", "open", "--limit", "30", "--json", "number,title,state,url,head,base,draft,headRefName,baseRefName"], 60_000); } @@ -27,8 +27,8 @@ export function mergePullRequest(number: number, dryRun: boolean): CommandJsonRe return cliJson(["gh", "pr", "merge", String(number), "--repo", HWLAB_REPO, "--merge", "--delete-branch", ...(dryRun ? ["--dry-run"] : [])], 100_000); } -export function getG14Head(): string | null { - const result = cliJson(["ssh", `${G14_PROVIDER}:${G14_WORKSPACE}`, "sh", "--", "git fetch origin G14 --prune >/dev/null 2>&1; git rev-parse origin/G14"], 120_000); +export function getLegacyRuntimeHead(): string | null { + const result = cliJson(["ssh", `${LEGACY_RUNTIME_PROVIDER}:${LEGACY_RUNTIME_WORKSPACE}`, "sh", "--", "git fetch origin G14 --prune >/dev/null 2>&1; git rev-parse origin/G14"], 120_000); if (!isCommandSuccess(result)) return null; const output = String(nested(result.parsed, ["data", "stdout"]) ?? result.stdout).trim(); const match = /[0-9a-f]{40}/iu.exec(output); @@ -36,19 +36,19 @@ export function getG14Head(): string | null { } export function refreshArgoDev(): void { - cliJson(["ssh", `${G14_PROVIDER}:k3s`, "kubectl", "annotate", "application", "-n", ARGO_NAMESPACE, DEV_APP, "argocd.argoproj.io/refresh=hard", "--overwrite"], 60_000); + cliJson(["ssh", `${LEGACY_RUNTIME_PROVIDER}:k3s`, "kubectl", "annotate", "application", "-n", ARGO_NAMESPACE, DEV_APP, "argocd.argoproj.io/refresh=hard", "--overwrite"], 60_000); } export function getPipelineStatus(sourceCommit: string): CommandJsonResult { - return cliJson(["ssh", `${G14_PROVIDER}:k3s`, "kubectl", "get", "pipelinerun", "-n", CI_NAMESPACE, `hwlab-g14-ci-poll-${shortSha(sourceCommit)}`, "-o", "jsonpath={.status.conditions[0].status}{\"\\n\"}{.status.conditions[0].reason}{\"\\n\"}{.status.conditions[0].message}{\"\\n\"}"], 60_000); + return cliJson(["ssh", `${LEGACY_RUNTIME_PROVIDER}:k3s`, "kubectl", "get", "pipelinerun", "-n", CI_NAMESPACE, `hwlab-g14-ci-poll-${shortSha(sourceCommit)}`, "-o", "jsonpath={.status.conditions[0].status}{\"\\n\"}{.status.conditions[0].reason}{\"\\n\"}{.status.conditions[0].message}{\"\\n\"}"], 60_000); } export function getArgoStatus(): CommandJsonResult { - return cliJson(["ssh", `${G14_PROVIDER}:k3s`, "kubectl", "get", "application", "-n", ARGO_NAMESPACE, DEV_APP, "-o", "jsonpath={.status.sync.revision}{\"\\n\"}{.status.sync.status}{\"\\n\"}{.status.health.status}{\"\\n\"}{.status.operationState.phase}{\"\\n\"}{.status.operationState.syncResult.revision}{\"\\n\"}"], 60_000); + return cliJson(["ssh", `${LEGACY_RUNTIME_PROVIDER}:k3s`, "kubectl", "get", "application", "-n", ARGO_NAMESPACE, DEV_APP, "-o", "jsonpath={.status.sync.revision}{\"\\n\"}{.status.sync.status}{\"\\n\"}{.status.health.status}{\"\\n\"}{.status.operationState.phase}{\"\\n\"}{.status.operationState.syncResult.revision}{\"\\n\"}"], 60_000); } export function getDevWorkloads(): CommandJsonResult { - return cliJson(["ssh", `${G14_PROVIDER}:k3s`, "kubectl", "get", "deploy,statefulset,pod", "-n", DEV_NAMESPACE, "-o", "wide"], 60_000); + return cliJson(["ssh", `${LEGACY_RUNTIME_PROVIDER}:k3s`, "kubectl", "get", "deploy,statefulset,pod", "-n", DEV_NAMESPACE, "-o", "wide"], 60_000); } export function getLiveHealth(): CommandJsonResult { @@ -140,7 +140,7 @@ export function pipelineTaskRunResultsJsonPath(): string { export function getPipelineTaskRunResults(pipelineRun: string): CommandJsonResult { return cliJson([ "ssh", - `${G14_PROVIDER}:k3s`, + `${LEGACY_RUNTIME_PROVIDER}:k3s`, "kubectl", "get", "taskrun", @@ -462,7 +462,7 @@ export function insertBriefIndexRow(indexBody: string, date: string, brief: { nu } export function ensureDailyBriefIssue(date: string, dryRun: boolean): Record { - const indexRead = readIssue(G14_BRIEF_INDEX_ISSUE); + const indexRead = readIssue(LEGACY_RUNTIME_BRIEF_INDEX_ISSUE); if (!isCommandSuccess(indexRead)) return { ok: false, phase: "read-index", indexRead }; const indexIssue = issueFromRead(indexRead); const indexBody = String(indexIssue.body ?? ""); @@ -483,14 +483,14 @@ export function ensureDailyBriefIssue(date: string, dryRun: boolean): Record 0 && parseBriefIssueFromIndex(indexBody, date) === null) { const nextBody = insertBriefIndexRow(indexBody, date, brief); - const bodyPath = writeStateFile(`issue-${G14_BRIEF_INDEX_ISSUE}-brief-index-${date}.md`, `${nextBody.trimEnd()}\n`); + const bodyPath = writeStateFile(`issue-${LEGACY_RUNTIME_BRIEF_INDEX_ISSUE}-brief-index-${date}.md`, `${nextBody.trimEnd()}\n`); if (dryRun) { - actions.push({ action: "would-update-brief-index", issue: G14_BRIEF_INDEX_ISSUE, bodyPath }); + actions.push({ action: "would-update-brief-index", issue: LEGACY_RUNTIME_BRIEF_INDEX_ISSUE, bodyPath }); } else { const bodySha = String(indexIssue.bodySha ?? ""); - const update = cliJson(["gh", "issue", "update", String(G14_BRIEF_INDEX_ISSUE), "--repo", HWLAB_REPO, "--mode", "replace", "--body-file", bodyPath, ...(bodySha.length > 0 ? ["--expect-body-sha", bodySha] : [])], 100_000); + const update = cliJson(["gh", "issue", "update", String(LEGACY_RUNTIME_BRIEF_INDEX_ISSUE), "--repo", HWLAB_REPO, "--mode", "replace", "--body-file", bodyPath, ...(bodySha.length > 0 ? ["--expect-body-sha", bodySha] : [])], 100_000); if (!isCommandSuccess(update)) return { ok: false, phase: "update-brief-index", update, bodyPath }; - actions.push({ action: "updated-brief-index", issue: G14_BRIEF_INDEX_ISSUE, bodyPath }); + actions.push({ action: "updated-brief-index", issue: LEGACY_RUNTIME_BRIEF_INDEX_ISSUE, bodyPath }); } } return { ok: true, date, brief, actions }; @@ -531,11 +531,11 @@ export function sourceCommitFromMergeResult(merge: CommandJsonResult, prNumber: return mergeCommitFromPr(commandData(prRead)); } -export async function waitForV02Head(expectedCommit: string | null, timeoutSeconds: number): Promise> { +export async function waitForDefaultRuntimeLaneHead(expectedCommit: string | null, timeoutSeconds: number): Promise> { const started = Date.now(); let head: string | null = null; while (Date.now() - started < timeoutSeconds * 1000) { - head = getV02Head(); + head = getDefaultRuntimeLaneHead(); if (expectedCommit === null) { if (head !== null) return { ok: true, sourceCommit: head, expectedCommit, matched: true, waitedSeconds: Math.round((Date.now() - started) / 1000) }; } else if (head === expectedCommit) { @@ -606,7 +606,7 @@ export function rolloutRecordBody(input: { ].join("\n"); } -export function appendRolloutBrief(options: G14RecordRolloutOptions, rollout: Record = {}): Record { +export function appendRolloutBrief(options: LegacyRuntimeRecordRolloutOptions, rollout: Record = {}): Record { const now = beijingParts(); const ensured = ensureDailyBriefIssue(now.date, options.dryRun); if (record(ensured).ok !== true) return ensured; @@ -656,12 +656,12 @@ export function appendRolloutBrief(options: G14RecordRolloutOptions, rollout: Re return { ok: true, date: now.date, brief, sourceCommit, pipelineRun, gitopsRevision, ciMetrics, bodyPath, update: commandData(update), ensured }; } -export function v02PrCommentStatePath(): string { +export function defaultRuntimeLanePrCommentStatePath(): string { return rootPath(".state", "hwlab-g14", "v02-pr-comment-signatures.json"); } -export function readV02PrCommentState(): Record { - const path = v02PrCommentStatePath(); +export function readDefaultRuntimeLanePrCommentState(): Record { + const path = defaultRuntimeLanePrCommentStatePath(); if (!existsSync(path)) return {}; try { const parsed = JSON.parse(readFileSync(path, "utf8")) as unknown; @@ -675,8 +675,8 @@ export function readV02PrCommentState(): Record { } } -export function writeV02PrCommentState(state: Record): string { - const path = v02PrCommentStatePath(); +export function writeDefaultRuntimeLanePrCommentState(state: Record): string { + const path = defaultRuntimeLanePrCommentStatePath(); mkdirSync(dirname(path), { recursive: true }); writeFileSync(path, `${JSON.stringify(state, null, 2)}\n`, "utf8"); return path; @@ -699,7 +699,7 @@ export function preflightSummary(preflight: CommandJsonResult): Record): string { +export function defaultRuntimeLanePrConflictState(summary: Record): string { const mergeable = String(summary.mergeable ?? "").toUpperCase(); const mergeStateStatus = String(summary.mergeStateStatus ?? "").toUpperCase(); const blockers = Array.isArray(summary.blockers) ? summary.blockers.map(String).join("\n") : ""; @@ -707,7 +707,7 @@ export function v02PrConflictState(summary: Record): string { return "clear-or-unknown"; } -export function summarizeV02CdStatus(status: Record): Record { +export function summarizeDefaultRuntimeLaneCdStatus(status: Record): Record { const pipelineRun = record(status.pipelineRun); const targetValidation = record(status.targetValidation); const gitMirror = record(status.gitMirror); @@ -737,12 +737,12 @@ export function summarizeV02CdStatus(status: Record): Record): boolean { +export function defaultRuntimeLaneCdPassed(status: Record): boolean { const state = String(nested(status, ["targetValidation", "state"]) ?? ""); return state === "passed" || state === "superseded"; } -export function v02ControlPlaneCloseout(status: Record): Record { +export function defaultRuntimeLaneControlPlaneCloseout(status: Record): Record { const closeout = record(status.closeout); const sourceCommit = stringOrNull(status.sourceCommit); const pipelineRun = stringOrNull(nested(status, ["statusTarget", "pipelineRun"])) ?? stringOrNull(nested(status, ["pipelineRun", "pipelineRun"])); @@ -769,16 +769,16 @@ export function v02ControlPlaneCloseout(status: Record): Record }; } -export function v02PipelineSucceeded(status: Record): boolean { +export function defaultRuntimeLanePipelineSucceeded(status: Record): boolean { return String(nested(status, ["pipelineRun", "status"]) ?? "") === "True"; } -export function v02CdFailed(status: Record): boolean { +export function defaultRuntimeLaneCdFailed(status: Record): boolean { const pipelineStatus = String(nested(status, ["pipelineRun", "status"]) ?? ""); return pipelineStatus === "False"; } -export function activeV02PipelineRuns(status: Record): Record[] { +export function activeDefaultRuntimeLanePipelineRuns(status: Record): Record[] { const items = Array.isArray(status.activePipelineRuns) ? status.activePipelineRuns : Array.isArray(record(status.activePipelineRuns).items) @@ -787,7 +787,7 @@ export function activeV02PipelineRuns(status: Record): Record record(item)).filter((item) => String(item.status ?? "") === "Unknown"); } -export function v02StatusHistoryPolicy(status: Record): Record { +export function defaultRuntimeLaneStatusHistoryPolicy(status: Record): Record { const history = record(status.history); return { included: history.included === true, @@ -798,7 +798,7 @@ export function v02StatusHistoryPolicy(status: Record): Record< }; } -export function v02PrCommentSignature(input: V02PrCommentInput): string { +export function defaultRuntimeLanePrCommentSignature(input: DefaultRuntimeLanePrCommentInput): string { const summary = input.preflight ?? {}; const cd = input.cd ?? {}; const flush = input.flush ?? {}; @@ -808,7 +808,7 @@ export function v02PrCommentSignature(input: V02PrCommentInput): string { phase: input.phase, conclusion: summary.conclusion ?? null, readyForCommanderMerge: summary.readyForCommanderMerge ?? null, - conflict: v02PrConflictState(summary), + conflict: defaultRuntimeLanePrConflictState(summary), blockers: summary.blockers ?? [], pending: summary.pending ?? [], sourceCommit: input.sourceCommit ?? null, @@ -833,7 +833,7 @@ export function scalarValue(value: unknown): string { return String(value); } -export function v02PrAutomationCommentBody(input: V02PrCommentInput): string { +export function defaultRuntimeLanePrAutomationCommentBody(input: DefaultRuntimeLanePrCommentInput): string { const preflight = input.preflight ?? {}; const cd = input.cd ?? {}; const flush = input.flush ?? {}; @@ -848,12 +848,12 @@ export function v02PrAutomationCommentBody(input: V02PrCommentInput): string { "", "- PR:", ` - [#${input.pr.number} ${title}](${url})`, - ` - base: \`${input.pr.baseRefName ?? V02_SOURCE_BRANCH}\`; head: \`${input.pr.headRefName ?? "unknown"}\``, + ` - base: \`${input.pr.baseRefName ?? DEFAULT_RUNTIME_LANE_SOURCE_BRANCH}\`; head: \`${input.pr.headRefName ?? "unknown"}\``, "- 自动化状态:", ` - state: \`${input.state}\`; phase: \`${input.phase}\``, ` - startedAt: \`${input.startedAt}\`; observedAt: \`${input.observedAt}\`; elapsed: ${elapsed}`, "- CI / mergeability:", - ` - conclusion: \`${scalarValue(preflight.conclusion)}\`; readyForCommanderMerge: \`${String(preflight.readyForCommanderMerge ?? "n/a")}\`; conflict: \`${v02PrConflictState(preflight)}\``, + ` - conclusion: \`${scalarValue(preflight.conclusion)}\`; readyForCommanderMerge: \`${String(preflight.readyForCommanderMerge ?? "n/a")}\`; conflict: \`${defaultRuntimeLanePrConflictState(preflight)}\``, ` - blockers: ${listValue(preflight.blockers)}`, ` - pending: ${listValue(preflight.pending)}`, "- CD / runtime:", @@ -868,22 +868,22 @@ export function v02PrAutomationCommentBody(input: V02PrCommentInput): string { ].join("\n"); } -export function commentV02PullRequest(input: V02PrCommentInput): Record { - const body = v02PrAutomationCommentBody(input); - const signature = v02PrCommentSignature(input); +export function commentDefaultRuntimeLanePullRequest(input: DefaultRuntimeLanePrCommentInput): Record { + const body = defaultRuntimeLanePrAutomationCommentBody(input); + const signature = defaultRuntimeLanePrCommentSignature(input); const cacheKey = `pr-${input.pr.number}`; if (input.dryRun === true) { return { ok: true, dryRun: true, skipped: true, signature, wouldComment: { bodyPreview: body.slice(0, 1200), bodyChars: body.length } }; } - const state = readV02PrCommentState(); + const state = readDefaultRuntimeLanePrCommentState(); if (state[cacheKey] === signature) { - return { ok: true, skipped: true, reason: "same-pr-comment-signature", signature, stateFile: v02PrCommentStatePath() }; + return { ok: true, skipped: true, reason: "same-pr-comment-signature", signature, stateFile: defaultRuntimeLanePrCommentStatePath() }; } const bodyPath = writeStateFile(`v02-pr-${input.pr.number}-${input.state}-${signature}.md`, `${body}\n`); const create = cliJson(["gh", "pr", "comment", "create", String(input.pr.number), "--repo", HWLAB_REPO, "--body-file", bodyPath], 100_000); if (!isCommandSuccess(create)) return { ok: false, phase: "pr-comment", signature, bodyPath, create }; state[cacheKey] = signature; - const stateFile = writeV02PrCommentState(state); + const stateFile = writeDefaultRuntimeLanePrCommentState(state); return { ok: true, signature, bodyPath, stateFile, create: commandData(create) }; } @@ -954,7 +954,7 @@ export function runtimeLaneCdFailed(status: Record): boolean { return String(nested(status, ["pipelineRun", "status"]) ?? "") === "False"; } -export function runtimeLanePrCommentSignature(spec: HwlabRuntimeLaneSpec, input: V02PrCommentInput): string { +export function runtimeLanePrCommentSignature(spec: HwlabRuntimeLaneSpec, input: DefaultRuntimeLanePrCommentInput): string { const summary = input.preflight ?? {}; const cd = input.cd ?? {}; const flush = input.flush ?? {}; @@ -965,7 +965,7 @@ export function runtimeLanePrCommentSignature(spec: HwlabRuntimeLaneSpec, input: phase: input.phase, conclusion: summary.conclusion ?? null, readyForCommanderMerge: summary.readyForCommanderMerge ?? null, - conflict: v02PrConflictState(summary), + conflict: defaultRuntimeLanePrConflictState(summary), blockers: summary.blockers ?? [], pending: summary.pending ?? [], sourceCommit: input.sourceCommit ?? null, @@ -980,7 +980,7 @@ export function runtimeLanePrCommentSignature(spec: HwlabRuntimeLaneSpec, input: })); } -export function runtimeLanePrAutomationCommentBody(spec: HwlabRuntimeLaneSpec, input: V02PrCommentInput): string { +export function runtimeLanePrAutomationCommentBody(spec: HwlabRuntimeLaneSpec, input: DefaultRuntimeLanePrCommentInput): string { const preflight = input.preflight ?? {}; const cd = input.cd ?? {}; const flush = input.flush ?? {}; @@ -1000,7 +1000,7 @@ export function runtimeLanePrAutomationCommentBody(spec: HwlabRuntimeLaneSpec, i ` - lane: \`${spec.lane}\`; state: \`${input.state}\`; phase: \`${input.phase}\``, ` - startedAt: \`${input.startedAt}\`; observedAt: \`${input.observedAt}\`; elapsed: ${elapsed}`, "- CI / mergeability:", - ` - conclusion: \`${scalarValue(preflight.conclusion)}\`; readyForCommanderMerge: \`${String(preflight.readyForCommanderMerge ?? "n/a")}\`; conflict: \`${v02PrConflictState(preflight)}\``, + ` - conclusion: \`${scalarValue(preflight.conclusion)}\`; readyForCommanderMerge: \`${String(preflight.readyForCommanderMerge ?? "n/a")}\`; conflict: \`${defaultRuntimeLanePrConflictState(preflight)}\``, ` - blockers: ${listValue(preflight.blockers)}`, ` - pending: ${listValue(preflight.pending)}`, "- CD / runtime:", @@ -1015,7 +1015,7 @@ export function runtimeLanePrAutomationCommentBody(spec: HwlabRuntimeLaneSpec, i ].join("\n"); } -export function commentRuntimeLanePullRequest(spec: HwlabRuntimeLaneSpec, input: V02PrCommentInput): Record { +export function commentRuntimeLanePullRequest(spec: HwlabRuntimeLaneSpec, input: DefaultRuntimeLanePrCommentInput): Record { const body = runtimeLanePrAutomationCommentBody(spec, input); const signature = runtimeLanePrCommentSignature(spec, input); const cacheKey = `pr-${input.pr.number}`; @@ -1073,7 +1073,7 @@ export function runtimeLaneAutomationIssueBody(input: { ` - startedAt: \`${input.startedAt}\`; observedAt: \`${input.observedAt}\``, ` - dedupeKey: \`${dedupeKey}\``, "- CI / mergeability:", - ` - conclusion: \`${scalarValue(preflight.conclusion)}\`; readyForCommanderMerge: \`${String(preflight.readyForCommanderMerge ?? "n/a")}\`; conflict: \`${v02PrConflictState(preflight)}\``, + ` - conclusion: \`${scalarValue(preflight.conclusion)}\`; readyForCommanderMerge: \`${String(preflight.readyForCommanderMerge ?? "n/a")}\`; conflict: \`${defaultRuntimeLanePrConflictState(preflight)}\``, ` - blockers: ${listValue(preflight.blockers)}`, ` - pending: ${listValue(preflight.pending)}`, "- CD / runtime:", diff --git a/scripts/src/hwlab-g14/remote.ts b/scripts/src/hwlab-legacy-runtime/remote.ts similarity index 91% rename from scripts/src/hwlab-g14/remote.ts rename to scripts/src/hwlab-legacy-runtime/remote.ts index d48f1783..05f055cc 100644 --- a/scripts/src/hwlab-g14/remote.ts +++ b/scripts/src/hwlab-legacy-runtime/remote.ts @@ -1,6 +1,6 @@ -// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. remote module for scripts/src/hwlab-g14.ts. +// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. remote module for scripts/src/hwlab-legacy-runtime.ts. -// Moved mechanically from scripts/src/hwlab-g14.ts:639-1204 for #903. +// Moved mechanically from scripts/src/hwlab-legacy-runtime.ts:639-1204 for #903. import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"; import { dirname, join } from "node:path"; @@ -10,9 +10,9 @@ import { runCommand } from "../command"; import { cancelJob, listJobs, readJob, startJob } from "../jobs"; import { hwlabRequiredNoProxyEntries, hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneIds, hwlabRuntimeLaneSpec, isHwlabRuntimeLane, type HwlabRuntimeLane, type HwlabRuntimeLaneSpec } from "../hwlab-node-lanes"; -import type { CommandJsonResult, G14MonitorLane, OpenPullRequest, RemoteAsyncCommandSpec } from "./types"; +import type { CommandJsonResult, LegacyRuntimeMonitorLane, OpenPullRequest, RemoteAsyncCommandSpec } from "./types"; import { tailText } from "./cleanup"; -import { G14_PROVIDER, G14_SOURCE_BRANCH, G14_WORKSPACE, V02_MASTER_ADMIN_API_KEY_LOCAL_ENV } from "./types"; +import { LEGACY_RUNTIME_PROVIDER, LEGACY_RUNTIME_SOURCE_BRANCH, LEGACY_RUNTIME_WORKSPACE, DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_LOCAL_ENV } from "./types"; export function positiveIntegerOption(args: string[], name: string, defaultValue: number, maxValue: number): number { const index = args.indexOf(name); @@ -172,7 +172,7 @@ export function runtimeLaneMasterAdminApiKeySecretName(spec: HwlabRuntimeLaneSpe } export function runtimeLaneMasterAdminApiKeyLocalEnv(spec: HwlabRuntimeLaneSpec): string { - if (spec.lane === "v02") return V02_MASTER_ADMIN_API_KEY_LOCAL_ENV; + if (spec.lane === "v02") return DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_LOCAL_ENV; return `/root/.config/hwlab-${spec.lane}/master-server-admin-api-key.env`; } @@ -306,11 +306,11 @@ export function isCommandSuccess(result: CommandJsonResult): boolean { return dataOk !== false; } -export function monitorBaseBranch(lane: G14MonitorLane): string { - return lane === "g14" ? G14_SOURCE_BRANCH : hwlabRuntimeLaneSpec(lane).sourceBranch; +export function monitorBaseBranch(lane: LegacyRuntimeMonitorLane): string { + return lane === "g14" ? LEGACY_RUNTIME_SOURCE_BRANCH : hwlabRuntimeLaneSpec(lane).sourceBranch; } -export function extractPullRequests(result: CommandJsonResult, baseBranch = G14_SOURCE_BRANCH): OpenPullRequest[] { +export function extractPullRequests(result: CommandJsonResult, baseBranch = LEGACY_RUNTIME_SOURCE_BRANCH): OpenPullRequest[] { const prs = nested(result.parsed, ["data", "pullRequests"]); if (!Array.isArray(prs)) return []; return prs @@ -341,7 +341,7 @@ export function printProgressEvent(event: string, data: Record process.stderr.write(`${JSON.stringify({ event, at: new Date().toISOString(), ...data })}\n`); } -export function printV02PrMonitorProgress(data: Record = {}): void { +export function printDefaultRuntimeLanePrMonitorProgress(data: Record = {}): void { printProgressEvent("hwlab.v02.pr-monitor.progress", data); } @@ -366,19 +366,19 @@ export function shortSha(sha: string): string { } export function precheckWorkspace(): CommandJsonResult { - return cliJson(["ssh", `${G14_PROVIDER}:${G14_WORKSPACE}`, "sh", "--", "pwd; git fetch origin G14 --prune; git status --short --branch; git remote -v | sed -n '1,4p'"], 120_000); + return cliJson(["ssh", `${LEGACY_RUNTIME_PROVIDER}:${LEGACY_RUNTIME_WORKSPACE}`, "sh", "--", "pwd; git fetch origin G14 --prune; git status --short --branch; git remote -v | sed -n '1,4p'"], 120_000); } -export function g14HostScript(script: string, timeoutMs = 120_000): CommandJsonResult { - return cliJson(["ssh", G14_PROVIDER, "sh", "--", script], timeoutMs); +export function legacyRuntimeHostScript(script: string, timeoutMs = 120_000): CommandJsonResult { + return cliJson(["ssh", LEGACY_RUNTIME_PROVIDER, "sh", "--", script], timeoutMs); } -export function g14K3s(args: string[], timeoutMs = 60_000): CommandJsonResult { - return cliJson(["ssh", `${G14_PROVIDER}:k3s`, ...args], timeoutMs); +export function legacyRuntimeK3s(args: string[], timeoutMs = 60_000): CommandJsonResult { + return cliJson(["ssh", `${LEGACY_RUNTIME_PROVIDER}:k3s`, ...args], timeoutMs); } -export function g14K3sInlineScriptWithInput(script: string, input: string, timeoutMs = 60_000): CommandJsonResult { - return commandJsonWithInput(["bun", "scripts/cli.ts", "ssh", `${G14_PROVIDER}:k3s`, "sh", "--", script], input, timeoutMs); +export function legacyRuntimeK3sInlineScriptWithInput(script: string, input: string, timeoutMs = 60_000): CommandJsonResult { + return commandJsonWithInput(["bun", "scripts/cli.ts", "ssh", `${LEGACY_RUNTIME_PROVIDER}:k3s`, "sh", "--", script], input, timeoutMs); } export function remoteAsyncStatusDir(label: string): string { @@ -511,9 +511,9 @@ export function parseRemoteAsyncPayload(result: CommandJsonResult): Record ["-f", file]), ]; - const command = ["bun", "scripts/cli.ts", "ssh", `${G14_PROVIDER}:k3s`, ...serverSideArgs]; + const command = ["bun", "scripts/cli.ts", "ssh", `${LEGACY_RUNTIME_PROVIDER}:k3s`, ...serverSideArgs]; const shellCommand = dryRun && spec.lane !== "v02" ? [ "set -eu", @@ -187,9 +187,9 @@ export function applyRuntimeLaneControlPlaneFiles(spec: HwlabRuntimeLaneSpec, re ? ["set -eu", shellCommand.replace(/^exec /, ""), ...cleanupCommands].join("\n") : shellCommand; const visibleCommand = cleanupCommands.length > 0 - ? ["bun", "scripts/cli.ts", "ssh", `${G14_PROVIDER}:k3s`, "sh", "--", script] + ? ["bun", "scripts/cli.ts", "ssh", `${LEGACY_RUNTIME_PROVIDER}:k3s`, "sh", "--", script] : command; - return runG14K3sRemoteAsync({ + return runLegacyRuntimeK3sRemoteAsync({ script, timeoutSeconds, label: `${spec.lane}-control-plane-apply`, @@ -198,11 +198,11 @@ export function applyRuntimeLaneControlPlaneFiles(spec: HwlabRuntimeLaneSpec, re }); } -export function applyV02ControlPlaneFiles(renderDir: string, dryRun: boolean, timeoutSeconds: number): CommandJsonResult { - return applyRuntimeLaneControlPlaneFiles(V02_LANE_SPEC, renderDir, dryRun, timeoutSeconds); +export function applyDefaultRuntimeLaneControlPlaneFiles(renderDir: string, dryRun: boolean, timeoutSeconds: number): CommandJsonResult { + return applyRuntimeLaneControlPlaneFiles(DEFAULT_RUNTIME_LANE_LANE_SPEC, renderDir, dryRun, timeoutSeconds); } -export interface V02RefreshMarker { +export interface DefaultRuntimeLaneRefreshMarker { ok: boolean; sourceCommit: string; refreshedAt: string; @@ -210,42 +210,42 @@ export interface V02RefreshMarker { renderDir?: string | null; } -export function v02ControlPlaneRefreshStateDir(): string { +export function defaultRuntimeLaneControlPlaneRefreshStateDir(): string { return rootPath(".state", "hwlab-g14", "v02-control-plane-refresh"); } -export function v02ControlPlaneRefreshScriptHash(sourceCommit: string): string { - return textHash(v02ControlPlaneRenderScript(sourceCommit, "contract-token")); +export function defaultRuntimeLaneControlPlaneRefreshScriptHash(sourceCommit: string): string { + return textHash(defaultRuntimeLaneControlPlaneRenderScript(sourceCommit, "contract-token")); } -export function v02ControlPlaneRefreshMarkerPath(sourceCommit: string): string { - return join(v02ControlPlaneRefreshStateDir(), `${shortSha(sourceCommit)}.json`); +export function defaultRuntimeLaneControlPlaneRefreshMarkerPath(sourceCommit: string): string { + return join(defaultRuntimeLaneControlPlaneRefreshStateDir(), `${shortSha(sourceCommit)}.json`); } -export function v02ControlPlaneRefreshLockDir(sourceCommit: string): string { - return join(v02ControlPlaneRefreshStateDir(), `${shortSha(sourceCommit)}.lock`); +export function defaultRuntimeLaneControlPlaneRefreshLockDir(sourceCommit: string): string { + return join(defaultRuntimeLaneControlPlaneRefreshStateDir(), `${shortSha(sourceCommit)}.lock`); } -export function readV02RefreshMarker(sourceCommit: string, scriptHash: string, nowMs = Date.now()): V02RefreshMarker | null { - const path = v02ControlPlaneRefreshMarkerPath(sourceCommit); +export function readDefaultRuntimeLaneRefreshMarker(sourceCommit: string, scriptHash: string, nowMs = Date.now()): DefaultRuntimeLaneRefreshMarker | null { + const path = defaultRuntimeLaneControlPlaneRefreshMarkerPath(sourceCommit); if (!existsSync(path)) return null; try { - const marker = JSON.parse(readFileSync(path, "utf8")) as V02RefreshMarker; - return v02ReusableRefreshMarker(marker, sourceCommit, scriptHash, nowMs); + const marker = JSON.parse(readFileSync(path, "utf8")) as DefaultRuntimeLaneRefreshMarker; + return defaultRuntimeLaneReusableRefreshMarker(marker, sourceCommit, scriptHash, nowMs); } catch { return null; } } -export function v02ReusableRefreshMarker(marker: unknown, sourceCommit: string, scriptHash: string, nowMs = Date.now()): V02RefreshMarker | null { - const candidate = record(marker) as V02RefreshMarker; +export function defaultRuntimeLaneReusableRefreshMarker(marker: unknown, sourceCommit: string, scriptHash: string, nowMs = Date.now()): DefaultRuntimeLaneRefreshMarker | null { + const candidate = record(marker) as DefaultRuntimeLaneRefreshMarker; const refreshedAtMs = timestampMs(candidate.refreshedAt); if (candidate.ok !== true || candidate.sourceCommit !== sourceCommit || candidate.renderScriptHash !== scriptHash) return null; - if (refreshedAtMs === null || nowMs - refreshedAtMs > V02_CONTROL_PLANE_REFRESH_TTL_MS) return null; + if (refreshedAtMs === null || nowMs - refreshedAtMs > DEFAULT_RUNTIME_LANE_CONTROL_PLANE_REFRESH_TTL_MS) return null; return candidate; } -export function writeV02RefreshMarker(sourceCommit: string, scriptHash: string, renderDir: string | null): V02RefreshMarker { +export function writeDefaultRuntimeLaneRefreshMarker(sourceCommit: string, scriptHash: string, renderDir: string | null): DefaultRuntimeLaneRefreshMarker { const marker = { ok: true, sourceCommit, @@ -253,16 +253,16 @@ export function writeV02RefreshMarker(sourceCommit: string, scriptHash: string, renderScriptHash: scriptHash, renderDir, }; - const dir = v02ControlPlaneRefreshStateDir(); + const dir = defaultRuntimeLaneControlPlaneRefreshStateDir(); mkdirSync(dir, { recursive: true }); - writeFileSync(v02ControlPlaneRefreshMarkerPath(sourceCommit), `${JSON.stringify(marker, null, 2)}\n`, "utf8"); + writeFileSync(defaultRuntimeLaneControlPlaneRefreshMarkerPath(sourceCommit), `${JSON.stringify(marker, null, 2)}\n`, "utf8"); return marker; } -export function acquireV02RefreshLock(sourceCommit: string): { acquired: boolean; lockDir: string; waitedMs: number } { - const stateDir = v02ControlPlaneRefreshStateDir(); +export function acquireDefaultRuntimeLaneRefreshLock(sourceCommit: string): { acquired: boolean; lockDir: string; waitedMs: number } { + const stateDir = defaultRuntimeLaneControlPlaneRefreshStateDir(); mkdirSync(stateDir, { recursive: true }); - const lockDir = v02ControlPlaneRefreshLockDir(sourceCommit); + const lockDir = defaultRuntimeLaneControlPlaneRefreshLockDir(sourceCommit); const startedAtMs = Date.now(); for (;;) { try { @@ -277,7 +277,7 @@ export function acquireV02RefreshLock(sourceCommit: string): { acquired: boolean return 0; } })(); - if (ageMs > V02_CONTROL_PLANE_REFRESH_LOCK_STALE_MS) { + if (ageMs > DEFAULT_RUNTIME_LANE_CONTROL_PLANE_REFRESH_LOCK_STALE_MS) { try { rmSync(lockDir, { recursive: true, force: true }); continue; @@ -285,14 +285,14 @@ export function acquireV02RefreshLock(sourceCommit: string): { acquired: boolean return { acquired: false, lockDir, waitedMs: Date.now() - startedAtMs }; } } - if (Date.now() - startedAtMs >= V02_CONTROL_PLANE_REFRESH_TTL_MS) return { acquired: false, lockDir, waitedMs: Date.now() - startedAtMs }; + if (Date.now() - startedAtMs >= DEFAULT_RUNTIME_LANE_CONTROL_PLANE_REFRESH_TTL_MS) return { acquired: false, lockDir, waitedMs: Date.now() - startedAtMs }; const wait = runCommand(["sleep", "1"], repoRoot, { timeoutMs: 2_000 }); if (wait.exitCode !== 0 && wait.timedOut) return { acquired: false, lockDir, waitedMs: Date.now() - startedAtMs }; } } } -export function releaseV02RefreshLock(lockDir: string): void { +export function releaseDefaultRuntimeLaneRefreshLock(lockDir: string): void { try { rmSync(lockDir, { recursive: true, force: true }); } catch { @@ -300,9 +300,9 @@ export function releaseV02RefreshLock(lockDir: string): void { } } -export function refreshV02ControlPlaneBeforeTrigger(sourceCommit: string, timeoutSeconds: number): Record { - const scriptHash = v02ControlPlaneRefreshScriptHash(sourceCommit); - const existingMarker = readV02RefreshMarker(sourceCommit, scriptHash); +export function refreshDefaultRuntimeLaneControlPlaneBeforeTrigger(sourceCommit: string, timeoutSeconds: number): Record { + const scriptHash = defaultRuntimeLaneControlPlaneRefreshScriptHash(sourceCommit); + const existingMarker = readDefaultRuntimeLaneRefreshMarker(sourceCommit, scriptHash); if (existingMarker !== null) { return { ok: true, @@ -311,10 +311,10 @@ export function refreshV02ControlPlaneBeforeTrigger(sourceCommit: string, timeou sourceCommit, renderDir: existingMarker.renderDir ?? null, marker: existingMarker, - markerTtlMs: V02_CONTROL_PLANE_REFRESH_TTL_MS, + markerTtlMs: DEFAULT_RUNTIME_LANE_CONTROL_PLANE_REFRESH_TTL_MS, }; } - const lock = acquireV02RefreshLock(sourceCommit); + const lock = acquireDefaultRuntimeLaneRefreshLock(sourceCommit); if (!lock.acquired) { return { ok: false, @@ -327,7 +327,7 @@ export function refreshV02ControlPlaneBeforeTrigger(sourceCommit: string, timeou }; } try { - const markerAfterWait = readV02RefreshMarker(sourceCommit, scriptHash); + const markerAfterWait = readDefaultRuntimeLaneRefreshMarker(sourceCommit, scriptHash); if (markerAfterWait !== null) { return { ok: true, @@ -337,10 +337,10 @@ export function refreshV02ControlPlaneBeforeTrigger(sourceCommit: string, timeou renderDir: markerAfterWait.renderDir ?? null, marker: markerAfterWait, waitedMs: lock.waitedMs, - markerTtlMs: V02_CONTROL_PLANE_REFRESH_TTL_MS, + markerTtlMs: DEFAULT_RUNTIME_LANE_CONTROL_PLANE_REFRESH_TTL_MS, }; } - const render = runV02RenderToTemp(sourceCommit); + const render = runDefaultRuntimeLaneRenderToTemp(sourceCommit); if (!isCommandSuccess(render.result)) { return { ok: false, @@ -351,11 +351,11 @@ export function refreshV02ControlPlaneBeforeTrigger(sourceCommit: string, timeou degradedReason: "control-plane-render-failed", }; } - const apply = applyV02ControlPlaneFiles(render.renderDir, false, timeoutSeconds); - const cleanupObsoleteCronJobs = isCommandSuccess(apply) ? deleteV02ObsoleteCronJobs(false) : null; - const cleanupRenderDir = isCommandSuccess(apply) ? cleanupV02RenderDir(render.renderDir) : null; + const apply = applyDefaultRuntimeLaneControlPlaneFiles(render.renderDir, false, timeoutSeconds); + const cleanupObsoleteCronJobs = isCommandSuccess(apply) ? deleteDefaultRuntimeLaneObsoleteCronJobs(false) : null; + const cleanupRenderDir = isCommandSuccess(apply) ? cleanupDefaultRuntimeLaneRenderDir(render.renderDir) : null; const ok = isCommandSuccess(apply) && (cleanupObsoleteCronJobs === null || isCommandSuccess(cleanupObsoleteCronJobs)); - const marker = ok ? writeV02RefreshMarker(sourceCommit, scriptHash, render.renderDir) : null; + const marker = ok ? writeDefaultRuntimeLaneRefreshMarker(sourceCommit, scriptHash, render.renderDir) : null; return { ok, phase: "control-plane-refresh", @@ -375,34 +375,34 @@ export function refreshV02ControlPlaneBeforeTrigger(sourceCommit: string, timeou : undefined, }; } finally { - releaseV02RefreshLock(lock.lockDir); + releaseDefaultRuntimeLaneRefreshLock(lock.lockDir); } } -export function getV02ObsoleteCronJobs(): CommandJsonResult { - return g14K3s([ +export function getDefaultRuntimeLaneObsoleteCronJobs(): CommandJsonResult { + return legacyRuntimeK3s([ "kubectl", "get", "cronjob", "-n", CI_NAMESPACE, - V02_POLLER, - V02_RECONCILER, + DEFAULT_RUNTIME_LANE_POLLER, + DEFAULT_RUNTIME_LANE_RECONCILER, "--ignore-not-found", "-o", "name", ], 60_000); } -export function deleteV02ObsoleteCronJobs(dryRun: boolean): CommandJsonResult { - return g14K3s([ +export function deleteDefaultRuntimeLaneObsoleteCronJobs(dryRun: boolean): CommandJsonResult { + return legacyRuntimeK3s([ "kubectl", "delete", "cronjob", "-n", CI_NAMESPACE, - V02_POLLER, - V02_RECONCILER, + DEFAULT_RUNTIME_LANE_POLLER, + DEFAULT_RUNTIME_LANE_RECONCILER, "--ignore-not-found=true", ...(dryRun ? ["--dry-run=server", "-o", "name"] : []), ], 60_000); diff --git a/scripts/src/hwlab-g14/retirement.ts b/scripts/src/hwlab-legacy-runtime/retirement.ts similarity index 65% rename from scripts/src/hwlab-g14/retirement.ts rename to scripts/src/hwlab-legacy-runtime/retirement.ts index e23336e9..9862233b 100644 --- a/scripts/src/hwlab-g14/retirement.ts +++ b/scripts/src/hwlab-legacy-runtime/retirement.ts @@ -1,6 +1,6 @@ -// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. retirement module for scripts/src/hwlab-g14.ts. +// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. retirement module for scripts/src/hwlab-legacy-runtime.ts. -// Moved mechanically from scripts/src/hwlab-g14.ts:5525-5845 for #903. +// Moved mechanically from scripts/src/hwlab-legacy-runtime.ts:5525-5845 for #903. import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"; import { dirname, join } from "node:path"; @@ -10,35 +10,35 @@ import { runCommand } from "../command"; import { cancelJob, listJobs, readJob, startJob } from "../jobs"; import { hwlabRequiredNoProxyEntries, hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneIds, hwlabRuntimeLaneSpec, isHwlabRuntimeLane, type HwlabRuntimeLane, type HwlabRuntimeLaneSpec } from "../hwlab-node-lanes"; -import type { G14LegacyRetirementOptions } from "./types"; +import type { LegacyRuntimeLegacyRetirementOptions } from "./types"; import { k8sMetadataName, parseSectionJsonArray } from "./observability"; import { statusText } from "./pr-monitor"; -import { compactCommandResult, g14K3s, isCommandSuccess, nested, record, shellQuote } from "./remote"; -import { ARGO_NAMESPACE, DEV_APP, DEV_NAMESPACE, G14_PROVIDER, PROD_APP, PROD_NAMESPACE, V02_APP, V02_RUNTIME_NAMESPACE } from "./types"; -import { parseShellSections, shellSectionOk } from "./v02-status"; +import { compactCommandResult, legacyRuntimeK3s, isCommandSuccess, nested, record, shellQuote } from "./remote"; +import { ARGO_NAMESPACE, DEV_APP, DEV_NAMESPACE, LEGACY_RUNTIME_PROVIDER, PROD_APP, PROD_NAMESPACE, DEFAULT_RUNTIME_LANE_APP, DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE } from "./types"; +import { parseShellSections, shellSectionOk } from "./runtime-status"; -export function legacyG14RetirementStatePath(): string { +export function legacyLegacyRuntimeRetirementStatePath(): string { return rootPath(".state", "hwlab-g14", "legacy-g14-retirement.json"); } -export function legacyG14RetirementApplications(): string[] { +export function legacyLegacyRuntimeRetirementApplications(): string[] { return [DEV_APP, PROD_APP]; } -export function legacyG14RetirementNamespaces(): string[] { +export function legacyLegacyRuntimeRetirementNamespaces(): string[] { return [DEV_NAMESPACE, PROD_NAMESPACE]; } -export function protectedG14RuntimeApplications(): string[] { - return [V02_APP, hwlabRuntimeLaneSpec("v03").app]; +export function protectedLegacyRuntimeRuntimeApplications(): string[] { + return [DEFAULT_RUNTIME_LANE_APP, hwlabRuntimeLaneSpec("v03").app]; } -export function protectedG14RuntimeNamespaces(): string[] { - return [V02_RUNTIME_NAMESPACE, hwlabRuntimeLaneSpec("v03").runtimeNamespace]; +export function protectedLegacyRuntimeRuntimeNamespaces(): string[] { + return [DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE, hwlabRuntimeLaneSpec("v03").runtimeNamespace]; } -export function readLegacyG14RetirementMarker(): Record | null { - const path = legacyG14RetirementStatePath(); +export function readLegacyLegacyRuntimeRetirementMarker(): Record | null { + const path = legacyLegacyRuntimeRetirementStatePath(); if (!existsSync(path)) return null; try { return record(JSON.parse(readFileSync(path, "utf8")) as unknown); @@ -47,33 +47,33 @@ export function readLegacyG14RetirementMarker(): Record | null } } -export function writeLegacyG14RetirementMarker(status: string, reason: string, details: Record = {}): Record { - const path = legacyG14RetirementStatePath(); +export function writeLegacyLegacyRuntimeRetirementMarker(status: string, reason: string, details: Record = {}): Record { + const path = legacyLegacyRuntimeRetirementStatePath(); mkdirSync(dirname(path), { recursive: true }); - const previous = readLegacyG14RetirementMarker(); + const previous = readLegacyLegacyRuntimeRetirementMarker(); const marker = { status, reason, requestedAt: typeof previous?.requestedAt === "string" ? previous.requestedAt : new Date().toISOString(), updatedAt: new Date().toISOString(), - legacyApplications: legacyG14RetirementApplications(), - legacyNamespaces: legacyG14RetirementNamespaces(), - protectedApplications: protectedG14RuntimeApplications(), - protectedNamespaces: protectedG14RuntimeNamespaces(), + legacyApplications: legacyLegacyRuntimeRetirementApplications(), + legacyNamespaces: legacyLegacyRuntimeRetirementNamespaces(), + protectedApplications: protectedLegacyRuntimeRuntimeApplications(), + protectedNamespaces: protectedLegacyRuntimeRuntimeNamespaces(), ...details, }; writeFileSync(path, `${JSON.stringify(marker, null, 2)}\n`, "utf8"); return { ...marker, path }; } -export function legacyG14RetirementBlocksMonitor(): Record | null { - const marker = readLegacyG14RetirementMarker(); +export function legacyLegacyRuntimeRetirementBlocksMonitor(): Record | null { + const marker = readLegacyLegacyRuntimeRetirementMarker(); if (marker === null) { return { status: "retired-by-contract", - path: legacyG14RetirementStatePath(), + path: legacyLegacyRuntimeRetirementStatePath(), reason: "legacy G14 DEV/PROD monitor is retired; inspect retirement status for live cluster evidence", - next: { status: "bun scripts/cli.ts hwlab g14 retirement status", v02Monitor: "bun scripts/cli.ts hwlab g14 monitor-prs --lane v02", v03Monitor: "bun scripts/cli.ts hwlab g14 monitor-prs --lane v03" }, + next: { status: "bun scripts/cli.ts hwlab g14 retirement status", defaultRuntimeLaneMonitor: "bun scripts/cli.ts hwlab g14 monitor-prs --lane v02", v03Monitor: "bun scripts/cli.ts hwlab g14 monitor-prs --lane v03" }, }; } const status = String(marker.status ?? ""); @@ -126,11 +126,11 @@ export function parseNamespacedResourcePreview(text: string): Record { - const result = g14K3s(["sh", "--", legacyG14RetirementStatusScript()], 60_000); +export function legacyLegacyRuntimeRetirementStatus(): Record { + const result = legacyRuntimeK3s(["sh", "--", legacyLegacyRuntimeRetirementStatusScript()], 60_000); const sections = parseShellSections(statusText(result)); const legacyApplications = parseSectionJsonArray(sections.legacyApplications).map(applicationSummary); const legacyNamespaces = parseSectionJsonArray(sections.legacyNamespaces).map(namespaceSummary); @@ -167,8 +167,8 @@ export function legacyG14RetirementStatus(): Record { const retirementState = retired ? "retired" : terminating ? "terminating" : "active"; const protectedAppNames = new Set(protectedApplications.map((item) => item.name).filter((name): name is string => typeof name === "string")); const protectedNamespaceNames = new Set(protectedNamespaces.map((item) => item.name).filter((name): name is string => typeof name === "string")); - const missingProtectedApplications = protectedG14RuntimeApplications().filter((name) => !protectedAppNames.has(name)); - const missingProtectedNamespaces = protectedG14RuntimeNamespaces().filter((name) => !protectedNamespaceNames.has(name)); + const missingProtectedApplications = protectedLegacyRuntimeRuntimeApplications().filter((name) => !protectedAppNames.has(name)); + const missingProtectedNamespaces = protectedLegacyRuntimeRuntimeNamespaces().filter((name) => !protectedNamespaceNames.has(name)); const sectionsOk = shellSectionOk(sections.legacyApplications) && shellSectionOk(sections.legacyNamespaces) && @@ -178,7 +178,7 @@ export function legacyG14RetirementStatus(): Record { return { ok: isCommandSuccess(result) && sectionsOk, command: "hwlab g14 retirement status", - provider: G14_PROVIDER, + provider: LEGACY_RUNTIME_PROVIDER, argoNamespace: ARGO_NAMESPACE, retirementState, retired, @@ -194,15 +194,15 @@ export function legacyG14RetirementStatus(): Record { missingNamespaces: missingProtectedNamespaces, ok: missingProtectedApplications.length === 0 && missingProtectedNamespaces.length === 0, }, - marker: readLegacyG14RetirementMarker(), + marker: readLegacyLegacyRuntimeRetirementMarker(), result: compactCommandResult(result), next: retired - ? { verifyV02: "bun scripts/cli.ts hwlab g14 control-plane status --lane v02", verifyV03: "bun scripts/cli.ts hwlab nodes control-plane status --node G14 --lane v03" } + ? { verifyDefaultRuntimeLane: "bun scripts/cli.ts hwlab g14 control-plane status --lane v02", verifyV03: "bun scripts/cli.ts hwlab nodes control-plane status --node G14 --lane v03" } : { plan: "bun scripts/cli.ts hwlab g14 retirement plan", execute: "bun scripts/cli.ts hwlab g14 retirement execute --confirm" }, }; } -export function legacyG14RetirementPlan(status = legacyG14RetirementStatus()): Record { +export function legacyLegacyRuntimeRetirementPlan(status = legacyLegacyRuntimeRetirementStatus()): Record { return { ok: status.ok === true, command: "hwlab g14 retirement plan", @@ -210,15 +210,15 @@ export function legacyG14RetirementPlan(status = legacyG14RetirementStatus()): R mutation: false, reason: "retire legacy G14 DEV/PROD runtime and support surface without touching v0.2/v0.3", destructiveTargets: { - applications: legacyG14RetirementApplications().map((name) => ({ apiVersion: "argoproj.io/v1alpha1", kind: "Application", namespace: ARGO_NAMESPACE, name })), - namespaces: legacyG14RetirementNamespaces().map((name) => ({ apiVersion: "v1", kind: "Namespace", name })), + applications: legacyLegacyRuntimeRetirementApplications().map((name) => ({ apiVersion: "argoproj.io/v1alpha1", kind: "Application", namespace: ARGO_NAMESPACE, name })), + namespaces: legacyLegacyRuntimeRetirementNamespaces().map((name) => ({ apiVersion: "v1", kind: "Namespace", name })), }, protectedTargets: { - applications: protectedG14RuntimeApplications().map((name) => ({ apiVersion: "argoproj.io/v1alpha1", kind: "Application", namespace: ARGO_NAMESPACE, name })), - namespaces: protectedG14RuntimeNamespaces().map((name) => ({ apiVersion: "v1", kind: "Namespace", name })), + applications: protectedLegacyRuntimeRuntimeApplications().map((name) => ({ apiVersion: "argoproj.io/v1alpha1", kind: "Application", namespace: ARGO_NAMESPACE, name })), + namespaces: protectedLegacyRuntimeRuntimeNamespaces().map((name) => ({ apiVersion: "v1", kind: "Namespace", name })), }, localSupportActions: [ - { action: "write-retirement-marker", path: legacyG14RetirementStatePath() }, + { action: "write-retirement-marker", path: legacyLegacyRuntimeRetirementStatePath() }, { action: "cancel-active-local-job", jobName: "hwlab_g14_pr_monitor" }, { action: "block-new-monitor-starts", command: "bun scripts/cli.ts hwlab g14 monitor-prs --lane g14" }, ], @@ -227,23 +227,23 @@ export function legacyG14RetirementPlan(status = legacyG14RetirementStatus()): R }; } -export function legacyG14RecordRolloutRetired(): Record { +export function legacyLegacyRuntimeRecordRolloutRetired(): Record { return { ok: false, command: "hwlab g14 record-rollout", phase: "retired", degradedReason: "legacy-g14-dev-prod-retired", message: "Legacy G14 DEV rollout recording is retired. Use active runtime lane closeout/status evidence instead.", - retirement: readLegacyG14RetirementMarker(), + retirement: readLegacyLegacyRuntimeRetirementMarker(), next: { retirementStatus: "bun scripts/cli.ts hwlab g14 retirement status", - v02Status: "bun scripts/cli.ts hwlab g14 control-plane status --lane v02", + defaultRuntimeLaneStatus: "bun scripts/cli.ts hwlab g14 control-plane status --lane v02", v03Status: "bun scripts/cli.ts hwlab nodes control-plane status --node G14 --lane v03", }, }; } -export function cancelLegacyG14MonitorJobs(dryRun: boolean): Record { +export function cancelLegacyLegacyRuntimeMonitorJobs(dryRun: boolean): Record { const candidates = listJobs() .filter((job) => job.name === "hwlab_g14_pr_monitor" && (job.status === "queued" || job.status === "running")) .map((job) => ({ id: job.id, name: job.name, status: job.status, createdAt: job.createdAt, runnerPid: job.runnerPid ?? null })); @@ -252,9 +252,9 @@ export function cancelLegacyG14MonitorJobs(dryRun: boolean): Record record(action).ok !== false), dryRun: false, candidates, actions }; } -export function legacyG14RetirementDeleteScript(): string { - const legacyApps = legacyG14RetirementApplications(); - const legacyNamespaces = legacyG14RetirementNamespaces(); +export function legacyLegacyRuntimeRetirementDeleteScript(): string { + const legacyApps = legacyLegacyRuntimeRetirementApplications(); + const legacyNamespaces = legacyLegacyRuntimeRetirementNamespaces(); return [ "set +e", "overall=0", @@ -278,13 +278,13 @@ export function legacyG14RetirementDeleteScript(): string { ].join("\n"); } -export function waitForLegacyG14Retirement(timeoutSeconds: number): Record { +export function waitForLegacyLegacyRuntimeRetirement(timeoutSeconds: number): Record { const startedAtMs = Date.now(); let lastStatus: Record = {}; let attempts = 0; while (Date.now() - startedAtMs <= timeoutSeconds * 1000) { attempts += 1; - lastStatus = legacyG14RetirementStatus(); + lastStatus = legacyLegacyRuntimeRetirementStatus(); if (lastStatus.retired === true) { return { ok: true, attempts, elapsedMs: Date.now() - startedAtMs, status: lastStatus }; } @@ -294,21 +294,21 @@ export function waitForLegacyG14Retirement(timeoutSeconds: number): Record { - const before = legacyG14RetirementStatus(); +export function runLegacyLegacyRuntimeRetirement(options: LegacyRuntimeLegacyRetirementOptions): Record { + const before = legacyLegacyRuntimeRetirementStatus(); if (options.action === "status") return before; - if (options.action === "plan" || options.dryRun) return { ...legacyG14RetirementPlan(before), command: `hwlab g14 retirement ${options.action}`, reason: options.reason }; + if (options.action === "plan" || options.dryRun) return { ...legacyLegacyRuntimeRetirementPlan(before), command: `hwlab g14 retirement ${options.action}`, reason: options.reason }; - const markerBeforeDelete = writeLegacyG14RetirementMarker("retiring", options.reason, { command: "hwlab g14 retirement execute --confirm" }); - const localJobs = cancelLegacyG14MonitorJobs(false); - const deleteResult = g14K3s(["sh", "--", legacyG14RetirementDeleteScript()], Math.max(60_000, options.timeoutSeconds * 1000)); + const markerBeforeDelete = writeLegacyLegacyRuntimeRetirementMarker("retiring", options.reason, { command: "hwlab g14 retirement execute --confirm" }); + const localJobs = cancelLegacyLegacyRuntimeMonitorJobs(false); + const deleteResult = legacyRuntimeK3s(["sh", "--", legacyLegacyRuntimeRetirementDeleteScript()], Math.max(60_000, options.timeoutSeconds * 1000)); const deleteSections = parseShellSections(statusText(deleteResult)); - const afterDelete = legacyG14RetirementStatus(); - const wait = options.wait ? waitForLegacyG14Retirement(options.timeoutSeconds) : null; + const afterDelete = legacyLegacyRuntimeRetirementStatus(); + const wait = options.wait ? waitForLegacyLegacyRuntimeRetirement(options.timeoutSeconds) : null; const finalStatus = wait === null ? afterDelete : record(wait.status); const liveMutationOk = isCommandSuccess(deleteResult); const finalRetired = finalStatus.retired === true; - const marker = writeLegacyG14RetirementMarker(finalRetired ? "retired" : liveMutationOk ? "retiring" : "failed", options.reason, { + const marker = writeLegacyLegacyRuntimeRetirementMarker(finalRetired ? "retired" : liveMutationOk ? "retiring" : "failed", options.reason, { command: "hwlab g14 retirement execute --confirm", deleteExitCode: deleteResult.exitCode, finalRetirementState: finalStatus.retirementState ?? null, @@ -333,7 +333,7 @@ export function runLegacyG14Retirement(options: G14LegacyRetirementOptions): Rec finalStatus, marker, next: finalRetired - ? { verifyV02: "bun scripts/cli.ts hwlab g14 control-plane status --lane v02", verifyV03: "bun scripts/cli.ts hwlab nodes control-plane status --node G14 --lane v03" } + ? { verifyDefaultRuntimeLane: "bun scripts/cli.ts hwlab g14 control-plane status --lane v02", verifyV03: "bun scripts/cli.ts hwlab nodes control-plane status --node G14 --lane v03" } : { status: "bun scripts/cli.ts hwlab g14 retirement status" }, }; } diff --git a/scripts/src/hwlab-g14/v02-status.ts b/scripts/src/hwlab-legacy-runtime/runtime-status.ts similarity index 90% rename from scripts/src/hwlab-g14/v02-status.ts rename to scripts/src/hwlab-legacy-runtime/runtime-status.ts index 8809de8c..568d5202 100644 --- a/scripts/src/hwlab-g14/v02-status.ts +++ b/scripts/src/hwlab-legacy-runtime/runtime-status.ts @@ -1,6 +1,6 @@ -// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. v02-status module for scripts/src/hwlab-g14.ts. +// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. v02-status module for scripts/src/hwlab-legacy-runtime.ts. -// Moved mechanically from scripts/src/hwlab-g14.ts:1309-2787 for #903. +// Moved mechanically from scripts/src/hwlab-legacy-runtime.ts:1309-2787 for #903. import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"; import { dirname, join } from "node:path"; @@ -10,16 +10,16 @@ import { runCommand } from "../command"; import { cancelJob, listJobs, readJob, startJob } from "../jobs"; import { hwlabRequiredNoProxyEntries, hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneIds, hwlabRuntimeLaneSpec, isHwlabRuntimeLane, type HwlabRuntimeLane, type HwlabRuntimeLaneSpec } from "../hwlab-node-lanes"; -import type { CommandJsonResult, ShellSection, V02ControlPlaneStatusTarget, V02StatusTargetMode } from "./types"; +import type { CommandJsonResult, ShellSection, DefaultRuntimeLaneControlPlaneStatusTarget, DefaultRuntimeLaneStatusTargetMode } from "./types"; import { commandErrorSummary } from "./cleanup"; import { gitMirrorCacheProbeScript } from "./git-mirror"; import { conditionStatus } from "./observability"; import { durationSeconds, statusText } from "./pr-monitor"; -import { fieldBoolean, g14K3s, isCommandSuccess, nested, record, redactedCommand, shellQuote, shortSha, stringOrNull } from "./remote"; -import { v02PipelineRunName } from "./source"; -import { ARGO_NAMESPACE, CI_NAMESPACE, GIT_MIRROR_NAMESPACE, V02_APP, V02_BUILD_TASKRUN_CRITICAL_SECONDS, V02_BUILD_TASKRUN_WARNING_SECONDS, V02_CICD_REPO, V02_CLOUD_API_URL, V02_CLOUD_WEB_URL, V02_PIPELINERUN_PREFIX, V02_POLLER, V02_RECONCILER, V02_WORKSPACE } from "./types"; +import { fieldBoolean, legacyRuntimeK3s, isCommandSuccess, nested, record, redactedCommand, shellQuote, shortSha, stringOrNull } from "./remote"; +import { defaultRuntimeLanePipelineRunName } from "./source"; +import { ARGO_NAMESPACE, CI_NAMESPACE, GIT_MIRROR_NAMESPACE, DEFAULT_RUNTIME_LANE_APP, DEFAULT_RUNTIME_LANE_BUILD_TASKRUN_CRITICAL_SECONDS, DEFAULT_RUNTIME_LANE_BUILD_TASKRUN_WARNING_SECONDS, DEFAULT_RUNTIME_LANE_CICD_REPO, DEFAULT_RUNTIME_LANE_CLOUD_API_URL, DEFAULT_RUNTIME_LANE_CLOUD_WEB_URL, DEFAULT_RUNTIME_LANE_PIPELINERUN_PREFIX, DEFAULT_RUNTIME_LANE_POLLER, DEFAULT_RUNTIME_LANE_RECONCILER, DEFAULT_RUNTIME_LANE_WORKSPACE } from "./types"; -export interface V02TriggerSnapshot { +export interface DefaultRuntimeLaneTriggerSnapshot { sourceCommit: string | null; pipelineRun: string | null; before: Record | null; @@ -27,7 +27,7 @@ export interface V02TriggerSnapshot { observedAtMs: number; } -export function parseV02TriggerSnapshot(result: CommandJsonResult, observedAtMs: number): V02TriggerSnapshot { +export function parseDefaultRuntimeLaneTriggerSnapshot(result: CommandJsonResult, observedAtMs: number): DefaultRuntimeLaneTriggerSnapshot { const output = String(nested(result.parsed, ["data", "stdout"]) ?? result.stdout); const fields = keyValueLinesFromText(output); const sourceCommit = stringOrNull(fields.sourceCommit?.match(/^[0-9a-f]{40}$/iu)?.[0]); @@ -52,13 +52,13 @@ export function parseV02TriggerSnapshot(result: CommandJsonResult, observedAtMs: }; } -export function getV02TriggerSnapshot(): V02TriggerSnapshot { +export function getDefaultRuntimeLaneTriggerSnapshot(): DefaultRuntimeLaneTriggerSnapshot { const script = [ "set +e", "one_line() { tr '\\r\\n\\t' ' ' | sed 's/[[:space:]][[:space:]]*/ /g' | cut -c1-2000; }", "tmp_dir=$(mktemp -d /tmp/hwlab-v02-trigger-snapshot.XXXXXX)", "trap 'rm -rf \"$tmp_dir\"' EXIT", - `cicd_repo=${shellQuote(V02_CICD_REPO)}`, + `cicd_repo=${shellQuote(DEFAULT_RUNTIME_LANE_CICD_REPO)}`, "source_commit=", "if [ -d \"$cicd_repo/objects\" ] && [ -f \"$cicd_repo/HEAD\" ]; then", " source_commit=$(git --git-dir=\"$cicd_repo\" rev-parse refs/remotes/origin/v0.2 2>/dev/null || true)", @@ -66,7 +66,7 @@ export function getV02TriggerSnapshot(): V02TriggerSnapshot { " printf 'snapshotError\\t%s\\n' \"v0.2 CI/CD repo path exists but is not a bare git repo: $cicd_repo\"", "fi", "pipeline_run=", - `if [ -n "$source_commit" ]; then pipeline_run=${shellQuote(V02_PIPELINERUN_PREFIX)}-$(printf '%s' "$source_commit" | cut -c1-12); fi`, + `if [ -n "$source_commit" ]; then pipeline_run=${shellQuote(DEFAULT_RUNTIME_LANE_PIPELINERUN_PREFIX)}-$(printf '%s' "$source_commit" | cut -c1-12); fi`, "if [ -n \"$pipeline_run\" ]; then", ` (kubectl get pipelinerun -n ${shellQuote(CI_NAMESPACE)} "$pipeline_run" -o 'jsonpath={.status.conditions[0].status}{"\\n"}{.status.conditions[0].reason}{"\\n"}{.status.conditions[0].message}{"\\n"}' >\"$tmp_dir/pipelinerun.out\" 2>\"$tmp_dir/pipelinerun.err\"; printf '%s' "$?" >\"$tmp_dir/pipelinerun.status\") &`, " pipeline_pid=$!", @@ -87,11 +87,11 @@ export function getV02TriggerSnapshot(): V02TriggerSnapshot { "printf 'message\\t%s\\n' \"$(printf '%s\\n' \"$status_text\" | sed -n '3p')\"", "printf 'pipelineRunStderr\\t%s\\n' \"$(one_line < \"$tmp_dir/pipelinerun.err\")\"", ].join("\n"); - const result = g14K3s(["sh", "--", script], 180_000); - return parseV02TriggerSnapshot(result, Date.now()); + const result = legacyRuntimeK3s(["sh", "--", script], 180_000); + return parseDefaultRuntimeLaneTriggerSnapshot(result, Date.now()); } -export function v02ExistingPipelineRunReuseDecision(input: { +export function defaultRuntimeLaneExistingPipelineRunReuseDecision(input: { sourceCommit: string; before: Record; latestSourceCommit: string | null; @@ -107,7 +107,7 @@ export function v02ExistingPipelineRunReuseDecision(input: { reason: "source-head-recheck-unresolved-before-existing-pipelinerun-reuse", sourceCommit: input.sourceCommit, latestSourceCommit, - previousPipelineRun: v02PipelineRunName(input.sourceCommit), + previousPipelineRun: defaultRuntimeLanePipelineRunName(input.sourceCommit), }; } if (latestSourceCommit !== null && latestSourceCommit !== input.sourceCommit) { @@ -117,8 +117,8 @@ export function v02ExistingPipelineRunReuseDecision(input: { reason: "source-head-advanced-before-existing-pipelinerun-reuse", sourceCommit: input.sourceCommit, latestSourceCommit, - previousPipelineRun: v02PipelineRunName(input.sourceCommit), - latestPipelineRun: v02PipelineRunName(latestSourceCommit), + previousPipelineRun: defaultRuntimeLanePipelineRunName(input.sourceCommit), + latestPipelineRun: defaultRuntimeLanePipelineRunName(latestSourceCommit), }; } return { @@ -127,12 +127,12 @@ export function v02ExistingPipelineRunReuseDecision(input: { reason: alreadyUsable ? "existing-pipelinerun-reused" : "existing-pipelinerun-terminal-failed", sourceCommit: input.sourceCommit, latestSourceCommit, - previousPipelineRun: v02PipelineRunName(input.sourceCommit), + previousPipelineRun: defaultRuntimeLanePipelineRunName(input.sourceCommit), }; } export function getPipelineRunCompact(name: string): Record { - const result = g14K3s([ + const result = legacyRuntimeK3s([ "kubectl", "get", "pipelinerun", @@ -336,7 +336,7 @@ export function secondsBetween(start: unknown, end: unknown): number | null { return Math.round((endMs - startMs) / 1000); } -export function pipelineRunStatusRowFromLine(line: string, nowMs: number, pipelineRunPrefix = V02_PIPELINERUN_PREFIX): Record | null { +export function pipelineRunStatusRowFromLine(line: string, nowMs: number, pipelineRunPrefix = DEFAULT_RUNTIME_LANE_PIPELINERUN_PREFIX): Record | null { const [ name = "", sourceCommit = "", @@ -364,7 +364,7 @@ export function pipelineRunStatusRowFromLine(line: string, nowMs: number, pipeli }; } -export function parsePipelineRunRows(text: string, limit: number, nowMs = Date.now(), pipelineRunPrefix = V02_PIPELINERUN_PREFIX): Record { +export function parsePipelineRunRows(text: string, limit: number, nowMs = Date.now(), pipelineRunPrefix = DEFAULT_RUNTIME_LANE_PIPELINERUN_PREFIX): Record { const rows = text .split(/\r?\n/u) .map((line) => pipelineRunStatusRowFromLine(line.trim(), nowMs, pipelineRunPrefix)) @@ -404,8 +404,8 @@ export function pipelineRunRowsJsonPath(): string { ].join(""); } -export function listV02PipelineRunsCompact(limit = 8): Record { - const result = g14K3s([ +export function listDefaultRuntimeLanePipelineRunsCompact(limit = 8): Record { + const result = legacyRuntimeK3s([ "kubectl", "get", "pipelinerun", @@ -469,8 +469,8 @@ export function shellSectionOk(section: ShellSection | undefined): boolean { return section?.exitCode === 0; } -export function v02ControlPlaneStatusBundle(target: V02ControlPlaneStatusTarget = {}): CommandJsonResult { - const targetMode: V02StatusTargetMode = target.mode +export function defaultRuntimeLaneControlPlaneStatusBundle(target: DefaultRuntimeLaneControlPlaneStatusTarget = {}): CommandJsonResult { + const targetMode: DefaultRuntimeLaneStatusTargetMode = target.mode ?? (target.pipelineRun !== undefined && target.pipelineRun !== null ? "pipeline-run" : target.sourceCommit !== undefined ? "source-commit" : "latest-source-head"); const targetInit = target.pipelineRun !== undefined && target.pipelineRun !== null ? [ @@ -480,7 +480,7 @@ export function v02ControlPlaneStatusBundle(target: V02ControlPlaneStatusTarget ].join("\n") : [ target.sourceCommit === undefined - ? `source_commit=$(git --git-dir=${shellQuote(V02_CICD_REPO)} rev-parse refs/remotes/origin/v0.2 2>/dev/null || true)` + ? `source_commit=$(git --git-dir=${shellQuote(DEFAULT_RUNTIME_LANE_CICD_REPO)} rev-parse refs/remotes/origin/v0.2 2>/dev/null || true)` : `source_commit=${shellQuote(target.sourceCommit ?? "")}`, "pipeline_run=", ].join("\n"); @@ -488,7 +488,7 @@ export function v02ControlPlaneStatusBundle(target: V02ControlPlaneStatusTarget "set +e", targetInit, `target_mode=${shellQuote(targetMode)}`, - `if [ -z "$pipeline_run" ] && [ -n "$source_commit" ]; then pipeline_run="${V02_PIPELINERUN_PREFIX}-$(printf '%s' "$source_commit" | cut -c1-12)"; fi`, + `if [ -z "$pipeline_run" ] && [ -n "$source_commit" ]; then pipeline_run="${DEFAULT_RUNTIME_LANE_PIPELINERUN_PREFIX}-$(printf '%s' "$source_commit" | cut -c1-12)"; fi`, "section() {", " name=\"$1\"", " shift", @@ -500,28 +500,28 @@ export function v02ControlPlaneStatusBundle(target: V02ControlPlaneStatusTarget "section statusTarget printf 'mode\\t%s\\nsourceCommit\\t%s\\npipelineRun\\t%s\\n' \"$target_mode\" \"$source_commit\" \"$pipeline_run\"", "section sourceCommit printf '%s\\n' \"$source_commit\"", "section pipelineRunName printf '%s\\n' \"$pipeline_run\"", - `section sourceHeads sh -c ${shellQuote(v02SourceHeadsProbeScript())} sh "$source_commit"`, + `section sourceHeads sh -c ${shellQuote(defaultRuntimeLaneSourceHeadsProbeScript())} sh "$source_commit"`, "section queryNow date -u +%Y-%m-%dT%H:%M:%SZ", `section controlPlane kubectl get pipeline,role,rolebinding,serviceaccount -n ${shellQuote(CI_NAMESPACE)} -l hwlab.pikastech.local/gitops-target=v02 -o name`, - `section obsoleteCronJobs kubectl get cronjob -n ${shellQuote(CI_NAMESPACE)} ${shellQuote(V02_POLLER)} ${shellQuote(V02_RECONCILER)} --ignore-not-found -o name`, - `section argo kubectl get application -n ${shellQuote(ARGO_NAMESPACE)} ${shellQuote(V02_APP)} -o 'jsonpath={.spec.source.targetRevision}{"\\n"}{.spec.source.path}{"\\n"}{.status.sync.revision}{"\\n"}{.status.sync.status}{"\\n"}{.status.health.status}{"\\n"}'`, + `section obsoleteCronJobs kubectl get cronjob -n ${shellQuote(CI_NAMESPACE)} ${shellQuote(DEFAULT_RUNTIME_LANE_POLLER)} ${shellQuote(DEFAULT_RUNTIME_LANE_RECONCILER)} --ignore-not-found -o name`, + `section argo kubectl get application -n ${shellQuote(ARGO_NAMESPACE)} ${shellQuote(DEFAULT_RUNTIME_LANE_APP)} -o 'jsonpath={.spec.source.targetRevision}{"\\n"}{.spec.source.path}{"\\n"}{.status.sync.revision}{"\\n"}{.status.sync.status}{"\\n"}{.status.health.status}{"\\n"}'`, `if [ -n "$pipeline_run" ]; then section pipelineRun kubectl get pipelinerun -n ${shellQuote(CI_NAMESPACE)} "$pipeline_run" -o 'jsonpath={.status.conditions[0].status}{"\\n"}{.status.conditions[0].reason}{"\\n"}{.status.conditions[0].message}{"\\n"}'; else section pipelineRun sh -c 'true'; fi`, `if [ -n "$pipeline_run" ]; then section taskRuns kubectl get taskrun -n ${shellQuote(CI_NAMESPACE)} -l "tekton.dev/pipelineRun=$pipeline_run" -o 'jsonpath={range .items[*]}{.metadata.name}{"\\t"}{.status.conditions[0].status}{"\\t"}{.status.conditions[0].reason}{"\\t"}{.status.startTime}{"\\t"}{.status.completionTime}{"\\n"}{end}'; else section taskRuns sh -c 'true'; fi`, - `if [ -n "$pipeline_run" ]; then section planArtifacts sh -c ${shellQuote(v02PlanArtifactsLogScript())} plan-artifacts "$pipeline_run"; else section planArtifacts sh -c 'true'; fi`, - `section runtimeWorkloads kubectl get deploy,statefulset,job -n hwlab-v02 -l hwlab.pikastech.local/gitops-target=v02 -o ${shellQuote(v02RuntimeWorkloadsColumns())} --no-headers`, + `if [ -n "$pipeline_run" ]; then section planArtifacts sh -c ${shellQuote(defaultRuntimeLanePlanArtifactsLogScript())} plan-artifacts "$pipeline_run"; else section planArtifacts sh -c 'true'; fi`, + `section runtimeWorkloads kubectl get deploy,statefulset,job -n hwlab-v02 -l hwlab.pikastech.local/gitops-target=v02 -o ${shellQuote(defaultRuntimeLaneRuntimeWorkloadsColumns())} --no-headers`, `section recentPipelineRuns kubectl get pipelinerun -n ${shellQuote(CI_NAMESPACE)} -l hwlab.pikastech.local/gitops-target=v02 -o ${shellQuote(pipelineRunRowsJsonPath())}`, `section gitMirrorCache kubectl exec -n ${shellQuote(GIT_MIRROR_NAMESPACE)} deploy/git-mirror-http -- sh -lc ${shellQuote(gitMirrorCacheProbeScript())}`, - `section webAssets sh -c ${shellQuote(v02WebAssetsProbeScript())}`, + `section webAssets sh -c ${shellQuote(defaultRuntimeLaneWebAssetsProbeScript())}`, ].join("\n"); - return g14K3s(["sh", "--", script], 60_000); + return legacyRuntimeK3s(["sh", "--", script], 60_000); } -export function v02SourceHeadsProbeScript(): string { +export function defaultRuntimeLaneSourceHeadsProbeScript(): string { return [ "set +e", "target_source_commit=${1:-}", - `cicd_repo=${shellQuote(V02_CICD_REPO)}`, - `workspace=${shellQuote(V02_WORKSPACE)}`, + `cicd_repo=${shellQuote(DEFAULT_RUNTIME_LANE_CICD_REPO)}`, + `workspace=${shellQuote(DEFAULT_RUNTIME_LANE_WORKSPACE)}`, "rev_cicd() { git --git-dir=\"$cicd_repo\" rev-parse \"$1\" 2>/dev/null || true; }", "rev_workspace() { git -C \"$workspace\" rev-parse \"$1\" 2>/dev/null || true; }", "origin_head=$(rev_cicd refs/remotes/origin/v0.2)", @@ -554,7 +554,7 @@ export function v02SourceHeadsProbeScript(): string { ].join("\n"); } -export function v02PlanArtifactsLogScript(): string { +export function defaultRuntimeLanePlanArtifactsLogScript(): string { return [ "pipeline_run=\"$1\"", `namespace=${shellQuote(CI_NAMESPACE)}`, @@ -567,7 +567,7 @@ export function v02PlanArtifactsLogScript(): string { ].join("\n"); } -export function v02RuntimeWorkloadsColumns(): string { +export function defaultRuntimeLaneRuntimeWorkloadsColumns(): string { return [ "custom-columns=KIND:.kind", "NAME:.metadata.name", @@ -580,11 +580,11 @@ export function v02RuntimeWorkloadsColumns(): string { ].join(","); } -export function v02WebAssetsProbeScript(): string { +export function defaultRuntimeLaneWebAssetsProbeScript(): string { return [ "set +e", - `base=${shellQuote(V02_CLOUD_WEB_URL)}`, - `api=${shellQuote(V02_CLOUD_API_URL)}`, + `base=${shellQuote(DEFAULT_RUNTIME_LANE_CLOUD_WEB_URL)}`, + `api=${shellQuote(DEFAULT_RUNTIME_LANE_CLOUD_API_URL)}`, "fetch_url() {", " if command -v curl >/dev/null 2>&1; then", " curl -fsS --connect-timeout 2 --max-time 10 \"$1\"", @@ -642,7 +642,7 @@ export function taskRunsCompactFromText(text: string, commandOk: boolean, pipeli stderr: stderr.trim().slice(0, 2000), counts: { succeeded: 0, failed: 0, running: 0, unknown: 0 }, items: [], - performance: v02TaskRunPerformanceSummary([]), + performance: defaultRuntimeLaneTaskRunPerformanceSummary([]), }; } const items = text @@ -666,7 +666,7 @@ export function taskRunsCompactFromText(text: string, commandOk: boolean, pipeli running: items.filter((item) => item.status === "Unknown").length, unknown: items.filter((item) => item.status !== "True" && item.status !== "False" && item.status !== "Unknown").length, }; - const performance = v02TaskRunPerformanceSummary(items); + const performance = defaultRuntimeLaneTaskRunPerformanceSummary(items); const performanceWarning = performance.ok === false ? `; ${String(performance.summary ?? "")}` : ""; return { ok: true, @@ -679,7 +679,7 @@ export function taskRunsCompactFromText(text: string, commandOk: boolean, pipeli }; } -export function v02TaskRunPipelineTaskName(name: string): string | null { +export function defaultRuntimeLaneTaskRunPipelineTaskName(name: string): string | null { const buildIndex = name.lastIndexOf("-build-"); if (buildIndex >= 0) return name.slice(buildIndex + 1); const knownSuffixes = [ @@ -694,14 +694,14 @@ export function v02TaskRunPipelineTaskName(name: string): string | null { return knownSuffixes.find((suffix) => name.endsWith(`-${suffix}`)) ?? null; } -export function v02TaskRunPerformanceSummary(taskRuns: unknown[]): Record { +export function defaultRuntimeLaneTaskRunPerformanceSummary(taskRuns: unknown[]): Record { const slowTaskRuns: Record[] = []; for (const itemRaw of taskRuns) { const item = record(itemRaw); const name = stringOrNull(item.name) ?? ""; - const pipelineTask = stringOrNull(item.pipelineTask) ?? v02TaskRunPipelineTaskName(name); + const pipelineTask = stringOrNull(item.pipelineTask) ?? defaultRuntimeLaneTaskRunPipelineTaskName(name); const durationSeconds = typeof item.durationSeconds === "number" ? item.durationSeconds : null; - if (!pipelineTask?.startsWith("build-") || durationSeconds === null || durationSeconds <= V02_BUILD_TASKRUN_WARNING_SECONDS) continue; + if (!pipelineTask?.startsWith("build-") || durationSeconds === null || durationSeconds <= DEFAULT_RUNTIME_LANE_BUILD_TASKRUN_WARNING_SECONDS) continue; const serviceId = pipelineTask.slice("build-".length) || null; slowTaskRuns.push({ name, @@ -710,9 +710,9 @@ export function v02TaskRunPerformanceSummary(taskRuns: unknown[]): Record= V02_BUILD_TASKRUN_CRITICAL_SECONDS ? "critical" : "warning", - message: `${pipelineTask} took ${durationSeconds}s, above v0.2 build TaskRun warning budget ${V02_BUILD_TASKRUN_WARNING_SECONDS}s`, + budgetSeconds: DEFAULT_RUNTIME_LANE_BUILD_TASKRUN_WARNING_SECONDS, + severity: durationSeconds >= DEFAULT_RUNTIME_LANE_BUILD_TASKRUN_CRITICAL_SECONDS ? "critical" : "warning", + message: `${pipelineTask} took ${durationSeconds}s, above v0.2 build TaskRun warning budget ${DEFAULT_RUNTIME_LANE_BUILD_TASKRUN_WARNING_SECONDS}s`, }); } slowTaskRuns.sort((left, right) => Number(right.durationSeconds ?? 0) - Number(left.durationSeconds ?? 0)); @@ -721,17 +721,17 @@ export function v02TaskRunPerformanceSummary(taskRuns: unknown[]): Record { +export function defaultRuntimeLanePlanArtifactsFromText(text: string, commandOk: boolean, pipelineRun: string | null, exitCode: number | null, stderr: string): Record { const events: Record[] = []; const pods: string[] = []; for (const rawLine of text.split(/\r?\n/u)) { @@ -858,7 +858,7 @@ export function v02PlanArtifactsFromText(text: string, commandOk: boolean, pipel }; } -export function v02RuntimeWorkloadsFromText(text: string, commandOk: boolean, exitCode: number | null, stderr: string): Record { +export function defaultRuntimeLaneRuntimeWorkloadsFromText(text: string, commandOk: boolean, exitCode: number | null, stderr: string): Record { if (!commandOk) { return { ok: false, @@ -900,13 +900,13 @@ export function keyValueLinesFromText(text: string): Record { return fields; } -export function v02SourceHeadsFromText(text: string, commandOk: boolean, exitCode: number | null, stderr: string): Record { +export function defaultRuntimeLaneSourceHeadsFromText(text: string, commandOk: boolean, exitCode: number | null, stderr: string): Record { const fields = keyValueLinesFromText(text); const dirtyCount = numericField(fields.workspaceDirtyCount); const targetSourceCommit = fields.targetSourceCommit || null; return { ok: commandOk, - cicdRepo: fields.cicdRepo || V02_CICD_REPO, + cicdRepo: fields.cicdRepo || DEFAULT_RUNTIME_LANE_CICD_REPO, cicdRepoExists: fields.cicdRepoExists === "yes", cicdSourceHead: fields.cicdSourceHead || null, originHead: fields.originHead || null, @@ -919,7 +919,7 @@ export function v02SourceHeadsFromText(text: string, commandOk: boolean, exitCod targetObjectExists: fieldBoolean(fields.targetObjectExists), targetAncestorOfOriginHead: fieldBoolean(fields.targetAncestorOfOriginHead), workspace: { - path: fields.workspacePath || V02_WORKSPACE, + path: fields.workspacePath || DEFAULT_RUNTIME_LANE_WORKSPACE, branch: fields.workspaceBranch || null, head: fields.workspaceHead || null, originHead: fields.workspaceOriginHead || null, @@ -932,7 +932,7 @@ export function v02SourceHeadsFromText(text: string, commandOk: boolean, exitCod }; } -export function v02FalseGreenGuard(input: { +export function defaultRuntimeLaneFalseGreenGuard(input: { sourceCommit: string | null; pipelineRun: Record | null; taskRuns: Record; @@ -1008,8 +1008,8 @@ export function v02FalseGreenGuard(input: { }; } -export function v02TargetValidation(input: { - targetMode: V02StatusTargetMode; +export function defaultRuntimeLaneTargetValidation(input: { + targetMode: DefaultRuntimeLaneStatusTargetMode; sourceCommit: string | null; pipelineRun: Record | null; argo: Record; @@ -1112,7 +1112,7 @@ export function v02TargetValidation(input: { }; } -export function v02LatestOnlyTargetValidation(input: { +export function defaultRuntimeLaneLatestOnlyTargetValidation(input: { targetMode: string; sourceCommit: string | null; pipelineRun: Record | null; @@ -1147,7 +1147,7 @@ export function v02LatestOnlyTargetValidation(input: { }; } -export function v02CloseoutRecommendedNext(input: { +export function defaultRuntimeLaneCloseoutRecommendedNext(input: { closeable: boolean; blockedReasons: string[]; pendingReasons: string[]; @@ -1180,7 +1180,7 @@ export function v02CloseoutRecommendedNext(input: { return { action: "inspect-status", command: input.statusCommand }; } -export function v02CloseoutVerdict(status: Record): Record { +export function defaultRuntimeLaneCloseoutVerdict(status: Record): Record { const statusTarget = record(status.statusTarget); const targetMode = stringOrNull(statusTarget.mode) ?? "latest-source-head"; const sourceCommit = stringOrNull(status.sourceCommit) ?? stringOrNull(statusTarget.sourceCommit); @@ -1259,7 +1259,7 @@ export function v02CloseoutVerdict(status: Record): Record): Record; gitMirrorSummary: Record; @@ -1357,8 +1357,8 @@ export function v02CommitAlignment(input: { const workspace = record(input.sourceHeads.workspace); const workspaceHead = stringOrNull(workspace.head); const workspaceOriginHead = stringOrNull(workspace.originHead); - const mirrorSourceHead = stringOrNull(input.gitMirrorSummary.localV02); - const mirrorGithubSourceHead = stringOrNull(input.gitMirrorSummary.githubV02); + const mirrorSourceHead = stringOrNull(input.gitMirrorSummary.localDefaultRuntimeLane); + const mirrorGithubSourceHead = stringOrNull(input.gitMirrorSummary.githubDefaultRuntimeLane); const recentItems = Array.isArray(input.recentPipelineRuns.items) ? input.recentPipelineRuns.items.map((item) => record(item)) : []; @@ -1406,7 +1406,7 @@ export function v02CommitAlignment(input: { expectedSourceHead, originHead, cicdSourceHead, - cicdRepo: input.sourceHeads.cicdRepo ?? V02_CICD_REPO, + cicdRepo: input.sourceHeads.cicdRepo ?? DEFAULT_RUNTIME_LANE_CICD_REPO, mirrorSourceHead, mirrorGithubSourceHead, latestPipelineRun: latestPipelineRun === null @@ -1437,7 +1437,7 @@ export function v02CommitAlignment(input: { gitopsInSync: input.gitMirrorSummary.gitopsInSync ?? null, staleReasons, workspace: { - path: workspace.path ?? V02_WORKSPACE, + path: workspace.path ?? DEFAULT_RUNTIME_LANE_WORKSPACE, branch: workspace.branch ?? null, head: workspaceHead, originHead: workspaceOriginHead, @@ -1484,7 +1484,7 @@ export function stringArray(value: unknown): string[] { return Array.isArray(value) ? value.filter((item): item is string => typeof item === "string" && item.length > 0) : []; } -export function listV02PipelineRunsCompactFromText(text: string, commandOk: boolean, command: string[] | string, exitCode: number | null, stderr: string, limit = 8, nowMs = Date.now()): Record { +export function listDefaultRuntimeLanePipelineRunsCompactFromText(text: string, commandOk: boolean, command: string[] | string, exitCode: number | null, stderr: string, limit = 8, nowMs = Date.now()): Record { if (!commandOk) { return { ok: false, diff --git a/scripts/src/hwlab-g14/secrets.ts b/scripts/src/hwlab-legacy-runtime/secrets.ts similarity index 84% rename from scripts/src/hwlab-g14/secrets.ts rename to scripts/src/hwlab-legacy-runtime/secrets.ts index a4105da9..d71dd3c0 100644 --- a/scripts/src/hwlab-g14/secrets.ts +++ b/scripts/src/hwlab-legacy-runtime/secrets.ts @@ -1,6 +1,6 @@ -// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. secrets module for scripts/src/hwlab-g14.ts. +// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. secrets module for scripts/src/hwlab-legacy-runtime.ts. -// Moved mechanically from scripts/src/hwlab-g14.ts:5055-5524 for #903. +// Moved mechanically from scripts/src/hwlab-legacy-runtime.ts:5055-5524 for #903. import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"; import { dirname, join } from "node:path"; @@ -10,25 +10,25 @@ import { runCommand } from "../command"; import { cancelJob, listJobs, readJob, startJob } from "../jobs"; import { hwlabRequiredNoProxyEntries, hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneIds, hwlabRuntimeLaneSpec, isHwlabRuntimeLane, type HwlabRuntimeLane, type HwlabRuntimeLaneSpec } from "../hwlab-node-lanes"; -import type { G14SecretOptions } from "./types"; +import type { LegacyRuntimeSecretOptions } from "./types"; import { statusText } from "./pr-monitor"; -import { compactCommandResult, g14K3s, g14K3sInlineScriptWithInput, isCommandSuccess, readOrCreateLocalMasterAdminApiKey, runtimeLaneMasterAdminApiKeySecretName, runtimeLaneOpenFgaSecretName, runtimeLanePostgresSecretName, runtimeLanePrimaryDbName, runtimeLaneSecretFieldManager, shellQuote } from "./remote"; -import { V02_MASTER_ADMIN_API_KEY_SECRET, V02_MASTER_ADMIN_API_KEY_SECRET_KEY, V02_OPENFGA_AUTHN_SECRET_KEY, V02_OPENFGA_DATASTORE_URI_SECRET_KEY, V02_OPENFGA_DB_NAME, V02_OPENFGA_DB_USER, V02_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY, V02_OPENFGA_SECRET, V02_RUNTIME_NAMESPACE } from "./types"; -import { keyValueLinesFromText, numericField } from "./v02-status"; +import { compactCommandResult, legacyRuntimeK3s, legacyRuntimeK3sInlineScriptWithInput, isCommandSuccess, readOrCreateLocalMasterAdminApiKey, runtimeLaneMasterAdminApiKeySecretName, runtimeLaneOpenFgaSecretName, runtimeLanePostgresSecretName, runtimeLanePrimaryDbName, runtimeLaneSecretFieldManager, shellQuote } from "./remote"; +import { DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_SECRET, DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_SECRET_KEY, DEFAULT_RUNTIME_LANE_OPENFGA_AUTHN_SECRET_KEY, DEFAULT_RUNTIME_LANE_OPENFGA_DATASTORE_URI_SECRET_KEY, DEFAULT_RUNTIME_LANE_OPENFGA_DB_NAME, DEFAULT_RUNTIME_LANE_OPENFGA_DB_USER, DEFAULT_RUNTIME_LANE_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY, DEFAULT_RUNTIME_LANE_OPENFGA_SECRET, DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE } from "./types"; +import { keyValueLinesFromText, numericField } from "./runtime-status"; -export function v02SecretScript(options: G14SecretOptions): string { +export function defaultRuntimeLaneSecretScript(options: LegacyRuntimeSecretOptions): string { const spec = hwlabRuntimeLaneSpec(options.lane); - if (options.preset === "generic-delete") return v02DeleteSecretScript(options); - if (options.preset === "master-server-admin-api-key") return v02MasterAdminApiKeySecretScript(options, spec); + if (options.preset === "generic-delete") return defaultRuntimeLaneDeleteSecretScript(options); + if (options.preset === "master-server-admin-api-key") return defaultRuntimeLaneMasterAdminApiKeySecretScript(options, spec); return [ - v02OpenFgaSecretScript(options, spec), + defaultRuntimeLaneOpenFgaSecretScript(options, spec), ].join("\n"); } -export function v02DeleteSecretScript(options: G14SecretOptions): string { +export function defaultRuntimeLaneDeleteSecretScript(options: LegacyRuntimeSecretOptions): string { return [ "set +e", - `namespace=${shellQuote(V02_RUNTIME_NAMESPACE)}`, + `namespace=${shellQuote(DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE)}`, `name=${shellQuote(options.name)}`, `dry_run=${shellQuote(options.dryRun ? "true" : "false")}`, "preset=generic-delete", @@ -62,7 +62,7 @@ export function v02DeleteSecretScript(options: G14SecretOptions): string { ].join("\n"); } -export function v02OpenFgaSecretScript(options: G14SecretOptions, spec: HwlabRuntimeLaneSpec): string { +export function defaultRuntimeLaneOpenFgaSecretScript(options: LegacyRuntimeSecretOptions, spec: HwlabRuntimeLaneSpec): string { const selectedKey = options.key ?? ""; const namespace = spec.runtimeNamespace; const openFgaSecret = runtimeLaneOpenFgaSecretName(spec); @@ -70,8 +70,8 @@ export function v02OpenFgaSecretScript(options: G14SecretOptions, spec: HwlabRun const primaryDbName = runtimeLanePrimaryDbName(spec); const dedicatedDb = spec.lane === "v02"; const dbMode = dedicatedDb ? "dedicated" : "primary"; - const dbName = dedicatedDb ? V02_OPENFGA_DB_NAME : primaryDbName; - const dbUser = dedicatedDb ? V02_OPENFGA_DB_USER : primaryDbName; + const dbName = dedicatedDb ? DEFAULT_RUNTIME_LANE_OPENFGA_DB_NAME : primaryDbName; + const dbUser = dedicatedDb ? DEFAULT_RUNTIME_LANE_OPENFGA_DB_USER : primaryDbName; const dbHost = `${postgresSecret}.${namespace}.svc.cluster.local`; const fieldManager = runtimeLaneSecretFieldManager(spec); return [ @@ -79,9 +79,9 @@ export function v02OpenFgaSecretScript(options: G14SecretOptions, spec: HwlabRun `namespace=${shellQuote(namespace)}`, `name=${shellQuote(openFgaSecret)}`, `selected_key=${shellQuote(selectedKey)}`, - `authn_key=${shellQuote(V02_OPENFGA_AUTHN_SECRET_KEY)}`, - `datastore_uri_key=${shellQuote(V02_OPENFGA_DATASTORE_URI_SECRET_KEY)}`, - `postgres_password_key=${shellQuote(V02_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY)}`, + `authn_key=${shellQuote(DEFAULT_RUNTIME_LANE_OPENFGA_AUTHN_SECRET_KEY)}`, + `datastore_uri_key=${shellQuote(DEFAULT_RUNTIME_LANE_OPENFGA_DATASTORE_URI_SECRET_KEY)}`, + `postgres_password_key=${shellQuote(DEFAULT_RUNTIME_LANE_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY)}`, `db_mode=${shellQuote(dbMode)}`, `db_name=${shellQuote(dbName)}`, `db_user=${shellQuote(dbUser)}`, @@ -248,7 +248,7 @@ export function v02OpenFgaSecretScript(options: G14SecretOptions, spec: HwlabRun ].join("\n"); } -export function v02MasterAdminApiKeySecretScript(options: G14SecretOptions, spec: HwlabRuntimeLaneSpec): string { +export function defaultRuntimeLaneMasterAdminApiKeySecretScript(options: LegacyRuntimeSecretOptions, spec: HwlabRuntimeLaneSpec): string { const namespace = spec.runtimeNamespace; const name = runtimeLaneMasterAdminApiKeySecretName(spec); const fieldManager = runtimeLaneSecretFieldManager(spec); @@ -256,7 +256,7 @@ export function v02MasterAdminApiKeySecretScript(options: G14SecretOptions, spec "set +e", `namespace=${shellQuote(namespace)}`, `name=${shellQuote(name)}`, - `api_key_name=${shellQuote(V02_MASTER_ADMIN_API_KEY_SECRET_KEY)}`, + `api_key_name=${shellQuote(DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_SECRET_KEY)}`, `action_request=${shellQuote(options.action)}`, `dry_run=${shellQuote(options.dryRun ? "true" : "false")}`, `field_manager=${shellQuote(fieldManager)}`, @@ -314,13 +314,13 @@ export function v02MasterAdminApiKeySecretScript(options: G14SecretOptions, spec ].join("\n"); } -export function v02SecretStatusFromText(text: string, commandOk: boolean, exitCode: number | null, stderr: string): Record { +export function defaultRuntimeLaneSecretStatusFromText(text: string, commandOk: boolean, exitCode: number | null, stderr: string): Record { const fields = keyValueLinesFromText(text); if (fields.preset === "generic-delete") { const absent = fields.afterExists !== "yes"; return { ok: commandOk && absent, - namespace: fields.namespace || V02_RUNTIME_NAMESPACE, + namespace: fields.namespace || DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE, secret: fields.secret || null, preset: "generic-delete", action: fields.action || null, @@ -350,9 +350,9 @@ export function v02SecretStatusFromText(text: string, commandOk: boolean, exitCo String(fields.afterApiKeyPrefix ?? "").startsWith("hwl_live_"); return { ok: commandOk && healthy, - namespace: fields.namespace || V02_RUNTIME_NAMESPACE, - secret: fields.secret || V02_MASTER_ADMIN_API_KEY_SECRET, - key: fields.key || V02_MASTER_ADMIN_API_KEY_SECRET_KEY, + namespace: fields.namespace || DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE, + secret: fields.secret || DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_SECRET, + key: fields.key || DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_SECRET_KEY, preset: "master-server-admin-api-key", action: fields.action || null, dryRun: fields.dryRun === "true", @@ -370,8 +370,8 @@ export function v02SecretStatusFromText(text: string, commandOk: boolean, exitCo stderr: commandOk ? "" : stderr.trim().slice(0, 2000), valuesRedacted: true, summary: healthy - ? `${fields.secret || V02_MASTER_ADMIN_API_KEY_SECRET}/${fields.key || V02_MASTER_ADMIN_API_KEY_SECRET_KEY} exists` - : `${fields.secret || V02_MASTER_ADMIN_API_KEY_SECRET}/${fields.key || V02_MASTER_ADMIN_API_KEY_SECRET_KEY} missing`, + ? `${fields.secret || DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_SECRET}/${fields.key || DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_SECRET_KEY} exists` + : `${fields.secret || DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_SECRET}/${fields.key || DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_SECRET_KEY} missing`, }; } if (fields.preset === "openfga") { @@ -390,8 +390,8 @@ export function v02SecretStatusFromText(text: string, commandOk: boolean, exitCo const healthy = keysHealthy && databaseHealthy; return { ok: commandOk && healthy, - namespace: fields.namespace || V02_RUNTIME_NAMESPACE, - secret: fields.secret || V02_OPENFGA_SECRET, + namespace: fields.namespace || DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE, + secret: fields.secret || DEFAULT_RUNTIME_LANE_OPENFGA_SECRET, key: fields.key || null, preset: "openfga", action: fields.action || null, @@ -422,21 +422,21 @@ export function v02SecretStatusFromText(text: string, commandOk: boolean, exitCo }, postgresAdminSecretPresent: fields.postgresAdminSecretPresent === "yes", postgresSecret: fields.postgresSecret || null, - dbName: fields.dbName || V02_OPENFGA_DB_NAME, - dbUser: fields.dbUser || V02_OPENFGA_DB_USER, + dbName: fields.dbName || DEFAULT_RUNTIME_LANE_OPENFGA_DB_NAME, + dbUser: fields.dbUser || DEFAULT_RUNTIME_LANE_OPENFGA_DB_USER, applyExitCode: numericField(fields.applyExitCode), dbEnsureExitCode: numericField(fields.dbEnsureExitCode), exitCode, stderr: commandOk ? "" : stderr.trim().slice(0, 2000), valuesRedacted: true, summary: healthy - ? `${fields.secret || V02_OPENFGA_SECRET} keys and Postgres database exist` - : `${fields.secret || V02_OPENFGA_SECRET} keys or Postgres database missing`, + ? `${fields.secret || DEFAULT_RUNTIME_LANE_OPENFGA_SECRET} keys and Postgres database exist` + : `${fields.secret || DEFAULT_RUNTIME_LANE_OPENFGA_SECRET} keys or Postgres database missing`, }; } return { ok: false, - namespace: fields.namespace || V02_RUNTIME_NAMESPACE, + namespace: fields.namespace || DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE, secret: fields.secret || null, preset: fields.preset || null, action: fields.action || null, @@ -449,16 +449,16 @@ export function v02SecretStatusFromText(text: string, commandOk: boolean, exitCo }; } -export function runG14Secret(options: G14SecretOptions): Record { +export function runLegacyRuntimeSecret(options: LegacyRuntimeSecretOptions): Record { const spec = hwlabRuntimeLaneSpec(options.lane); - const script = v02SecretScript(options); + const script = defaultRuntimeLaneSecretScript(options); const localAdminApiKey = options.preset === "master-server-admin-api-key" ? readOrCreateLocalMasterAdminApiKey(spec, options.action !== "ensure" || options.dryRun) : null; const result = options.preset === "master-server-admin-api-key" - ? g14K3sInlineScriptWithInput(script, localAdminApiKey?.key ?? "", options.timeoutSeconds * 1000 + 2000) - : g14K3s(["sh", "--", script], options.timeoutSeconds * 1000); - const status = v02SecretStatusFromText(statusText(result), isCommandSuccess(result), result.exitCode, result.stderr); + ? legacyRuntimeK3sInlineScriptWithInput(script, localAdminApiKey?.key ?? "", options.timeoutSeconds * 1000 + 2000) + : legacyRuntimeK3s(["sh", "--", script], options.timeoutSeconds * 1000); + const status = defaultRuntimeLaneSecretStatusFromText(statusText(result), isCommandSuccess(result), result.exitCode, result.stderr); const dryRunOk = options.action === "ensure" && options.dryRun && isCommandSuccess(result); const deleteDryRunOk = options.action === "delete" && options.dryRun && isCommandSuccess(result); const ok = dryRunOk || deleteDryRunOk ? true : status.ok === true; diff --git a/scripts/src/hwlab-g14/source.ts b/scripts/src/hwlab-legacy-runtime/source.ts similarity index 81% rename from scripts/src/hwlab-g14/source.ts rename to scripts/src/hwlab-legacy-runtime/source.ts index e8b65ed4..e84d37e4 100644 --- a/scripts/src/hwlab-g14/source.ts +++ b/scripts/src/hwlab-legacy-runtime/source.ts @@ -1,6 +1,6 @@ -// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. source module for scripts/src/hwlab-g14.ts. +// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. source module for scripts/src/hwlab-legacy-runtime.ts. -// Moved mechanically from scripts/src/hwlab-g14.ts:1205-1308 for #903. +// Moved mechanically from scripts/src/hwlab-legacy-runtime.ts:1205-1308 for #903. import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"; import { dirname, join } from "node:path"; @@ -11,10 +11,10 @@ import { cancelJob, listJobs, readJob, startJob } from "../jobs"; import { hwlabRequiredNoProxyEntries, hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneIds, hwlabRuntimeLaneSpec, isHwlabRuntimeLane, type HwlabRuntimeLane, type HwlabRuntimeLaneSpec } from "../hwlab-node-lanes"; import type { CommandJsonResult } from "./types"; -import { g14HostScript } from "./images"; +import { legacyRuntimeHostScript } from "./images"; import { statusText } from "./pr-monitor"; import { commandJson, isCommandSuccess, nested, shellQuote, shortSha } from "./remote"; -import { V02_GIT_URL, V02_LANE_SPEC } from "./types"; +import { DEFAULT_RUNTIME_LANE_GIT_URL, DEFAULT_RUNTIME_LANE_LANE_SPEC } from "./types"; export function runtimeLaneCicdRepoEnsureScript(spec: HwlabRuntimeLaneSpec): string { return [ @@ -59,14 +59,14 @@ export function runtimeLaneCicdRepoEnsureScript(spec: HwlabRuntimeLaneSpec): str ].join("\n"); } -export function v02CicdRepoEnsureScript(): string { - return runtimeLaneCicdRepoEnsureScript(V02_LANE_SPEC); +export function defaultRuntimeLaneCicdRepoEnsureScript(): string { + return runtimeLaneCicdRepoEnsureScript(DEFAULT_RUNTIME_LANE_LANE_SPEC); } -export function resolveV02Head(): { sourceCommit: string | null; result: CommandJsonResult } { - const result = g14HostScript([ +export function resolveDefaultRuntimeLaneHead(): { sourceCommit: string | null; result: CommandJsonResult } { + const result = legacyRuntimeHostScript([ "set -eu", - v02CicdRepoEnsureScript(), + defaultRuntimeLaneCicdRepoEnsureScript(), "git --git-dir=\"$cicd_repo\" rev-parse refs/remotes/origin/v0.2", ].join("\n"), 180_000); if (!isCommandSuccess(result)) return { sourceCommit: null, result }; @@ -75,12 +75,12 @@ export function resolveV02Head(): { sourceCommit: string | null; result: Command return { sourceCommit: match?.[0] ?? null, result }; } -export function getV02Head(): string | null { - return resolveV02Head().sourceCommit; +export function getDefaultRuntimeLaneHead(): string | null { + return resolveDefaultRuntimeLaneHead().sourceCommit; } -export function resolveV02LatestRemoteHead(): { sourceCommit: string | null; result: CommandJsonResult } { - const result = commandJson(["git", "ls-remote", V02_GIT_URL, "refs/heads/v0.2"], 30_000); +export function resolveDefaultRuntimeLaneLatestRemoteHead(): { sourceCommit: string | null; result: CommandJsonResult } { + const result = commandJson(["git", "ls-remote", DEFAULT_RUNTIME_LANE_GIT_URL, "refs/heads/v0.2"], 30_000); if (!isCommandSuccess(result)) return { sourceCommit: null, result }; const output = statusText(result); const match = /^[0-9a-f]{40}/imu.exec(output); @@ -88,7 +88,7 @@ export function resolveV02LatestRemoteHead(): { sourceCommit: string | null; res } export function resolveRuntimeLaneHead(spec: HwlabRuntimeLaneSpec): { sourceCommit: string | null; result: CommandJsonResult } { - const result = g14HostScript([ + const result = legacyRuntimeHostScript([ "set -eu", runtimeLaneCicdRepoEnsureScript(spec), `git --git-dir="$cicd_repo" rev-parse refs/remotes/origin/${spec.sourceBranch}`, @@ -116,6 +116,6 @@ export function runtimeLaneRerunPipelineRunName(spec: HwlabRuntimeLaneSpec, sour return `${runtimeLanePipelineRunName(spec, sourceCommit)}-r${stamp}`; } -export function v02PipelineRunName(sourceCommit: string): string { - return runtimeLanePipelineRunName(V02_LANE_SPEC, sourceCommit); +export function defaultRuntimeLanePipelineRunName(sourceCommit: string): string { + return runtimeLanePipelineRunName(DEFAULT_RUNTIME_LANE_LANE_SPEC, sourceCommit); } diff --git a/scripts/src/hwlab-legacy-runtime/types.ts b/scripts/src/hwlab-legacy-runtime/types.ts new file mode 100644 index 00000000..ed29c545 --- /dev/null +++ b/scripts/src/hwlab-legacy-runtime/types.ts @@ -0,0 +1,363 @@ +// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. types module for scripts/src/hwlab-legacy-runtime.ts. + +// Moved mechanically from scripts/src/hwlab-legacy-runtime.ts:1-288 for #903. + +import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { createHash, randomBytes } from "node:crypto"; +import { repoRoot, rootPath, type Config } from "../config"; +import { runCommand } from "../command"; +import { cancelJob, listJobs, readJob, startJob } from "../jobs"; +import { hwlabRequiredNoProxyEntries, hwlabRuntimeLaneConfigPath, hwlabRuntimeLaneIds, hwlabRuntimeLaneSpec, isHwlabRuntimeLane, type HwlabRuntimeLane, type HwlabRuntimeLaneSpec } from "../hwlab-node-lanes"; + +import { durationSeconds } from "./pr-monitor"; + +export const HWLAB_REPO = "pikasTech/HWLAB"; + +export const LEGACY_RUNTIME_SOURCE_BRANCH = "v0.3"; + +export const LEGACY_RUNTIME_PROVIDER = "NC01"; + +export const LEGACY_RUNTIME_WORKSPACE = "/root/hwlab-v03"; + +export const DEFAULT_RUNTIME_LANE_LANE_SPEC = hwlabRuntimeLaneSpec("v02") ?? hwlabRuntimeLaneSpec("v03"); + +export const DEFAULT_RUNTIME_LANE_SOURCE_BRANCH = DEFAULT_RUNTIME_LANE_LANE_SPEC.sourceBranch; + +export const DEFAULT_RUNTIME_LANE_WORKSPACE = DEFAULT_RUNTIME_LANE_LANE_SPEC.workspace; + +export const DEFAULT_RUNTIME_LANE_CICD_REPO = DEFAULT_RUNTIME_LANE_LANE_SPEC.cicdRepo; + +export const DEV_NAMESPACE = "hwlab-dev"; + +export const PROD_NAMESPACE = "hwlab-prod"; + +export const CI_NAMESPACE = "hwlab-ci"; + +export const ARGO_NAMESPACE = "argocd"; + +export const DEV_APP = "hwlab-g14-dev"; + +export const PROD_APP = "hwlab-g14-prod"; + +export const DEFAULT_RUNTIME_LANE_APP = DEFAULT_RUNTIME_LANE_LANE_SPEC.app; + +export const DEFAULT_RUNTIME_LANE_PIPELINE = DEFAULT_RUNTIME_LANE_LANE_SPEC.pipeline; + +export const DEFAULT_RUNTIME_LANE_POLLER = "hwlab-v02-branch-poller"; + +export const DEFAULT_RUNTIME_LANE_RECONCILER = "hwlab-v02-control-plane-reconciler"; + +export const DEFAULT_RUNTIME_LANE_PIPELINERUN_PREFIX = DEFAULT_RUNTIME_LANE_LANE_SPEC.pipelineRunPrefix; + +export const DEFAULT_RUNTIME_LANE_CONTROL_PLANE_FIELD_MANAGER = DEFAULT_RUNTIME_LANE_LANE_SPEC.controlPlaneFieldManager; + +export const DEFAULT_RUNTIME_LANE_GIT_URL = DEFAULT_RUNTIME_LANE_LANE_SPEC.gitUrl; + +export const DEFAULT_RUNTIME_LANE_GIT_READ_URL = DEFAULT_RUNTIME_LANE_LANE_SPEC.gitReadUrl; + +export const DEFAULT_RUNTIME_LANE_GIT_WRITE_URL = DEFAULT_RUNTIME_LANE_LANE_SPEC.gitWriteUrl; + +export const DEFAULT_RUNTIME_LANE_GITOPS_BRANCH = DEFAULT_RUNTIME_LANE_LANE_SPEC.gitopsBranch; + +export const DEFAULT_RUNTIME_LANE_CATALOG_PATH = DEFAULT_RUNTIME_LANE_LANE_SPEC.catalogPath; + +export const DEFAULT_RUNTIME_LANE_RUNTIME_PATH = DEFAULT_RUNTIME_LANE_LANE_SPEC.runtimePath; + +export const DEFAULT_RUNTIME_LANE_RUNTIME_NAMESPACE = DEFAULT_RUNTIME_LANE_LANE_SPEC.runtimeNamespace; + +export const DEFAULT_RUNTIME_LANE_OPENFGA_SECRET = "hwlab-v02-openfga"; + +export const DEFAULT_RUNTIME_LANE_OPENFGA_AUTHN_SECRET_KEY = "authn-preshared-key"; + +export const DEFAULT_RUNTIME_LANE_OPENFGA_DATASTORE_URI_SECRET_KEY = "datastore-uri"; + +export const DEFAULT_RUNTIME_LANE_OPENFGA_POSTGRES_PASSWORD_SECRET_KEY = "postgres-password"; + +export const DEFAULT_RUNTIME_LANE_OPENFGA_DB_NAME = "hwlab_openfga"; + +export const DEFAULT_RUNTIME_LANE_OPENFGA_DB_USER = "hwlab_openfga"; + +export const DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_SECRET = "hwlab-v02-master-server-admin-api-key"; + +export const DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_SECRET_KEY = "api-key"; + +export const DEFAULT_RUNTIME_LANE_MASTER_ADMIN_API_KEY_LOCAL_ENV = "/root/.config/hwlab-v02/master-server-admin-api-key.env"; + +export const DEFAULT_RUNTIME_LANE_REGISTRY_PREFIX = DEFAULT_RUNTIME_LANE_LANE_SPEC.registryPrefix; + +export const DEFAULT_RUNTIME_LANE_BASE_IMAGE = DEFAULT_RUNTIME_LANE_LANE_SPEC.baseImage; + +export const GIT_MIRROR_NAMESPACE = "devops-infra"; + +export const GIT_MIRROR_MANIFEST_FIELD_MANAGER = "unidesk-hwlab-git-mirror"; + +export const GIT_MIRROR_SYNC_JOB_PREFIX = "git-mirror-hwlab-sync-manual"; + +export const GIT_MIRROR_LEGACY_CRONJOB = "git-mirror-hwlab-sync"; + +export const LEGACY_RUNTIME_OBSERVABILITY_NAMESPACE = "devops-infra"; + +export const LEGACY_RUNTIME_OBSERVABILITY_FIELD_MANAGER = "unidesk-g14-observability"; + +export const LEGACY_RUNTIME_PROMETHEUS_OPERATOR_VERSION = "v0.91.0"; + +export const LEGACY_RUNTIME_PROMETHEUS_VERSION = "v3.12.0"; + +export const LEGACY_RUNTIME_PROMETHEUS_NAME = "g14-shared"; + +export const LEGACY_RUNTIME_PROMETHEUS_SERVICE = "prometheus-g14-shared"; + +export const LEGACY_RUNTIME_PROMETHEUS_SERVICE_ACCOUNT = "g14-observability-prometheus"; + +export const LEGACY_RUNTIME_PROMETHEUS_OPERATOR_RELEASE_ASSET = `https://github.com/prometheus-operator/prometheus-operator/releases/download/${LEGACY_RUNTIME_PROMETHEUS_OPERATOR_VERSION}/bundle.yaml`; + +export const DEFAULT_RUNTIME_LANE_SERVICE_IDS = [...DEFAULT_RUNTIME_LANE_LANE_SPEC.serviceIds]; + +export const DEFAULT_RUNTIME_LANE_CLOUD_WEB_URL = DEFAULT_RUNTIME_LANE_LANE_SPEC.publicWebUrl; + +export const DEFAULT_RUNTIME_LANE_CLOUD_API_URL = DEFAULT_RUNTIME_LANE_LANE_SPEC.publicApiUrl; + +export const DEFAULT_RUNTIME_LANE_OBSERVABILITY_SERVICE_IDS = [ + "hwlab-agent-skills", + "hwlab-cloud-api", + "hwlab-cloud-web", + "hwlab-deepseek-proxy", + "hwlab-edge-proxy", +]; + +export const DEFAULT_RUNTIME_LANE_OBSERVABILITY_EXPECTED_TARGET_COUNT = DEFAULT_RUNTIME_LANE_OBSERVABILITY_SERVICE_IDS.length; + +export const DEFAULT_RUNTIME_LANE_OBSERVABILITY_QUERIES = { + scrapeReachable: 'up{namespace="hwlab-v02"}', + sidecarServing: 'hwlab_service_up{namespace="hwlab-v02"}', + businessHealthProbe: 'hwlab_service_health_probe_success{namespace="hwlab-v02"}', + healthProbeConfigured: 'hwlab_service_health_probe_configured{namespace="hwlab-v02"}', + healthProbeStatusCode: 'hwlab_service_health_probe_status_code{namespace="hwlab-v02"}', + healthProbeDurationSeconds: 'hwlab_service_health_probe_duration_seconds{namespace="hwlab-v02"}', + processUptimeSeconds: 'hwlab_service_process_uptime_seconds{namespace="hwlab-v02"}', + scrapeDurationSeconds: 'scrape_duration_seconds{namespace="hwlab-v02"}', + scrapeSamplesScraped: 'scrape_samples_scraped{namespace="hwlab-v02"}', +}; + +export const DEFAULT_RUNTIME_LANE_OBSERVABILITY_CLOSEOUT_QUERY_NAMES = ["scrapeReachable", "sidecarServing", "businessHealthProbe"] as const; + +export const DEFAULT_RUNTIME_LANE_OBSERVABILITY_BOOLEAN_QUERY_NAMES = [...DEFAULT_RUNTIME_LANE_OBSERVABILITY_CLOSEOUT_QUERY_NAMES, "healthProbeConfigured"]; + +export function defaultRuntimeLanePipelineServiceIds(): string[] { + return [...DEFAULT_RUNTIME_LANE_SERVICE_IDS]; +} + +export const LEGACY_RUNTIME_CI_TOOLS_IMAGE_REPO = "127.0.0.1:5000/hwlab/hwlab-ci-node-tools"; + +export const LEGACY_RUNTIME_CI_TOOLS_BASE_TAG = "node22-alpine-v1"; + +export const DEFAULT_INTERVAL_SECONDS = 600; + +export const DEFAULT_MAX_CYCLES = 0; + +export const DEFAULT_TIMEOUT_SECONDS = 1800; + +export const LEGACY_RUNTIME_BRIEF_INDEX_ISSUE = 7; + +export const BEIJING_OFFSET_MS = 8 * 60 * 60 * 1000; + +export const DEFAULT_RUNTIME_LANE_BUILD_TASKRUN_WARNING_SECONDS = 120; + +export const DEFAULT_RUNTIME_LANE_BUILD_TASKRUN_CRITICAL_SECONDS = 180; + +export const DEFAULT_RUNTIME_LANE_CONTROL_PLANE_REFRESH_TTL_MS = 5 * 60 * 1000; + +export const DEFAULT_RUNTIME_LANE_CONTROL_PLANE_REFRESH_LOCK_STALE_MS = 5 * 60 * 1000; + +export const DEFAULT_RUNTIME_LANE_GIT_MIRROR_PRESYNC_MAX_WAIT_MS = 120 * 1000; + +export const DEFAULT_RUNTIME_LANE_GIT_MIRROR_PRESYNC_LOCK_STALE_MS = 5 * 60 * 1000; + +export const DEFAULT_RUNTIME_LANE_GIT_MIRROR_PRESYNC_POLL_MS = 3 * 1000; + +export type LegacyRuntimeMonitorLane = "g14" | HwlabRuntimeLane; + +export interface LegacyRuntimeMonitorOptions { + lane: LegacyRuntimeMonitorLane; + intervalSeconds: number; + maxCycles: number; + once: boolean; + dryRun: boolean; + worker: boolean; + timeoutSeconds: number; +} + +export interface LegacyRuntimeRecordRolloutOptions { + prNumber: number; + sourceCommit?: string; + pipelineRun?: string; + gitopsRevision?: string; + mergedAt?: string; + pipelineSucceededAt?: string; + finishedAt?: string; + dryRun: boolean; +} + +export interface LegacyRuntimeControlPlaneOptions { + action: "status" | "closeout" | "apply" | "trigger-current" | "refresh" | "cleanup-runs" | "cleanup-released-pvs" | "runtime-migration"; + lane: HwlabRuntimeLane | "g14" | "all"; + dryRun: boolean; + confirm: boolean; + wait: boolean; + rerun: boolean; + allowLiveDbRead: boolean; + timeoutSeconds: number; + minAgeMinutes: number; + limit: number; + sourceCommit?: string; + pipelineRun?: string; + history: boolean; +} + +export interface LegacyRuntimeLegacyRetirementOptions { + action: "status" | "plan" | "execute"; + dryRun: boolean; + confirm: boolean; + wait: boolean; + timeoutSeconds: number; + reason: string; +} + +export type DefaultRuntimeLaneStatusTargetMode = "latest-source-head" | "source-commit" | "pipeline-run"; + +export interface DefaultRuntimeLaneControlPlaneStatusTarget { + sourceCommit?: string | null; + pipelineRun?: string | null; + mode?: DefaultRuntimeLaneStatusTargetMode; + includeHistory?: boolean; +} + +export interface LegacyRuntimeToolsImageOptions { + action: "status" | "build"; + name: "ci-node-tools"; + tag: string; + dockerfile: string; + dryRun: boolean; + confirm: boolean; + timeoutSeconds: number; +} + +export interface LegacyRuntimeUpstreamImageOptions { + action: "status" | "ensure"; + name: "openfga"; + tag: string; + dryRun: boolean; + confirm: boolean; + timeoutSeconds: number; +} + +export interface LegacyRuntimeGitMirrorOptions { + action: "status" | "apply" | "sync" | "flush"; + lane: HwlabRuntimeLane; + dryRun: boolean; + confirm: boolean; + wait: boolean; + timeoutSeconds: number; +} + +export interface LegacyRuntimeObservabilityOptions { + action: "status" | "apply" | "query" | "targets" | "boundary" | "closeout"; + lane: "v02"; + dryRun: boolean; + confirm: boolean; + wait: boolean; + timeoutSeconds: number; + query: string; + expectCount?: number; + expectValue?: string; +} + +export interface LegacyRuntimeSecretOptions { + action: "status" | "ensure" | "delete"; + lane: HwlabRuntimeLane; + dryRun: boolean; + confirm: boolean; + name: string; + key?: string; + preset: "openfga" | "master-server-admin-api-key" | "generic-delete"; + timeoutSeconds: number; +} + +export interface CommandJsonResult { + ok: boolean; + command: string[]; + exitCode: number | null; + stdout: string; + stderr: string; + parsed: unknown | null; + durationMs?: number; + timedOut?: boolean; + stdoutBytes?: number; + stderrBytes?: number; +} + +export interface RemoteAsyncCommandSpec { + script: string; + timeoutSeconds: number; + label: string; + token: string; + command: string[]; +} + +export interface ShellSection { + stdout: string; + exitCode: number | null; +} + +export interface OpenPullRequest { + number: number; + title?: string; + url?: string; + baseRefName?: string; + headRefName?: string; + mergeable?: string | null; + mergeStateStatus?: string | null; + draft?: boolean; +} + +export interface CiServiceMetric { + taskRun: string; + serviceId: string; + status: string; + durationSeconds: number | null; + buildBackend: string | null; + reusedFrom: string | null; + imageTag: string | null; + sourceCommitId: string | null; +} + +export interface CiPipelineMetrics { + ok: boolean; + pipelineRun: string; + serviceTotal: number; + reusedCount: number; + rebuildCount: number; + reusedServices: string[]; + rebuildServices: string[]; + services: CiServiceMetric[]; + degradedReason?: string; + rawText?: string; +} + +export interface DefaultRuntimeLanePrCommentInput { + pr: OpenPullRequest; + phase: string; + state: "waiting-ci" | "blocked" | "merge-failed" | "cd-started" | "cd-succeeded" | "cd-superseded" | "cd-failed" | "cd-timeout" | "cd-blocked"; + startedAt: string; + observedAt: string; + elapsedSeconds: number | null; + preflight?: Record; + merge?: Record; + sourceCommit?: string | null; + pipelineRun?: string | null; + cd?: Record; + flush?: Record; + dryRun?: boolean; + message?: string; +} diff --git a/scripts/src/hwlab-node-transport.ts b/scripts/src/hwlab-node-transport.ts index ee32d029..e510608d 100644 --- a/scripts/src/hwlab-node-transport.ts +++ b/scripts/src/hwlab-node-transport.ts @@ -1,10 +1,10 @@ // SPEC: PJ2026-01060505 Workbench Performance draft-2026-06-17-p0. // Responsibility: HWLAB node transport/delegation adapters for legacy shared commands. import type { Config } from "./config"; -import { runHwlabG14Command } from "./hwlab-g14"; +import { runHwlabLegacyRuntimeCommand } from "./hwlab-legacy-runtime"; export type DelegatedNodeDomain = "control-plane" | "git-mirror"; export async function runDelegatedHwlabNodeCommand(config: Config, domain: DelegatedNodeDomain, args: string[]): Promise { - return runHwlabG14Command(config, [domain, ...args]); + return runHwlabLegacyRuntimeCommand(config, [domain, ...args]); } diff --git a/scripts/src/jobs.ts b/scripts/src/jobs.ts index 8614968e..5bcd04e3 100644 --- a/scripts/src/jobs.ts +++ b/scripts/src/jobs.ts @@ -319,7 +319,7 @@ export function renderJobLaunchSummary(command: string, result: unknown): Render function summarizeJobProgress(job: JobRecord, maxBytes = 96_000, tails?: { stdoutTail: string; stderrTail: string }): JobProgressSummary { const nowMs = Date.now(); const knownWorkflow = job.name === "hwlab_g14_v02_trigger_current"; - const v02PrMonitorWorkflow = job.name === "hwlab_g14_v02_pr_monitor"; + const defaultRuntimeLanePrMonitorWorkflow = job.name === "hwlab_g14_v02_pr_monitor"; const runtimeLaneTriggerWorkflow = /^hwlab_nodes_v[0-9]{2}_control-plane_trigger-current$/u.test(job.name); const agentRunYamlLaneTriggerWorkflow = /^agentrun_v[0-9]{2}_trigger_current$/u.test(job.name); const gitMirrorWorkflow = job.name === "hwlab_g14_git_mirror_sync" @@ -332,12 +332,12 @@ function summarizeJobProgress(job: JobRecord, maxBytes = 96_000, tails?: { stdou const progressTailBytes = Math.max(4096, Math.floor(maxBytes)); const stderrTail = tails?.stderrTail ?? tailFile(job.stderrFile, progressTailBytes); const agentRunYamlLaneProgressObserved = agentRunYamlLaneTriggerWorkflow || hasAgentRunYamlLaneProgressEvents(stderrTail); - if (!knownWorkflow && !v02PrMonitorWorkflow && !runtimeLaneTriggerWorkflow && !agentRunYamlLaneProgressObserved && !gitMirrorWorkflow) return genericJobProgress(job, stderrTail); + if (!knownWorkflow && !defaultRuntimeLanePrMonitorWorkflow && !runtimeLaneTriggerWorkflow && !agentRunYamlLaneProgressObserved && !gitMirrorWorkflow) return genericJobProgress(job, stderrTail); const stdoutTail = tails?.stdoutTail ?? tailFile(job.stdoutFile, progressTailBytes); if (gitMirrorWorkflow) return summarizeGitMirrorJobProgress(job, stdoutTail, stderrTail, nowMs); if (runtimeLaneTriggerWorkflow) return summarizeRuntimeLaneTriggerJobProgress(job, stdoutTail, stderrTail, nowMs); if (agentRunYamlLaneProgressObserved) return summarizeAgentRunYamlLaneTriggerJobProgress(job, stdoutTail, stderrTail, nowMs); - const events = v02PrMonitorWorkflow + const events = defaultRuntimeLanePrMonitorWorkflow ? [ ...parseJsonLineEvents(stderrTail, "hwlab.v02.pr-monitor.progress"), ...parseJsonLineEvents(stderrTail, "hwlab.v02.trigger.progress"), @@ -354,7 +354,7 @@ function summarizeJobProgress(job: JobRecord, maxBytes = 96_000, tails?: { stdou ? false : null; const lastEventAt = stringField(lastEvent.at); - const kind = events.length > 0 || knownWorkflow || v02PrMonitorWorkflow ? "hwlab-v02-trigger" : "generic"; + const kind = events.length > 0 || knownWorkflow || defaultRuntimeLanePrMonitorWorkflow ? "hwlab-v02-trigger" : "generic"; const elapsedSeconds = jobElapsedSeconds(job, nowMs); const stageElapsedSeconds = currentStageElapsedSeconds(events, stage, stageStatus, job, nowMs); const lastEventAgeSeconds = lastEventAt === null ? null : secondsSince(lastEventAt, job.finishedAt ?? nowMs); diff --git a/scripts/src/d601-k3s-guard.ts b/scripts/src/k3s-target-guard.ts similarity index 56% rename from scripts/src/d601-k3s-guard.ts rename to scripts/src/k3s-target-guard.ts index 52c20230..c63fc1c3 100644 --- a/scripts/src/d601-k3s-guard.ts +++ b/scripts/src/k3s-target-guard.ts @@ -1,9 +1,9 @@ -export const d601NativeKubeconfig = "/etc/rancher/k3s/k3s.yaml"; -export const d601RequiredNodeName = "d601"; +export const defaultNativeKubeconfig = "/etc/rancher/k3s/k3s.yaml"; +export const requiredNativeNodeName = "d601"; -export type D601K3sGuardStatus = "pass" | "refused" | "blocked"; +export type K3sGuardStatus = "pass" | "refused" | "blocked"; -export interface D601K3sTargetObservation { +export interface K3sTargetObservation { kubeconfig: string; expectedKubeconfig?: string; currentContext: string | null; @@ -13,7 +13,7 @@ export interface D601K3sTargetObservation { combinedText: string; } -export interface D601K3sDefaultKubectlDiagnostic { +export interface K3sDefaultKubectlDiagnostic { checked: boolean; currentContext: string | null; apiServer: string | null; @@ -22,8 +22,8 @@ export interface D601K3sDefaultKubectlDiagnostic { summary: string; } -export interface D601K3sGuardClassification { - status: D601K3sGuardStatus; +export interface K3sGuardClassification { + status: K3sGuardStatus; refusal: boolean; refusalSignals: string[]; kubeconfig: string; @@ -35,11 +35,11 @@ export interface D601K3sGuardClassification { requiredNodeName: string; requiredNodePresent: boolean; commandsOk: boolean; - defaultKubectlDiagnostic?: D601K3sDefaultKubectlDiagnostic; + defaultKubectlDiagnostic?: K3sDefaultKubectlDiagnostic; summary: string; } -export interface D601K3sGuardShellOptions { +export interface K3sGuardShellOptions { passOutput?: "stdout" | "stderr" | "quiet"; } @@ -47,7 +47,7 @@ function uniqueSignals(signals: Array): string[] { return [...new Set(signals.filter((signal): signal is string => signal !== null))]; } -export function d601ForbiddenKubeSignals(text: string): string[] { +export function forbiddenKubeSignals(text: string): string[] { return uniqueSignals([ /docker-desktop/iu.test(text) ? "docker-desktop" : null, /desktop-control-plane/iu.test(text) ? "desktop-control-plane" : null, @@ -55,13 +55,13 @@ export function d601ForbiddenKubeSignals(text: string): string[] { ]); } -export function classifyD601DefaultKubectlDiagnostic(input: { +export function classifyDefaultKubectlDiagnostic(input: { currentContext: string | null; apiServer: string | null; combinedText: string; commandsOk: boolean; -}): D601K3sDefaultKubectlDiagnostic { - const refusalSignals = d601ForbiddenKubeSignals(input.combinedText); +}): K3sDefaultKubectlDiagnostic { + const refusalSignals = forbiddenKubeSignals(input.combinedText); if (!input.commandsOk) { return { checked: true, @@ -69,7 +69,7 @@ export function classifyD601DefaultKubectlDiagnostic(input: { apiServer: input.apiServer, refusalSignals, status: "unavailable", - summary: "Default kubectl diagnostic could not read context/server; this does not block the explicit D601 target.", + summary: "Default kubectl diagnostic could not read context/server; this does not block the explicit target.", }; } if (refusalSignals.length > 0) { @@ -79,7 +79,7 @@ export function classifyD601DefaultKubectlDiagnostic(input: { apiServer: input.apiServer, refusalSignals, status: "stale-forbidden-default", - summary: "Default kubectl resolves to a forbidden local control-plane signal; explicit D601 KUBECONFIG remains the deploy target.", + summary: "Default kubectl resolves to a forbidden local control-plane signal; explicit KUBECONFIG remains the deploy target.", }; } return { @@ -92,32 +92,32 @@ export function classifyD601DefaultKubectlDiagnostic(input: { }; } -export function classifyD601K3sTarget( - observation: D601K3sTargetObservation, - defaultKubectlDiagnostic?: D601K3sDefaultKubectlDiagnostic, -): D601K3sGuardClassification { - const expectedKubeconfig = observation.expectedKubeconfig ?? d601NativeKubeconfig; - const refusalSignals = d601ForbiddenKubeSignals(observation.combinedText); - const requiredNodePresent = observation.nodeNames.includes(d601RequiredNodeName); +export function classifyK3sTarget( + observation: K3sTargetObservation, + defaultKubectlDiagnostic?: K3sDefaultKubectlDiagnostic, +): K3sGuardClassification { + const expectedKubeconfig = observation.expectedKubeconfig ?? defaultNativeKubeconfig; + const refusalSignals = forbiddenKubeSignals(observation.combinedText); + const requiredNodePresent = observation.nodeNames.includes(requiredNativeNodeName); const wrongKubeconfig = observation.kubeconfig !== expectedKubeconfig; const refusal = refusalSignals.length > 0; - const status: D601K3sGuardStatus = refusal + const status: K3sGuardStatus = refusal ? "refused" : !observation.commandsOk || wrongKubeconfig || !requiredNodePresent ? "blocked" : "pass"; const defaultStale = defaultKubectlDiagnostic?.status === "stale-forbidden-default"; const summary = refusal - ? "Refusing D601 k3s operation because the explicit target kubeconfig resolved to a forbidden Docker Desktop control-plane signal." + ? "Refusing k3s operation because the explicit target kubeconfig resolved to a forbidden Docker Desktop control-plane signal." : wrongKubeconfig - ? `D601 k3s guard blocked: expected explicit KUBECONFIG=${expectedKubeconfig}.` + ? `k3s target guard blocked: expected explicit KUBECONFIG=${expectedKubeconfig}.` : !observation.commandsOk - ? "D601 k3s guard blocked: explicit target kubeconfig could not read context, server, and nodes." + ? "k3s target guard blocked: explicit target kubeconfig could not read context, server, and nodes." : !requiredNodePresent - ? `D601 k3s guard blocked: explicit target kubeconfig did not report node ${d601RequiredNodeName}.` + ? `k3s target guard blocked: explicit target kubeconfig did not report node ${requiredNativeNodeName}.` : defaultStale - ? "D601 native k3s guard passed with explicit KUBECONFIG; stale default kubectl context was observed only as a diagnostic." - : "D601 native k3s guard passed with explicit KUBECONFIG."; + ? "native k3s target guard passed with explicit KUBECONFIG; stale default kubectl context was observed only as a diagnostic." + : "native k3s target guard passed with explicit KUBECONFIG."; return { status, refusal, @@ -128,7 +128,7 @@ export function classifyD601K3sTarget( apiServer: observation.apiServer, nodeNames: observation.nodeNames, nodeCount: observation.nodeNames.length, - requiredNodeName: d601RequiredNodeName, + requiredNodeName: requiredNativeNodeName, requiredNodePresent, commandsOk: observation.commandsOk, ...(defaultKubectlDiagnostic === undefined ? {} : { defaultKubectlDiagnostic }), @@ -140,49 +140,49 @@ function shellQuote(value: string): string { return `'${value.replace(/'/gu, "'\\''")}'`; } -export function d601K3sGuardShellLines(kubeconfig = d601NativeKubeconfig, options: D601K3sGuardShellOptions = {}): string[] { +export function k3sGuardShellLines(kubeconfig = defaultNativeKubeconfig, options: K3sGuardShellOptions = {}): string[] { const passOutput = options.passOutput ?? "stdout"; const passLine = passOutput === "quiet" ? ":" : passOutput === "stderr" - ? "printf 'd601_native_k3s_guard=pass kubeconfig=%s context=%s server=%s node=%s\\n' \"$required_kubeconfig\" \"$context\" \"$server\" \"$required_node\" >&2" - : "printf 'd601_native_k3s_guard=pass kubeconfig=%s context=%s server=%s node=%s\\n' \"$required_kubeconfig\" \"$context\" \"$server\" \"$required_node\""; + ? "printf 'k3s_target_guard=pass kubeconfig=%s context=%s server=%s node=%s\\n' \"$required_kubeconfig\" \"$context\" \"$server\" \"$required_node\" >&2" + : "printf 'k3s_target_guard=pass kubeconfig=%s context=%s server=%s node=%s\\n' \"$required_kubeconfig\" \"$context\" \"$server\" \"$required_node\""; return [ `export KUBECONFIG=${shellQuote(kubeconfig)}`, - "d601_k3s_guard() {", + "k3s_target_guard() {", ` required_kubeconfig=${shellQuote(kubeconfig)}`, - ` required_node=${shellQuote(d601RequiredNodeName)}`, + ` required_node=${shellQuote(requiredNativeNodeName)}`, " if [ \"${KUBECONFIG:-}\" != \"$required_kubeconfig\" ]; then", - " printf 'd601_native_k3s_guard=blocked reason=wrong-kubeconfig expected=%s actual=%s\\n' \"$required_kubeconfig\" \"${KUBECONFIG:-}\" >&2", + " printf 'k3s_target_guard=blocked reason=wrong-kubeconfig expected=%s actual=%s\\n' \"$required_kubeconfig\" \"${KUBECONFIG:-}\" >&2", " return 1", " fi", " if ! command -v kubectl >/dev/null 2>&1; then", - " echo 'd601_native_k3s_guard=blocked reason=kubectl-missing' >&2", + " echo 'k3s_target_guard=blocked reason=kubectl-missing' >&2", " return 1", " fi", " if ! context=$(kubectl config current-context 2>&1); then", - " printf 'd601_native_k3s_guard=blocked reason=context-read-failed detail=%s\\n' \"$context\" >&2", + " printf 'k3s_target_guard=blocked reason=context-read-failed detail=%s\\n' \"$context\" >&2", " return 1", " fi", " if ! server=$(kubectl config view --minify -o 'jsonpath={.clusters[0].cluster.server}' 2>&1); then", - " printf 'd601_native_k3s_guard=blocked reason=server-read-failed detail=%s\\n' \"$server\" >&2", + " printf 'k3s_target_guard=blocked reason=server-read-failed detail=%s\\n' \"$server\" >&2", " return 1", " fi", " if ! nodes=$(kubectl get nodes -o 'jsonpath={range .items[*]}{.metadata.name}{\"\\n\"}{end}' 2>&1); then", - " printf 'd601_native_k3s_guard=blocked reason=nodes-read-failed detail=%s\\n' \"$nodes\" >&2", + " printf 'k3s_target_guard=blocked reason=nodes-read-failed detail=%s\\n' \"$nodes\" >&2", " return 1", " fi", " combined=$(printf '%s\\n%s\\n%s\\n' \"$context\" \"$server\" \"$nodes\")", " if printf '%s\\n' \"$combined\" | grep -Eiq 'docker-desktop|desktop-control-plane|127\\.0\\.0\\.1:11700'; then", - " printf 'd601_native_k3s_guard=refused reason=forbidden-control-plane context=%s server=%s nodes=%s\\n' \"$context\" \"$server\" \"$(printf '%s' \"$nodes\" | tr '\\n' ',')\" >&2", + " printf 'k3s_target_guard=refused reason=forbidden-control-plane context=%s server=%s nodes=%s\\n' \"$context\" \"$server\" \"$(printf '%s' \"$nodes\" | tr '\\n' ',')\" >&2", " return 1", " fi", " if ! printf '%s\\n' \"$nodes\" | grep -Fx \"$required_node\" >/dev/null; then", - " printf 'd601_native_k3s_guard=blocked reason=missing-d601-node context=%s server=%s nodes=%s\\n' \"$context\" \"$server\" \"$(printf '%s' \"$nodes\" | tr '\\n' ',')\" >&2", + " printf 'k3s_target_guard=blocked reason=missing-required-node context=%s server=%s nodes=%s\\n' \"$context\" \"$server\" \"$(printf '%s' \"$nodes\" | tr '\\n' ',')\" >&2", " return 1", " fi", ` ${passLine}`, "}", - "d601_k3s_guard", + "k3s_target_guard", ]; } diff --git a/scripts/src/recovery-guardrails.ts b/scripts/src/recovery-guardrails.ts index 09c7bd3f..3b3fecbc 100644 --- a/scripts/src/recovery-guardrails.ts +++ b/scripts/src/recovery-guardrails.ts @@ -283,7 +283,7 @@ const forbiddenAutomaticActions = [ "git reset --hard live worktree", ]; -export function runD601RecoveryGuardrails(config: UniDeskConfig, fixture: RecoveryGuardrailsFixture = {}): RecoveryGuardrailsResult { +export function runRecoveryGuardrails(config: UniDeskConfig, fixture: RecoveryGuardrailsFixture = {}): RecoveryGuardrailsResult { const observedAt = fixture.observedAt ?? new Date().toISOString(); const filesRead: string[] = []; const commandsAttempted: string[][] = []; @@ -352,7 +352,7 @@ export function runD601RecoveryGuardrails(config: UniDeskConfig, fixture: Recove }; } -export function compactD601RecoveryGuardrails(result: RecoveryGuardrailsResult): CompactRecoveryGuardrailsResult { +export function compactRecoveryGuardrails(result: RecoveryGuardrailsResult): CompactRecoveryGuardrailsResult { return { ok: result.ok, surface: result.surface,