// Copyright (C) 2023 Gradle, Inc.
//
// Licensed under the Creative Commons Attribution-Noncommercial-ShareAlike 4.0 International License.;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

[[publishing_portal]]
= Publishing Plugins to the Gradle Plugin Portal
:portal: Gradle Plugin Portal
:plugin: Greeting Plugin
:publishplugin: Plugin Publishing Plugin
:plugin-reference-documentation: https://plugins.gradle.org/docs/publish-plugin[reference documentation of the {publishplugin}]

Publishing a plugin is the main way to make it available for others to use.
One approach is to publish the plugin to a private repository, which is common when you want to restrict who can use it.
But if you want the plugin to be available to anyone in the world, i.e. public, then you should publish it to the https://plugins.gradle.org[{portal}], a centralized, searchable repository dedicated to Gradle plugins.

This section will show you how to use the https://plugins.gradle.org/plugin/com.gradle.plugin-publish[{publishplugin}] to publish plugins to the {portal} using a convenient DSL.
Taking this approach eliminates a large number of configuration steps and provides a number of checks to validate that your plugin meets the criteria enforced by the {portal}.

== Start with an existing Gradle plugin project

You will need an existing plugin project for this tutorial.
If you don't have your own, you may use the link:../samples/sample_gradle_plugin.html[Greeting plugin sample].

Don't worry about cluttering up the {portal} with a trivial example plugin: trying to publish this plugin will safely fail with a permission error.

== Create an account on the {portal}

If you have never published a plugin to the {portal} before, you first need to create an account there.
This consists of three steps:

. Create an account
. Create an API key
. Add your API key to your Gradle configuration

Start by going to the https://plugins.gradle.org/user/register[registration page] — which looks like the image below – and creating an account.

.Registration page
image::plugin-portal-registration-page.png[]

Follow the instructions on that page.
Once you have logged in, you can get your API key via the "API Keys" tab of your profile page.

.API keys is the third tab
image::plugin-portal-api-keys.png[]

It is common practice to copy and paste the text into your <<build_environment.adoc#sec:gradle_configuration_properties,$HOME/.gradle/gradle.properties>> file, but you can also place it in any other valid location.
All that the plugin requires is that `gradle.publish.key` and `gradle.publish.secret` are available as project properties when the appropriate Plugin Portal tasks are executed.

If you are concerned about placing your credentials in `gradle.properties`, investigate use of
https://plugins.gradle.org/plugin/de.qaware.seu.as.code.credentials[Seauc Credentials plugin] or the
https://plugins.gradle.org/plugin/nu.studer.credentials[Gradle Credentials plugin].

Once you have the API key you can publish as many plugins as you like.

[[plugin-publishing-plugin]]
== Add the {publishplugin} to the project

Add the {publishplugin} to the `plugins` block.

====
include::sample[dir="snippets/developingPlugins/publishingPlugins/kotlin",files="build.gradle.kts[tags=plugins_block]"]
include::sample[dir="snippets/developingPlugins/publishingPlugins/groovy",files="build.gradle[tags=plugins_block]"]
====
The latest version of the {publishplugin} can be found on the https://plugins.gradle.org/plugin/com.gradle.plugin-publish[{portal}].

NOTE: Since version 1.0.0 the Plugin Publish Plugin automatically applies the
<<java_gradle_plugin.adoc#java_gradle_plugin,Java Gradle Plugin Development Plugin>> (assists with developing Gradle plugins) and the
<<publishing_maven.adoc#publishing_maven, Maven Publish Plugin>> (generates plugin publication metadata).
If using older versions of the Plugin Publish Plugin, these helper plugins need to be applied explicitly.

[[configure_the_plugin_publishing_plugin]]
== Configure the {publishplugin}

The first thing to do when configuring the publication of your plugins is to specify the common properties that apply to all of them.
This includes their identity plus the sources and documentation related to them.
This will help people browsing the portal find more information about your plugins and learn how to contribute to their development.

====
include::sample[dir="snippets/developingPlugins/publishingPlugins/kotlin",files="build.gradle.kts[tags=global_config]"]
include::sample[dir="snippets/developingPlugins/publishingPlugins/groovy",files="build.gradle[tags=global_config]"]
====
<1> Make sure your project has a `group` set which is used to identify the artifacts (jar and metadata) you publish for your plugins
in the repository of the {portal} and which is descriptive of the plugin author or the organization the plugins belong too.
<2> Set the version of your project, which will also be used as the version of your plugins.
<3> Use the `gradlePlugin` block provided by the <<java_gradle_plugin.adoc#java_gradle_plugin,Java Gradle Plugin Development Plugin>>
to configure further options of your plugin publication.
<4> Set the website for your plugin's project.
<5> Provide the source repository URI so that others can find it, if they want to contribute.
<6> Set specific properties for each of the plugins you want to publish; see next section.

Next you need to define the specific plugins you intend to publish.
Their most important property is their `id`, as that both uniquely identifies plugins on the {portal} and prevents namespace clashes between different plugin authors.

