Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 43 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,54 @@ nextflowPlugin {

publishing {
registry {
url = 'https://plugins.nextflow.io/api'
authToken = project.findProperty('registry_access_token')
// Registry URL (optional, defaults to plugin-registry.seqera.io/api)
url = 'https://plugin-registry.seqera.io/api'

// API key for authentication (required)
apiKey = project.findProperty('npr.apiKey')
}
}
}
```

### Registry Configuration

The registry publishing configuration supports multiple ways to provide the URL and API key:

#### Registry URL
The registry URL can be configured via (in order of priority):
1. `nextflowPlugin.publishing.registry.url` in build.gradle
2. Gradle property: `-Pnpr.apiUrl=https://your-registry.com/api`
3. Environment variable: `NPR_API_URL=https://your-registry.com/api`
4. Default: `https://plugin-registry.seqera.io/api`

#### API Key
The API key can be configured via (in order of priority):
1. `nextflowPlugin.publishing.registry.apiKey` in build.gradle
2. Gradle property: `-Pnpr.apiKey=your-api-key`
3. Environment variable: `NPR_API_KEY=your-api-key`

**Note:** The API key is required for publishing. If none is provided, the plugin will show an error with configuration instructions.

#### Example Configurations

Using gradle.properties:
```properties
npr.apiUrl=https://my-custom-registry.com/api
npr.apiKey=your-secret-api-key
```

Using environment variables:
```bash
export NPR_API_URL=https://my-custom-registry.com/api
export NPR_API_KEY=your-secret-api-key
./gradlew releasePlugin
```

This will add some useful tasks to your Gradle build:
* `assemble` - compile the Nextflow plugin code and assemble it into a zip file
* `installPlugin` - copy the assembled plugin into your local Nextflow plugins dir
* `releasePlugin` - publish the assembled plugin to the plugin registry
* `assemble` - Compile the Nextflow plugin code and assemble it into a zip file
* `installPlugin` - Copy the assembled plugin into your local Nextflow plugins dir
* `releasePlugin` - Release the assembled plugin to the plugin registry

