How can I publish an existing plugin jar to the plugin portal?

At Boxfuse we have a separate build & publish flow, as not all our builds are meant to be publicly available. Only after we promote a build does it become available in our public Maven repository (http://files.boxfuse.com).

How can I publish a specific version our Gradle plugin to the plugin portal when we are ready to promote it after it has already been built?

As a guess, you could use the onlyIf method of tasks:

publishPlugins.onlyIf { promoted == true }

It’s hard to give you anything more concrete without knowing how the promotion works.

Promotion in our case currently involves previously built artifacts being copied over to S3. We would now like to take one of those artifacts (the Boxfuse Gradle plugin jar) and push it to the Gradle Plugin portal instead.

Can the publishing plugin take an existing jar (containing all necessary metadata) and start from there?

Can anyone from Gradleware recommend a way to achieve this?

Hi boxfuse!

It is possible, just a bit fiddly. The publishing plugin will upload jars from the places it expects them to be under build/, so if you put the published ones there then those ones will be uploaded. I go into more detail in this thread.

Hope that helps

Hi Tom,

I did manage to get the plugin published (https://plugins.gradle.org/plugin/com.boxfuse.client) using “./gradlew publishPlugins -x jar” as it otherwise insisted on rebuilding everything.

I put the jar and pom.xml under build/libs and build/publish-generated-resources

However this broke in numerous ways. First it insisted on always replacing the jar with an empty one, hence the “-x jar” to fix this. It however does the same for the pom.xml and I have not yet found a way to fix this.

Additionally, the plugin jar is dependent on other jars present in our own Maven repo, which must somehow be found. It would be great if Gradle could pick up a list of additional repos required for resolving a plugin’s dependencies.

Finally the publishing plugin always expects a source and javadoc jar, which we had to replace by empty ones as this is not van OSS plugin.

How would you recommend tackling these issues? Is the publishing plugin available publicly somewhere (ex. GitHub)?

Also please remove the current version published on the Portal as it causes Gradle to break with “Could not generate a proxy class for class com.boxfuse.client.gradle.task.CreateTask” as it misses dependencies referenced in the pom.xml that got overwritten.

I’m pretty sure this is the source code for the plugin.

Anyone at Gradleware have any idea how to resolve this?

Hi @boxfuse

Here’s an example build file that downloads a jar from a different repo and uploads it as a plugin.

The key parts are clearing out the default archives artifacts and adding the downloaded file.

This will work if your S3 bucket is set up as a maven compatible repo. If not, you’ll need to download the file in some other way and replace:

artifacts {
    // add downloaded jar to the archives configuration set of artifacts
    archives configurations.downloaded.resolve()[0]
}

with

artifacts {
    // add downloaded jar to the archives configuration set of artifacts
    archives new File("path/to/downloaded/file/here.jar")
}

and rip out the downloaded configuration stuff. How you download the jar will depend on how your S3 bucket and credentials are set up, but I’ll presume you can get the jar onto the local file system somehow.

I’d keep this build in a separate project, or a separate sub-project to the one that builds the jar, since we’re messing with the archives configuration here.

Hope that helps

Do you still need the existing plugin deleted?

Regards

Tom

Hi Tom,

yes as it ignored the pom.xml I supplied and therefore will not find a dependent jar not present in Maven Central. How can I have a plugin depend on such a jar and still work when used from the plugin portal?

Our current solution is to ask our users to add this to their build:

buildscript {
    repositories {
        // https is disabled until https://issues.gradle.org/browse/GRADLE-3250 is fixed
        maven { url 'http://files.boxfuse.com' }
    }
    dependencies {
        classpath "com.boxfuse.client:boxfuse-gradle-plugin:1.10.2.709"
    }
}

apply plugin: 'boxfuse'

boxfuse {
    user='your-boxfuse-client-user'
    secret='your-boxfuse-client-secret'
}

We would however really like to direct our users to the plugin portal. Is there a way to automatically add that additional repo and the dependency?

Thanks

Yes.

It’s not documented right now as it may be subject to change in the future, but there is a way to modify the dependencies that your plugin uses. The pluginBundle block has a withDependencies closure that you can use to modify the dependencies:

pluginBundle {
    // etc
    withDependencies { dependencies ->
        dependencies.add(new Dependency(groupId: 'foo', artifactId: 'bar', version: '12.3', classifier: 'etc'))
    }
}

It will be passed a List of org.apache.maven.model.Dependency. Exactly what gets passed in here is what may change in the future. But for the time being, you can add a new dependency to the list or remove dependencies that you don’t want in there in this closure.

You can’t add the repo automatically though, as we can’t modify end users’ repos to third party ones - this is a security risk.

Hope that solves the problem

Tom

Thank you Tom. Is there then a way to also upload the dependent jar to the portal?

Not really. We’re not intending to be a general purpose repo, so the expectation is that external dependencies for plugins would be published in the normal way wherever those dependencies live.

If you can’t publish the dependency somewhere like Bintray or Maven Central, or if the dependency itself is tied to the plugin quite closely, you could bundle the dependency into the plugin jar. This would look something like:

jar {
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}

Please ensure that you only bundle your own dependency and not any common ones published to public repositories.

Hi Tom,

Your solution for withDependencies seems to have a problem and results in “You cannot create an instance from the abstract interface ‘org.gradle.api.artifacts.Dependency’”. Which class should I use instead?

Also is there a way to perform a dry run to ensure the results are good before uploading?

Could you also please delete all existing versions of the Boxfuse plugin as all are broken so far until a correct one is uploaded?

Thanks

It’s org.apache.maven.model.Dependency

Not really. This is definitely something we’d like to improve in the future.

I’ve deleted the versions that were there.

Cheers

Tom

Thank you Tom.

Two new issues appeared:

  1. I got Artifact [group: gradle.plugin.com.boxfuse.client, artifactId: client,version: 1.11.0.713, classifier: None, extension: pom] has already been published -> Can you please also delete the previously uploaded poms?
  2. I got “Could not find method archives() for arguments ...” and had to add apply plugin: 'maven' -> Is that the correct way to fix this? (BTW, the example you linked has this issue too)

Thanks

This is a bit involved as we usually don’t allow overwriting of existing artifacts for security reasons. Can you just bump the version number?

archives is brought in by the java plugin, so you’ll need to apply that. It’s normally assumed that the java plugin will be applied in a Gradle plugin project.

Thank you very much Tom. The latest version is now working.

Two issues remain:

  1. How can I also publish a JavaDoc jar?
  2. The description and the tags are not updated with new versions. This is unfortunate as we would like to evolve these over time as features get added. Is there a way to force this? If not, could you do it manually for the current version (apply tags & description of 1.11.2 to plugin in general)?

Thanks

Hi Tom or anyone at Gradleware,

any idea how to solve these two issues?

Thanks

Anyone at Gradle knows how to solve this? Or can you confirm that this isn’t possible?

Thanks!