如何使用1.0+版本将我的插件发布到插件门户?

注意:如果您正在使用旧版(0.X)的插件,请切换到本页面的旧版版本页面

注意:如果您正在使用插件的1.0.X版本,请更新到至少版本1.1.0,该版本包含关键的错误修复。

注意:如果您以前通过Bintray发布了Gradle插件,请阅读此信息

注意:在发布插件之前,请确保您同意使用条款

门户设置

创建一个账户。

您可以通过注册页面快速轻松地创建新账户。

您可以使用相同的账户发布尽可能多的插件。

创建一个API密钥。

登录后,您可以通过个人资料页面的“API密钥”选项卡获取您的API密钥。

您可以使用相同的API密钥发布尽可能多的插件。

本地设置

创建API密钥后,您个人资料页面的“API密钥”选项卡将提供一个代码片段,您可以将其复制并将其粘贴到您的Gradle用户属性文件中。

Gradle用户属性文件的默认位置是 $USER_HOME/.gradle/gradle.properties,其中$USER_HOME指您的用户主目录。

注意:还有一个实验性任务“login”,它是插件发布插件的组成部分,可自动执行此步骤。

或者,您可以通过GRADLE_PUBLISH_KEYGRADLE_PUBLISH_SECRET环境变量提供API密钥。

此方法可能对CI/CD管道有用。

发布

插件发布插件提供了将您的插件上传到插件门户的任务。它还可以用于发布您插件的更新版本。此插件不是Gradle分发的组成部分,而是托管在插件门户上的。

配置后,您可以通过简单地运行插件构建的publishPlugins任务来发布您的插件。请参阅Gradle插件发布文档以获取详细说明。请注意,要选择与实际使用的 Gradle 版本匹配的版本,但不能早于v7.6(这是手册开始关注插件更现代版本的版本,即1.0或更高版本)。

辅助插件

插件开发插件

从版本1.0.0开始,插件开发插件成为插件发布插件的一个强制性组件,并且与它自动应用。有关它如何与 Maven 发布插件交互的更多信息(也被插件发布插件自动应用)可以在这里找到。

Maven 发布插件

从版本 1.0.0 开始,使用 插件发布插件 生成发布元数据(类似 Maven GAV 坐标,即组、组件、版本)的唯一支持方式是使用 Maven 发布插件。实际上,当应用 plugin-publish 插件时,会自动应用 maven-publish 插件。

同时存在 Maven 发布和插件开发插件(两者均为自动应用),会触发特定 Maven 发布的配置,这些发布将被推送到插件门户。有关更多信息,请参阅 此处

签署插件

从版本 1.0.0 开始,插件发布插件 可以自动对其发布到门户的工件进行签名。所有包含在 主 & 标记 Maven 发布 中的工件都将包含在内,不仅仅是 JAR 文件、POM 文件和 Gradle 模块元数据文件。此功能通过简单地应用 签名插件 启用。

影子插件

从版本 1.0.0 开始,插件发布插件 可以自动与已应用的 com.github.johnrengelman.shadow 插件 交互。它将自动发布由 shadowJar 任务生成的 JAR 文件,作为主工件。请注意,此交互需要使用 Gradle v6.0.1 或更高版本,才能正常工作。

重大变更

自版本 1.0.0 以来,插件发布插件 仅与 Gradle 4.10.3 或更高版本兼容(由于依赖 maven 发布)。

使 Maven 发布插件强制执行会触发以下 API 更改

  • mavenCoordinates 块不再定义,无法用于覆盖发布 GAV 坐标。坐标总是基于 Maven 发布的 GAV(默认为 Project 的组、名称和版本)。
  • withDependencies 块不再定义;所有依赖项都来自 Java 组件,以及我们定义 Java 库依赖项的方式。

示例

插件发布插件 v1.0.0 通过合并 pluginBundle 块到 gradlePlugin 中简化了插件发布的配置。

然而,这些简化需要 Gradle API 的支持,因此仅在使用 Gradle v7.6 或更高版本的插件发布插件时才可用。

build.gradle.kts

// First, apply the publishing plugin
plugins {
  // Apply the Plugin Publish plugin to make plugin publication possible
  // The Plugin Publish plugin will in turn auto-apply the Gradle Plugin Development Plugin (java-gradle-plugin)
  // and the Maven Publish plugin (maven-publish)
  id("com.gradle.plugin-publish") version "1.2.1"

  // Apply the signing plugin (signing) if you want the published artifacts of your plugin be automatically signed.

  // Apply the shadow plugin (com.github.johnrengelman.shadow) if you want to automatically make the main jar
  // of your plugin be a fat one, shadowing its dependencies.

  // Apply more plugins, if needed, for example the kotlin plugin for a plugin written in Kotlin
  // or the groovy plugin if the plugin uses Groovy.
}