You should also ensure that your project's `settings.gradle` declares the plugin name, eg:
```gradle
Expand Down Expand Up @@ -92,5 +129,5 @@ Then use this command:


```
./gradlew publishPlugins
./gradlew releasePlugins
```
18 changes: 9 additions & 9 deletions src/main/groovy/io/nextflow/gradle/NextflowPlugin.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -129,22 +129,22 @@ class NextflowPlugin implements Plugin<Project> {

// add registry publish task, if configured
if (config.publishing.registry) {
// publishPluginToRegistry - publishes plugin to a plugin registry
project.tasks.register('publishPluginToRegistry', RegistryUploadTask)
project.tasks.publishPluginToRegistry.dependsOn << project.tasks.packagePlugin
publishTasks << project.tasks.publishPluginToRegistry
// releasePluginToRegistry - publishes plugin to a plugin registry
project.tasks.register('releasePluginToRegistry', RegistryUploadTask)
project.tasks.releasePluginToRegistry.dependsOn << project.tasks.packagePlugin
publishTasks << project.tasks.releasePluginToRegistry
}


// finally, configure the destination-agnostic 'publish' task
// finally, configure the destination-agnostic 'release' task
if (!publishTasks.isEmpty()) {
// publishPlugin - all the release/publishing actions
project.tasks.register('publishPlugin', {
// releasePlugin - all the release/publishing actions
project.tasks.register('releasePlugin', {
group = 'Nextflow Plugin'
description = 'publish plugin to configured destinations'
description = 'Release plugin to configured destination'
})
for (task in publishTasks) {
project.tasks.publishPlugin.dependsOn << task
project.tasks.releasePlugin.dependsOn << task
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ class RegistryClient {
private final Gson gson = new Gson()

private final URI url
private final String authToken
private final String apiKey

RegistryClient(URI url, String authToken) {
RegistryClient(URI url, String apiKey) {
this.url = !url.toString().endsWith("/")
? URI.create(url.toString() + "/")
: url
this.authToken = authToken
this.apiKey = apiKey
}

def publish(String id, String version, File file) {
def req = new HttpPost(url.resolve("publish"))
req.addHeader("Authorization", "Bearer ${authToken}")
req.addHeader("Authorization", "Bearer ${apiKey}")
req.setEntity(MultipartEntityBuilder.create()
.addTextBody("id", id)
.addTextBody("version", version)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,67 @@ class RegistryPublishConfig {
/**
* Location of the registry api
*/
String url = 'https://plugins.nextflow.io/api'
String url

/**
* Registry authentication token
* Registry API key
*/
String authToken
String apiKey

RegistryPublishConfig(Project project) {
this.project = project
}

/**
* Get the registry URL, checking fallbacks if not explicitly set
*/
String getResolvedUrl() {
// If explicitly set, use it
if (url) {
return url
}

// Try gradle property
def gradleProp = project.findProperty('npr.apiUrl')
if (gradleProp) {
return gradleProp.toString()
}

// Try environment variable
def envVar = System.getenv('NPR_API_URL')
if (envVar) {
return envVar
}

// Default URL
return 'https://plugin-registry.seqera.io/api'
}

/**
* Get the API key, checking fallbacks if not explicitly set
*/
String getResolvedApiKey() {
// If explicitly set, use it
if (apiKey) {
return apiKey
}

// Try gradle property
def gradleProp = project.findProperty('npr.apiKey')
if (gradleProp) {
return gradleProp.toString()
}

// Try environment variable
def envVar = System.getenv('NPR_API_KEY')
if (envVar) {
return envVar
}

// No API key found
throw new RuntimeException('Registry API key not provided. Set it via:\n' +
' - nextflowPlugin.publishing.registry.apiKey in build.gradle\n' +
' - gradle property: npr.apiKey\n' +
' - environment variable: NPR_API_KEY')
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class RegistryUploadTask extends DefaultTask {
final plugin = project.extensions.getByType(NextflowPluginConfig)
final config = plugin.publishing.registry

def client = new RegistryClient(new URI(config.url), config.authToken)
def client = new RegistryClient(new URI(config.getResolvedUrl()), config.getResolvedApiKey())
client.publish(project.name, version, project.file(zipFile))
}
}
22 changes: 11 additions & 11 deletions src/test/groovy/io/nextflow/gradle/NextflowPluginTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class NextflowPluginTest extends Specification {
project.pluginManager.apply('io.nextflow.nextflow-plugin')
}

def "should register publishPlugin task when publishing is configured"() {
def "should register releasePlugin task when publishing is configured"() {
given:
project.nextflowPlugin {
description = 'A test plugin'
Expand All @@ -38,13 +38,13 @@ class NextflowPluginTest extends Specification {
project.evaluate()

then:
project.tasks.findByName('publishPlugin') != null
project.tasks.publishPlugin.group == 'Nextflow Plugin'
project.tasks.publishPlugin.description == 'publish plugin to configured destinations'
project.tasks.findByName('releasePlugin') != null
project.tasks.releasePlugin.group == 'Nextflow Plugin'
project.tasks.releasePlugin.description == 'Release plugin to configured destination'
}


def "should make publishPlugin depend on registry publishing task"() {
def "should make releasePlugin depend on registry publishing task"() {
given:
project.nextflowPlugin {
description = 'A test plugin'
Expand All @@ -63,13 +63,13 @@ class NextflowPluginTest extends Specification {
project.evaluate()

then:
def publishPlugin = project.tasks.publishPlugin
def publishToRegistry = project.tasks.publishPluginToRegistry
publishPlugin.taskDependencies.getDependencies(publishPlugin).contains(publishToRegistry)
def releasePlugin = project.tasks.releasePlugin
def releaseToRegistry = project.tasks.releasePluginToRegistry
releasePlugin.taskDependencies.getDependencies(releasePlugin).contains(releaseToRegistry)
}


def "should not register publishPlugin task when no publishing is configured"() {
def "should not register releasePlugin task when no publishing is configured"() {
given:
project.nextflowPlugin {
description = 'A test plugin'
Expand All @@ -83,7 +83,7 @@ class NextflowPluginTest extends Specification {
project.evaluate()

then:
project.tasks.findByName('publishPlugin') == null
project.tasks.findByName('releasePlugin') == null
}

}
}