nf-core-utils 遷移
將 nf-core 管線從內建工具程式碼移至 nf-core-utils 外掛(以及直接的 nf-schema 呼叫),一次一個外掛版本,且不破壞使用額外設定檔啟動的管線執行。
從模組 meta.yml 建立的工具引用(citationsOnTheFly、publication 區塊)會在下方的引用章節中涵蓋,作為遷移後的另一個 PR。nf-test 基礎設施(tests/lib、快照輔助函數、nft-utils)不在範圍內:如果看到請提及作為後續事項,不要將其納入遷移 PR。
開始前值得閱讀的參考遷移:nf-core/rnavar#233(首次移除內建子工作流)、nf-core/rnavar#252(基因組與版本輔助函數)、nf-core/seqinspector#241 和 nf-core/rnaseq#1977(完整替換)。使用 gh pr diff <n> -R nf-core/<repo> 擷取它們。
1. 盤點已遷移的內容
遷移分階段進行:每個外掛版本會吸收更多輔助函數,所以一個「已經使用 nf-core-utils」的管線通常仍帶有遮蔽外掛函數的本地複本。不要假設使用者描述的起始狀態是最新的。檢查:
ls subworkflows/nf-core/ | grep '^utils_' # 仍存在的內建子工作流
grep -n '"utils_' modules.json # 它們在 modules.json 中的條目
grep -rn "from 'plugin/" main.nf workflows subworkflows/local # 已經從外掛匯入的內容
grep -n "^def " main.nf workflows/*.nf subworkflows/local/utils_*/main.nf # 本地輔助函數定義
grep -n "id '" nextflow.config # 目前的外掛鎖定版本
將每個本地 def 與目標外掛版本匯出的函數(步驟 2)進行比較。與外掛匯出同名的本地 def 是候選刪除對象。保留包含管線特定邏輯的 def(自訂驗證、工具列表、管線特定的摘要文字)。
2. 讀取要鎖定的外掛版本的簽章
外掛 API 在不同版本之間會有變動,而其他管線的 diff 可能針對不同的版本。從快取的外掛中讀取真實簽章,而不是憑記憶:
nextflow plugin install nf-core-utils@<ver> # 或執行管線一次;外掛會放到 ~/.nextflow/plugins/
P=~/.nextflow/plugins/nf-core-utils-<ver>
grep Plugin-Requires $P/classes/META-INF/MANIFEST.MF # 最低 Nextflow 版本
python3 -c "import json;[print(x['spec']['name'],[p['type'] for p in x['spec']['parameters']]) for x in json.load(open('$P/classes/META-INF/spec.json'))['definitions'] if x['type']=='Function']"
javap -cp $P/classes nfcore.plugin.NfUtilsExtension | grep <function>
javap -cp ~/.nextflow/plugins/nf-schema-<ver>/classes nextflow.validation.ValidationExtension | grep <function>
如果 Plugin-Requires 高於 manifest.nextflowVersion,請在同一 PR 中升級 manifest.nextflowVersion、.github/workflows/nf-test.yml 中的最小 NXF_VER,以及 README 徽章。
當你故意保留較舊的鎖定版本時(例如 nf-schema 2.x,因為 3.x 棄用了 paramsSummaryLog(Map, WorkflowMetadata)),請在 PR 描述中列出在下一個主要版本中會中斷的呼叫位置,以便後續事項可見。
3. 替換輔助函數
使用 references/function-map.md 逐一替換每個內建子工作流和本地輔助函數的呼叫。在 nextflow.config 中鎖定外掛版本:
plugins {
id 'nf-core-utils@<ver>' // nf-core-utils 是 Nextflow 管線的實用工具集合
id 'nf-schema@<ver>' // 驗證管線參數並從樣品表建立輸入通道
}
然後刪除 subworkflows/nf-core/utils_nextflow_pipeline、utils_nfcore_pipeline 和 utils_nfschema_plugin(包括它們的 tests/)以及它們在 modules.json 中的條目。偏好使用 nf-core subworkflows remove <name> 以保持 modules.json 一致;如果你必須手動編輯 modules.json,請在之後執行 npx -y prettier@3 --write modules.json,因為 JSON 傾印會炸開 installed_by 陣列。
4. 在每個不是 nextflow.config 的設定檔中鎖定外掛
啟動時設定檔(Seqera Platform 的 nextflow_config 在 .github/workflows/awsfulltest.yml / awstest.yml、Tower 設定檔、機構的 -c 設定檔)中的 plugins {} 區塊會取代管線自身的 plugins {} 區塊,而不是與其合併。任何管線使用 include { ... } from 'plugin/<name>' 匯入但未在該區塊中鎖定的外掛都會解析到最新版本,一旦新的主要版本發布就會中斷。
在每個此類區塊中重複 nextflow.config 中的確切版本,再加上該區塊為自身新增的任何外掛:
nextflow_config: |
plugins {
id 'nf-core-utils@<與 nextflow.config 相同>'
id 'nf-schema@<與 nextflow.config 相同>'
id '[email protected]'
}
檢查這些鎖定版本是否一致:
grep -rhoE "id '(nf-core-utils|nf-schema)@[^']+'" nextflow.config .github/workflows/ | sort | uniq -c
每個外掛應只出現一個版本。
5. 從證據診斷外掛失敗
Missing process or function X(...) -- Did you mean 'X' instead? 表示存在名為 X 的函數,但沒有多載符合參數。將其解讀為外掛版本不匹配,而不是錯字:找出實際載入的版本,然後比較其簽章(步驟 2)與呼叫位置。
在變更任何內容之前確認載入的版本:
- Megatest / Platform 執行:
gh run list -R nf-core/<pipeline> -w "nf-core AWS full size tests"和gh run view <id> --log,或 nf-slack 張貼的 Slack 訊息,或 Platform 執行日誌。尋找Downloading plugin <name>@<ver>/Starting plugin <name>@<ver>。 - 本地重現設定覆蓋:使用僅包含外部
plugins {}區塊的設定檔執行,並檢查日誌。
printf "plugins {\n id '[email protected]'\n}\n" > /tmp/override.config
nextflow run . -profile test,docker --outdir /tmp/out -c /tmp/override.config 2>&1 | head -40
grep -E "plugin (nf-schema|nf-core-utils)@" .nextflow.log
只有在這些來源都沒有結果時,才要求使用者提供日誌。
6. 驗證
在報告任何失敗之前,先將你造成的失敗與 dev 上既有的失敗區分開來:在乾淨的工作樹上重新執行失敗的測試或 lint。
git worktree add /tmp/dev-baseline origin/dev
(cd /tmp/dev-baseline && <相同的測試或 lint 命令>)
git worktree remove --force /tmp/dev-baseline
至少執行:
nextflow lint main.nf workflows subworkflows/local(嚴格的語法檢查)nf-core pipelines lint- 管線 nf-tests,並將
NXF_VER設為管線的最低 Nextflow 版本 nextflow run . --help、--help_full和--version,因為這些路徑會提早退出,並且在內嵌UTILS_NFSCHEMA_PLUGIN/UTILS_NEXTFLOW_PIPELINE時容易出錯
引用(獨立 PR)
一旦輔助函數來自外掛,MultiQC 方法描述就可以引用實際執行的工具,使用 citationsOnTheFly(nf-core-utils 0.7.0 或更新版本)和每個模組 meta.yml 中的 tools: 條目。將此部分保留在遷移 PR 之外:它會觸及許多模組檔案,全面變更管線快照,並涉及使用者應做出的歸屬決策。
在開始之前閱讀 references/citations.md。簡而言之:
- 將
channel.topic("versions").collect(flat: false)接線到citationsOnTheFly,將在收集後執行的工具(MultiQC)作為額外項目傳入。 - 預測哪些工具會記錄
No citation metadata found並破壞快照;一次一個確切條目地引用真實工具,忽略通用的實用工具。 - 與使用者協商引用元資料的存放位置:上游的 nf-core/modules、模組修補程式,或本地覆蓋檔案。
- 每個 DOI、作者列表和標題都來自 Crossref / PubMed,絕不憑記憶,並在替換模組的引用論文之前提出詢問。
- 將模組修補程式限制在
meta.yml,並從測試執行中讀取渲染後的Tools used文字。
陷阱
- 快照:來自外掛的
softwareVersionsToYAML會將元組版本保持為加引號的字串,因此之前包含數字版本(1.21而不是"1.21")的快照會跨許多檔案變更。這是預期的;檢查是否只有引號變更。 - 收集版本以使元組和空串流存活:rnaseq#1977 使用
.toList()收集,並透過entry instanceof Path ? entry.text : entry讀取舊式versions.yml發射,以便遠端工作目錄繼續運作。 - 如果內建的
UTILS_NFSCHEMA_PLUGIN呼叫依賴validateParameters(cast_cli_params: false),請保留它;在內嵌前檢查舊呼叫。 getWorkflowVersion()讀取 manifest;如果管線之前列印過 git 後綴,請傳入workflow.manifest.version, workflow.commitId。- 來自外掛的
methodsDescriptionText接受String路徑,因此傳入file.toString(),而不是Path。 - nf-core YAML 檔案有時會引用鍵(
- "gatk4":)。使用正規表示法的批次編輯必須匹配引用和未引用的鍵,然後計算編輯的檔案數量是否與預期列表相符。 - 如果必須修補模組,
nf-core modules patch也會區分modules/nf-core/<m>/tests/下被 gitignore 的檔案,因此請先將其重置為鎖定的 SHA(git -C ~/.config/nfcore/nf-core/modules show <git_sha>:modules/nf-core/<m>/<file>),並檢查每個.diff只包含你打算變更的檔案。
PR
- 先開啟 PR,然後再使用真實的 PR 編號撰寫 CHANGELOG 條目。猜測下一個編號會與其他貢獻者發生衝突。
- CHANGELOG:
Changed下的一個條目,如果 PR 修復了外掛鎖定版本則加上一個Fixed條目,以及一個包含新舊版本的Dependencies - Nextflow plugins表格。 - PR 描述:外掛版本的變更前/後、你鎖定的每個外部
plugins {}區塊、哪些輔助函數移至外掛以及哪些保留下來(以及原因)、後續事項(下一個主要版本的呼叫位置、引用、測試基礎設施)。