Skip to content

Commit 03da64e

Browse files
authored
Check Nextflow version before loading plugins (#6591)
Signed-off-by: Ben Sherman <[email protected]>
1 parent 56f0f00 commit 03da64e

File tree

4 files changed

+79
-84
lines changed

4 files changed

+79
-84
lines changed

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

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ import nextflow.util.NameGenerator
8888
import nextflow.util.SysHelper
8989
import nextflow.util.ThreadPoolManager
9090
import nextflow.util.Threads
91-
import nextflow.util.VersionNumber
9291
import org.apache.commons.lang3.exception.ExceptionUtils
9392
import sun.misc.Signal
9493
import sun.misc.SignalHandler
@@ -686,7 +685,6 @@ class Session implements ISession {
686685
throw new IllegalStateException("Not a valid config env object: $config.env")
687686
}
688687

689-
@Memoized
690688
Manifest getManifest() {
691689
if( !config.manifest )
692690
return new Manifest()
@@ -890,13 +888,6 @@ class Session implements ISession {
890888

891889
ExecutorService getExecService() { execService }
892890

893-
/**
894-
* Check preconditions before run the main script
895-
*/
896-
protected void validate() {
897-
checkVersion()
898-
}
899-
900891
@PackageScope void checkConfig() {
901892
final enabled = config.navigate('nextflow.enable.configProcessNamesValidation', true) as boolean
902893
if( enabled ) {
@@ -918,36 +909,6 @@ class Session implements ISession {
918909
config.navigate('workflow.failOnIgnore', false) as boolean
919910
}
920911

921-
@PackageScope VersionNumber getCurrentVersion() {
922-
new VersionNumber(BuildInfo.version)
923-
}
924-
925-
@PackageScope void checkVersion() {
926-
def version = manifest.getNextflowVersion()?.trim()
927-
if( !version )
928-
return
929-
930-
// when the version string is prefix with a `!`
931-
// an exception is thrown is the version does not match
932-
boolean important = false
933-
if( version.startsWith('!') ) {
934-
important = true
935-
version = version.substring(1).trim()
936-
}
937-
938-
if( !getCurrentVersion().matches(version) ) {
939-
important ? showVersionError(version) : showVersionWarning(version)
940-
}
941-
}
942-
943-
@PackageScope void showVersionError(String ver) {
944-
throw new AbortOperationException("Nextflow version $BuildInfo.version does not match workflow required version: $ver")
945-
}
946-
947-
@PackageScope void showVersionWarning(String ver) {
948-
log.warn "Nextflow version $BuildInfo.version does not match workflow required version: $ver -- Execution will continue, but things may break!"
949-
}
950-
951912
/**
952913
* Validate the config file
953914
*
@@ -1090,7 +1051,6 @@ class Session implements ISession {
10901051
}
10911052

10921053
void notifyBeforeWorkflowExecution() {
1093-
validate()
10941054
}
10951055

10961056
void notifyAfterWorkflowExecution() {

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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import nextflow.SysEnv
3838
import nextflow.config.ConfigBuilder
3939
import nextflow.config.ConfigMap
4040
import nextflow.config.ConfigValidator
41+
import nextflow.config.Manifest
4142
import nextflow.exception.AbortOperationException
4243
import nextflow.file.FileHelper
4344
import nextflow.plugin.Plugins
@@ -49,6 +50,7 @@ import nextflow.secret.SecretsLoader
4950
import nextflow.util.CustomPoolFactory
5051
import nextflow.util.Duration
5152
import nextflow.util.HistoryFile
53+
import nextflow.util.VersionNumber
5254
import org.apache.commons.lang3.StringUtils
5355
import org.fusesource.jansi.AnsiConsole
5456
import org.yaml.snakeyaml.Yaml
@@ -360,6 +362,9 @@ class CmdRun extends CmdBase implements HubOptions {
360362
ConfigMap config = builder.build()
361363
Map configParams = builder.getConfigParams()
362364

365+
// -- Check Nextflow version
366+
checkVersion(config)
367+
363368
// -- Load plugins (may register secret providers)
364369
Plugins.load(config)
365370

@@ -677,6 +682,45 @@ class CmdRun extends CmdBase implements HubOptions {
677682
return result
678683
}
679684

685+
/**
686+
* Check the Nextflow version against the version required by
687+
* the pipeline via `manifest.nextflowVersion`.
688+
*
689+
* When the version spec is prefixed with '!', the run will fail
690+
* if the Nextflow version does not match.
691+
*
692+
* @param config
693+
*/
694+
protected void checkVersion(Map config) {
695+
final manifest = new Manifest(config.manifest as Map ?: Collections.emptyMap())
696+
String version = manifest.nextflowVersion?.trim()
697+
if( !version )
698+
return
699+
700+
final important = version.startsWith('!')
701+
if( important )
702+
version = version.substring(1).trim()
703+
704+
if( !getCurrentVersion().matches(version) ) {
705+
if( important )
706+
showVersionError(version)
707+
else
708+
showVersionWarning(version)
709+
}
710+
}
711+
712+
protected VersionNumber getCurrentVersion() {
713+
return new VersionNumber(BuildInfo.version)
714+
}
715+
716+
protected void showVersionError(String ver) {
717+
throw new AbortOperationException("Nextflow version ${BuildInfo.version} does not match version required by pipeline: ${ver}")
718+
}
719+
720+
protected void showVersionWarning(String ver) {
721+
log.warn "Nextflow version ${BuildInfo.version} does not match version required by pipeline: ${ver} -- execution will continue, but things might break!"
722+
}
723+
680724
@Memoized // <-- avoid parse multiple times the same file and params
681725
Map parsedParams(Map configVars) {
682726

modules/nextflow/src/test/groovy/nextflow/SessionTest.groovy

Lines changed: 1 addition & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ class SessionTest extends Specification {
317317
when:
318318
def session = new Session([manifest: MAN])
319319
then:
320-
session.manifest.with {
320+
session.getManifest().with {
321321
author == 'pablo'
322322
nextflowVersion == '1.2.3'
323323
name == 'foo'
@@ -401,49 +401,6 @@ class SessionTest extends Specification {
401401
session.fetchContainers() == 'ngi/rnaseq:1.2'
402402
}
403403

404-
405-
def 'should validate version'() {
406-
407-
given:
408-
def manifest = Mock(Manifest)
409-
def session = Spy(Session)
410-
411-
when:
412-
session.checkVersion()
413-
then:
414-
session.getManifest() >> manifest
415-
1 * session.getCurrentVersion() >> new VersionNumber('1.1')
416-
1 * manifest.getNextflowVersion() >> '>= 1.0'
417-
0 * session.showVersionWarning(_)
418-
419-
when:
420-
session.checkVersion()
421-
then:
422-
session.getManifest() >> manifest
423-
1 * session.getCurrentVersion() >> new VersionNumber('1.1')
424-
1 * manifest.getNextflowVersion() >> '>= 1.2'
425-
1 * session.showVersionWarning('>= 1.2')
426-
427-
when:
428-
session.checkVersion()
429-
then:
430-
session.getManifest() >> manifest
431-
1 * session.getCurrentVersion() >> new VersionNumber('1.1')
432-
1 * manifest.getNextflowVersion() >> '! >= 1.2'
433-
1 * session.showVersionError('>= 1.2')
434-
thrown(AbortOperationException)
435-
436-
when:
437-
session.checkVersion()
438-
then:
439-
session.getManifest() >> manifest
440-
1 * manifest.getNextflowVersion() >> null
441-
0 * session.getCurrentVersion() >> null
442-
0 * session.showVersionWarning(_)
443-
0 * session.showVersionError(_)
444-
445-
}
446-
447404
@Unroll
448405
def 'should get module binaries status'() {
449406
given:

modules/nextflow/src/test/groovy/nextflow/cli/CmdRunTest.groovy

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import nextflow.NextflowMeta
2323
import nextflow.SysEnv
2424
import nextflow.config.ConfigMap
2525
import nextflow.exception.AbortOperationException
26+
import nextflow.util.VersionNumber
2627
import spock.lang.Specification
2728
import spock.lang.Unroll
2829

@@ -438,4 +439,37 @@ class CmdRunTest extends Specification {
438439
true | [:] | [NXF_ENABLE_STRICT: true ] | true
439440

440441
}
442+
443+
def 'should validate Nextflow version against version required by pipeline'() {
444+
445+
given:
446+
def cmd = Spy(new CmdRun())
447+
448+
when:
449+
cmd.checkVersion([manifest: [nextflowVersion: '>= 1.0']])
450+
then:
451+
1 * cmd.getCurrentVersion() >> new VersionNumber('1.1')
452+
0 * cmd.showVersionWarning(_)
453+
454+
when:
455+
cmd.checkVersion([manifest: [nextflowVersion: '>= 1.2']])
456+
then:
457+
1 * cmd.getCurrentVersion() >> new VersionNumber('1.1')
458+
1 * cmd.showVersionWarning('>= 1.2')
459+
460+
when:
461+
cmd.checkVersion([manifest: [nextflowVersion: '! >= 1.2']])
462+
then:
463+
1 * cmd.getCurrentVersion() >> new VersionNumber('1.1')
464+
1 * cmd.showVersionError('>= 1.2')
465+
thrown(AbortOperationException)
466+
467+
when:
468+
cmd.checkVersion([:])
469+
then:
470+
0 * cmd.getCurrentVersion()
471+
0 * cmd.showVersionWarning(_)
472+
0 * cmd.showVersionError(_)
473+
}
474+
441475
}

0 commit comments

Comments
 (0)