关于 migrate-nextflow-code
用于逐步将 Nextflow 流水线迁移到新语言模式的技能,并要求保持原有行为。它指导开发者进行语法检查、静态类型和工作流输出等迁移,并与基线结果验证。
主要功能
- 01使用 lint 迁移严格语法
- 02迁移到 topic channel
- 03为流程和工作流添加静态类型
- 04迁移到工作流输出
- 05提供流水线组合指导
- 06验证迁移前后的行为
适用场景
- 01让流水线通过 nextflow lint
- 02用 topic channel 替换 ch_versions
- 03为流水线组件添加静态类型
- 04用工作流输出替换 publishDir
安装
复制下面的命令,在终端中运行。
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 template 3.0.0 或更高版本。如果流水线包含 .nf-core.yml,请检查最后生成该模板的 nf-core/tools 版本。如果未指定 nf_core_version 或其版本低于 3.0.0,请停止并告知用户先升级模板。这将修复模板代码中的语法错误,并提供更整洁的基线。
迁移
按照以下顺序,逐一应用用户请求的迁移。每项迁移都要求先完成其前面的迁移。
每项迁移都链接了相关文档。如果不确定如何操作,例如该使用哪种类型、某种类型对应使用哪个方法,或如何使用特定的通道运算符,请查阅这些文档。不要猜测,也不要只依赖以往的知识。Linter 可以提供指引,但文档包含示例和最佳实践。
严格语法
更新流水线,使其符合 nextflow lint 的要求。在严格语法解析器引入之前编写的流水线可能包含不再有效的模式。
- 对整个项目运行 linter:
nextflow lint -o concise . - 在不改变行为的前提下修复每个问题。尽量减少改动。
- 根据需要重新运行 linter 并反复调整,直到没有错误。
参考文档:
Topic 通道
将流水线中的 ch_versions 数据传递逻辑替换为 versions topic 通道。
- 将进程版本输出发送到
versionstopic。将emit: versions替换为topic: versions。将 YAML 版本文件替换为由进程名称、工具名称和 eval 命令组成的元组。 - 写入版本文件时,使用
channel.topic('versions')消费versionstopic。按进程对元素分组。 - 删除
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'
topic 通道下游的任何进程都不得向该 topic 输出内容,否则流水线会死锁。
参考文档:
静态类型检查
迁移流水线,使用带类型的进程、带类型的工作流、带类型的参数和记录。从底层开始迁移组件。边迁移边使用 nextflow lint 进行类型检查。
规则:
- 在进程中使用解构的记录作为输入和输出。
- 仔细检查进程的
path输入/输出应为单个文件(Path)还是文件集合(List<Path>、Set<Path>等)。 - 每个进程都应输出单个宽记录。每个工作流都应将相关输出合并到一个宽记录通道中。这样更容易迁移到工作流输出。
- 使用记录类型描述工作流的通道输入/输出。记录类型应与工作流一起定义,而不是放在共享类型模块中。
- 如果流水线使用
nf-schema插件,请将其更新至 2.7.2 或更高版本,以避免静态类型检查导致的运行时问题。 - 脚本使用的参数必须在脚本中声明。仅影响配置设置的参数应在配置文件中声明。配置可以覆盖脚本中的参数默认值,但最好在某个配置档案(例如
test)中覆盖。 - 全局
params记录只能在入口工作流中使用。将参数作为显式输入传递给进程和工作流。使用记录类型将相关参数打包为单个工作流输入(例如,workflow ALIGNER→record AlignerParams),这样就可以直接从入口工作流传递params。 - 仅当类型确实未知时才使用类型强制转换(
x as Type),例如channel.topic()。
参考:
工作流输出
迁移管道以使用工作流输出。将所有 publishDir 指令替换为顶层 output 块,以生成相同的输出目录结构。
如果管道尚未迁移到静态类型和记录,请停止并提醒用户。output 块要求将进程输出传递到入口工作流。如果管道仍使用窄元组(例如 (meta, file)),就会导致工作流发出的内容过多。将窄元组通道合并为宽记录通道后,便可通过 output 块发布通道。
- 找出进程和配置文件中的所有
publishDir指令。 - 对于每个发布器,确定:目标进程、要发布的文件,以及文件的发布位置。
- 对于每项已发布输出,将相应的进程输出传递到入口工作流(通过
emit:),并发布它们(通过publish:)。 - 添加顶层
output块,为每个已发布通道声明输出并设置path指令。 - 在配置中定义全局发布行为(
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。它应已通过output块发布所有输出,而不是使用publishDir指令。 -
检查项目级资源(
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 - Stub 运行:
nextflow run . -stub
关键规则
- 一次只进行一项迁移。 完成一项迁移后,再开始另一项。
- 阅读文档。 不确定如何操作时,请查阅链接中的文档。
- 保留行为。 迁移前后,流水线应生成相同的输出。