Skip to content

Commit 4f35040

Browse files
pditommasoclaude
andcommitted
Make registry configuration optional with fallback support
- Remove intermediate 'publishing' block, move 'registry' to top level - Always create release tasks regardless of configuration - Add fallback support for npr.apiUrl/NPR_API_URL and npr.apiKey/NPR_API_KEY - Add comprehensive test coverage for all configuration scenarios - Update README with detailed configuration options and examples - Delete unused PluginReleaseConfig class 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> Signed-off-by: Paolo Di Tommaso <[email protected]>
1 parent b9a79b4 commit 4f35040

File tree

9 files changed

+459
-81
lines changed

9 files changed

+459
-81
lines changed

README.md

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,56 @@ nextflowPlugin {
3636
'com.example.ExampleFunctions'
3737
]
3838
39-
publishing {
40-
registry {
41-
url = 'https://registry.nextflow.io/api'
42-
authToken = project.findProperty('registry_access_token')
43-
}
39+
registry {
40+
url = 'https://registry.nextflow.io/api'
41+
authToken = project.findProperty('registry_access_token')
4442
}
4543
}
4644
```
4745

46+
### Registry Configuration
47+
48+
The `registry` block is optional and supports several configuration methods:
49+
50+
**Option 1: Explicit configuration**
51+
```gradle
52+
registry {
53+
url = 'https://registry.nextflow.io/api'
54+
authToken = 'your-auth-token'
55+
}
56+
```
57+
58+
**Option 2: Using project properties**
59+
```gradle
60+
registry {
61+
// Uses npr.apiUrl and npr.apiKey project properties as fallbacks
62+
}
63+
```
64+
65+
**Option 3: Using environment variables**
66+
```gradle
67+
registry {
68+
// Uses NPR_API_URL and NPR_API_KEY environment variables as fallbacks
69+
}
70+
```
71+
72+
**Option 4: No registry block (uses fallbacks)**
73+
```gradle
74+
nextflowPlugin {
75+
// ... other configuration ...
76+
// No registry block - will use npr.apiUrl/NPR_API_URL and npr.apiKey/NPR_API_KEY
77+
}
78+
```
79+
80+
The configuration precedence is: explicit values → project properties → environment variables → defaults.
81+
82+
### Available Tasks
83+
4884
This will add some useful tasks to your Gradle build:
4985
* `assemble` - Compile the Nextflow plugin code and assemble it into a zip file
5086
* `installPlugin` - Copy the assembled plugin into your local Nextflow plugins dir
51-
* `releasePlugin` - Release the assembled plugin to the plugin registry
87+
* `releasePlugin` - Release the assembled plugin to the plugin registry (always available)
88+
* `releasePluginToRegistry` - Release the plugin to the configured registry (always available)
5289

5390
You should also ensure that your project's `settings.gradle` declares the plugin name, eg:
5491
```gradle

src/main/groovy/io/nextflow/gradle/NextflowPlugin.groovy

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -123,31 +123,16 @@ class NextflowPlugin implements Plugin<Project> {
123123
project.tasks.test.dependsOn << project.tasks.assemble
124124

125125
project.afterEvaluate {
126-
if (config.publishing) {
127-
// track the release tasks
128-
def releaseTasks = []
129-
130-
// add registry release task, if configured
131-
if (config.publishing.registry) {
132-
// releasePluginToRegistry - releases plugin to a plugin registry
133-
project.tasks.register('releasePluginToRegistry', RegistryReleaseTask)
134-
project.tasks.releasePluginToRegistry.dependsOn << project.tasks.packagePlugin
135-
releaseTasks << project.tasks.releasePluginToRegistry
136-
}
137-
138-
139-
// finally, configure the destination-agnostic 'release' task
140-
if (!releaseTasks.isEmpty()) {
141-
// releasePlugin - all the release actions
142-
project.tasks.register('releasePlugin', {
143-
group = 'Nextflow Plugin'
144-
description = 'Release plugin to configured destination'
145-
})
146-
for (task in releaseTasks) {
147-
project.tasks.releasePlugin.dependsOn << task
148-
}
149-
}
150-
}
126+
// Always create registry release task - it will use fallback configuration if needed
127+
project.tasks.register('releasePluginToRegistry', RegistryReleaseTask)
128+
project.tasks.releasePluginToRegistry.dependsOn << project.tasks.packagePlugin
129+
130+
// Always create the main release task
131+
project.tasks.register('releasePlugin', {
132+
group = 'Nextflow Plugin'
133+
description = 'Release plugin to configured destination'
134+
})
135+
project.tasks.releasePlugin.dependsOn << project.tasks.releasePluginToRegistry
151136
}
152137
}
153138

