[CLAUDE] Api: bỏ dấu phẩy trong tên 2 template .docx — vá MSB4186 làm CI #489 đỏ (gotcha #93)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 9m28s

CI run #489 ĐỎ sau 2m42s ở test-gate Infrastructure — nhưng lỗi thật ở BUILD, không phải test:

  Microsoft.NET.Publish.targets(851,9): error MSB4186: Invalid static method invocation syntax:
  "[MSBuild]::MakeRelative($(MSBuildProjectDirectory), …nhan cong, vat tu.docx)". Method not found.

MSBuild property-function tách tham số bằng DẤU PHẨY ⇒ đường dẫn chứa ", " biến lời gọi
2-tham-số thành 3 ⇒ không có overload ⇒ MSB4186, chặn ngay ở build nên test chưa kịp khởi động.

🔴 LOCAL KHÔNG TÁI HIỆN ĐƯỢC: global.json để rollForward=latestFeature ⇒ CI nhảy SDK 10.0.202
còn local 10.0.104. Đo: grep -c "MakeRelative" trong Publish.targets của SDK local = 0
(control dương "ContentWithTargetPath" = 8 ⇒ thước sống) — dòng mã gây lỗi KHÔNG TỒN TẠI trên
máy dev. "Local 699 PASS" là đúng-với-local, không phải đo ẩu.

Vá: đổi tên 2 file bỏ phẩy ("nhan cong, vat tu" → "nhan cong va vat tu"), sửa 2 chuỗi seed
DbInitializer + 4 chú thích nguồn trong lib/contractBody. Control: 4 template cũ cùng thư mục
không có phẩy ⇒ CI xanh nhiều tháng; 2 file mới có phẩy ⇒ đỏ ngay run đầu; biến duy nhất = phẩy.

+ gotcha #93 + luật khắc tại chỗ trong DbInitializer: tên file dưới wwwroot CẤM chứa dấu phẩy.

Đo lại sau vá: build 0 error (bin/obj dọn sạch trước) · test 699 PASS · 0 file wwwroot còn phẩy
· 2 cặp file body002_0*.ts vẫn trùng sha256.

🔸 CHƯA vá lớp gốc (SDK drift CI⟂local): siết rollForward sang latestPatch/disable sẽ đóng cả
lớp NHƯNG runner đang có 10.0.202 — pin về 10.0.1xx mà runner không cài thì CI chết hẳn thay vì
đỏ một run. Phải đo SDK trên runner trước; quyết định của chủ dự án.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-08-14 04:30:51 +07:00
parent 7663cd7e30
commit 4ba2b16b70
8 changed files with 41 additions and 6 deletions

View File

@ -1515,3 +1515,30 @@ for h in resp.points: # ← .points không phải iterable trực tiếp
34. Nếu Gitea Actions run CANCELLED ngay sau khi push 2 commit sát nhau → auto-cancel cùng-branch: đọc run CUỐI của range + verify artifact-level (bundle/marker/seeder-log), KHÔNG đọc CANCELLED thành deploy-fail; side-effect @startup chỉ chạy 1 lần cho cả cụm (#86)
35. Nếu probe endpoint để hỏi **authz** mà nhận **415/411** → đó là mã **PRE-AUTH**, vô nghĩa cho câu hỏi authz: request bị loại ở tầng **action-selection / IIS** TRƯỚC authorization filter. Re-probe đúng dạng body (multipart cho endpoint upload; có body cho SignalR negotiate) rồi mới đọc 401/403 (#87)
36. Nếu login prod 500 "transient failure UseSqlServer" + DB RECOVERY_PENDING sau sự cố disk đầy → check **cờ nén NTFS** trên .mdf/.ldf (`compact <file>`, Msg 5118): SET OFFLINE → backup copy → restart service nhả handle → `compact /U` → SET ONLINE. CẤM nén cây SQL DATA (#88)
### 93. Dấu PHẨY trong tên file asset ⇒ `MSB4186` — CI đỏ mà LOCAL không tài nào tái hiện (Session 194)
**Triệu chứng:** commit thêm 2 file `.docx` vào `wwwroot/templates/`. Local: build 0 error, **699 test PASS**, `tsc` sạch. Push → CI run **#489 ĐỎ sau 2m42s**, chết giữa test-gate Infrastructure, **chưa tới build FE, chưa tới deploy**.
```
Microsoft.NET.Publish.targets(851,9): error MSB4186: Invalid static method invocation syntax:
"[MSBuild]::MakeRelative($(MSBuildProjectDirectory), …\SOL-CCM-FO-002.02.v01 Hop dong tron goi nhan cong, vat tu.docx)".
Method '[MSBuild]::MakeRelative' not found.
```
**Cơ chế:** MSBuild property-function **tách tham số bằng dấu phẩy**. Tên file chứa `, ` biến lời gọi 2-tham-số thành **3 tham số** ⇒ không có overload ⇒ `MSB4186`. Lỗi ở **BUILD**, nên test không kịp khởi động — đọc log thấy "test fail" là đọc nhầm tầng.
🔴 **Vì sao LOCAL KHÔNG BAO GIỜ BẮT ĐƯỢC — đây mới là phần đắt:**
`global.json` = `{"sdk":{"version":"10.0.104","rollForward":"latestFeature"}}`. `latestFeature` **cho phép nhảy feature-band** ⇒ local `10.0.104`, CI `10.0.202`. Đo quyết định:
```
grep -c "MakeRelative" <SDK 10.0.104>/Microsoft.NET.Publish.targets = 0 ← dòng gây lỗi KHÔNG TỒN TẠI ở local
grep -c "ContentWithTargetPath" cùng file = 8 ← CONTROL DƯƠNG (thước sống)
ls "C:\Program Files\dotnet\sdk\" = 10.0.104, 9.0.311 (không có 10.0.2xx)
```
*"Local 699 PASS"***đúng-với-local**, không phải đo ẩu. Chạy lại bao nhiêu lần cũng không đỏ.
**Control có sẵn ngay trong thư mục, không cần dựng thêm:** 4 template CŨ cùng chỗ **không có phẩy** → CI xanh nhiều tháng (control dương). 2 file mới **có phẩy** → đỏ ngay run đầu (control âm). Biến duy nhất đổi = dấu phẩy.
**LUẬT:** 🔴 **tên file dưới `wwwroot/` CẤM chứa dấu phẩy.** Khoảng trắng thì OK (4 file cũ đều có). Đổi tên phải sửa kèm chuỗi seed trong `DbInitializer.cs` (2 điểm tham chiếu).
**Họ hàng với #92:** cùng lớp *build-env CI trôi khỏi local*, nhưng #92 ở tầng **npm** (đã khoá bằng lockfile + `npm ci`), còn đây ở tầng **.NET SDK** — vẫn **thả trôi** qua `rollForward: latestFeature`. Siết thành `latestPatch`/`disable` sẽ đóng cả lớp, **nhưng rủi ro thật**: runner đang có `10.0.202`; pin về feature-band `10.0.1xx` mà runner không cài bản đó thì **CI chết hẳn** thay vì chỉ đỏ một run. Cần đo SDK có trên runner TRƯỚC khi siết — quyết định của chủ dự án.