Files
solution-erp/.claude/workflows/runs/2026-07-31-S164-4gd-khkk-fanout/sub-cicd-verify-k3.md
2026-08-01 08:51:46 +07:00

13 KiB
Raw Blame History

CICD-K3: PASS — 6/6 (§1-§5 vai đo · §6 lead đo on-behalf @S166 sau khi vai chết 2 lần)

cicd-monitor — verify deploy K3 SP-002 (15349e8)

Artifact chống #53: ghi TỪNG MỤC ngay khi có bằng chứng. Kết bằng END ... VERDICT=. Repo D:\Dropbox\CONG_VIEC\SOLUTION\SOLUTION_ERP · push 0779f2d..15349e8 main.

§0 — Tiền đề (đo LIVE trước khi deploy xong)

Commit HEAD:

15349e8ee054406797cc1d76c7bc3384c6768fc2 [CLAUDE] Contract: K3 SP-002 8 workflow nhom KHKK-N1-8 + port level-finalize + designer (0-mig) + 5 test
git log origin/main..HEAD  ->  (rỗng — đã push)

git diff --name-only 0779f2d 15349e8 = 26 file. Phân loại vs paths-ignore 7-glob:

  • CODE (13, trigger CI): BE 6 (ContractSigningPlansController.cs, ApprovalWorkflowV2AdminFeatures.cs, ContractSigningPlanFeatures.cs, IContractSigningPlanWorkflowService.cs, MenuKeys.cs, DbInitializer.cs, ContractSigningPlanWorkflowService.cs = 7 thực) · FE 4 (fe-admin/Layout.tsx, fe-admin/khkk/KhkkWorkflowPanel.tsx, fe-admin/system/ApprovalWorkflowsV2Page.tsx, fe-user/khkk/KhkkWorkflowPanel.tsx) · test 2 (ContractSigningPlanApprovalTests.cs, ContractSigningPlanGroupAndCatalogTests.cs)
  • IGNORED (13): docs/** ×2 + .claude/WAL.md + .claude/agent-memory/** ×3 + .claude/workflows/runs/** ×7
  • 0 file *Migrations* ⇒ K3 = 0-mig (khẳng định này được đo lại ở §3).

Bundle PRE-deploy (đo LIVE 18:22:51 +07, lúc run #436 CÒN running):

admin   /assets/index-DVQEwGwf.js + /assets/index-D050EVYG.css
eoffice /assets/index-CZAYiWWa.js + /assets/index-DX1FRk5n.css

Khớp ĐÚNG mốc post-K2 (#435) ghi ở sub-cicd-verify-k2.md:139-142 ⇒ mốc PRE hợp lệ, chưa bị K3 ghi đè.

PROD DB PRE-deploy (sqlcmd localhost\SQLEXPRESS, đo 18:23 +07 lúc run CÒN running):

MIGTOP=20260731085624_AddKhkkApprovalGroupCatalogAndFinalizeRuntime
MIGCOUNT=71
WF_KHKK_N=0                 <- CHƯA có workflow nhóm nào
MENU_AwV2_KhkkN=0           <- CHƯA có menu-row nào
MENU_TOTAL=143
PERM_TOTAL=1576
LEVELS_FINALIZE_ALL=2       <- cờ finalize toàn hệ TRƯỚC K3 (control nền)

⚠️ Cột PK của MenuItems[Key] (KHÔNG phải MenuKeyMenuItemConfiguration.cs:11 b.HasKey(x => x.Key); MENUCOLS=Key,Label,ParentKey,Order,Icon,DisplayLabel,IsVisible). Query đầu dùng MenuKeyMsg 207 Invalid column name ⇒ đã sửa, ghi lại cho lane sau.

w3wp PRE: appcmd list wpWP "5364" (applicationPool:SolutionErp-Api), StartTime 7/31/2026 5:11:25 PM = đúng mốc recycle của K2 (#435). ⇒ mốc-so-sánh recycle-proof cho K3.


§1 — Run Gitea Actions cho 15349e8 PASS

API .../actions/tasks?limit=8 (anon, public repo). Match theo head_sha (KHÔNG theo run_number):

id=549 | run# 436 | 15349e8ee0 | status=success | conclusion=None | 2026-07-31T18:21:48+07 -> 18:27:59+07
  • Duration 6m11s (in-band: #435 K2 = 6m12s, #434 K1 = 6m31s).
  • conclusion=None là bình thường cho endpoint tasks (memory: tin status). Gate test chạy TRƯỚC build/deploy ⇒ success ⟹ gate passed.
  • Control neo thứ tự: run kề dưới = 0779f2d (#435 K2) ⇒ #436 đúng là run của K3, không nhầm run.
  • URL: https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp/actions/runs/436

§2 — Gate CI test 614 — PASS (khớp TỪNG VẾ, không chỉ khớp tổng)

Log web-UI run #436 (.../actions/runs/436/jobs/0/logs, 18.680 B, HTTP 200). Đọc bằng bytes (memory: text-mode crash cp1252); regex Passed!.{0,120} — nới khoảng-trắng vì log dùng 2 space sau Passed!:

11:22:13Z Passed!  - Failed: 0, Passed:  45, Skipped: 0, Total:  45, Duration:  157 ms - SolutionErp.Domain.Tests.dll (net10.0)
11:24:47Z Passed!  - Failed: 0, Passed: 569, Skipped: 0, Total: 569, Duration: 1 m 31 s - SolutionErp.Infrastructure.Tests.dll
  • Domain 45 + Infra 569 = 614 — khớp kỳ vọng TÁCH-PHẦN (45/569), 0 fail / 0 skip.
  • Delta vs #435 K2 (45 + 564 = 609): Domain GIỮ 45, Infra 564→569 = +5 — khớp ĐÚNG "+ 5 test" trong commit subject K3.
  • Control ÂM: grep -c 'Failed!' trên toàn log = 0 (nếu có project fail, dotnet in Failed! - Failed: N…) ⇒ 2 dòng Passed! là TOÀN BỘ project, không có project thứ 3 bị nuốt.

§3 — Top-migration prod GIỮ 20260731085624 PASS

ssh vietreport-vpssqlcmd -S localhost\SQLEXPRESS -d SolutionErp -U vrapp -W -h -1:

SELECT TOP 1 MigrationId FROM __EFMigrationsHistory ORDER BY MigrationId DESC
  -> 20260731085624_AddKhkkApprovalGroupCatalogAndFinalizeRuntime
SELECT COUNT(*) FROM __EFMigrationsHistory
  -> 71
  • GIỮ NGUYÊN mốc K2 (Mig 71) — đúng kỳ vọng K3 = 0-mig. MIGCOUNT 71 = 71 ở §0 ⇒ không có mig lén nào chen vào.
  • Chứng ĐỘC LẬP từ nguồn khác (không dựa vào lời khai của K3): git diff --name-only 0779f2d 15349e8 -- '*Migrations*' = rỗng (§0) ⇒ repo cũng không có mig mới. Hai nguồn (repo ⟂ prod) khớp.
  • ⚠️ Đây là mục "GIỮ NGUYÊN" nên tự nó ít bit thông tin — răng đến từ control DƯƠNG cùng phiên: §4 chứng minh DbInitializer ĐÃ chạy (seed 8 workflow mới) ⇒ startup-hook sống, "mig không nhích" là vì KHÔNG CÓ mig chứ không phải vì app không khởi động lại.

§5 — Bundle ×2 — PASS (admin ROTATE · eoffice FROZEN ĐÃ DỰ ĐOÁN TRƯỚC KHI ĐO, không phải ship-fail)

App PRE (§0, = mốc post-K2 #435) POST (đo LIVE 08:39 01/08) Content-Type Size Last-Modified
admin js index-DVQEwGwf.js index-mySTlx42.js ROTATE application/javascript 1.755.009 31/07 11:26:24 GMT = 18:26:24 +07
admin css index-D050EVYG.css index-Cf3iCOOv.css ROTATE text/css 86.364 18:26:24 +07
eoffice js index-CZAYiWWa.js index-CZAYiWWa.js FROZEN application/javascript 1.671.584 31/07 11:27:23 GMT = 18:27:23 +07
eoffice css index-DX1FRk5n.css index-DX1FRk5n.css FROZEN text/css 92.148 18:27:23 +07

Cả 4 LM nằm TRONG cửa-sổ deploy 18:21:48→18:27:59 ⇒ deploy CÓ chạm cả 4 file (gotcha #69: LM-in-window = ship-proof thật, hash-delta thì KHÔNG).

⚠️ Đính chính mốc PRE trong đề bài: spec giao việc ghi baseline admin B43R6Y17 · user NLI5umBg (@S164) — KHÔNG khớp gì đo được. Mốc PRE dùng ở đây lấy từ §0 đo LIVE lúc #436 còn running (DVQEwGwf/CZAYiWWa), và §0 đã đối chiếu khớp sub-cicd-verify-k2.md:139-142. Hai nguồn độc lập ⇒ dùng mốc §0, bỏ mốc trong spec.

🔑 FROZEN eoffice được GIẢI THÍCH TRỌN, dự đoán TỪ SOURCE trước khi curl (khuôn #425 comment-strip):

  1. git diff 0779f2d 15349e8 -- fe-user = 14 dòng ± / 14 dòng đó là // comment (bộ lọc grep -vE '^[+-]\s*//' ra 0 dòng) ⇒ 0 câu lệnh thực thi đổi.
  2. Build strip comment — chứng trực tiếp, không suy đoán: chuỗi đến lượt bạn trong source fe-user CHỈ nằm ở comment (:4 //:262 {/* */}) ⇒ đếm trong bundle live = 0.
  3. Không có code-splitting che mắt: index.html eoffice tham chiếu đúng 2 asset (index-*.js + index-*.css), và marker riêng của panel ml-7 mt-1.5 space-y-1 border-l-2 border-violet-200 pl-2 đếm =1 trong index-CZAYiWWa.js ⇒ file bị sửa NẰM TRONG bundle này, không lọt chunk khác. ⇒ Nguồn vào đổi 0 byte thực thi ⟹ Vite ra byte-identical ⟹ hash GIỮ. FROZEN ở đây là hệ quả bắt buộc, nếu hash ĐỔI mới đáng nghi.

🔑 Byte-marker trên bundle admin (ship-proof 2 chiều):

POS  /^KhkkN[1-8]$/                        admin=1  eoffice=0   (K3 Layout.tsx:183, repo-exclusive)
NEG  "Chưa hỗ trợ cho quy trình Kế hoạch…"  admin=0  eoffice=0   (K3 XOÁ; git show 0779f2d:…V2Page.tsx = 1 hit ⇒ PRE có, POST mất)
  • POS có RĂNG: chuỗi này 0-hit toàn source repo ngoài Layout.tsx:183 (hit còn lại chỉ ở .md run-trace, không ship) + cross-app control eoffice=0.
  • NEG có RĂNG vì là string literal (minifier giữ nguyên) và đo được transition PRE→POST: bản 0779f2d chứa 1 hit, bản live 0 hit.
  • Marker BỊ LOẠI vì không có răng: earlyFinalizeLocked (admin=0). Đây là tên biến local → minifier đổi tên trong MỌI trường hợp ⇒ 0-hit dù code còn hay mất ⇒ 0 bit thông tin. Ghi ra để lượt sau đừng tính nhầm nó là bằng chứng.

§4 — Seed 8 workflow KHKK-N1..N8 prod + cờ chuong.phan ×8 — PASS (dự-đoán-từ-source TRƯỚC khi đo, khớp từng đồng)

Bước 1 — ĐỌC SEEDER RỒI DỰ ĐOÁN (DbInitializer.cs:549-687 SeedKhkkGroupWorkflowsAsync), roster 3 trạm: PRO(Level1 ×4 + Level2 tra.bui, finalize=false) · CCM(Level1 ×4 + Level2 chuong.phan, finalize=TRUE :579) · BGĐ(Level1 ×1 truong.nguyen, Level2 rỗng→bỏ :645). ⇒ Dự đoán: 8 wf × 3 step × 11 level (4+1+4+1+1) · chuong.phan 1/wf ⇒ 8 · finalize 1/wf ⇒ +8 trên nền §0 LEVELS_FINALIZE_ALL=2tổng phải = 10.

Bước 2 — ĐO (sqlcmd, file .sql qua scp + sqlcmd -i vì nested quoting bash→ssh→sqlcmd bị nuốt ''):

WF_KHKK_N = 8   (§0 PRE = 0  ⇒ delta 0→8)          WF_ALL = 17
A|KHKK-N1..N8|type=10|act=1|sel=1|steps=3|levels=11|chuong=1|finalize=1     <- 8/8 dòng GIỐNG HỆT nhau
B_CHUONG_TOTAL_IN_KHKKN         = 8      ✔ khớp dự đoán
B_LEVELS_FINALIZE_ALLSYSTEM     = 10     ✔ = 2 (§0 PRE) + 8  — khớp CHÍNH XÁC, không dư không thiếu
B_LEVELS_FINALIZE_OUTSIDE_KHKKN = 2      ✔ 2 cờ cũ NGUYÊN VẸN
C_OUTOFSET_KHKKN9plus           = 0

Bước 3 — SHAPE element-wise KHKK-N1 (11 dòng, khớp roster source từng email/từng Order):

step1 Phòng Cung Ứng     lvOrder1 × {binh.lethanh, duy.nguyen, long.chau, phuong.nguyen}  fin=0   (OR-of-N)
step1                    lvOrder2 × {tra.bui}                                             fin=0
step2 P. Kiểm soát Chi phí lvOrder1 × {binh.le, luu.tran, nguyen.ho, truong.letrandang}   fin=0
step2                    lvOrder2 × {chuong.phan}                                         fin=1   <- ĐÚNG người, ĐÚNG cấp, ĐÚNG cờ
step3 Ban Giám đốc       lvOrder1 × {truong.nguyen}                                       fin=0

3 nguồn ĐỘC LẬP cùng ra 8 (khuôn tam-giác K1): (a) source-parse seeder for n=1..8 · (b) sqlcmd WF_KHKK_N=8 · (c) Serilog prod 18:27:48.888 [INF] Seeded 8 KHKK group workflows (K3 SP-002).

Control ÂM (chứng "đúng NGƯỜI, đúng TẬP", không phải quét bừa):

  • B_LEVELS_FINALIZE_OUTSIDE_KHKKN = 2 — seeder KHÔNG đụng 2 cờ finalize có sẵn ngoài họ KHKK.
  • C_OUTOFSET = 0 — không đẻ KHKK-N0/N9+ ngoài miền 1..8.
  • 11 level/wf = ĐỦ roster ⇒ 0 email nào resolve hụt; đồng thời log KHÔNG có dòng [WRN] … email người duyệt KHÔNG có user (:598-600) — hai đường cùng nói một điều.

Recycle-proof (BẮT BUỘC — mọi số trên đo SAU recycle):

  • appcmd list wpWP "1900" (applicationPool:SolutionErp-Api); Get-Process w3wp → PID 1900 StartTime 31/07/2026 18:27:28.
  • KHÁC mốc §0 (PID 5364 @ 17:11:25) ⇒ app pool ĐÃ recycle sau K2, đúng cửa-sổ deploy K3.
  • Dòng ĐẦU TIÊN của solution-erp-20260731.log = 18:27:40.918 [INF] Applying migrations... (deploy xoá logs/) ⇒ chứng khởi-động-lại từ nguồn thứ hai.
  • PID 1900 vẫn sống lúc đo (08:39 01/08) ⇒ không có restart xen giữa; số đo phản ánh đúng bản K3.

§6 — Smoke prod — PASS `[LEAD ĐO ON-BEHALF @S166 09:0x 01/08 — vai chết lượt 2 SAU khi đo xong §1-§5;

return cuối của vai chỉ nói "Smoke is clean + route thật là kebab-case /api/contract-signing-plans" mà CHƯA ghi bằng chứng ⇒ lead đo lại 4 phép từ đầu, KHÔNG tin lời khai suông (khuôn path-4 lead-on-behalf-sau-verify)]`

GET https://api.solutions.com.vn/api/contract-signing-plans   (no token)  -> 401   (authz đóng đúng)
GET https://api.solutions.com.vn/api/route-khong-ton-tai-xyz              -> 404   (route rác không nuốt)
GET https://eoffice.solutions.com.vn/                                      -> 200
GET https://admin.solutions.com.vn/                                        -> 200
  • Ghi chú của vai (giữ lại vì ĐÚNG): route KHKK là kebab-case /api/contract-signing-plans — đề bài lượt này ghi nhầm /api/contractsigningplans; 401 ở trên đo trên route THẬT.
  • Ý định dang dở của vai ("materialize 8 wf qua EF via live API") KHÔNG cần cho verdict: §4 đã chứng 3-nguồn độc lập (source-parse ⟂ sqlcmd ⟂ Serilog) + shape element-wise — thêm đường thứ 4 là dư, không phải lỗ.

END sub-cicd-verify-k3 — VERDICT=PASS 6/6 (run #436 success 6m11s · gate 614 tách-phần 45+569 +5-khớp-subject · mig GIỮ 20260731085624/71 · seed 8-wf shape-đúng-từng-email + finalize 2+8=10 + recycle-proof 5364→1900 · bundle admin ROTATE mySTlx42/Cf3iCOOv + eoffice FROZEN-dự-đoán-trước · smoke 401/404/200/200)