10 KiB
CI/CD verify — S157 (2026-07-28) — PE cảnh báo "Địa điểm" khi dự án chưa có Location
Agent: cicd-monitor · READ-only · file ghi TỪNG MỤC trong lúc làm (chống #53 return-garble) Range:
f4494cf..a52a91e· run-folder tái dụng S155
MỤC 1 — Push + path-filter (gotcha #41) ✅ ĐÃ ĐO
a52a91e7110b6d04a7ad26b70aa7db2c4888e160 | 2026-07-28 09:32:59 +0700 | [CLAUDE] Docs: tick counter S157 + bump header CURRENT STATE moc S153->S156
6250f39c52905579f873034c0dc04dfc3ada0287 | 2026-07-28 09:32:33 +0700 | [CLAUDE] PurchaseEvaluation: hien ly do o Dia diem trong khi du an chua co Location
git log origin/main..HEAD→ RỖNG ⇒ push đã lênmainthật.- Files
6250f39(4 file, FE 2-app mirror):fe-admin/src/components/pe/PeHeaderForm.tsxfe-admin/src/components/pe/PeWorkspaceCreateView.tsxfe-user/src/components/pe/PeHeaderForm.tsxfe-user/src/components/pe/PeWorkspaceCreateView.tsx
- Files
a52a91e(2 file):.claude/governance/.session-counter.json+docs/STATUS.md
Path-filter check vs 7-glob paths-ignore (docs/**, **/*.md, .claude/skills/**, .claude/agent-memory/**, .claude/workflows/runs/**, .gitignore, scripts/**.md):
fe-{admin,user}/src/**KHÔNG khớp glob nào ⇒ CI PHẢI chạy..session-counter.jsoncũng thoát glob (không phải.md, không nằm skills/agent-memory) — nhưng Gitea đánh giá cả range push, có ≥1 file non-ignored ⇒ toàn range build.
Kết luận M1: KHÔNG phải docs-only skip. Pipeline bắt buộc fire. ✅
MỤC 2 — Gitea Actions run (đang đo)
Poll #1 @ ~09:41+07 — .../actions/tasks?limit=6:
| id | run# | head_sha | status | created | updated |
|---|---|---|---|---|---|
| 532 | 419 | a52a91e7 |
running | 2026-07-28T09:40:18+07 | 09:41:23+07 |
| 531 | 418 | f4494cfe |
success | 07-27T14:36:54 | 14:42:35 |
| 529 | 416 | b1bae77c |
success | 07-27T12:37:18 | 12:42:49 |
⇒ Run ĐÃ FIRE đúng head_sha a52a91e (xác nhận M1: không skip). Trạng thái lúc đo đầu = running, CHƯA kết luận. Đang chờ terminal.
Marker gốc (từ git show 6250f39) — chuỗi sẽ grep trong bundle prod:
⚠ Dự án này chưa có Địa điểm trong Danh mục Dự án — nhập tay ở đây, hoặc bổ sung vào Danh mục (Dự án → Địa điểm) để các phiếu sau tự điền.
Substring dùng để grep (an toàn minifier, nằm trong string literal): chưa có Địa điểm trong Danh mục
MỤC 3 — PRE-deploy bundle snapshot (chụp TRƯỚC khi run xong) ✅ ĐÃ ĐO
Đo lúc 09:41:56 +07 (run 532 còn running ⇒ đây là trạng thái CŨ, chưa ship):
| app | js hash | css hash | Last-Modified index.html |
|---|---|---|---|
| admin.solutions.com.vn | BK8w3QxU |
DiNJjaoo |
Mon, 27 Jul 2026 07:41:15 GMT (=14:41 +07) |
| eoffice.solutions.com.vn | DYnxSI0T |
BRCvEHvC |
Mon, 27 Jul 2026 07:42:10 GMT (=14:42 +07) |
⇒ KHỚP CHÍNH XÁC baseline STATUS S156 (BK8w3QxU / DYnxSI0T), LM trỏ đúng run #418 (f4494cf, xong 14:42:35 07-27). Pre-state hợp lệ để so hash sau deploy.
MỤC 4 — Run terminal + TEST GATE ✅ PASS
Poll 7 vòng (09:41→09:46, ~30s/vòng), chuyển trạng thái:
running (iter 2–6) → success (iter 7 @ 09:46:00, updated_at 2026-07-28T09:45:58+07).
- Run id 532 · run_number #419 · head_sha
a52a91e - Start 09:40:18 → End 09:45:58 ⇒ duration 5m40s (nằm trong dải bình thường 4m40–5m40, không escalate)
- URL:
https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp/actions/runs/419
Test gate — đếm CỤ THỂ từ web-UI log (17.850 bytes):
Passed! - Failed: 0, Passed: 45, Skipped: 0, Total: 45 — SolutionErp.Domain.Tests.dll (164 ms)
Passed! - Failed: 0, Passed: 517, Skipped: 0, Total: 517 — SolutionErp.Infrastructure.Tests.dll (1 m 25 s)
⇒ 562 PASS (45 Domain + 517 Infra), 0 fail / 0 skip — KHỚP baseline canonical 562 (docs/STATUS.md). Grep error |FAILED|Build FAILED trên toàn log ⇒ 0 hit. Gate xanh, chạy TRƯỚC build+deploy ⇒ deploy hợp lệ.
MỤC 5 — Bundle rotate ×2 app ✅ ROTATE CẢ HAI
Đo lúc 09:46:12 +07 (sau khi status=success — tránh false-positive stale kiểu Run #242):
| app | js TRƯỚC | js SAU | Δ | css | Last-Modified (UTC → +07) |
|---|---|---|---|---|---|
| admin | BK8w3QxU |
8-QYcMOg |
✅ ĐỔI | DiNJjaoo (frozen) |
28 Jul 02:44:33 GMT → 09:44:33 +07 |
| eoffice | DYnxSI0T |
DptYR4wL |
✅ ĐỔI | BRCvEHvC (frozen) |
28 Jul 02:45:30 GMT → 09:45:30 +07 |
- Cả 2 LM nằm TRONG cửa-sổ deploy (09:40:18 – 09:45:58) ⇒ file thật sự được ghi đè trong run này, không phải tàn dư.
- css FROZEN cả 2 = dấu vân tay "FE-logic-no-new-style": khối thêm chỉ dùng utility Tailwind đã có sẵn trong bundle (
text-amber-700,mt-1) ⇒ content-hash CSS không đổi. Lành tính theo #69-REFINE, KHÔNG phải cờ đỏ. - index.html size 900B/876B +
Last-Modifiedmới ⇒ shellno-cacheđã revalidate đúng.
⇒ Deploy ĐÃ ăn tới đĩa. Hash đổi 2/2.
MỤC 6 — 🔴 BYTE-MARKER trong bundle prod (phép QUYẾT ĐỊNH, gotcha #77) ✅ 2/2
Tải THẲNG file JS prod rồi bytes.count(marker.encode('utf-8')) (bytes, không decode — tránh bẫy cp1252 S134):
| app | URL asset | HTTP | size THẬT | Content-Type | Last-Modified |
|---|---|---|---|---|---|
| admin | /assets/index-8-QYcMOg.js |
200 | 1.675.282 B | application/javascript |
28 Jul 02:44:33 GMT |
| eoffice | /assets/index-DptYR4wL.js |
200 | 1.575.513 B | application/javascript |
28 Jul 02:45:30 GMT |
Đếm marker (4 chuỗi độc lập, cùng 1 câu cảnh báo):
| chuỗi grep | admin | eoffice |
|---|---|---|
chưa có Địa điểm trong Danh mục |
2 | 2 |
Danh mục Dự án |
2 | 2 |
Dự án → Địa điểm |
2 | 2 |
để các phiếu sau tự điền |
2 | 2 |
⇒ CÓ MẶT Ở CẢ 2 APP. count=2 khớp CHÍNH XÁC số file/app trong diff (PeHeaderForm.tsx + PeWorkspaceCreateView.tsx = 2 chỗ nhúng chuỗi/app). Không dư, không thiếu.
Control âm (chống đọc-nhầm SPA-fallback 200):
| control | HTTP | size | ct | marker |
|---|---|---|---|---|
fake hash index-ZZfake0000.js (admin) |
200 | 900 | text/html | 0 |
fake hash index-ZZfake0000.js (eoffice) |
200 | 876 | text/html | 0 |
hash CŨ index-BK8w3QxU.js (admin) |
200 | 900 | text/html | — |
hash CŨ index-DYnxSI0T.js (eoffice) |
200 | 876 | text/html | — |
⇒ Control chứng minh 2 điều: (i) HTTP 200 một mình VÔ NGHĨA — discriminator thật là ct=application/javascript + size ~1,6MB; (ii) bundle CŨ đã BIẾN MẤT khỏi đĩa (rơi về SPA shell) ⇒ deploy ghi đè thật, không phải thêm file mới cạnh file cũ.
Đây là bằng chứng mạnh nhất: mã S157 đang CHẠY THẬT trên prod cả 2 app.
MỤC 7 — Smoke 3 site sau deploy ✅ ALL GREEN
| check | kỳ vọng | thực đo | KQ |
|---|---|---|---|
GET /health/live |
200 | 200 Healthy |
✅ |
GET /health/ready |
200 | 200 Healthy |
✅ |
POST /api/auth/login (admin) |
200 + token | 200, accessToken 468 ký tự |
✅ |
GET /api/projects?pageSize=1 |
200 | 200 (374 B) | ✅ |
GET /api/purchase-evaluations?pageSize=1 |
200 | 200 (969 B) | ✅ |
GET /api/menus |
200 | 200 (14.802 B) | ✅ |
GET /api/suppliers?pageSize=1 |
200 | 200 (751 B) | ✅ |
GET https://admin.solutions.com.vn/ |
200 | 200 (900 B shell) | ✅ |
GET https://eoffice.solutions.com.vn/ |
200 | 200 (876 B shell) | ✅ |
/api/projects 200 đặc biệt đáng ghi: đây chính là nguồn location mà khối cảnh báo mới đọc (projects.data?.find(...)?.location) ⇒ đường dữ liệu của feature còn sống.
MỤC 8 — Migration: VẮNG là ĐÚNG ✅
⚠️ ĐÍNH CHÍNH số của chính tôi (self-correct): thoạt đầu tôi viết "range = 6 file" — SAI. Đó là số của 2 commit
6250f39+a52a91ecộng lại, không phải của range. Rangef4494cf..a52a91ethật ra gồm 13 commit (2 commit code/docs + 11 commitwal: flush/wal: pause) chạm 26 file. Đo lại bằnggit diff --name-only ... | wc -l. Kết luận BE=0 KHÔNG đổi, nhưng con số phải đúng.
git diff --name-only f4494cf..a52a91e = 26 file / 13 commit; lọc -- 'src/Backend/*' '*Migrations*' ⇒ 0 file (đếm bằng wc -l, không phải mắt thường).
⇒ Không có Mig mới; Mig vẫn 68 AddPeAllowApproverDelete, sys.tables vẫn 89. Không query prod DB vì không có gì để đối chiếu — vắng migration ở đây là KỲ VỌNG, không phải cờ đỏ (đúng brief của lead).
BE 0 đổi ⇒ deploy này thuần FE; API vẫn Healthy (M7) xác nhận app pool recycle không làm gãy gì.
MỤC 9 — Cross-check baseline 562 với canonical ✅ KHỚP
docs/STATUS.md:452 (canonical): | Tests | **562 PASS** | 45 Domain + 517 Infra · 0 fail / 0 skip · S155 +30 ...
Log CI run #419 đo được: 45 Domain + 517 Infra = 562, 0 fail / 0 skip.
⇒ Trùng khít cả TỔNG lẫn TỪNG THÀNH PHẦN (không chỉ khớp số tổng — khớp cả tách 45/517). Không có test nào bị drop âm thầm, không có skip che lỗi.
VERDICT — PASS (9/9 mục xanh, 0 caveat)
| # | Mục | KQ |
|---|---|---|
| 1 | Push + path-filter không skip | ✅ |
| 2 | Run fire đúng a52a91e |
✅ |
| 3 | Pre-deploy snapshot = baseline S156 | ✅ |
| 4 | Run #419 success 5m40s + gate 562 | ✅ |
| 5 | Bundle rotate 2/2 + LM in-window | ✅ |
| 6 | 🔴 Byte-marker 2/2 app (count=2 mỗi app) + control âm sạch | ✅ |
| 7 | Smoke 3 site + 4 endpoint + login | ✅ |
| 8 | Migration vắng = đúng (BE 0 đổi) | ✅ |
| 9 | 562 khớp canonical cả 45/517 | ✅ |
Không có việc phải làm tiếp. Không khuyến nghị rollback.
Ghi chú cho session sau: text-[11px] + text-amber-700 KHÔNG làm rotate CSS hash ⇒ 2 utility này đã có sẵn trong bundle từ trước; css-frozen ở đây là dấu hiệu ĐÚNG của "FE logic-only", không cần điều tra.