diff --git a/docs/config.md b/docs/config.md index ef1ac5a97c..ccdc71933a 100644 --- a/docs/config.md +++ b/docs/config.md @@ -113,6 +113,15 @@ The following constants are globally available in a Nextflow configuration file: `projectDir` : The directory where the main script is located. +## Functions + +The following functions are globally available in a Nextflow configuration file: + +`env( name )` +: :::{versionadded} 24.11.0-edge + ::: +: Get the value of the environment variable with the specified name in the Nextflow launch environment. + (config-params)= ## Parameters diff --git a/docs/reference/stdlib.md b/docs/reference/stdlib.md index 8c09f1ac96..633e51b0eb 100644 --- a/docs/reference/stdlib.md +++ b/docs/reference/stdlib.md @@ -197,6 +197,11 @@ The following functions are available in Nextflow scripts: `branchCriteria( closure )` : Create a branch criteria to use with the {ref}`operator-branch` operator. +`env( name )` +: :::{versionadded} 24.11.0-edge + ::: +: Get the value of the environment variable with the specified name in the Nextflow launch environment. + `error( message = null )` : Throw a script runtime error with an optional error message. diff --git a/docs/vscode.md b/docs/vscode.md index f132368289..c889ddb27c 100644 --- a/docs/vscode.md +++ b/docs/vscode.md @@ -275,6 +275,14 @@ The Nextflow language specification does not support implicit environment variab println "PWD = ${System.getenv('PWD')}" ``` +:::{versionadded} 24.11.0-edge +The `env()` function can be used instead of `System.getenv()`: + +```nextflow +println "PWD = ${env('PWD')}" +``` +::: + ### Restricted syntax The following patterns are still supported but have been restricted, i.e. some syntax variants have been removed. diff --git a/modules/nextflow/src/main/groovy/nextflow/Nextflow.groovy b/modules/nextflow/src/main/groovy/nextflow/Nextflow.groovy index 3f1257a01c..e7dc15884c 100644 --- a/modules/nextflow/src/main/groovy/nextflow/Nextflow.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/Nextflow.groovy @@ -57,6 +57,17 @@ class Nextflow { private static final Random random = new Random() + /** + * Get the value of an environment variable from the launch environment. + * + * @param name + * The environment variable name to be referenced + * @return + * The value associate with the specified variable name or {@code null} if the variable does not exist. + */ + static String env(String name) { + return SysEnv.get(name) + } static private fileNamePattern( FilePatternSplitter splitter, Map opts ) { diff --git a/modules/nextflow/src/main/groovy/nextflow/config/ConfigBase.groovy b/modules/nextflow/src/main/groovy/nextflow/config/ConfigBase.groovy index 46a6f182da..a97e23f19a 100644 --- a/modules/nextflow/src/main/groovy/nextflow/config/ConfigBase.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/config/ConfigBase.groovy @@ -16,12 +16,12 @@ package nextflow.config -import ch.artecat.grengine.Grengine -import groovy.transform.Memoized - import java.nio.file.NoSuchFileException import java.nio.file.Path +import ch.artecat.grengine.Grengine +import groovy.transform.Memoized +import nextflow.SysEnv import nextflow.exception.IllegalConfigException import nextflow.file.FileHelper import org.codehaus.groovy.control.CompilerConfiguration @@ -74,6 +74,18 @@ abstract class ConfigBase extends Script { this.configStack = stack } + /** + * Get the value of an environment variable from the launch environment. + * + * @param name + * The environment variable name to be referenced + * @return + * The value associate with the specified variable name or {@code null} if the variable does not exist. + */ + String env(String name) { + return SysEnv.get(name) + } + /** * Implements the config file include */ diff --git a/modules/nextflow/src/test/groovy/nextflow/NextflowTest.groovy b/modules/nextflow/src/test/groovy/nextflow/NextflowTest.groovy index c32a461ecb..f49db65779 100644 --- a/modules/nextflow/src/test/groovy/nextflow/NextflowTest.groovy +++ b/modules/nextflow/src/test/groovy/nextflow/NextflowTest.groovy @@ -35,6 +35,17 @@ class NextflowTest extends Specification { System.getenv('CI_GROOVY_VERSION') == GroovySystem.getVersion() } + def 'should get an environment variable' () { + given: + SysEnv.push(FOO: 'FOO_VALUE') + + expect: + Nextflow.env('FOO') == 'FOO_VALUE' + + cleanup: + SysEnv.pop() + } + def testFile() { expect: Nextflow.file('file.log').toFile() == new File('file.log').canonicalFile diff --git a/modules/nextflow/src/test/groovy/nextflow/config/ConfigParserTest.groovy b/modules/nextflow/src/test/groovy/nextflow/config/ConfigParserTest.groovy index ebe6f02e47..a128f0fd36 100644 --- a/modules/nextflow/src/test/groovy/nextflow/config/ConfigParserTest.groovy +++ b/modules/nextflow/src/test/groovy/nextflow/config/ConfigParserTest.groovy @@ -16,8 +16,6 @@ package nextflow.config -import spock.lang.Ignore - import java.nio.file.Files import java.nio.file.NoSuchFileException import java.nio.file.Path @@ -26,11 +24,12 @@ import com.sun.net.httpserver.Headers import com.sun.net.httpserver.HttpExchange import com.sun.net.httpserver.HttpHandler import com.sun.net.httpserver.HttpServer +import nextflow.SysEnv import nextflow.exception.ConfigParseException -import spock.lang.Specification - import nextflow.util.Duration import nextflow.util.MemoryUnit +import spock.lang.Ignore +import spock.lang.Specification /** * @@ -38,6 +37,23 @@ import nextflow.util.MemoryUnit */ class ConfigParserTest extends Specification { + def 'should get an environment variable' () { + given: + SysEnv.push(MAX_CPUS: '1') + + when: + def CONFIG = ''' + process.cpus = env('MAX_CPUS') + ''' + def config = new ConfigParser().parse(CONFIG) + + then: + config.process.cpus == '1' + + cleanup: + SysEnv.pop() + } + def 'should parse plugins id' () { given: def CONFIG = '''