Skip to content

Commit b019b0b

Browse files
bentshermanchristopher-hakkaartpditommaso
authored
Add Config parser v2 (and loader) (#4744)
Signed-off-by: Ben Sherman <bentshermann@gmail.com> Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com> Co-authored-by: Chris Hakkaart <chris.hakkaart@seqera.io> Co-authored-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
1 parent ed9da46 commit b019b0b

34 files changed

Lines changed: 2184 additions & 673 deletions

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ jobs:
133133
fail-fast: false
134134
matrix:
135135
java_version: [17, 23]
136-
test_mode: ["test_integration", "test_docs", "test_aws", "test_azure", "test_google", "test_wave"]
136+
test_mode: ["test_integration", "test_parser_v2", "test_docs", "test_aws", "test_azure", "test_google", "test_wave"]
137137
steps:
138138
- name: Checkout
139139
uses: actions/checkout@v4

build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ allprojects {
8585
maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
8686
maven { url = "https://s3-eu-west-1.amazonaws.com/maven.seqera.io/releases" }
8787
maven { url = "https://s3-eu-west-1.amazonaws.com/maven.seqera.io/snapshots" }
88+
maven {
89+
url 'https://jitpack.io'
90+
content { includeGroup 'com.github.nextflow-io.language-server' }
91+
}
8892
}
8993

9094
configurations {

docs/config.md

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -254,13 +254,12 @@ With the above configuration:
254254

255255
## Config profiles
256256

257-
Configuration files can contain the definition of one or more *profiles*. A profile is a set of configuration attributes that can be selected during pipeline execution by using the `-profile` command line option.
257+
Configuration files can define one or more *profiles*. A profile is a set of configuration settings that can be selected during pipeline execution using the `-profile` command line option.
258258

259-
Configuration profiles are defined by using the special scope `profiles`, which group the attributes that belong to the same profile using a common prefix. For example:
259+
Configuration profiles are defined in the `profiles` scope. For example:
260260

261261
```groovy
262262
profiles {
263-
264263
standard {
265264
process.executor = 'local'
266265
}
@@ -276,41 +275,47 @@ profiles {
276275
process.container = 'cbcrg/imagex'
277276
docker.enabled = true
278277
}
279-
280278
}
281279
```
282280

283-
This configuration defines three different profiles: `standard`, `cluster`, and `cloud`, that each set different process
284-
configuration strategies depending on the target runtime platform. The `standard` profile is used by default when no profile is specified.
281+
The above configuration defines three profiles: `standard`, `cluster`, and `cloud`. Each profile provides a different configuration for a given execution environment. The `standard` profile is used by default when no profile is specified.
285282

286-
:::{tip}
287-
Multiple configuration profiles can be specified by separating the profile names with a comma, for example:
283+
Configuration profiles can be specified at runtime as a comma-separated list:
288284

289285
```bash
290286
nextflow run <your script> -profile standard,cloud
291287
```
292288

293289
Config profiles are applied in the order in which they were defined in the config file, regardless of the order they are specified on the command line.
290+
291+
:::{versionadded} 25.02.0-edge
292+
When using the {ref}`strict config syntax <updating-config-syntax>`, profiles are applied in the order in which they are specified on the command line.
294293
:::
295294

296295
:::{danger}
297-
When using the `profiles` feature in your config file, do NOT set attributes in the same scope both inside and outside a `profiles` context. For example:
296+
When defining a profile in the config file, avoid using both the dot and block syntax for the same scope. For example:
298297

299298
```groovy
300-
process.cpus = 1
301-
302299
profiles {
303-
foo {
304-
process.memory = '2 GB'
305-
}
300+
foo {
301+
process.memory = '2 GB'
302+
process {
303+
cpus = 2
304+
}
305+
}
306+
}
307+
```
306308

307-
bar {
308-
process.memory = '4 GB'
309-
}
309+
Due to a limitation of the legacy config parser, the first setting will be overwritten by the second:
310+
311+
```console
312+
$ nextflow config -profile foo
313+
process {
314+
cpus = 2
310315
}
311316
```
312317

313-
In the above example, the `process.cpus` attribute is not correctly applied because the `process` scope is also used in the `foo` and `bar` profiles.
318+
This limitation can be avoided by using the {ref}`strict config syntax <updating-config-syntax>`.
314319
:::
315320

316321
## Workflow handlers

docs/reference/env-vars.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ The following environment variables control the configuration of the Nextflow ru
182182
:::
183183
: Enable the use of Spack recipes defined by using the {ref}`process-spack` directive. (default: `false`).
184184

185+
`NXF_SYNTAX_PARSER`
186+
: :::{versionadded} 25.02.0-edge
187+
:::
188+
: Set to `'v2'` to use the {ref}`strict syntax <updating-syntax-page>` for Nextflow config files (default: `'v1'`).
189+
185190
`NXF_TEMP`
186191
: Directory where temporary files are stored
187192

docs/updating-syntax.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,8 +487,14 @@ The process `when` section is deprecated. Use conditional logic, such as an `if`
487487

488488
The process `shell` section is deprecated. Use the `script` block instead. The VS Code extension provides syntax highlighting and error checking to help distinguish between Nextflow variables and Bash variables.
489489

490+
(updating-config-syntax)=
491+
490492
### Configuration syntax
491493

494+
:::{versionadded} 25.02.0-edge
495+
The strict config syntax can be enabled in Nextflow by setting `NXF_SYNTAX_PARSER=v2`.
496+
:::
497+
492498
See {ref}`Configuration <config-syntax>` for a comprehensive description of the configuration language.
493499

494500
Currently, Nextflow parses config files as Groovy scripts, allowing the use of scripting constructs like variables, helper functions, try-catch blocks, and conditional logic for dynamic configuration:

modules/nextflow/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ compileGroovy {
2020
dependencies {
2121
api(project(':nf-commons'))
2222
api(project(':nf-httpfs'))
23+
api 'com.github.nextflow-io.language-server:compiler:main-SNAPSHOT'
2324
api "org.apache.groovy:groovy:4.0.25"
2425
api "org.apache.groovy:groovy-nio:4.0.25"
2526
api "org.apache.groovy:groovy-xml:4.0.25"

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ class ConfigBuilder {
7171

7272
List<Path> parsedConfigFiles = []
7373

74-
List<String> parsedProfileNames
75-
7674
boolean showClosures
7775

7876
boolean stripSecrets
@@ -347,7 +345,7 @@ class ConfigBuilder {
347345
assert env != null
348346

349347
final ignoreIncludes = options ? options.ignoreConfigIncludes : false
350-
final slurper = new ConfigParser()
348+
final slurper = ConfigParserFactory.create()
351349
.setRenderClosureAsString(showClosures)
352350
.setStripSecrets(stripSecrets)
353351
.setIgnoreIncludes(ignoreIncludes)
@@ -384,9 +382,8 @@ class ConfigBuilder {
384382
}
385383
}
386384

387-
this.parsedProfileNames = new ArrayList<>(slurper.getProfileNames())
388385
if( validateProfile ) {
389-
checkValidProfile(slurper.getConditionalBlockNames())
386+
checkValidProfile(slurper.getProfiles())
390387
}
391388

392389
}
@@ -421,7 +418,7 @@ class ConfigBuilder {
421418

422419
log.debug "Applying config profile: `${profile}`"
423420
def allNames = profile.tokenize(',')
424-
slurper.registerConditionalBlock('profiles', allNames)
421+
slurper.setProfiles(allNames)
425422

426423
def config = parse0(slurper,entry)
427424
validate(config,entry)

0 commit comments

Comments
 (0)