128 lines
8.1 KiB
Markdown
128 lines
8.1 KiB
Markdown
CICD-K7: IN-PROGRESS (đang đo — verdict ở dòng cuối)
|
||
|
||
# sub-cicd-verify-k7 — deploy verify K7 (bridge KHKK→HĐ), S167 2026-08-01
|
||
|
||
> Artifact chống-#53: ghi TỪNG MỤC ngay khi có bằng chứng. Return chỉ là tóm tắt.
|
||
> Baseline PRE đọc từ `sub-cicd-verify-k6.md` (post-#440): admin js `Ig1R5tAh` · eoffice js `DFOCQ2ks` · gate 622=45+577 · Mig 71 · sys.tables 97.
|
||
|
||
---
|
||
|
||
## M0 — Push + path-filter (ĐÃ ĐO)
|
||
|
||
- HEAD = `aaed699228f418fa31ecba07414709de465502fc`
|
||
subject: `[CLAUDE] Contract: K7 SP-002 bridge KHKK->HD hoi-2-khoa + Line.ContractId + grant seeder (gate PASS-WITH-FLAGS 10, F-8 fixed)`
|
||
committed: 2026-08-01 13:04:49 +0700
|
||
- `git log origin/main..HEAD` = **RỖNG** ⇒ đã push thật.
|
||
- Range `1c6d77a..aaed699` = 7 commit (6 × `wal: flush` + 1 code).
|
||
- **File code trong range (13/13 khớp đề bài):**
|
||
- BE (4): `Api/Controllers/ContractSigningPlansController.cs` · `Application/ContractSigningPlans/ContractSigningPlanFeatures.cs` · `Application/ContractSigningPlans/CreateContractFromSigningPlanFeatures.cs` · `Infrastructure/Persistence/DbInitializer.cs`
|
||
- FE mirror ×2 app (6): `fe-{admin,user}/src/hooks/usePipelineStages.ts` · `.../pages/khkk/KhkkDetailPage.tsx` · `.../types/khkk.ts`
|
||
- Test (3): `Api/AuthorizePolicyRegressionTests.cs` · `Api/KhkkBridgeAuthzTests.cs` · `Application/CreateContractFromSigningPlanTests.cs`
|
||
- (còn lại 14 file đều `.claude/**` = paths-ignore, KHÔNG trigger)
|
||
- **M3-phần-1 (git):** `git diff --name-only 1c6d77a..aaed699 -- '*Migrations*'` = **0 file** ⇒ 0-mig chứng-minh-được từ git.
|
||
- Path-filter: có file `src/**` + `fe-*/**` ⇒ CI PHẢI chạy (không skip).
|
||
|
||
---
|
||
|
||
## M1 — Run Gitea 🔴 PHÁT HIỆN LỚN: run của `aaed699` bị **CANCELLED**, KHÔNG success
|
||
|
||
Đo lúc 13:09-13:10 qua `actions/tasks?limit=3` (khớp theo `head_sha`, KHÔNG theo run_number):
|
||
|
||
| run | head_sha | status | started | updated | ghi chú |
|
||
|---|---|---|---|---|---|
|
||
| **#441** (id 554) | **`aaed699`** | 🔴 **cancelled** | 13:04:57 | 13:07:59 | sống ~3m02s rồi bị **huỷ giữa chừng** |
|
||
| **#442** (id 555) | `628132c` | running → (đo tiếp) | 13:08:26 | … | run-2 lead báo |
|
||
| #440 (id 553) | `1c6d77a` | success | 11:54:38 | 12:01:07 | mốc PRE (K6) |
|
||
|
||
**Cơ chế:** push `628132c` lúc 13:08:26 ⇒ Gitea **cancel-in-progress** giết run #441 đang chạy.
|
||
⇒ **Đề bài mục 1 ("run `aaed699` success") KHÔNG THOẢ THEO NGHĨA ĐEN** — `aaed699` chưa bao giờ tự deploy xong.
|
||
|
||
**Nhưng K7 VẪN ship, chứng minh bằng ancestry (không phải suy đoán):**
|
||
- `git merge-base --is-ancestor aaed699 628132c` = **YES** ⇒ cây của run #442 CHỨA trọn 13 file K7.
|
||
- `git diff --name-only aaed699..628132c` = 6 file (`docs/STATUS.md` · `fe-{admin,user}/…/KhkkWorkflowPanel.tsx` · 3 `scripts/*.ps1`) — không đụng file K7 nào.
|
||
⇒ **run #442 = phương-tiện ship DUY NHẤT của K7.** Mọi phép đo POST vì thế quy về #442.
|
||
|
||
### 🔴 GOTCHA MỚI đề-xuất (#86) — "push-đè nuốt deploy im lặng"
|
||
Push code A rồi push B ngay sau (<run-time của A) ⇒ run A **cancelled**. Nếu B **rơi trọn vào `paths-ignore`**
|
||
(docs/memory-only) thì run B **skip** ⇒ **code A KHÔNG BAO GIỜ deploy**, mà bảng Actions trông vẫn "lành"
|
||
(1 cancelled + 0 run) và `git log` thì đã push. Lần này thoát **NHỜ MAY**: `628132c` có chạm `fe-*/src/**`
|
||
nên mới đẻ run. **Luật rút ra: sau 2 push liên tiếp, PHẢI xác minh run cuối cùng có head_sha là TIP và
|
||
tip ⊇ commit code, chứ không được đọc "có run xanh" là xong.**
|
||
|
||
**Hệ quả cho mục 5 (restart-proof):** giả định "run-1 + run-2 = restart ×2 miễn phí" của lead **KHÔNG còn
|
||
đúng** — run #441 bị giết TRƯỚC bước deploy nên **không hề restart pool**. Trong cửa sổ này chỉ có **1 lần
|
||
restart thật** (từ #442). Idempotent-qua-2-restart do đó phải hạ cấp thành "chưa chứng-minh-được trong
|
||
cửa-sổ" (xem M5) — tao KHÔNG tự restart pool prod (READ-only, cấm #6).
|
||
|
||
---
|
||
|
||
## M4-PRE — mốc bundle + tập marker (ĐO TRƯỚC khi deploy đè, 13:06-13:07)
|
||
|
||
**Bundle PRE (live, khớp đúng baseline K6 post-#440):**
|
||
|
||
| app | js | css | Last-Modified (GMT) | size js |
|
||
|---|---|---|---|---|
|
||
| admin | `index-Ig1R5tAh.js` | `index-DqXm5Hpn.css` | Sat 01 Aug 2026 **04:59:40** (=11:59:40 +07) | 1.758.853 B |
|
||
| eoffice | `index-DFOCQ2ks.js` | `index-DlN3yZ5L.css` | Sat 01 Aug 2026 **05:00:41** (=12:00:41 +07) | 1.676.752 B |
|
||
|
||
**Kiểm-tra-tiền-đề cho marker (bài K6 nâng cấp — kiểm ĐƠN-VỊ-MÃ-HOÁ + ĐỊA-CHỈ trước khi tin 0-hit):**
|
||
1. `file` báo bundle "ASCII text" ⇒ **nghi non-ASCII bị `\u`-escape**. Bác bỏ bằng đo: `grep -c -F 'Hợp đồng'`
|
||
= **4**, `'Kế hoạch'` = **3** trên bundle PRE ⇒ tiếng Việt nằm **thô (UTF-8)**, `grep -F` đọc được. ✅
|
||
2. **Nghi code-split** (nếu `KhkkDetailPage` nằm chunk lazy riêng thì marker 0-hit là vô nghĩa): index.html chỉ
|
||
trỏ **đúng 2 asset** (`index-*.js` + `index-*.css`), và bundle **0 ref** dạng `"./xxx-<hash>.js"` ⇒ **single-bundle**, không lazy-chunk. ✅
|
||
3. **CONTROL DƯƠNG** (chứng `KhkkDetailPage` THẬT nằm trong `index-*.js` + grep có răng) — 4 chuỗi bản **tiền-K7**
|
||
của chính file đó, đo trên **cả 2** bundle PRE: `Phiếu nguồn chưa có NCC trúng thầu.`=1/1 ·
|
||
`Chưa khai căn cứ nào.`=1/1 · `Giá tham chiếu (phiếu NCC)`=1/1 · `Tên TVGS xử lý`=1/1 ⇒ **4/4 hiện diện**. ✅
|
||
|
||
**CONTROL ÂM / tập marker K7 — 0-hit PRE trên CẢ 2 bundle (8/8, `grep -c -F`):**
|
||
|
||
| marker (chuỗi UI nút bridge) | adm PRE | eof PRE |
|
||
|---|---|---|
|
||
| `Đưa dòng kế hoạch vào Hợp đồng` | 0 | 0 |
|
||
| `Chọn dòng đưa vào hợp đồng` | 0 | 0 |
|
||
| `Loại hợp đồng` | 0 | 0 |
|
||
| `Quy trình duyệt hợp đồng` | 0 | 0 |
|
||
| `Phiếu chưa có dòng nhà cung cấp nào.` | 0 | 0 |
|
||
| `khkk-bridge-line` | 0 | 0 |
|
||
| `Tạo hợp đồng` | 0 | 0 |
|
||
| `Chưa có giá chốt` | 0 | 0 |
|
||
|
||
⇒ marker có **tín hiệu thật** (0→≥1 mới là bằng chứng ship). Diff FE đối xứng: `fe-admin` và `fe-user`
|
||
mỗi bên +308 dòng `KhkkDetailPage.tsx`, +61 `usePipelineStages.ts`, +49 `types/khkk.ts` (796 insert/40 delete tổng)
|
||
⇒ kỳ vọng **element-wise 8/8 ở CẢ 2 app**.
|
||
|
||
---
|
||
|
||
## M3 — Migration (phần git, ĐÃ CHỐT) + prod PRE
|
||
|
||
- git: `1c6d77a..aaed699` **0 file** dưới `*Migrations*` ⇒ **0-mig**. (Range mở rộng tới `628132c` cũng 0 — 6 file kia không có Migrations.)
|
||
- prod PRE (sqlcmd 13:06): `MIG_TOP` = `20260731085624_AddKhkkApprovalGroupCatalogAndFinalizeRuntime` = **Mig 71** ✅ ·
|
||
`sys.tables(is_ms_shipped=0)` = **97** ✅ · `MenuItems`=**200** · `Permissions`=**2221** (khớp anchor #438/#440).
|
||
|
||
---
|
||
|
||
## M5-PRE — trạng thái quyền `Contracts` TRƯỚC deploy (mấu chốt K7)
|
||
|
||
`SELECT COUNT(*) FROM Permissions WHERE MenuKey='Contracts' AND CanCreate=1` → **PRE = 1** ✅ (đúng dự-đăng-ký của gate-K7)
|
||
`SELECT COUNT(*) … WHERE MenuKey='Contracts'` (mọi cờ) → **PRE = 13 row** (13 role, mỗi role 1 row)
|
||
|
||
Bảng đầy đủ 13 role PRE — `CanRead=1` **toàn bộ**, `CanCreate=1` **duy nhất Admin**:
|
||
|
||
| role | create | read | | role | create | read |
|
||
|---|---|---|---|---|---|---|
|
||
| Accounting | 0 | 1 | | Equipment | 0 | 1 |
|
||
| **Admin** | **1** | 1 | | Finance | 0 | 1 |
|
||
| AuthorizedSigner | 0 | 1 | | HrAdmin | 0 | 1 |
|
||
| CatalogManager | 0 | 1 | | **Procurement** | **0** | 1 |
|
||
| CostControl | 0 | 1 | | ProjectManager | 0 | 1 |
|
||
| DeptManager | 0 | 1 | | | | |
|
||
| Director | 0 | 1 | | | | |
|
||
| **Drafter** | **0** | 1 | | | | |
|
||
|
||
⇒ **Drafter + Procurement ĐÃ CÓ row sẵn** (read=1, create=0) ⇒ seeder phải **UPGRADE 2 row**, **KHÔNG add row nào**
|
||
⇒ acceptance `0 added + 2 upgraded` **nhất-quán với trạng thái prod đo được**, và kỳ vọng POST:
|
||
**CanCreate=1 → 3** đồng thời **tổng row `Contracts` GIỮ NGUYÊN 13** (nếu thành 15 ⇒ seeder add trùng ⇒ FAIL).
|
||
Đọc code seeder xác nhận khuôn UPGRADE-ONLY: `SeedContractCreateAccessAsync` gọi **sau** revoker, chỉ nâng cờ, không hạ.
|
||
|
||
---
|