NOTE: If you would like to associate your plugin with a particular organization, you also set the ID based on that organization’s domain using the reverse-domain pattern used for Java packages, for example `org.example.greeting`.
If the plugin doesn't belong to any specific organization, then the plugin ID should be associated with the author, for example by using the author's GitHub ID in a reverse domain pattern, like `io.github.johndoe`.
Remember that the plugin id and project group should match, i.e. have the same top level namespace.

====
include::sample[dir="snippets/developingPlugins/publishingPlugins/kotlin",files="build.gradle.kts[tags=per_plugin_config]"]
include::sample[dir="snippets/developingPlugins/publishingPlugins/groovy",files="build.gradle[tags=per_plugin_config]"]
====
<1> Plugin specific configuration also goes into the `gradlePlugin` block.
<2> This is where we previously added global properties.
<3> Each plugin you publish will have its own block inside `plugins`.
<4> The name of a plugin block needs to be unique for each plugin you are publishing; this is a property used only locally by your build and will not be part of the publication.
<5> Set the unique `id` of the plugin, as it will be identified in the publication.
<6> Set the plugin name in human-readable form.
<7> Set a description to be displayed on the portal. It provides useful information to people who might want to use your plugin.
<8> Specifies the categories your plugin covers. Makes the plugin more likely to be discovered by people needing its functionality.


As an example consider the configuration for the https://plugins.gradle.org/plugin/org.ysb33r.gradletest[GradleTest plugin], which is already published to the {portal}.

====
include::sample[dir="snippets/developingPlugins/publishingPlugins/kotlin",files="build.gradle.kts[tags=plugin_example]"]
include::sample[dir="snippets/developingPlugins/publishingPlugins/groovy",files="build.gradle[tags=plugin_example]"]
====

If you browse the associated page on the {portal} for the https://plugins.gradle.org/plugin/org.ysb33r.gradletest[GradleTest plugin], you will see how the specified metadata is displayed.

.GradleTest plugin metadata on the {portal}
image::plugin-portal-plugin-page.png[]

=== Sources & Javadoc ===

The Plugin Publish Plugin automatically generates and publishes the <<building_java_projects.adoc#sec:java_packaging,Javadoc and sources JARs>> for your plugin publication.

=== Sign artifacts ===

Starting from version 1.0.0 of Plugin Publish Plugin, signing of published plugin artifacts has been made automatic.
To enable it, all that's needed is to apply the <<signing_plugin.adoc#signing_plugin,`signing`>> plugin in your build.

=== Shadow dependencies ===

Starting from version 1.0.0 of Plugin Publish Plugin, shadowing the dependencies of your plugin (ie. publishing it as a fat jar) has been made automatic.
To enable it, all that's needed is to apply the https://github.com/johnrengelman/shadow[`com.github.johnrengelman.shadow`] plugin in your build.

[[custom-plugin-repositories]]
== Publish your plugin to a local repository

To check how the artifacts of your published plugin look, or to use it only locally or internal in your company, you can publish it to any maven repository, including a local folder.
For that, you only need to <<publishing_maven.adoc#publishing_maven:repositories,configure repositories for publishing>>.
Then you can run the `publish` task to publish your plugin to all repositories you have defined (but not the {portal}).

====
include::sample[dir="snippets/developingPlugins/publishingPlugins/kotlin",files="build.gradle.kts[tags=local_repository]"]
include::sample[dir="snippets/developingPlugins/publishingPlugins/groovy",files="build.gradle[tags=local_repository]"]
====

To use the repository in another build, you have to add it to <<plugins.adoc#sec:custom_plugin_repositories,the repositories of the `pluginManagement {}` block>> in your `settings.gradle(.kts)` file.

== Publish your plugin to the Plugin Portal

Publish the plugin by using the `publishPlugin` task.

[listing]
----
$ ./gradlew publishPlugins
----

You can validate your plugins before actually publishing them using the `--validate-only` flag:

[listing]
----
$ ./gradlew publishPlugins --validate-only
----


If you have not configured your {portal} key and secret values in your `gradle.properties` file, you can specify them on the command-line

[listing]
----
$ ./gradlew publishPlugins -Pgradle.publish.key=<key> -Pgradle.publish.secret=<secret>
----

NOTE: If you attempt to publish the example Greeting Plugin with the ID used in this section, you will encounter a permission failure.
That's expected and ensures that the portal won't be overrun with multiple experimental and duplicate greeting-type plugins.


[[consume]]
== Consume the published plugin

Once you successfully publish a plugin it won't immediately appear on the Portal.
It also needs to pass an approval process, which is manual and relatively slow for the initial version of your plugin, but is fully automatic for subsequent versions.
For further details see https://plugins.gradle.org/docs/publish-plugin-new#approval[here].

Once your plugin is approved, you'll be able to find instructions for its use at a URL of the form *+https://plugins.gradle.org/plugin/<your-plugin-id>+*.
For example, the Greeting Plugin example is already on the portal at https://plugins.gradle.org/plugin/org.example.greeting.