// If your plugin has any external dependencies, users might need to declare repositories in their
// build settings so that Gradle can download them when using the plugins DSL.
repositories {
  mavenCentral()
}

// The project version will be used as your plugin version when publishing.
version = "1.2"
group = "io.github.johndoe"

// Use java-gradle-plugin to generate plugin descriptors and specify both global and individual plugin properties.
// The names of the blocks inside "plugins" need to be unique, they will identify the plugins being configured.
// All properties are mandatory.
gradlePlugin {
  website.set("https://github.com/johndoe/GradlePlugins")
  vcsUrl.set("https://github.com/johndoe/GradlePlugins")
  plugins {
    create("greetingsPlugin") {
      id = "io.github.johndoe.greeting"
      implementationClass = "io.github.johndoe.gradle.GreetingPlugin"
      displayName = "Gradle Greeting plugin"
      description = "Gradle plugin to say hello!"
      tags.set(listOf("search", "tags", "for", "your", "hello", "plugin"))
    }
    create("goodbyePlugin") {
      id = "io.github.johndoe.goodbye"
      implementationClass = "io.github.johndoe.gradle.GoodbyePlugin"
      displayName = "Gradle Goodbye plugin"
      description = "Gradle plugin to say goodbye!"
      tags.set(listOf("search", "tags", "for", "your", "goodbye", "plugin"))
    }
  }
}

build.gradle

// First, apply the publishing plugin
plugins {
  // Apply the Plugin Publish plugin to make plugin publication possible.
  // The Plugin Publish plugin will in turn auto-apply the Gradle Plugin Development Plugin (java-gradle-plugin)
  // and the Maven Publish plugin (maven-publish).
  id 'com.gradle.plugin-publish' version '1.2.1'

  // Apply the signing plugin (signing) if you want the published artifacts of your plugin be automatically signed.

  // Apply the shadow plugin (com.github.johnrengelman.shadow) if you want to automatically make the main jar
  // of your plugin be a fat one, shadowing its dependencies.

  // Apply more plugins, if needed, for example the kotlin plugin for a plugin written in Kotlin
  // or the groovy plugin if the plugin uses Groovy.
}

// If your plugin has any external dependencies, users might need to declare repositories in their
// build settings so that Gradle can download them when using the plugins DSL.
repositories {
  mavenCentral()
}

// The project version will be used as your plugin version when publishing.
version = '1.2'
group = 'io.github.johndoe'

// Use java-gradle-plugin to generate plugin descriptors and specify both global and individual plugin properties.
// The names of the blocks inside 'plugins' need to be unique, they will identify the plugins being configured.
// All properties are mandatory.
gradlePlugin {
  website = 'https://github.com/johndoe/GradlePlugins'
  vcsUrl = 'https://github.com/johndoe/GradlePlugins'
  plugins {
    greetingsPlugin {
      id = 'io.github.johndoe.greeting'
      implementationClass = 'io.github.johndoe.gradle.GreetingPlugin'
      displayName = 'Gradle Greeting plugin'
      description = 'Gradle plugin to say hello!'
      tags.set(['search', 'tags', 'for', 'your', 'hello', 'plugin'])
    }
    goodbyePlugin {
      id = 'io.github.johndoe.goodbye'
      implementationClass = 'io.github.johndoe.gradle.GoodbyePlugin'
      displayName = 'Gradle Goodbye plugin'
      description = 'Gradle plugin to say goodbye!'
      tags.set(['search', 'tags', 'for', 'your', 'goodby', 'plugin'])
    }
  }
}

批准

当发布一个新插件时,它将经历一个手动审查过程。这通常只发生在初始版本中。当发布时,插件发布插件会告诉你你的插件是否处于待批准状态。

注意:任何 Maven 组或插件 ID 的更改都将再次触发手动审批流程。

Gradle 工程师将检查元数据并决定是否在门户上公布它或要求对其进行更改。如果您的插件在可以接受之前需要更改,将通过与您帐户关联的电子邮件地址联系您。当您的插件被接受时,您也会收到一封电子邮件。

所有插件都必须遵守以下规则

插件必须有一些功能

