Skip to content

Commit 8a7e539

Browse files
pditommasoclaude
andauthored
Default Fusion to v2.6 for Seqera executor (#6933) [ci fast]
* Default Fusion to v2.6 for Seqera executor When Fusion is not explicitly configured (no containerConfigUrl), the Seqera executor now injects targetVersion=2.6 into the fusion config, so the resolved Fusion URLs use v2.6 instead of the default v2.5. Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com> * Fix Spock data table variable names in FusionConfigTest Rename URL/VERSION to FUSION_URL/VER/TARGET_VER to avoid clashing with class names in Spock data table headers. Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com> * Fix SeqeraExecutorTest missing SysEnv.push in new tests The cleanup() method calls SysEnv.pop(), so every test must push first. Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com> --------- Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 27785b1 commit 8a7e539

6 files changed

Lines changed: 130 additions & 7 deletions

File tree

modules/nextflow/src/main/groovy/nextflow/fusion/FusionConfig.groovy

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ class FusionConfig implements ConfigScope {
5656

5757
final static private Pattern VERSION_JSON = ~/https:\/\/.*\/releases\/v(\d+(?:\.\w+)*)-(\w*)\.json$/
5858

59+
final static private Pattern VERSION_PATTERN = ~/v(\d+(?:\.\w+)*)/
60+
5961
@ConfigOption
6062
@Description("""
6163
Enable the Fusion file system (default: `false`).
@@ -110,6 +112,8 @@ class FusionConfig implements ConfigScope {
110112
""")
111113
final String tags
112114

115+
final String targetVersion
116+
113117
boolean enabled() { enabled }
114118

115119
boolean exportStorageCredentials() {
@@ -149,6 +153,7 @@ class FusionConfig implements ConfigScope {
149153
this.privileged = opts.privileged == null || opts.privileged as boolean
150154
this.cacheSize = opts.cacheSize as MemoryUnit
151155
this.snapshots = opts.snapshots as boolean
156+
this.targetVersion = opts.targetVersion as String
152157

153158
if( containerConfigUrl && !validProtocol(containerConfigUrl))
154159
throw new IllegalArgumentException("Fusion container config URL should start with 'http:' or 'https:' protocol prefix - offending value: $containerConfigUrl")
@@ -201,7 +206,25 @@ class FusionConfig implements ConfigScope {
201206

202207
String version() {
203208
return enabled
204-
? retrieveFusionVersion(this.containerConfigUrl ?: DEFAULT_FUSION_AMD64_URL)
209+
? retrieveFusionVersion(this.containerConfigUrl ?: targetFusionUrl(DEFAULT_FUSION_AMD64_URL))
205210
: null
206211
}
212+
213+
/**
214+
* Replace the version in a Fusion URL with the specified version.
215+
*
216+
* @param url The original URL e.g. {@code https://fusionfs.seqera.io/releases/v2.5-amd64.json}
217+
* @param version The target version e.g. {@code 2.6}
218+
* @return The URL with the version replaced e.g. {@code https://fusionfs.seqera.io/releases/v2.6-amd64.json}
219+
*/
220+
static String replaceVersion(String url, String version) {
221+
return url.replaceFirst(VERSION_PATTERN.pattern(), "v${version}")
222+
}
223+
224+
/**
225+
* Resolve the default Fusion URL, applying the {@code targetVersion} override if set.
226+
*/
227+
String targetFusionUrl(String url) {
228+
return targetVersion ? replaceVersion(url, targetVersion) : url
229+
}
207230
}

modules/nextflow/src/test/groovy/nextflow/fusion/FusionConfigTest.groovy

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,42 @@ class FusionConfigTest extends Specification {
151151
'https://foo.com/releases/v4.0-amd64.json' | true | '4.0'
152152
'https://foo.com/releases/v4.0.1-amd64.json' | true | '4.0.1'
153153
}
154+
155+
@Unroll
156+
def 'should replace version in url' () {
157+
expect:
158+
FusionConfig.replaceVersion(FUSION_URL, VER) == EXPECTED
159+
where:
160+
FUSION_URL | VER | EXPECTED
161+
'https://fusionfs.seqera.io/releases/v2.5-amd64.json' | '2.6' | 'https://fusionfs.seqera.io/releases/v2.6-amd64.json'
162+
'https://fusionfs.seqera.io/releases/v2.5-arm64.json' | '2.6' | 'https://fusionfs.seqera.io/releases/v2.6-arm64.json'
163+
'https://fusionfs.seqera.io/releases/v2.5-snap_amd64.json' | '2.6' | 'https://fusionfs.seqera.io/releases/v2.6-snap_amd64.json'
164+
'https://fusionfs.seqera.io/releases/v2.5-snap_arm64.json' | '2.6' | 'https://fusionfs.seqera.io/releases/v2.6-snap_arm64.json'
165+
'https://fusionfs.seqera.io/releases/v2.5-amd64.json' | '3.0' | 'https://fusionfs.seqera.io/releases/v3.0-amd64.json'
166+
}
167+
168+
@Unroll
169+
def 'should resolve default fusion url with version override' () {
170+
given:
171+
def config = new FusionConfig([targetVersion: TARGET_VER])
172+
expect:
173+
config.targetFusionUrl(FUSION_URL) == EXPECTED
174+
where:
175+
FUSION_URL | TARGET_VER | EXPECTED
176+
FusionConfig.DEFAULT_FUSION_AMD64_URL | null | FusionConfig.DEFAULT_FUSION_AMD64_URL
177+
FusionConfig.DEFAULT_FUSION_AMD64_URL | '2.6' | 'https://fusionfs.seqera.io/releases/v2.6-amd64.json'
178+
FusionConfig.DEFAULT_FUSION_ARM64_URL | '2.6' | 'https://fusionfs.seqera.io/releases/v2.6-arm64.json'
179+
FusionConfig.DEFAULT_SNAPSHOT_AMD64_URL | '2.6' | 'https://fusionfs.seqera.io/releases/v2.6-snap_amd64.json'
180+
FusionConfig.DEFAULT_SNAPSHOT_ARM64_URL | '2.6' | 'https://fusionfs.seqera.io/releases/v2.6-snap_arm64.json'
181+
}
182+
183+
def 'should get version with targetVersion override' () {
184+
expect:
185+
new FusionConfig([enabled:ENABLED, targetVersion:TARGET_VER]).version() == EXPECTED
186+
where:
187+
ENABLED | TARGET_VER | EXPECTED
188+
false | '2.6' | null
189+
true | null | '2.5'
190+
true | '2.6' | '2.6'
191+
}
154192
}

plugins/nf-seqera/src/main/io/seqera/executor/SeqeraExecutor.groovy

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ class SeqeraExecutor extends Executor implements ExtensionPoint {
5656

5757
public static final String SEQERA = 'seqera'
5858

59+
private static final String DEFAULT_FUSION_VERSION = '2.6'
60+
5961
private ExecutorOpts seqeraConfig
6062

6163
private SchedClient client
@@ -66,9 +68,17 @@ class SeqeraExecutor extends Executor implements ExtensionPoint {
6668

6769
@Override
6870
protected void register() {
71+
applyFusionDefaults()
6972
createClient()
7073
}
7174

75+
protected void applyFusionDefaults() {
76+
final fusionConfig = session.config.fusion as Map
77+
if( fusionConfig!=null && !fusionConfig.containerConfigUrl ) {
78+
fusionConfig.put('targetVersion', DEFAULT_FUSION_VERSION)
79+
}
80+
}
81+
7282
@Override
7383
void shutdown() {
7484
// Flush any pending batch jobs before terminating run

plugins/nf-seqera/src/test/io/seqera/executor/SeqeraExecutorTest.groovy

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package io.seqera.executor
1818

1919
import io.seqera.config.SeqeraConfig
2020
import io.seqera.sched.client.SchedClientConfig
21+
import nextflow.Session
2122
import nextflow.SysEnv
2223
import nextflow.platform.PlatformHelper
2324
import spock.lang.Specification
@@ -109,6 +110,36 @@ class SeqeraExecutorTest extends Specification {
109110
config.refreshToken == 'config-refresh-token'
110111
}
111112

113+
def 'should set fusion default version when not configured' () {
114+
given:
115+
SysEnv.push([:])
116+
def fusionConfig = [enabled: true]
117+
def config = [fusion: fusionConfig]
118+
def session = Mock(Session) { getConfig() >> config }
119+
def executor = new SeqeraExecutor(session: session)
120+
121+
when:
122+
executor.applyFusionDefaults()
123+
124+
then:
125+
fusionConfig.targetVersion == '2.6'
126+
}
127+
128+
def 'should not override fusion version when containerConfigUrl is set' () {
129+
given:
130+
SysEnv.push([:])
131+
def fusionConfig = [enabled: true, containerConfigUrl: 'https://custom.url/v3.0-amd64.json']
132+
def config = [fusion: fusionConfig]
133+
def session = Mock(Session) { getConfig() >> config }
134+
def executor = new SeqeraExecutor(session: session)
135+
136+
when:
137+
executor.applyFusionDefaults()
138+
139+
then:
140+
fusionConfig.targetVersion == null
141+
}
142+
112143
/**
113144
* Builds a SchedClientConfig using the same logic as {@link SeqeraExecutor#createClient()}
114145
*/

plugins/nf-wave/src/main/io/seqera/wave/plugin/WaveClient.groovy

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -383,15 +383,17 @@ class WaveClient {
383383
}
384384

385385
protected URL fusionAmd64(boolean snapshots) {
386-
return snapshots
387-
? URI.create(FusionConfig.DEFAULT_SNAPSHOT_AMD64_URL).toURL()
388-
: URI.create(FusionConfig.DEFAULT_FUSION_AMD64_URL).toURL()
386+
final url = snapshots
387+
? FusionConfig.DEFAULT_SNAPSHOT_AMD64_URL
388+
: FusionConfig.DEFAULT_FUSION_AMD64_URL
389+
return URI.create(fusion.targetFusionUrl(url)).toURL()
389390
}
390391

391392
protected URL fusionArm64(boolean snapshots) {
392-
return snapshots
393-
? URI.create(FusionConfig.DEFAULT_SNAPSHOT_ARM64_URL).toURL()
394-
: URI.create(FusionConfig.DEFAULT_FUSION_ARM64_URL).toURL()
393+
final url = snapshots
394+
? FusionConfig.DEFAULT_SNAPSHOT_ARM64_URL
395+
: FusionConfig.DEFAULT_FUSION_ARM64_URL
396+
return URI.create(fusion.targetFusionUrl(url)).toURL()
395397
}
396398

397399
protected URL defaultS5cmdUrl(String platform) {

plugins/nf-wave/src/test/io/seqera/wave/plugin/WaveClientTest.groovy

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,25 @@ class WaveClientTest extends Specification {
976976
'linux/arm64' | true | 'https://fusionfs.seqera.io/releases/v2.5-snap_arm64.json'
977977
}
978978

979+
@Unroll
980+
def 'should get fusion default url with version override' () {
981+
given:
982+
def sess = Mock(Session) {getConfig() >> [fusion:[snapshots:SNAP, targetVersion:'2.6']] }
983+
and:
984+
def wave = Spy(new WaveClient(sess))
985+
986+
expect:
987+
wave.defaultFusionUrl(ARCH).toURI().toString() == EXPECTED
988+
989+
where:
990+
ARCH | SNAP | EXPECTED
991+
'linux/amd64' | null | 'https://fusionfs.seqera.io/releases/v2.6-amd64.json'
992+
'linux/arm64' | null | 'https://fusionfs.seqera.io/releases/v2.6-arm64.json'
993+
and:
994+
'linux/amd64' | true | 'https://fusionfs.seqera.io/releases/v2.6-snap_amd64.json'
995+
'linux/arm64' | true | 'https://fusionfs.seqera.io/releases/v2.6-snap_arm64.json'
996+
}
997+
979998
@Unroll
980999
def 'should get s5cmd default url' () {
9811000
given:

0 commit comments

Comments
 (0)