This repository has been archived on 2026-07-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
code-review/skills/code-review-nuget/SKILL.md
T

157 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: code-review-nuget
description: 將 C# / .NET 專案的 NuGet 套件更新到最新可用版本。當使用者要求更新 NuGet、升級 PackageReference、清理重複套件參考、檢查專案參考中的重複 NuGet、或逐包更新並確認 build 時觸發。流程會依專案分組列出套件,檢查 ProjectReference 上層專案是否已引用相同套件並移除可安全移除的重複參考,接著逐一更新套件版本;每更新或移除一個套件都必須 restore/build 驗證。若更新到最新版本後編譯失敗,改由目前版本之後的最小可用版本逐版升級,直到遇到第一個編譯失敗版本,保留最後一個可編譯版本。不適用於:非 .NET 專案、只想查詢套件清單不更新、或只要人工建議不修改檔案。
argument-hint: "[<solution-or-project>] [--include-prerelease] [--no-dedupe] [--build <command>] [--yes]"
---
# code-review-nuget — 更新 C# 專案 NuGet 套件
把 C# / .NET repo 內的 NuGet 套件依專案盤點、清理可安全移除的重複參考,然後逐一更新到最新可用版本。每個套件異動後都要驗證專案可以正常編譯;若最新版本失敗,改從目前版本之後的最小可用版本逐版升級,直到第一個編譯失敗版本為止,保留最後一個可編譯版本並記錄失敗點。
## 輸出規範
- 所有面向使用者的輸出一律使用繁體中文(台灣用語);套件 id、檔名、指令、版本號保留原文。
- 修改前先輸出簡短執行計畫;除非使用者要求確認、遇到多個 solution 無法判斷、或編譯失敗需要取捨,否則依計畫執行。
- 每個套件都要留下結果:已更新 / 已降階到可編譯版本 / 已略過 / 已回復 / 已移除重複參考,以及對應版本與驗證指令。
- 不主動 commit、push 或開 PR;使用者明確要求時才做。
- **遇到 `JSC` 開頭的套件(套件 id 前綴為 `JSC`)時,必須先通知使用者並詢問是否要繼續處理該套件,取得明確同意後才可動作(更新版本或移除重複參考)。此確認為強制項,不得被 `--yes` 略過。使用者若拒絕,將該套件記為「已略過(JSC 套件,使用者未同意)」並繼續處理其他套件。**
## 參數
`[<solution-or-project>] [--include-prerelease] [--no-dedupe] [--build <command>] [--yes]`
- `<solution-or-project>``.sln``.slnx``.csproj` 路徑。省略時自動搜尋;若找到多個 solution 且無法判斷主專案,必須詢問。
- `--include-prerelease`:更新時允許 prerelease 版本;未指定時只更新 stable 版本。
- `--no-dedupe`:略過 ProjectReference 重複 PackageReference 清理,只更新版本。
- `--build <command>`:覆寫驗證指令,例如 `dotnet build My.sln -c Release`。未指定時用 `dotnet build <solution-or-project> --no-restore`
- `--yes`:可略過一般確認,但仍不可忽略多 solution 選擇、無法安全清理重複參考、編譯失敗的必要決策、或 `JSC` 開頭套件的繼續確認。
## 執行流程
### 1. 探測專案與工具
1. 確認目前在 repo 根目錄或可找到 git root。
2. 檢查工具:
```bash
dotnet --info
dotnet --list-sdks
```
3. 找出目標:
- 參數有指定 `.sln` / `.slnx` / `.csproj` → 使用該路徑。
- 未指定 → 依序搜尋 `.slnx`、`.sln`、`.csproj`。
- 多個 solution 且無明顯唯一主檔 → 詢問使用者選擇,不可猜測。
4. 先執行 baseline 驗證:
```bash
dotnet restore <目標>
dotnet build <目標> --no-restore
```
baseline build 失敗時停止,回報現況;不要在不可編譯的基準上升級套件。
### 2. 依專案分組列出 NuGet 套件
1. 找出目標涵蓋的所有 `.csproj`
- solution:可用 `dotnet sln <solution> list`,必要時解析輸出中的 `.csproj`。
- 單一 project:只處理該 project 與其 ProjectReference 圖。
2. 對每個專案列出 direct 套件:
```bash
dotnet list <project.csproj> package --outdated
dotnet list <project.csproj> package --include-transitive
```
3. 讀取 `.csproj`、`Directory.Packages.props`、`Directory.Build.props`,判斷是否使用 Central Package Management`ManagePackageVersionsCentrally` / `PackageVersion`)。
4. 產出「依專案分組」清單:
| 專案 | 套件 | 目前版本 | 最新版本 | 參考來源 | 備註 |
| --- | --- | --- | --- | --- | --- |
`參考來源` 標註 `PackageReference`、`Directory.Packages.props`、`transitive` 或 `ProjectReference`。
### 3. 檢查 ProjectReference 重複套件
> 這裡的「上層專案」指目前專案透過 `ProjectReference` 直接或間接參考到的專案;若該被參考專案已 direct reference 同一個 NuGet 套件,且該套件會透過專案參考傳遞,當前專案通常不需要重複 direct reference。
1. 建立 ProjectReference graph
- 讀每個 `.csproj` 的 `<ProjectReference Include="...">`。
- 正規化路徑,建立「目前專案 → 被參考專案」的 direct / transitive 關係。
2. 比對 direct PackageReference
- 若目前專案與其 direct/transitive ProjectReference 上層專案有相同套件 id,列為重複候選。
- 若目前專案的套件參考含 `PrivateAssets="all"`、`IncludeAssets` / `ExcludeAssets` 特殊設定、analyzers/build/source generators、或版本刻意高於上層專案,先列為「需人工確認」,不要自動移除。
- 若上層專案的參考含 `PrivateAssets="all"` 或不會傳遞必要 assets,不可視為可替代。
3. 對可安全移除的重複 direct reference 逐一處理:
- **若該套件 id 為 `JSC` 開頭,先通知使用者並詢問是否繼續移除,取得同意才處理;未同意則記為「已略過(JSC 套件,使用者未同意)」。此確認不得被 `--yes` 略過。**
- 先記錄目前檔案狀態與套件版本。
- 移除當前專案的重複 `PackageReference`;若使用 Central Package Management,只有在沒有任何專案仍需要該 `PackageVersion` 時才移除中央版本項。
- 執行:
```bash
dotnet restore <目標>
dotnet build <目標> --no-restore
```
- build 成功 → 保留移除。
- build 失敗 → 回復該移除,重新 restore/build 確認回復後可編譯,並記錄失敗原因。
### 4. 逐一更新套件版本
1. 排除不應更新的項目:
- transitive-only 套件不直接更新;更新提供它的 direct 套件。
- 明確 pin 住版本且註解或 props 顯示有相容性原因者,先列入「需人工確認」。
- `PrivateAssets="all"` 的 analyzer / generator / build tooling 可更新,但要特別注意 build 驗證結果。
- **`JSC` 開頭的套件:在更新版本前,必須先通知使用者「即將處理 JSC 套件 `<PackageId>`」並詢問是否繼續,取得同意才更新;未同意則記為「已略過(JSC 套件,使用者未同意)」。此確認不得被 `--yes` 略過。**
2. 逐一更新 direct 套件:
- 一次只更新一個套件 id。
- 若多個專案引用同一套件,先判斷是否使用 Central Package Management
- CPM:更新對應 `Directory.Packages.props` 的單一 `PackageVersion`。
- 非 CPM:依專案逐一更新該套件。
- 優先使用 `dotnet add <project> package <PackageId>` 讓 NuGet 選擇最新相容 stable 版本;若 `dotnet list package --outdated` 已提供最新版本,也可用 `--version <latest>` 明確更新。
- 指定 `--include-prerelease` 時,查詢與更新都允許 prerelease;未指定時不得升到 prerelease。
3. 每更新一個套件後立即驗證:
```bash
dotnet restore <目標>
dotnet build <目標> --no-restore
```
若使用者提供 `--build <command>`,以該命令取代 build 步驟,但 restore 仍需執行。
4. 驗證結果:
- 成功:記錄 `PackageId oldVersion -> newVersion`,保留變更。
- 最新版本失敗:先回復最新版本異動與 lock file 變更,確認回到可編譯狀態;接著查詢該套件「目前版本之後、最新版本之前或等於最新版本」的所有可用版本,由最低版本開始逐一升級並每版 restore/build。遇到成功就暫時保留並繼續下一版;遇到第一個失敗版本就停止此套件升級、回復到上一個成功版本,記錄為「已降階到可編譯版本」。如果第一個候選版本就失敗,回復到原版本並記錄為「已回復」。
- 查詢可用版本時優先使用目前專案既有 feed 設定(`nuget.config`);可用 `dotnet package search`、`nuget list`、NuGet v3 API 或專案環境可用的等價工具。不得改用未設定的公開 feed 造成私有套件版本判斷錯誤。
- 因相依套件版本衝突導致失敗:可嘗試更新同一 dependency chain 中的必要 direct 套件,但仍必須一次一包、每包驗證。
### 5. 特殊檔案與版本管理
- `packages.lock.json` 存在時,更新套件後允許 lock file 跟著變更;回復失敗更新時也要回復 lock file。
- `nuget.config` 有私有 feed 時,不輸出 credential;錯誤訊息若含 token / password 必須遮蔽。
- `packages.config` 專案不套用 `dotnet add package` 流程;先回報這是舊格式,使用 `nuget.exe update` 或請使用者確認遷移策略。
- 多 target framework 專案以完整目標 build 為準,不只 build 單一 framework。
### 6. 最終總結
完成後輸出:
| 類別 | 套件 / 專案 | 結果 |
| --- | --- | --- |
至少包含:
- 重複 PackageReference:移除幾筆、回復幾筆、需人工確認幾筆。
- NuGet 更新:成功幾筆、已是最新幾筆、降階到可編譯版本幾筆、回復幾筆、略過幾筆。
- 最後一次成功驗證的指令。
- 尚待人工處理的套件與原因。
若所有變更後最終 build 成功,明確寫「最終編譯驗證成功」。若有套件因最新版本失敗而降階或回復,說明目前工作區保留的是已通過 build 的變更集合,並列出失敗版本與最後成功版本。
## 呼叫方式
| 助理 | 呼叫 |
| --- | --- |
| Claude Code / Antigravity | `/jsc:code-review-nuget`,或 `/jsc:code-review-nuget MySolution.sln --include-prerelease` |
| Codex | `$code-review-nuget`,或 `$code-review-nuget src/App/App.csproj --build "dotnet build App.sln -c Release"` |
| OpenCode | 描述需求(如「把這個 .NET solution 的 NuGet 都更新到最新,先清掉 ProjectReference 已提供的重複套件,每更新一包就 build」)自動觸發 |