Skip to content

Commit 4dea251

Browse files
committed
test(#6092): Add Pixi environment support
- Introduced PixiConfig and PixiCache classes for managing Pixi environments. - Updated Session class to include PixiConfig retrieval. - Enhanced CmdRun with options to enable/disable Pixi environments. - Modified ConfigBuilder to apply Pixi environment settings based on command-line options. - Updated BashWrapperBuilder to include Pixi activation in the execution script. - Added pixiEnv property to TaskBean and methods in TaskRun for Pixi environment handling. - Updated ProcessConfig to include 'pixi' in process configuration options. This commit integrates Pixi environment management into the Nextflow framework, allowing users to specify and control Pixi environments during execution. Signed-off-by: Edmund Miller <[email protected]>
1 parent c2c879d commit 4dea251

File tree

10 files changed

+512
-5
lines changed

10 files changed

+512
-5
lines changed

modules/nextflow/src/main/groovy/nextflow/Session.groovy

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ import nextflow.script.ScriptFile
6868
import nextflow.script.ScriptMeta
6969
import nextflow.script.ScriptRunner
7070
import nextflow.script.WorkflowMetadata
71+
import nextflow.pixi.PixiConfig
7172
import nextflow.spack.SpackConfig
7273
import nextflow.trace.AnsiLogObserver
7374
import nextflow.trace.TraceObserver
@@ -1195,6 +1196,12 @@ class Session implements ISession {
11951196
return new SpackConfig(opts, getSystemEnv())
11961197
}
11971198

1199+
@Memoized
1200+
PixiConfig getPixiConfig() {
1201+
final cfg = config.pixi as Map ?: Collections.emptyMap()
1202+
return new PixiConfig(cfg, getSystemEnv())
1203+
}
1204+
11981205
/**
11991206
* Get the container engine configuration for the specified engine. If no engine is specified
12001207
* if returns the one enabled in the configuration file. If no configuration is found

modules/nextflow/src/main/groovy/nextflow/cli/CmdRun.groovy

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,12 @@ class CmdRun extends CmdBase implements HubOptions {
250250
@Parameter(names=['-without-spack'], description = 'Disable the use of Spack environments')
251251
Boolean withoutSpack
252252

253+
@Parameter(names=['-with-pixi'], description = 'Use the specified Pixi environment package or file (must end with .toml suffix)')
254+
String withPixi
255+
256+
@Parameter(names=['-without-pixi'], description = 'Disable the use of Pixi environments')
257+
Boolean withoutPixi
258+
253259
@Parameter(names=['-offline'], description = 'Do not check for remote project updates')
254260
boolean offline = System.getenv('NXF_OFFLINE')=='true'
255261

modules/nextflow/src/main/groovy/nextflow/config/ConfigBuilder.groovy

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ class ConfigBuilder {
190190

191191
def result = []
192192
if ( files ) {
193-
for( String fileName : files ) {
193+
for( String fileName : files ) {
194194
def thisFile = currentDir.resolve(fileName)
195195
if(!thisFile.exists()) {
196196
throw new AbortOperationException("The specified configuration file does not exist: $thisFile -- check the name or choose another file")
@@ -594,6 +594,19 @@ class ConfigBuilder {
594594
config.spack.enabled = true
595595
}
596596

597+
if( cmdRun.withoutPixi && config.pixi instanceof Map ) {
598+
// disable pixi execution
599+
log.debug "Disabling execution with Pixi as requested by command-line option `-without-pixi`"
600+
config.pixi.enabled = false
601+
}
602+
603+
// -- apply the pixi environment
604+
if( cmdRun.withPixi ) {
605+
if( cmdRun.withPixi != '-' )
606+
config.process.pixi = cmdRun.withPixi
607+
config.pixi.enabled = true
608+
}
609+
597610
// -- sets the resume option
598611
if( cmdRun.resume )
599612
config.resume = cmdRun.resume
@@ -861,7 +874,7 @@ class ConfigBuilder {
861874
final value = entry.value
862875
final previous = getConfigVal0(config, key)
863876
keys << entry.key
864-
877+
865878
if( previous==null ) {
866879
config[key] = value
867880
}

modules/nextflow/src/main/groovy/nextflow/executor/BashWrapperBuilder.groovy

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ class BashWrapperBuilder {
341341
binding.before_script = getBeforeScriptSnippet()
342342
binding.conda_activate = getCondaActivateSnippet()
343343
binding.spack_activate = getSpackActivateSnippet()
344+
binding.pixi_activate = getPixiActivateSnippet()
344345

345346
/*
346347
* add the task environment
@@ -394,7 +395,7 @@ class BashWrapperBuilder {
394395
binding.fix_ownership = fixOwnership() ? "[ \${NXF_OWNER:=''} ] && (shopt -s extglob; GLOBIGNORE='..'; chown -fR --from root \$NXF_OWNER ${workDir}/{*,.*}) || true" : null
395396

396397
binding.trace_script = isTraceRequired() ? getTraceScript(binding) : null
397-
398+
398399
return binding
399400
}
400401

@@ -560,6 +561,29 @@ class BashWrapperBuilder {
560561
return result
561562
}
562563

564+
private String getPixiActivateSnippet() {
565+
if( !pixiEnv )
566+
return null
567+
def result = "# pixi environment\n"
568+
569+
// Check if there's a .pixi file that points to the project directory
570+
final pixiFile = pixiEnv.resolve('.pixi')
571+
if( pixiFile.exists() ) {
572+
// Read the project directory path
573+
final projectDir = pixiFile.text.trim()
574+
result += "cd ${Escape.path(projectDir as String)} && "
575+
result += "eval \"\$(pixi shell-hook --shell bash)\" && "
576+
result += "cd \"\$OLDPWD\"\n"
577+
}
578+
else {
579+
// Direct activation from environment directory
580+
result += "cd ${Escape.path(pixiEnv)} && "
581+
result += "eval \"\$(pixi shell-hook --shell bash)\" && "
582+
result += "cd \"\$OLDPWD\"\n"
583+
}
584+
return result
585+
}
586+
563587
protected String getTraceCommand(String interpreter) {
564588
String result = "${interpreter} ${fileStr(scriptFile)}"
565589
if( input != null )
@@ -628,7 +652,7 @@ class BashWrapperBuilder {
628652
private String copyFileToWorkDir(String fileName) {
629653
copyFile(fileName, workDir.resolve(fileName))
630654
}
631-
655+
632656

633657
String getCleanupCmd(String scratch) {
634658
String result = ''

0 commit comments

Comments
 (0)