“Hello world” 类型的提交或任何其他没有一些基本有用功能的插件将被拒绝。

插件应该对广大用户有用

针对特定用例或公司的插件将被拒绝。如果适用,请考虑将其发布到私有 Maven 或 Ivy 仓库。

插件应该有文档

应该有一个指定插件意图的 description

标签应设置用于描述插件覆盖的类别。

项目URL应指向英语文档、项目源代码,或两者都有。

VCL URL应指向插入脚本源代码。理想情况下,插件应该是开源的,除非有充分的理由不这么做。私有插件作者应该与我们联系

插件标识符应能追溯到作者。

组和工件必须合理地代表组织、个人和插件。

如果GitHub用户johndoe发布了一个名为myplugin的插件,那么一个可接受的插件标识符将是io.github.johndoe.myplugin

注意:为了与Maven Central策略一致,com.github不再被接受作为前缀。

另一个例子是一个企业插件,假设来自mybusiness.com;那么插件的标识符应类似于com.mybusiness.pluginname。在这种情况下,作者还应通过企业帐户/电子邮件地址提交插件。我们更倾向于使用团体(而不是个人)地址,以突出组织(或其下属的一个小组)是该插件的所有者。

如果我们无法链接到域名,我们将要求提供证据,以在DNS条目中添加TXT记录的形式。

插件ID和组ID应共享相同的顶级命名空间。

我们要求插件在其ID和组坐标中有一个共有前缀。

应仅发布最终版本。

我们将拒绝SNAPSHOT版本,因为它们无法被覆盖。

插件应从非分叉仓库发布。

门户网站上不应该发布同一插件的多个变体。插件开发者应努力与原始作者一起将他们的更改/改进集成。某些例外是可以接受的,例如,当原始存储库被遗弃,且不接受贡献时。

插件应遵守Gradle行为准则。

请参阅我们的行为准则

故障排除

发布失败

这里描述的问题发生在插件发布过程中,通常会导致发布过程失败。

GitHub组ID前缀不能是com.github

Github在2013年推出了针对其页面服务的新、专用域名(github.io)(见此处)。今年,他们停止了从旧、传统的域名(github.com)自动转发到新域名。

Maven Central随后宣布他们将做出反应,并将不再允许com.github作为有效的组ID前缀(见此处)。

Gradle插件门户网站也已采用此惯例,因此请在插件配置中使用io.github前缀。

插件版本不能是SNAPSHOT

插件门户网站不允许发布以SNAPSHOT结尾的插件,因为这些插件的行为可能不会如预期所示。所有版本都被认为是一致的,因此同一版本的重新发布是不可能的,因此快照的概念将变得毫无意义。

请使用固定版本。

拒绝批准

这里描述的问题发生在发布插件第一个版本成功之后,如果插件被门户网站管理员标记为手动批准,并且他们因各种原因拒绝了插件,他们将会发送一封包含拒绝原因的电子邮件。

无法建立所有权

这个问题的一个典型场景是当从GitHub(或类似平台)发布插件时,但GitHub帐户无法与发布插件的插件门户网站帐户链接。解决方案是使用与GitHub帐户链接的插件门户网站帐户(您可以通过GitHub帐户登录插件门户网站),或将支撑您插件门户网站帐户的电子邮件地址在GitHub帐户上公开可见。

另一种典型情况是当一个组织的插件正在发布时,但发布插件门户账户无法与组织关联。在这种情况下,您可能需要通过向组织的域名主机添加一些随机的TXT DNS记录来证明对组织域的所有权。门户管理员会联系您并提供确切的记录。

插件基于分支存储库

从分支、可能分歧的存储库发布的同一插件的不同变体可能导致很多困惑,因此通常不鼓励这样做。如果您发现自己处于这种情况,我们鼓励您将您的贡献作为拉取请求提交到原始存储库。

此规则的例外是已废弃的存储库,确实在选择分叉和拥有所有权时是唯一的选择。

插件缺少公共文档

这种情况通常出现在插件发布期间提供的网站或VCS URL指向一个损坏的或不可以访问的目标时。另一个例子是URL指向,例如,一个公开的GitHub存储库,但没有文档(空README文件)或没有文档是英文的。

缺乏文档的问题在于它使得社区采用该插件的可能性非常低。

解决这个问题的方法是制作公开可用的文档,或者如果您确实拥有私有插件,考虑将其发布到私有工件存储库。

您完成了!

您的插件现在已是Gradle插件门户的一部分,并可被全世界的Gradle用户使用。

感谢您的贡献。