Files
solution-erp/.claude/workflows/runs/2026-07-31-S164-4gd-khkk-fanout/sub-cicd-verify-k1.md
2026-07-31 15:59:14 +07:00

9.3 KiB
Raw Blame History

CICD-K1: PASS — 6/6 mục

cicd-monitor — verify deploy K1 SP-002 (50e6d8c)

Artifact chống #53: ghi TỪNG mục NGAY khi đo xong. Kết bằng dòng END … VERDICT=. Spawn 2026-07-31 · commit 50e6d8c38283a9dd45da2001bd2fc6596595558f · READ-only (0 ghi prod)

Stage 1 — Push + path-filter (PRE-điều-kiện)

  • git log -150e6d8c38283a9dd45da2001bd2fc6596595558f|[CLAUDE] Contract: K1 SP-002 danh muc loai HD - ContractCatalogEntries (Mig 70) + seed 86 + CQRS + FE kind-5 x2 app + 8 test|2026-07-31 15:45:50 +0700
  • git log origin/main..HEADRỖNG (đã push hết)
  • git diff --name-only 50e6d8c^ 50e6d8c20 file (neo bằng X^..X theo LUẬT S162 CẤM-HEAD~1, vì phiên có Stop-hook WAL auto-commit): BE 11 · FE 6 · Test 1 · Docs 2
  • vs paths-ignore 7-glob: 18/20 file KHÔNG bị ignore ⇒ CI PHẢI chạy.

Stage 1b — DỰ ĐOÁN TRƯỚC KHI ĐO (chống xác-nhận-ngược)

