Skip to content

Commit 3fc4c39

Browse files
edmundmillerclaude
andcommitted
feat: Add package directive to process configuration
Extends process configuration to support the unified package directive: - ProcessConfig: Adds 'package' to the list of valid directives - TaskRun: Implements getPackageSpec() method with caching - TaskBean: Adds packageSpec field for task execution Also adds deprecation warnings when conda/pixi directives are used with the preview.package feature enabled, encouraging migration to the new unified syntax. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> Signed-off-by: Edmund Miller <[email protected]>
1 parent ce0050c commit 3fc4c39

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

modules/nextflow/src/main/groovy/nextflow/processor/TaskBean.groovy

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import groovy.transform.PackageScope
2323
import nextflow.container.ContainerConfig
2424
import nextflow.executor.BashWrapperBuilder
2525
import nextflow.executor.TaskArrayExecutor
26+
import nextflow.packages.PackageSpec
2627
import nextflow.util.MemoryUnit
2728
/**
2829
* Serializable task value object. Holds configuration values required to
@@ -53,6 +54,8 @@ class TaskBean implements Serializable, Cloneable {
5354

5455
Path pixiEnv
5556

57+
PackageSpec packageSpec
58+
5659
List<String> moduleNames
5760

5861
Path workDir
@@ -141,6 +144,7 @@ class TaskBean implements Serializable, Cloneable {
141144
this.useMicromamba = task.getCondaConfig()?.useMicromamba()
142145
this.spackEnv = task.getSpackEnv()
143146
this.pixiEnv = task.getPixiEnv()
147+
this.packageSpec = task.getPackageSpec()
144148
this.moduleNames = task.config.getModule()
145149
this.shell = task.config.getShell() ?: BashWrapperBuilder.BASH
146150
this.script = task.getScript()

modules/nextflow/src/main/groovy/nextflow/processor/TaskRun.groovy

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ import nextflow.script.params.StdInParam
5454
import nextflow.script.params.ValueOutParam
5555
import nextflow.pixi.PixiCache
5656
import nextflow.pixi.PixiConfig
57+
import nextflow.packages.PackageManager
58+
import nextflow.packages.PackageSpec
5759
import nextflow.spack.SpackCache
5860
/**
5961
* Models a task instance
@@ -646,6 +648,11 @@ class TaskRun implements Cloneable {
646648
if( !config.conda || !getCondaConfig().isEnabled() )
647649
return null
648650

651+
// Show deprecation warning if new package system is enabled
652+
if (PackageManager.isEnabled(processor.session)) {
653+
log.warn "The 'conda' directive is deprecated when preview.package is enabled. Use 'package \"${config.conda}\", provider: \"conda\"' instead"
654+
}
655+
649656
final cache = new CondaCache(getCondaConfig())
650657
cache.getCachePathFor(config.conda as String)
651658
}
@@ -665,6 +672,11 @@ class TaskRun implements Cloneable {
665672
if( !config.pixi || !processor.session.getPixiConfig().isEnabled() )
666673
return null
667674

675+
// Show deprecation warning if new package system is enabled
676+
if (PackageManager.isEnabled(processor.session)) {
677+
log.warn "The 'pixi' directive is deprecated when preview.package is enabled. Use 'package \"${config.pixi}\", provider: \"pixi\"' instead"
678+
}
679+
668680
final cache = new PixiCache(processor.session.getPixiConfig())
669681
cache.getCachePathFor(config.pixi as String)
670682
}
@@ -690,6 +702,36 @@ class TaskRun implements Cloneable {
690702
cache.getCachePathFor(config.spack as String, arch)
691703
}
692704

705+
PackageSpec getPackageSpec() {
706+
// note: use an explicit function instead of a closure or lambda syntax
707+
cache0.computeIfAbsent('packageSpec', new Function<String,PackageSpec>() {
708+
@Override
709+
PackageSpec apply(String it) {
710+
return getPackageSpec0()
711+
}})
712+
}
713+
714+
private PackageSpec getPackageSpec0() {
715+
if (!PackageManager.isEnabled(processor.session))
716+
return null
717+
718+
if (!config.package)
719+
return null
720+
721+
def packageManager = new PackageManager(processor.session)
722+
723+
// Parse the package configuration
724+
def packageDef = config.package
725+
def defaultProvider = processor.session.config.navigate('packages.provider', 'conda') as String
726+
727+
try {
728+
return PackageManager.parseSpec(packageDef, defaultProvider)
729+
} catch (Exception e) {
730+
log.warn "Failed to parse package specification: ${e.message}"
731+
return null
732+
}
733+
}
734+
693735
protected ContainerInfo containerInfo() {
694736
// note: use an explicit function instead of a closure or lambda syntax, otherwise
695737
// when calling this method from a subclass it will result into a MissingMethodException

modules/nextflow/src/main/groovy/nextflow/script/ProcessConfig.groovy

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ class ProcessConfig implements Map<String,Object>, Cloneable {
8989
'maxRetries',
9090
'memory',
9191
'module',
92+
'package',
9293
'penv',
9394
'pixi',
9495
'pod',

0 commit comments

Comments
 (0)