安全地從程式碼中移除功能開關,同時保留正式環境的行為。當使用者想要從程式碼中移除開關、刪除開關參考,或在功能推出完成後建立將獲勝變化寫死的 PR 時使用。
LaunchDarkly Flag Cleanup
你正在使用一個技能,它會引導你安全地從程式碼中移除功能開關,同時保留正式環境的行為。你的工作是探索程式碼庫以了解開關的使用方式,查詢 LaunchDarkly 以確定正確的前向值,乾淨地移除開關程式碼,並驗證結果。
如果你尚未識別要清理的開關,請先使用開關發現技能來審視整體情況並找出候選項目。
先決條件
此技能需要在你的環境中設定遠端託管的 LaunchDarkly MCP 伺服器。
必要的 MCP 工具:
check-removal-readiness:詳細的安全檢查(並行協調開關設定、跨環境狀態、相依性、程式碼參考和到期目標)get-flag:取得特定環境的開關設定
選用的 MCP 工具:
archive-flag:在程式碼移除後封存 LaunchDarkly 中的開關delete-flag:永久刪除開關(不可逆,建議封存)
核心原則
- 安全第一:始終保留當前的正式環境行為。
- 以 LaunchDarkly 為真相來源:絕不猜測前向值。查詢實際設定。
- 遵循慣例:尊重現有的程式碼風格和結構。
- 最小變更:僅移除與開關相關的程式碼。不進行無關的重構。
工作流程
步驟 1:探索程式碼庫
在接觸 LaunchDarkly 或移除程式碼之前,了解此開關在程式碼庫中的使用方式。
-
找出所有對開關鍵的參考。 在整個程式碼庫中搜尋開關鍵字串(例如
new-checkout-flow)。檢查:- 直接 SDK 評估呼叫(
variation()、boolVariation()、useFlags()等) - 參考該鍵的常數/列舉
- 抽象 SDK 的包裝器/服務模式
- 設定檔、測試和文件
- 請參閱 SDK 模式 以取得按語言分類的完整模式列表
- 直接 SDK 評估呼叫(
-
了解分支邏輯。 對於每個參考,識別:
- 當開關為
true(或變化 A)時執行哪些程式碼? - 當開關為
false(或變化 B)時執行哪些程式碼? - 是否有副作用、提前返回或巢狀條件?
- 當開關為
-
注意範圍。 此開關觸及多少檔案、元件或模組?在一個
if區塊中使用的開關比貫穿多個層級的開關更簡單。
步驟 2:執行移除就緒檢查
使用 check-removal-readiness 取得詳細的安全評估。這個單一工具呼叫會並行協調多項檢查:
- 開關設定和目標定位狀態
- 跨環境狀態
- 相依開關(先決條件)
- 到期目標
- 程式碼參考統計
該工具會傳回移除就緒判定:
safe:沒有阻擋或警告。繼續移除。
caution:沒有硬性阻擋,但存在警告(例如其他儲存庫中的程式碼參考、已排程的到期目標、開關標記為永久)。呈現警告並讓使用者決定。
blocked:硬性阻擋阻止安全移除(例如相依開關、正在接收請求、目標定位已啟用且有活躍規則)。呈現阻擋項目:使用者必須先解決它們。
步驟 3:確定前向值
使用 get-flag 取得每個關鍵環境中的開關設定。前向值是取代程式碼中開關的變化。
| 情境 | 前向值 |
|---|---|
| 所有關鍵環境 ON,相同的 fallthrough,沒有規則/目標 | 使用 fallthrough.variation |
| 所有關鍵環境 OFF,相同的 offVariation | 使用 offVariation |
| 關鍵環境的 ON/OFF 狀態不同 | 不安全:停止並通知使用者 |
| 關鍵環境提供不同的變化 | 不安全:停止並通知使用者 |
步驟 4:呈現清理計畫
在修改任何程式碼之前,向使用者呈現摘要並等待確認:
- 前向值 — 哪個變化將被寫死以及原因(基於開關的當前狀態)。
- 找到的所有程式碼參考 — 來自步驟 1 的檔案路徑和行號。
- 計畫的變更 — 對於每個參考,描述將移除哪些內容以及保留哪些內容。
- 移除就緒判定 —
check-removal-readiness的結果(safe、caution 或 blocked)以及任何警告。 - LaunchDarkly 動作 — 確認在程式碼變更完成後將封存開關。
在使用者明確確認之前,不要進行程式碼變更。
步驟 5:從程式碼中移除開關
現在使用你在步驟 1 中學到的內容執行移除。
-
將開關評估替換為前向值。
- 保留與前向值匹配的程式碼分支
- 完全移除死分支
- 如果開關值被賦值給變數,則將變數替換為字面值或內聯化
-
清理死程式碼。
- 移除僅為開關而存在的匯入、常數和型別定義
- 移除僅為死分支而存在的函式、元件或檔案
- 檢查孤立的匯出、鉤子、輔助函式、樣式和測試檔案
- 如果儲存庫使用未使用匯出工具(Knip、ts-prune、lint 規則),執行它並移除任何與開關相關的孤立項目
-
不要過度清理。
- 僅移除直接與開關相關的程式碼
- 不要重構、最佳化或「改進」周圍的程式碼
- 不要變更未觸及程式碼的格式或風格
範例轉換(布林開關,前向值 = true):
// Before
const showNewCheckout = await ldClient.variation('new-checkout-flow', user, false);
if (showNewCheckout) {
return renderNewCheckout();
} else {
return renderOldCheckout();
}
// After
return renderNewCheckout();
步驟 6:建立 Pull Request
使用 references/pr-template.md 中的範本建立結構化的 PR 描述。PR 應清楚傳達:
- 移除了哪個開關以及原因
- 前向值是什麼以及為什麼它是正確的
- 就緒評估結果(來自
check-removal-readiness) - 移除了哪些程式碼以及保留了哪些行為
- 其他儲存庫是否仍參考此開關
步驟 7:驗證
在認為工作完成之前:
- 程式碼編譯並通過 lint。 執行專案的建置和 lint 步驟。
- 測試通過。 如果開關用於測試,則應更新測試以反映寫死的行為。
- 沒有遺留的參考。 再次搜尋程式碼庫中的開關鍵,以確保沒有遺漏任何內容。
- PR 完整。 描述涵蓋就緒評估、前向值理由以及任何需要的跨儲存庫協調。
邊緣情況
| 情況 | 動作 |
|---|---|
| 在 LaunchDarkly 中找不到開關 | 通知使用者,檢查鍵是否有拼寫錯誤 |
| 開關已封存 | 詢問是否仍需要程式碼清理(開關已從 LD 中消失,但程式碼可能仍參考它) |
| 程式碼庫中有多種 SDK 模式 | 搜尋所有模式:variation()、boolVariation()、variationDetail()、allFlags()、useFlags(),以及任何包裝器 |
動態開關鍵(flag-${id}) |
警告自動化移除可能不完整:需要手動審查 |
| 程式碼與 LD 中的預設值不同 | 在 PR 描述中標記為不一致 |
| 移除後遺留孤立的匯出/檔案 | 執行未使用匯出檢查並移除死檔案 |
不該做的事
- 不要變更與開關清理無關的程式碼。
- 不要重構或最佳化超出開關移除的範圍。
- 不要移除仍在積極推出的開關。
- 不要猜測前向值:始終查詢 LaunchDarkly。
清理之後
一旦 PR 合併並部署:
- 在 LaunchDarkly 中封存開關,使用
archive-flag。封存是可逆的;刪除則不可逆。始終先封存。 - 通知其他團隊,如果
check-removal-readiness報告其他儲存庫中有程式碼參考。 - 如果開關有待處理的目標變更,可以忽略:開關正在被移除。






