Files
solution-erp/.claude/workflows/runs/2026-07-31-S164-4gd-khkk-fanout/sub-cicd-verify-k5-k4c.md
2026-08-01 11:35:35 +07:00

131 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

CICD-K5K4C: PASS — 5/5
# cicd-monitor — verify deploy K5 + K4c (S166, 2026-08-01)
Push range `88e7ecf..e202393`. FE-ONLY, 0-mig cả 2 commit. Run **#439** (id 552) — **success**, 11:08:17 → 11:14:33 (**6m16s**).
Artifact ghi TỪNG MỤC ngay khi có bằng chứng (luật #53: ghi-đĩa-TRONG-lúc-làm; return chỉ là tóm tắt).
---
## M0 — Mốc PRE (tự đo LIVE, KHÔNG tin số spec) — ĐO LÚC RUN CÒN `running`
Cửa sổ vàng: bắt được #439 ở trạng thái `running` lúc **11:09:15** ⇒ bundle LIVE lúc đó = PRE thật (không phải số chép lại).
| App | index-*.js | index-*.css | size (B) | Last-Modified | Content-Type |
|---|---|---|---|---|---|
| admin | `index-qOcoitOr.js` | `index-Cf3iCOOv.css` | 1.756.651 | 01 Aug 03:15:14 GMT (=10:15:14 +07) | application/javascript |
| eoffice | `index-D9J3BbcA.js` | `index-DX1FRk5n.css` | 1.673.668 | 01 Aug 03:16:16 GMT (=10:16:16 +07) | application/javascript |
🔑 **PRE tự chứng là bundle #438 bằng LM, không chỉ bằng hash**: LM 10:15:14 / 10:16:16 nằm TRỌN trong cửa-sổ deploy #438 (10:10:19 → 10:16:42). Kết quả trùng baseline MEMORY — nhưng trùng đó là KẾT QUẢ ĐO, không phải giả-định đầu vào. (Bài "mốc PRE lão hoá sau MỖI deploy".)
Content-Type `application/javascript` + ~1,7MB ⇒ không dính bẫy SPA-fallback (`text/html` ~900B).
## M0-bis — Chọn byte-marker CÓ RĂNG (verify 0-hit PRE TRƯỚC khi dùng)
**M-K5 (kỳ vọng CẢ 2 app)**`Chưa có phiếu ở nhóm này`
- PRE eoffice **0** · PRE admin **0**
- control-DƯƠNG cùng file/cùng pipeline grep: `Kết cấu` = **1** ở CẢ 2 ⇒ 0-hit là ĐO THẬT, không phải grep chết / encoding hỏng.
- src@`88e7ecf`: `git grep` exit=1 (0 hit) ⇒ marker **chưa tồn tại ở mốc PRE** — không dính bài "marker đã có sẵn từ deploy trước = 0 bit" (`Kết cấu` ở K4ab).
- src@HEAD: có ở **cả** `fe-admin/src/components/pipeline/PipelineStageFolders.tsx:200` **và** `fe-user/.../PipelineStageFolders.tsx:200`, là JSX text (không phải comment).
**M-K4c (kỳ vọng CHỈ eoffice — differential)**`Xem tất cả nhóm` · `quy trình ở nhóm khác` · `được Admin ghim cho nhóm`
- cả 3: PRE eoffice **0**, PRE admin **0**; src@HEAD **chỉ**`fe-user/src/pages/pe/WorkflowMatrixViewPage.tsx` (dòng 134/161), 0 hit fe-admin.
- ⇒ bất-đối-xứng CỐ Ý: POST phải eoffice ≥1 / admin **0**. Differential này tự chứng comment-strip + tự chứng ship đúng app.
**LOẠI marker `xem tất cả`** (chữ thường): 3/3 hit trong repo đều nằm trong `//` comment (`Layout.tsx` ×2 + `WorkflowMatrixViewPage.tsx:55`) ⇒ Vite strip ⇒ **0 bit**. Soi ĐIỀU KIỆN trong source TRƯỚC khi phong làm marker (bài K3 `earlyFinalizeLocked`).
---
## Mục 1 — Run Gitea cho `e202393` ✅ PASS
| | |
|---|---|
| head_sha | `e2023932568e731c5a6f8b7dd4ccd4ff4b3c6130` (khớp HEAD; `git log origin/main..HEAD` **rỗng**) |
| run | **#439** / task id **552** / `status=success` |
| thời gian | created 11:08:17 → updated 11:14:33 = **6m16s** (dải quen 5m3x6m3x) |
| tail log | `Deploy done. App pool started.``API /health/live -> 200``🏁 Job succeeded` |
**Range phủ `ce35f90`:** `88e7ecf..e202393` = **9 commit** — 2 code (`ce35f90` K5 10:44:32, `e202393` K4c 11:08:09) + **7** `wal:` commit (`ff4d4dc`,`13f7f82`,`284233f`,`80b8cf5`,`2023f41`,`d163f6d`,`fa999d8`).
⚠️ Đề bài ghi "2 wal-commit kèm" — **đo được 7**. Không đổi kết luận (Gitea build cả *range*, K5 nằm trong range ⇒ được phủ), nhưng ghi lại vì đây lại là một mốc-đề-bài lệch với đĩa.
`paths-ignore` (7-glob): `.claude/agent-memory/**` + `.claude/workflows/runs/**` bị bỏ qua, **nhưng** `fe-admin/**`, `fe-user/**`, `tests/**` KHÔNG ⇒ CI đúng ra phải chạy, và nó đã chạy.
## Mục 2 — Gate CI **622 = 45 D + 577 I** ✅ PASS (tách-phần, khớp từng vế)
Đo ở web-UI log `…/actions/runs/439/jobs/0/logs` (18.674 B):
| Project | dòng log | Failed | Passed | Skipped |
|---|---|---|---|---|
| `SolutionErp.Domain.Tests.dll` | L29 | **0** | **45** | 0 |
| `SolutionErp.Infrastructure.Tests.dll` | L47 | **0** | **577** | 0 |
| **Tổng** | | **0** | **622** | 0 |
- Khớp **dự đoán TRƯỚC khi đo**: 621 → 622, delta **+1** rơi TRỌN vào Infra (45 Domain đứng im) — đúng 1 `[Fact]` mới `ListDeletedContractSigningPlans_FiltersByApprovalGroup_ServerSide` trong `ContractSigningPlanCrudTests.cs` (file test DUY NHẤT trong range).
- **control ÂM:** `grep -c 'Failed!'` = **0**; pattern lỗi build/test = **1 hit duy nhất** và là dòng vô hại của runner `Failed to setup Pty Unsupported` (L12, có ở mọi run) — không phải lỗi build/test.
- **Flaky đã khai** `DeleteContractSigningPlan_SoftDeletes` (1/12 theo commit-msg K4c): run này **KHÔNG đỏ** (Failed:0; tên test 0-hit trong log vì log chỉ in dòng tổng-kết). Ghi mốc: #439 xanh sạch, chưa cần re-run.
## Mục 3 — Mig GIỮ 71 + `sys.tables` 97 ✅ PASS (2 nguồn)
- **Nguồn 1 — git:** `git diff 88e7ecf..e202393 -- '*Migrations*'` = **rỗng** ⇒ 0-mig ở phía code.
- **Nguồn 2 — sqlcmd prod (đo SAU `status=success`, tức sau recycle):**
`MIGTOP=20260731085624_AddKhkkApprovalGroupCatalogAndFinalizeRuntime` (= Mig 71, GIỮ) · `MIGCOUNT=71` · `SYSTABLES=97` (is_ms_shipped=0).
- 🔑 **Mạnh hơn khớp-tổng — set-diff 2 chiều:** so DANH SÁCH `MigrationId` prod với danh sách file mig repo → **IN-PROD-NOT-IN-REPO = rỗng****IN-REPO-NOT-IN-PROD = rỗng**. Không drift chiều nào.
🔴 **Bắt được bug trong CHÍNH công thức đếm của tao (MEMORY).** Lần đếm đầu ra **70** ≠ prod 71 → suýt hô drift. Truy ra: recipe cũ `ls *.cs | grep -v Designer | grep -v Snapshot` **ăn nhầm** `20260717032812_AddPeApprovedBudgetSnapshot.cs` (Mig 67 có chữ "Snapshot" trong TÊN). Filter đúng phải neo đuôi: `grep -vE 'Designer\.cs$|ModelSnapshot\.cs$'`**71**, khớp prod. Đúng lớp "vắng-mặt trông giống ổn": một mig biến mất im lặng khỏi phép đếm, và nếu prod cũng lệch 1 thì hai cái sai sẽ triệt tiêu nhau thành "xanh".
## Mục 4 — Bundle rotate ×2 app + byte-marker ✅ PASS
| App | PRE js | POST js | size PRE→POST | Δ | LM POST (=+07) | trong cửa-sổ deploy? |
|---|---|---|---|---|---|---|
| admin | `qOcoitOr` | **`C2FhHCNT`** | 1.756.651 → 1.758.685 | **+2.034** | 04:13:05 GMT = 11:13:05 | ✅ (11:08:1711:14:33) |
| eoffice | `D9J3BbcA` | **`DFOCQ2ks`** | 1.673.668 → 1.676.752 | **+3.084** | 04:14:05 GMT = 11:14:05 | ✅ |
CSS cũng xoay: admin `Cf3iCOOv``DqXm5Hpn` · eoffice `DX1FRk5n``DlN3yZ5L`.
**Byte-marker POST (điểm gắt nhất):**
| Marker | eoffice | admin | kỳ vọng | |
|---|---|---|---|---|
| `Chưa có phiếu ở nhóm này` (K5, ×2 app) | **1** | **1** | 1 / 1 | ✅ |
| `Xem tất cả nhóm` (K4c) | **1** | **0** | 1 / 0 | ✅ |
| `quy trình ở nhóm khác` (K4c) | **1** | **0** | 1 / 0 | ✅ |
| `được Admin ghim cho nhóm` (K4c) | **1** | **0** | 1 / 0 | ✅ |
| control-DƯƠNG `Kết cấu` | 1 | 1 | >0 cả 2 | ✅ grep còn sống |
| control-ÂM chuỗi bịa `…nàyZZZ` | 0 | 0 | 0 cả 2 | ✅ grep không khớp-bừa |
🔑 **Differential khớp element-wise 4/4**: K5 vào CẢ HAI app, K4c CHỈ vào eoffice — đúng y hình dạng của diff (`fe-admin` chỉ bị K5 chạm; `WorkflowMatrixViewPage.tsx` chỉ có ở `fe-user`). Δ size cũng cùng chiều: eoffice +3.084 > admin +2.034 vì eoffice gánh K5+K4c còn admin chỉ K5 — một nhân-chứng ĐỘC LẬP với grep.
🔑 **Control âm tầng-2 (chứng ghi-đè thật, không phải thêm file):** GET hash CŨ sau deploy → `index-D9J3BbcA.js` = **200 `text/html` 876B**, `index-qOcoitOr.js` = **200 `text/html` 900B** ⇒ rơi về SPA-fallback ⇒ **bundle cũ đã biến mất khỏi đĩa**. (200 ở đây KHÔNG phải "còn sống" — discriminator là Content-Type, không phải status.)
## Mục 5 — Smoke 4 phép + spot route ✅ PASS (spot: đạt-bar nhưng 0-bit, xem caveat)
Bearer admin: `POST /api/auth/login``accessToken` len **468**
| Endpoint | code |
|---|---|
| `GET /api/contracts` | **200** |
| `GET /api/purchase-evaluations` | **200** |
| `GET /api/menus` | **200** |
| `GET /api/contract-signing-plans` | **200** |
| control-ÂM `GET /api/khong-ton-tai-zzz` (có bearer) | **404** ✅ |
| control-ÂM `GET /api/contracts` KHÔNG token | **401** ✅ |
**Spot `/khkk/workflow-matrix?type=10&group=3` (eoffice):****200** `text/html` **876B**.
⚠️ **CAVEAT — con 200 này 0 bit.** Control-ÂM cùng dạng `/khkk/duong-dan-bia-zzz?type=10&group=3` cũng trả **200 `text/html` 876B**, **byte y hệt**. Đây là SPA-fallback rewrite `/*``index.html`: mọi đường dẫn đều 200. Bar đề bài ("chỉ cần app 200") ĐẠT, nhưng nó không phân biệt được route có thật hay không ⇒ không đọc thành "route chạy đúng".
**Bằng chứng THẬT cho route** nằm ở 2 chỗ khác, và cả 2 đều dương:
1. route đăng ký trong `fe-user/src/App.tsx:83``<Route path="/khkk/workflow-matrix" element={<WorkflowMatrixViewPage />} />`; leaf sidebar `Layout.tsx:86` `Khkk_WfView: '/khkk/workflow-matrix?type=10&group=1'`.
2. logic lọc `?group=` của K4c đã có mặt **trong bundle eoffice đã ship** (3/3 marker = 1), và **không** có ở admin (0/3).
---
## Verdict
**PASS 5/5.** Run #439 `e202393` success 6m16s · gate **622 = 45 D + 577 I** (Failed 0, delta +1 khớp đúng 1 Fact mới) · Mig GIỮ **71** + `sys.tables` **97**, set-diff repo↔prod rỗng 2 chiều · bundle rotate ×2 app, LM in-window, marker differential 4/4 element-wise + 2 tầng control · smoke 4/4 + 2 control-âm.
**Treo / khuyến nghị (không chặn):**
1. Bar "FE route 200" **không có răng** với SPA-fallback (POS ≡ NEG byte-identical). Lần sau muốn đo route: đo bằng byte-marker trong bundle, hoặc gọi API mà route đó dùng, đừng đo bằng status code của đường dẫn client.
2. Recipe đếm mig trong MEMORY có **false-negative** (ăn `AddPeApprovedBudgetSnapshot`) — đã sửa sang filter neo-đuôi + ưu tiên set-diff thay khớp-tổng.
3. Flaky `DeleteContractSigningPlan_SoftDeletes` (khai 1/12) chưa cắn ở #439; nếu đỏ ở run sau, đối chiếu mốc này trước khi coi là hồi-quy mới.
**Bundle baseline MỚI (post-#439):** admin `C2FhHCNT`/`DqXm5Hpn` · eoffice `DFOCQ2ks`/`DlN3yZ5L`. *(Snapshot-per-run — sẽ lão hoá ngay ở deploy kế.)*
END — CICD-K5K4C VERDICT=PASS 5/5