src/main/groovy/io/nextflow/gradle/NextflowPluginConfig.groovy

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package io.nextflow.gradle
22

33
import com.github.zafarkhaja.semver.Version
44
import groovy.transform.CompileStatic
5+
import io.nextflow.gradle.registry.RegistryReleaseConfig
56
import org.gradle.api.Project
67

78
/**
@@ -17,6 +18,10 @@ import org.gradle.api.Project
1718
* extensionPoints = [
1819
* 'com.example.ExampleFunctions'
1920
* ]
21+
* registry {
22+
* url = 'https://registry.nextflow.io/api'
23+
* authToken = 'my-auth-token'
24+
* }
2025
* }
2126
* </pre>
2227
*/
@@ -57,9 +62,9 @@ class NextflowPluginConfig {
5762
List<String> extensionPoints = []
5863

5964
/**
60-
* Configure how the plugin will be released (optional)
65+
* Configure registry publishing settings (optional)
6166
*/
62-
PluginReleaseConfig publishing
67+
RegistryReleaseConfig registry
6368

6469
NextflowPluginConfig(Project project) {
6570
this.project = project
@@ -87,10 +92,9 @@ class NextflowPluginConfig {
8792
}
8893
}
8994

90-
// initialises the 'publishing' sub-config
91-
def publishing(Closure config) {
92-
publishing = new PluginReleaseConfig(project)
93-
project.configure(publishing, config)
94-
publishing.validate()
95+
// initialises the 'registry' sub-config
96+
def registry(Closure config) {
97+
registry = new RegistryReleaseConfig(project)
98+
project.configure(registry, config)
9599
}
96100
}

src/main/groovy/io/nextflow/gradle/PluginReleaseConfig.groovy

Lines changed: 0 additions & 30 deletions
This file was deleted.

src/main/groovy/io/nextflow/gradle/registry/RegistryReleaseConfig.groovy

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class RegistryReleaseConfig {
1717
* The registry API base URL.
1818
* Defaults to the official Nextflow registry.
1919
*/
20-
String url = 'https://registry.nextflow.io/api'
20+
String url
2121

2222
/**
2323
* The authentication token (bearer token) for registry access.
@@ -28,4 +28,32 @@ class RegistryReleaseConfig {
2828
RegistryReleaseConfig(Project project) {
2929
this.project = project
3030
}
31+
32+
/**
33+
* Gets the resolved registry URL with fallback to environment variable.
34+
* @return the resolved URL or default if not configured
35+
*/
36+
String getResolvedUrl() {
37+
return url ?:
38+
project.findProperty('npr.apiUrl') ?:
39+
System.getenv('NPR_API_URL') ?:
40+
'https://registry.nextflow.io/api'
41+
}
42+
43+
/**
44+
* Gets the resolved auth token with fallback to environment variable.
45+
* @return the resolved auth token
46+
* @throws RuntimeException if no auth token is configured
47+
*/
48+
String getResolvedAuthToken() {
49+
def token = authToken ?:
50+
project.findProperty('npr.apiKey') ?:
51+
System.getenv('NPR_API_KEY')
52+
53+
if (!token) {
54+
throw new RuntimeException('Registry authentication token must be configured either via authToken property, npr.apiKey project property, or NPR_API_KEY environment variable')
55+
}
56+
57+
return token
58+
}
3159
}

src/main/groovy/io/nextflow/gradle/registry/RegistryReleaseTask.groovy

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,17 @@ class RegistryReleaseTask extends DefaultTask {
4646
def run() {
4747
final version = project.version.toString()
4848
final plugin = project.extensions.getByType(NextflowPluginConfig)
49-
final config = plugin.publishing.registry
49+
50+
// Get or create registry configuration
51+
def registryConfig
52+
if (plugin.registry) {
53+
registryConfig = plugin.registry
54+
} else {
55+
// Create default registry config that will use fallback values
56+
registryConfig = new RegistryReleaseConfig(project)
57+
}
5058

51-
def client = new RegistryClient(new URI(config.url), config.authToken)
59+
def client = new RegistryClient(new URI(registryConfig.resolvedUrl), registryConfig.resolvedAuthToken)
5260
client.release(project.name, version, project.file(zipFile))
5361
}
5462
}

src/test/groovy/io/nextflow/gradle/NextflowPluginTest.groovy

Lines changed: 78 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,8 @@ class NextflowPluginTest extends Specification {
2727
className = 'com.example.TestPlugin'
2828
nextflowVersion = '24.04.0'
2929
extensionPoints = ['com.example.TestExtension']
30-
publishing {
31-
registry {
32-
url = 'https://example.com/registry'
33-
}
30+
registry {
31+
url = 'https://example.com/registry'
3432
}
3533
}
3634

@@ -52,10 +50,8 @@ class NextflowPluginTest extends Specification {
5250
className = 'com.example.TestPlugin'
5351
nextflowVersion = '24.04.0'
5452
extensionPoints = ['com.example.TestExtension']
55-
publishing {
56-
registry {
57-
url = 'https://example.com/registry'
58-
}
53+
registry {
54+
url = 'https://example.com/registry'
5955
}
6056
}
6157

@@ -69,7 +65,7 @@ class NextflowPluginTest extends Specification {
6965
}
7066

7167

72-
def "should not register releasePlugin task when no publishing is configured"() {
68+
def "should always register releasePlugin tasks even when no registry is configured"() {
7369
given:
7470
project.nextflowPlugin {
7571
description = 'A test plugin'
@@ -83,7 +79,79 @@ class NextflowPluginTest extends Specification {
8379
project.evaluate()
8480

8581
then:
86-
project.tasks.findByName('releasePlugin') == null
82+
project.tasks.findByName('releasePlugin') != null
83+
project.tasks.findByName('releasePluginToRegistry') != null
84+
project.tasks.releasePlugin.group == 'Nextflow Plugin'
85+
project.tasks.releasePlugin.description == 'Release plugin to configured destination'
86+
}
87+
88+
def "should register releasePlugin tasks when no explicit registry configuration exists"() {
89+
given:
90+
project.nextflowPlugin {
91+
description = 'A test plugin'
92+
provider = 'Test Author'
93+
className = 'com.example.TestPlugin'
94+
nextflowVersion = '24.04.0'
95+
extensionPoints = ['com.example.TestExtension']
96+
// No registry block - should use fallback configuration
97+
}
98+
99+
when:
100+
project.evaluate()
101+
102+
then:
103+
project.tasks.findByName('releasePlugin') != null
104+
project.tasks.findByName('releasePluginToRegistry') != null
105+
}
106+
107+
def "should create releasePlugin task that works with fallback configuration"() {
108+
given:
109+
project.nextflowPlugin {
110+
description = 'A test plugin'
111+
provider = 'Test Author'
112+
className = 'com.example.TestPlugin'
113+
nextflowVersion = '24.04.0'
114+
extensionPoints = ['com.example.TestExtension']
115+
// No registry block - should use fallback configuration
116+
}
117+
118+
when:
119+
project.evaluate()
120+
def task = project.tasks.findByName('releasePlugin')
121+
122+
then:
123+
task != null
124+
task.group == 'Nextflow Plugin'
125+
126+
and: "Other tasks should also exist"
127+
project.tasks.findByName('packagePlugin') != null
128+
project.tasks.findByName('installPlugin') != null
129+
project.tasks.findByName('releasePluginToRegistry') != null
130+
}
131+
132+
def "should handle empty registry block and use fallback configuration"() {
133+
given:
134+
project.nextflowPlugin {
135+
description = 'A test plugin'
136+
provider = 'Test Author'
137+
className = 'com.example.TestPlugin'
138+
nextflowVersion = '24.04.0'
139+
extensionPoints = ['com.example.TestExtension']
140+
registry {
141+
// completely empty registry block
142+
}
143+
}
144+
145+
when:
146+
project.evaluate()
147+
148+
then:
149+
project.tasks.findByName('releasePlugin') != null
150+
project.tasks.findByName('releasePluginToRegistry') != null
151+
152+
and: "Other tasks should also exist"
153+
project.tasks.findByName('packagePlugin') != null
154+
project.tasks.findByName('installPlugin') != null
87155
}
88156

89157
}

0 commit comments

Comments
 (0)