migrate-nextflow-code について
Nextflow パイプラインを新しい言語パターンへ段階的に移行し、動作を維持するためのスキルです。lint、型付け、ワークフロー出力などの移行を案内し、基準となる実行結果との検証も行います。
主な機能
- 01lint による厳密構文への移行
- 02topic channel への移行
- 03プロセスとワークフローの静的型付け
- 04ワークフロー出力への移行
- 05パイプライン合成のガイダンス
- 06移行前後の動作検証
活用シーン
- 01パイプラインを nextflow lint に適合
- 02ch_versions を topic channel に置換
- 03パイプライン要素への静的型付け
- 04publishDir をワークフロー出力に置換
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nextflow-io/ agent-skills --skill migrate-nextflow-codeインストール後、Claude Code で/migrate-nextflow-codeを入力して読み込まれたか確認します。
詳細
Nextflow コードの移行
Nextflow パイプラインを新しい言語パターンに移行します。Nextflow ドキュメントのベストプラクティスに従ってください。作業中は nextflow lint を使ってコードを検証してください。移行前後でパイプラインが同じ結果を生成することを確認してください。
要件
型チェックに対応した nextflow lint コマンドを使うには、Nextflow 26.10 以降が必要です。
該当する場合、nf-core テンプレート 3.0.0 以降が必要です。パイプラインに .nf-core.yml がある場合は、最後にテンプレートを生成した nf-core/tools のバージョンを確認してください。nf_core_version が指定されていない場合、または 3.0.0 未満の場合は、作業を中止し、まずテンプレートをアップグレードするようユーザーに伝えてください。これにより、テンプレートコードの構文エラーが解消され、よりクリーンなベースラインが得られます。
移行
ユーザーが依頼した各移行を、以下の順序で一度に 1 つずつ適用してください。各移行を行うには、それより前の移行が必要です。
各移行には、関連するドキュメントへのリンクがあります。実装方法が不明な場合は、これらのドキュメントを参照してください。たとえば、使用する型、特定の型で使うメソッド、特定のチャネル演算子の使い方などです。推測したり、過去の知識だけに頼ったりしないでください。リンターは手がかりになりますが、ドキュメントには例とベストプラクティスが記載されています。
厳密構文
パイプラインを nextflow lint に準拠するよう更新します。厳密構文パーサーの導入前に書かれたパイプラインには、現在は無効となっているパターンが含まれている場合があります。
- プロジェクト全体にリンターを実行します:
nextflow lint -o concise . - 動作を変えずに、各問題を修正します。変更は最小限に抑えてください。
- 必要に応じてリンターを再実行し、エラーがなくなるまで繰り返します。
参考資料:
トピックチャネル
パイプライン内の ch_versions の接続処理を、versions トピックチャネルに置き換えます。
- プロセスのバージョン出力を
versionsトピックに送ります。emit: versionsをtopic: versionsに置き換えます。YAML のバージョンファイルは、プロセス名、ツール名、eval コマンドのタプルに置き換えます。 - バージョンファイルを書き出す際に、
channel.topic('versions')でversionsトピックを受け取ります。要素をプロセスごとにグループ化します。 ch_versionsの接続処理を削除します。
// before
output:
path "versions.yml", emit: versions
// after
output:
tuple val("${task.process}"), val('bash'), eval('bash --version'), topic: versions
// after (typed)
topic:
tuple(task.process, 'bash', eval('bash --version')) >> 'versions'
トピックチャネルの下流にあるプロセスは、そのトピックに出力してはいけません。そうしないと、パイプラインがデッドロックします。
参考資料:
静的型付け
パイプラインを移行して、型付きプロセス、型付きワークフロー、型付きパラメーター、レコードを使用します。コンポーネントは下位から移行してください。移行中は nextflow lint を使用して型をチェックします。
- プロセスを型付きプロセスに移行します
- ワークフローを型付きワークフローに移行します
- パイプラインのパラメーターを型付きパラメーターに移行します
- エラーがなくなるまで、必要に応じてリンターを再実行します。
ルール:
- プロセスでは、分割代入されたレコード入力/出力を使用します。
- プロセスの
path入力/出力が単一ファイル(Path)か、ファイルコレクション(List<Path>、Set<Path>など)かを慎重に確認します。 - 各プロセスの出力は、単一のワイドレコードにします。各ワークフローでは、関連する出力をワイドレコードチャンネルに結合します。これにより、ワークフロー出力への移行が容易になります。
- ワークフローのチャンネル入力/出力の記述にはレコード型を使用します。レコード型は、共有の型モジュールではなく、そのワークフローとともに定義します。
- パイプラインで
nf-schemaプラグインを使用している場合は、静的型付けに関する実行時の問題を避けるため、バージョン 2.7.2 以降に更新します。 - スクリプトで使用するパラメーターはスクリプト内で宣言します。設定にのみ影響するパラメーターは設定ファイル内で宣言します。設定でスクリプトのパラメーターのデフォルト値を上書きできますが、できればプロファイル(例:
test)で行います。 - グローバルな
paramsレコードはエントリーワークフローでのみ使用します。パラメーターは明示的な入力としてプロセスやワークフローに渡します。関連するパラメーターはレコード型を使って単一のワークフロー入力にまとめ(例:workflow ALIGNER→record AlignerParams)、エントリーワークフローからparamsを直接渡せるようにします。 - 型が本当に不明な場合(例:
channel.topic())に限り、型変換(x as Type)を使用します。
参考資料:
ワークフロー出力
パイプラインを移行して、ワークフロー出力を使用します。すべての publishDir ディレクティブを、同じ出力ディレクトリツリーを生成するトップレベルの output ブロックに置き換えます。
パイプラインがまだ静的型付けとレコードに移行されていない場合は、作業を中止し、その旨をユーザーに警告してください。output ブロックを使用するには、プロセス出力をエントリーワークフローに伝播させる必要があります。そのため、パイプラインがまだ幅の狭いタプル(例:(meta, file))を使用していると、ワークフローの emit が過剰な数になります。幅の狭いタプルチャンネルを幅の広いレコードチャンネルにまとめると、output ブロックを通じてチャンネルを公開できるようになります。
- プロセスと設定ファイルにあるすべての
publishDirディレクティブを特定します。 - 各公開設定について、対象のプロセス、公開するファイル、公開先を確認します。
- 公開する出力ごとに、対応するプロセス出力をエントリーワークフローに伝播させ(
emit:を使用)、公開します(publish:を使用)。 - 公開する各チャンネルに対して、宣言と
pathディレクティブを含むトップレベルのoutputブロックを追加します。 - 設定でグローバルな公開動作(
outputDir、workflow.output.modeなど)を定義します。必要に応じて、outputブロックで公開設定を上書きします。 publishDirディレクティブを削除します。
ルール:
- ドキュメントを参照して、
publishDirのオプション、出力のpathディレクティブ、workflow.outputのオプションを確認します。従来の設定を新しい設定にどう対応させるかを判断します。 - ツールごとの出力を多数作成するより、サンプルごとの出力をまとめることを優先します。インデックスファイルを作成するのは、パイプラインがすでに作成している場合に限ります(下記の
collectFileを参照)。 - チャンネルを公開するために、ファイルを手動で抽出したりフラット化したりする必要はありません。Nextflow は、公開する値(リスト、マップ、レコード、タプル)からファイルを自動的に抽出します。
storeDir:を指定したcollectFile演算子も、ファイルを公開する方法のひとつです。storeDir:を削除し、代わりにoutputブロックで公開します。たとえば、サンプルごとの出力をまとめたサンプルシートであれば、出力のindexディレクティブに置き換えられる場合もあります。- メイン設定ファイルに一括適用の
publishDirがあるパイプラインもあります。これは削除できる可能性があります。
参照:
パイプラインの合成
パイプラインを合成可能にし、直接実行したり、別のパイプラインに組み込んだりできるようにします。
パイプラインが静的型付けに移行されていない場合、または params ブロックと output ブロックがない場合は、作業を中止し、その旨をユーザーに伝えてください。パイプラインの合成は、これらの言語機能に大きく依存します。
-
paramsブロックを確認します。データフロー型にリファクタリングできるパラメーターを判断してください。サンプルシート入力は、レコードのチャネル(Channel<Sample>)にリファクタリングできます。インデックスファイル入力は、データフロー値(Value<Path>)でラップできます。ユーザーから別途指示がない限り、サンプルシート入力をリファクタリングし、それ以外はそのままにしてください。 -
グローバルな params の使用状況を確認します。パイプラインでは、エントリーワークフローと
outputブロック以外でグローバルな params を使用しないでください。また、すべての出力をpublishDirディレクティブではなくoutputブロック経由で公開するようにしてください。 -
プロジェクトレベルのアセット(
projectDir、bin、lib)を確認します。これらの代わりに、合成可能な手段(params、モジュールのresources/とmoduleDir、ヘルパー関数)を使用してください。 -
プロセス設定(
conf/modules、ext.args、withName)を確認します。これをパイプラインコードに移動してリファクタリングしてください(以下を参照)。
おそらく最も大きな問題となるのは ext 設定です。nf-core モジュールでは、ツール引数やファイル名のプレフィックス/サフィックスなどの特定の入力に ext を使用します。ユーザーはこの設定を構成から簡単に上書きできます。パイプラインでは、プロセスセレクターを使って構成内に独自のデフォルト値を指定できる場合があります。そのため、パイプラインの合成が難しくなります。
解決策は、パイプラインコード内で ext 設定をリファクタリングすることです。
- モジュールでは
args/prefix/suffixを明示的な入力として受け取り、task.ext.<name> ?: <input> ?: <default>として解決します。ユーザーは引き続き、実行時に構成を使って任意のツールを上書きできます。 - 各
ext設定をパイプラインコードに移します。サンプルごとに値が異なるかどうかに応じて、mapまたはcombineを使って各サンプルレコードに設定を追加します。 - 複雑な
ext設定をワークフローのロジックから分離するには、ヘルパー関数を使用します。まずオプションのマップを作成し、次に別個のcli()ヘルパーで CLI 文字列に変換します。
参考資料:
検証
各移行の後に、プロジェクトのテストスイートを使ってベースラインと照らし合わせ、動作を検証してください。例:
- テストプロファイルで移行前/移行後を実行:
nextflow run . -profile test,docker - nf-test:
nf-test test - スタブ実行:
nextflow run . -stub
重要なルール
- 一度に行う移行は1つだけです。 次の移行を始める前に、1つの移行を完了してください。
- ドキュメントを読んでください。 実装方法がわからない場合は、リンク先のドキュメントを参照してください。
- 動作を維持してください。 移行の前後で、パイプラインが同じ出力を生成するようにしてください。