Đọc DbInitializer.SeedContractCatalogAsync (dòng 3163-3325) trước khi chạm prod:

  • Parse lần 1 (regex line-anchored) → 78 ⇒ SAI (tuple xuống dòng). Vứt, KHÔNG báo cáo số này.
  • Parse lần 2 (multiline) → 86; cross-check độc-lập raw code-literal = 86, distinct = 86, dup = [].
  • Dự đoán GROUP BY ApprovalGroup: 1:5 · 2:10 · 3:5 · 4:23 · 5:14 · 6:15 · 7:13 · 8:1
  • Dự đoán GROUP BY GroupCode: 11 nhóm — A1:5 A2:1 A3:9 A4:5 B1:23 B2:14 B3:15 C1:6 C2:3 C3:4 CEO:1
  • Seeder idempotent (existingCodes.Contains(code) continue + IgnoreQueryFilters né #75/#76) ⇒ deploy đầu added=86.
  • Serilog dự kiến: Seeded 86 contract catalog entries (S164 SP-002) (chỉ ghi khi added>0).

Bundle PRE-deploy (đo LIVE lúc run đang chạy, 15:47)

App js css
admin index-B43R6Y17.js index-BZ5F-g1w.css
eoffice index-NLI5umBg.js index-yNZDmVNz.css

Khớp nguyên văn hash đề-bài (B43R6Y17 / NLI5umBg) ⇒ mốc "TRƯỚC" hợp lệ.


Mục 1 — Gitea Actions run

  • Run id=547 · run_number=#434 · head_sha 50e6d8c3 · job build-deploy · runner vps-vietreport-runner v0.2.13
  • created 2026-07-31T15:46:06+07:00 (push 15:45:50 → pick sau 16s)
  • Poll 7 iter × ~40s → iter7 status=success, updated 2026-07-31T15:52:37+07:00
  • Duration ≈ 6m31s · conclusion=None (tasks API không populate — tin status, đúng khuôn đã biết)
  • URL: https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp/actions/runs/434
  • PASS

Mục 2 — Test gate 598

Nguyên văn từ web-UI log (/actions/runs/434/jobs/0/logs, 18.698 B):

2026-07-31T08:46:34.2961110Z Passed!  - Failed:     0, Passed:    45, Skipped:     0, Total:    45, Duration: 196 ms - SolutionErp.Domain.Tes…
2026-07-31T08:49:26.8226799Z Passed!  - Failed:     0, Passed:   553, Skipped:     0, Total:   553, Duration: 1 m 44 s - SolutionErp.Infrastr…
  • Domain 45 + Infra 553 = 598 — khớp baseline MỚI đề bài (590+8). Đối chiếu TÁCH-PHẦN: Domain 45 GIỮ NGUYÊN, Infra 545→553 = +8 ⇒ đúng "7 lane K1 + T5b gate-fix" (delta rơi trọn vào Infra, đúng nơi file test mới nằm).
  • 0 fail / 0 skip cả 2 project. Failed!/error CSxxxx = 0 hit.
  • ⚠️ Ghi chú phương-pháp: grep đầu tiên 0 hit do format nhiều-khoảng-trắng (Passed! - Failed: 0); đã soi lại format thật rồi mới trích — KHÔNG báo "không thấy dòng test".
  • PASS

Mục 3 — EF migration prod

20260731072441_AddContractCatalogEntries      ← TOP
20260729122015_AddContractSigningPlans
20260727033522_AddPeAllowApproverDelete
20260717032812_AddPeApprovedBudgetSnapshot
  • __EFMigrationsHistory TOP == repo HEAD mig ⇒ Mig 70 applied prod.
  • Chân-kiềng (i) chứng-minh-restart-thật: w3wp PID 2644 StartTime 7/31/2026 3:52:13 PM (trong cửa-sổ deploy 15:46:06→15:52:37) + dòng ĐẦU Serilog 2026-07-31 15:52:19.770 +07:00 [INF] Applying migrations... ⇒ mọi số DB dưới đây đo SAU recycle (né đúng lỗi #423).
  • PASS

Mục 4 — Seed prod 86 + phân bố 8 nhóm

sqlcmd (SQL-auth vrapp, sau recycle):

Đo Kết quả
COUNT(*) FROM ContractCatalogEntries 86
GROUP BY ApprovalGroup 1:5 · 2:10 · 3:5 · 4:23 · 5:14 · 6:15 · 7:13 · 8:1
COUNT(DISTINCT Code) 86 (0 trùng)
IsActive=1 86 · IsDeleted=1 = 0
COUNT(DISTINCT GroupCode) 11

Serilog (solution-erp-20260731.log) nguyên văn:

2026-07-31 15:52:27.074 +07:00 [INF] Seeded 86 contract catalog entries (S164 SP-002)
2026-07-31 15:52:25.867 +07:00 [INF] Seeded 1 menu items
2026-07-31 15:52:26.030 +07:00 [INF] Seeded 1 admin permissions
  • Control ÂM: findstr "contract catalog KHONGTONTAI"0 hit ⇒ findstr có răng, không phải khớp bừa.
  • Đối chứng: 2 dòng Seeded 1 menu items / Seeded 1 admin permissions = menu-row ContractCatalog + permission cũng vào (leaf Catalogs thứ 5).
  • 🔑 TAM-GIÁC 3 NGUỒN ĐỘC-LẬP khớp từng đồng: source-parse (86 / 8 nhóm) == sqlcmd prod (86 / 8 nhóm) == API materialize qua EF (86 / 8 nhóm, xem Mục 6). Không nguồn nào suy ra nguồn kia.
  • PASS

Mục 5 — Bundle đổi ×2 app (#77 byte-level)

Vế DƯƠNG — hash MỚI là asset THẬT:

URL code content-type size
admin /assets/index-CKgq0YlH.js 200 application/javascript 1.751.576
admin /assets/index-DD3xQhNt.css 200 text/css 86.298
eoffice /assets/index-CHMCU35C.js 200 application/javascript 1.667.782
eoffice /assets/index-CdXRNT7E.css 200 text/css 92.092

Vế ÂM — hash CŨ phải BIẾN MẤT khỏi đĩa (né SPA-fallback-200-trap S72, discriminator = Content-Type không phải status):

URL cũ code content-type size
admin index-B43R6Y17.js 200 text/html 900
admin index-BZ5F-g1w.css 200 text/html 900
eoffice index-NLI5umBg.js 200 text/html 876
eoffice index-yNZDmVNz.css 200 text/html 876

⇒ cả 4 rơi về SPA-shell 876/900 B (trùng khít size index.html) = file cũ đã bị ghi đè thật, KHÔNG phải cache.

Ship-proof Last-Modified in-window (#69 TWO-MODE — hash-delta một mình không đủ):

  • admin /Last-Modified: Fri, 31 Jul 2026 08:51:06 GMT = 15:51:06 +07 ✔ in-window · Cache-Control: no-cache
  • eoffice /Last-Modified: Fri, 31 Jul 2026 08:52:07 GMT = 15:52:07 +07 ✔ in-window · Cache-Control: no-cache

4/4 hash ROTATE + 4/4 hash cũ chết + LM in-window. PASS

Mục 6 — Smoke

Check Kỳ vọng Đo được KL
GET /health (bare) 404 control — route bare không tồn tại
GET /health/ready 200 200
GET /health/live 200 200
GET /api/catalogs/contract-catalog KHÔNG token 401 401 authz sống
CONTROL …/contract-catalog-KHONGTONTAI 404 404 401 CÓ NGHĨA
CONTROL …/bia-dat-hoan-toan 404 404 (route bịa ⇒ 401 ở trên không phải blanket)
https://admin.solutions.com.vn/ 200 200
https://eoffice.solutions.com.vn/ 200 200
CÓ token admin GET …/contract-catalog 200 + 86 row 200, 25.374 B, 86 row

Cross-check EF-materialize (mạnh hơn sqlcmd vì đi qua Domain→Infra→Api thật):

rows materialized via EF = 86
by approvalGroup: 1:5 . 2:10 . 3:5 . 4:23 . 5:14 . 6:15 . 7:13 . 8:1
distinct codes = 86
sample row: code=A1-01 group=1 signer=TP.CCM

Class-level [Authorize] + ghi [Authorize(Roles="Admin")] (đọc ContractCatalogController.cs:21-22,39-56) ⇒ 401-không-token đúng thiết-kế, không phải #44 silent-403.

  • PASS

Ghi chú lệch / quan sát (KHÔNG phải FAIL)

  1. Hash CI ≠ hash local build. Đề bài dự-báo local ra admin BE7zE81C/user DSXJJbJq; CI ra CKgq0YlH/CHMCU35C. Tiêu chí đề bài (ĐỔI so với trước + curl 200) thoả. Nghĩa: artifact CI khác byte với artifact local (thường do Node minor / cây npm resolve khác) — bình thường, nhưng ⇒ đừng bao giờ dùng hash local làm mốc kỳ vọng cho prod, luôn re-snapshot LIVE.
  2. Duration 6m31s — dài nhất 4 run gần đây (#432 5m50s · #433 5m55s · #431 5m50s). Chưa tới ngưỡng escalate; hợp lý vì run này có thêm Mig 70 + seed 86 row + 8 test mới. Theo dõi tiếp, chưa cần hành động.
  3. Passed! grep 2-khoảng-trắng — lần grep đầu 0-hit là DƯƠNG-GIẢ do format; đã soi format rồi mới kết luận (bài học: 0-hit phải kèm control-dương trước khi báo).
  4. [WRN] global-query-filter (ContractSigningPlan/Contract ↔ Approval/Changelog/LevelOpinion) là warning EF có sẵn từ trước (Mig 69 S161), không do commit này sinh ra.

Kết luận

Không có critical issue. Không đề xuất rollback. 0 thao tác ghi lên prod.

END sub-cicd-verify-k1 — VERDICT=PASS 6/6 (run #434 id=547 success 6m31s · gate 598=45D+553I · Mig 70 top prod · seed 86/8-nhóm khớp 3 nguồn · bundle 4/4 rotate + 4/4 hash cũ chết · smoke 8/8 + 401 có-nghĩa)