Kotlin Multiplatform Development Help

将你的库发布到 Maven Central – 教程

在本教程中,你将学习如何将 Kotlin Multiplatform 库发布到 Maven Central 仓库。

发布库需要完成以下步骤:

  1. 设置凭证,包括 Maven Central 账户和用于签名的 PGP 密钥。

  2. 在库项目中配置发布插件。

  3. 向发布插件提供凭证,以便对构件进行签名和上传。

  4. 在本地或通过持续集成运行发布任务。

本教程假设你:

  • 正在创建一个开源库。

  • 将库代码存储在 GitHub 仓库中。

  • 使用 macOS 或 Linux。如果是 Windows 用户,请使用 GnuPG 或 Gpg4win 生成密钥对。

  • 尚未在 Maven Central 注册,或拥有适合发布到 Central Portal 的现有账户(创建于 2024 年 3 月 12 日之后,或已通过支持迁移到 Central Portal)。

  • 使用 GitHub Actions 进行持续集成。

示例库

在本教程中,你将使用 fibonacci 库作为示例。你可以参考该仓库的代码来了解发布设置的工作原理。

如果你想重用代码, 必须将所有示例值替换为项目特定的值。

准备账户和凭证

要开始向 Maven Central 发布,请在 Maven Central 门户登录(或创建新账户)。

选择并验证命名空间

你需要一个已验证的命名空间来唯一标识 Maven Central 上的库构件。

Maven 构件由其坐标标识,例如 com.example:fibonacci-library:1.0.0 。这些坐标由三部分组成,用冒号分隔:

  • groupId 采用反向 DNS 形式,例如 com.example

  • artifactId :库本身的唯一名称,例如 fibonacci-library

  • version :版本字符串,例如 1.0.0 。版本可以是任何字符串,但不能以 -SNAPSHOT 结尾

你注册的命名空间允许你为 Maven Central 上的 groupId 设置格式。例如,如果你注册了 com.example 命名空间,可以发布 groupId 设置为 com.examplecom.example.librarynamecom.example.module.feature 等的构件。

登录 Maven Central 后,导航到 Namespaces 页面。然后点击 Add Namespace 按钮并注册你的命名空间:

如果你没有域名,使用 GitHub 账户创建命名空间是一个不错的选择:

  1. 输入 io.github.<你的用户名> 作为命名空间,例如 io.github.kotlinhandson ,然后点击 Submit

  2. 复制新创建命名空间下显示的 Verification Key

  3. 在 GitHub 上,使用你注册的用户名登录,并创建一个新的公共仓库,仓库名称即为验证密钥,例如 http://github.com/kotlin-hands-on/ex4mpl3c0d

  4. 返回 Maven Central 并点击 Verify Namespace 按钮。验证成功后,你可以删除创建的仓库。

要使用你拥有的域名作为命名空间:

  1. 以反向 DNS 形式输入你的域名作为命名空间。如果你的域名是 example.com ,则输入 com.example

  2. 复制显示的 Verification Key

  3. 创建一个新的 TXT DNS 记录,内容为验证密钥。

    有关如何在各种域名注册商中执行此操作的更多信息,请参阅 Maven Central 的 FAQ

  4. 返回 Maven Central 并点击 Verify Namespace 按钮。验证成功后,你可以删除创建的 TXT 记录。

生成密钥对

在向 Maven Central 发布内容之前,你需要使用 PGP 签名对构件进行签名,以便用户可以验证构件的来源。

要开始签名,你需要生成一个密钥对:

  • 私钥 用于签名你的构件,绝不应与他人共享。

  • 公钥 可以与他人共享,以便他们验证你的构件签名。

GnuPG 网站提供了可以为你管理签名的 gpg 工具。你也可以使用 Homebrew 等包管理器安装它:

brew install gpg
  1. 使用以下命令开始生成密钥对,并在提示时提供所需信息:

    gpg --full-generate-key
  2. 选择推荐的默认密钥类型。你可以留空并按 Enter 接受默认值。

    请选择要生成的密钥类型: (1) RSA 和 RSA (2) DSA 和 Elgamal (3) DSA(仅签名) (4) RSA(仅签名) (9) ECC(签名和加密)*默认* (10) ECC(仅签名) (14) 从卡中导入现有密钥 你的选择?9 请选择椭圆曲线: (1) Curve 25519 *默认* (4) NIST P-384 (6) Brainpool P-256 你的选择?1

  3. 当提示指定密钥的有效期时,你可以选择默认的无过期日期选项。

    如果你选择创建一个在一段时间后自动过期的密钥,你需要在它过期时延长其有效期

    请指定密钥的有效期。 0 = 密钥永不过期 <n> = 密钥在 n 天后过期 <n>w = 密钥在 n 周后过期 <n>m = 密钥在 n 个月后过期 <n>y = 密钥在 n 年后过期 密钥的有效期是?(0) 0 密钥永不过期 确认吗?(y/N) y
  4. 输入你的姓名、电子邮件和可选注释以将密钥与身份关联(你可以将注释字段留空):

    GnuPG 需要构造一个用户 ID 来标识你的密钥。 真实姓名:Jane Doe 电子邮件地址:janedoe@example.com 注释: 你选择的 USER-ID: "Jane Doe <janedoe@example.com>"
  5. 输入一个密码短语来加密密钥,并在提示时重复。

    请安全且私密地保存此密码短语。稍后你需要用它来访问私钥以签名构件。

  6. 使用以下命令查看你创建的密钥:

    gpg --list-keys

输出将类似于以下内容:

pub ed25519 2024-10-06 [SC] F175482952A225BFD4A07A713EE6B5F76620B385CE uid [ultimate] Jane Doe <janedoe@example.com> sub cv25519 2024-10-06 [E]

在接下来的步骤中,你需要使用输出中显示的密钥的长字母数字标识符。

上传公钥

你需要将公钥上传到密钥服务器以便 Maven Central 接受它。有多个可用的密钥服务器,我们使用 keyserver.ubuntu.com 作为默认选择。

运行以下命令使用 gpg 上传你的公钥, 替换为你自己的密钥 ID

gpg --keyserver keyserver.ubuntu.com --send-keys F175482952A225BFC4A07A715EE6B5F76620B385CE

导出私钥

为了让你的 Gradle 项目访问私钥,你需要将其导出到文件。系统会提示你输入创建密钥时使用的密码短语。

使用以下命令, 传入你自己的密钥 ID 作为参数:

gpg --armor --export-secret-keys F175482952A225BFC4A07A715EE6B5F76620B385CE > key.gpg

此命令将创建一个包含私钥的 key.gpg 文件。

如果你查看 .gpg 文件的内容,应该会看到类似以下的文本:

-----BEGIN PGP PRIVATE KEY BLOCK----- lQdGBGby2X4BEACvFj7cxScsaBpjty40ehgB6xRmt8ayt+zmgB8p+z8njF7m2XiN ... bpD/h7ZI7FC0Db2uCU4CYdZoQVl0MNNC1Yr56Pa68qucadJhY0sFNiB23KrBUoiO -----END PGP PRIVATE KEY BLOCK-----

配置项目

准备库项目

如果你从模板项目开始开发库,现在是更改项目中所有默认名称以匹配你的库名称的好时机。这包括库模块的名称和顶层 build.gradle.kts 文件中根项目的名称。

如果你的项目中有 Android 目标,你应该遵循准备 Android 库发布的步骤 。至少,此过程要求你为库指定适当的命名空间 ,以便在编译资源时生成唯一的 R 类。请注意,此命名空间与之前创建的 Maven 命名空间不同。

// build.gradle.kts android { namespace = "io.github.kotlinhandson.fibonacci" }

设置发布插件

本教程使用 vanniktech/gradle-maven-publish-plugin 来帮助发布到 Maven Central。你可以在此处阅读有关该插件优势的更多信息。有关其用法和可用配置选项的更多信息,请参阅插件文档

要将插件添加到项目中,请将以下行添加到库模块的 build.gradle.kts 文件的 plugins {} 块中:

// <module directory>/build.gradle.kts plugins { id("com.vanniktech.maven.publish") version "0.30.0" }

在同一文件中,添加以下配置,确保为你的库自定义所有值:

// <module directory>/build.gradle.kts mavenPublishing { publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL) signAllPublications() coordinates(group.toString(), "fibonacci", version.toString()) pom { name = "Fibonacci library" description = "A mathematics calculation library." inceptionYear = "2024" url = "https://github.com/kotlin-hands-on/fibonacci/" licenses { license { name = "The Apache License, Version 2.0" url = "https://www.apache.org/licenses/LICENSE-2.0.txt" distribution = "https://www.apache.org/licenses/LICENSE-2.0.txt" } } developers { developer { id = "kotlin-hands-on" name = "Kotlin Developer Advocate" url = "https://github.com/kotlin-hands-on/" } } scm { url = "https://github.com/kotlin-hands-on/fibonacci/" connection = "scm:git:git://github.com/kotlin-hands-on/fibonacci.git" developerConnection = "scm:git:ssh://git@github.com/kotlin-hands-on/fibonacci.git" } } }

这里最重要的设置是:

使用持续集成发布到 Maven Central

生成用户令牌

你需要一个 Maven 访问令牌来授权 Maven Central 的发布请求。打开 Setup Token-Based Authentication 页面并点击 Generate User Token 按钮。

输出类似于以下示例,包含用户名和密码。如果你丢失了这些凭证,以后需要生成新的,因为它们不会由 Maven Central 存储。

<server> <id>${server}</id> <username>l2nfaPmz</username> <password>gh9jT9XfnGtUngWTZwTu/8141keYdmQpipqLPRKeDLTh</password> </server>

向 GitHub 添加密钥

要在 GitHub Action 工作流中使用发布所需的密钥和凭证,同时保持其私密性,你需要将这些值存储为密钥。

  1. 在你的 GitHub 仓库 Settings 页面,点击 Security | Secrets and variables | Actions

  2. 点击 New repository secret 按钮并添加以下密钥:

    • MAVEN_CENTRAL_USERNAMEMAVEN_CENTRAL_PASSWORD 是 Central Portal 网站为用户令牌生成的值。

    • SIGNING_KEY_ID 是你的签名密钥标识符的最后 8 个字符 ,例如 F175482952A225BFC4A07A715EE6B5F76620B385CE20B385CE

    • SIGNING_PASSWORD 是你生成 GPG 密钥时提供的密码短语。

    • GPG_KEY_CONTENTS 应包含你的 key.gpg 文件的全部内容。

    向 GitHub 添加密钥

你将在下一步的 CI 配置中使用这些密钥的名称。

向项目添加 GitHub Actions 工作流

你可以设置持续集成以自动构建和发布库。我们将以 GitHub Actions 为例。

首先,在仓库的 .github/workflows/publish.yml 文件中添加以下工作流:

# .github/workflows/publish.yml name: Publish on: release: types: [released, prereleased] jobs: publish: name: Release build and publish runs-on: macOS-latest steps: - name: Check out code uses: actions/checkout@v4 - name: Set up JDK 21 uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 21 - name: Publish to MavenCentral run: ./gradlew publishToMavenCentral --no-configuration-cache env: ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }} ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.SIGNING_KEY_ID }} ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_PASSWORD }} ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_KEY_CONTENTS }}

提交并推送此文件后,每当你在托管项目的 GitHub 仓库中创建发布(包括预发布)时,工作流将自动运行。工作流会检出当前版本的代码,设置 JDK,然后运行 publishToMavenCentral Gradle 任务。

使用 publishToMavenCentral 任务时,你仍然需要检查并在 Maven Central 网站上手动发布部署 。或者,你可以使用 publishAndReleaseToMavenCentral 任务完全自动化发布过程。

你还可以配置工作流以在推送标签到仓库时触发

此操作需要你的签名详细信息和 Maven Central 凭证,这些是你创建的仓库密钥

工作流配置会自动将这些密钥传输到环境变量中,使它们对 Gradle 构建过程可用。

在 GitHub 上创建发布

设置好工作流和密钥后,你现在可以创建发布来触发库的发布。

  1. 确保库的 build.gradle.kts 文件中指定的版本号是你想要发布的版本。

  2. 转到你的 GitHub 仓库主页。

  3. 在右侧边栏中,点击 Releases

  4. 点击 Draft a new release 按钮(或 Create a new release 按钮,如果你之前没有为此仓库创建过发布)。

  5. 每个发布都有一个标签。在标签下拉菜单中创建一个新标签,并设置发布标题(标签名称和标题可以相同)。

    你可能希望这些与你在 build.gradle.kts 文件中指定的库版本号相同。

    在 GitHub 上创建发布
  6. 仔细检查你要针对发布的目标分支(特别是如果它不是默认分支),并为新版本添加适当的发布说明。

  7. 使用描述下方的复选框将发布标记为预发布(适用于 alpha、beta 或 RC 等早期访问版本)。

    你还可以将发布标记为最新版本(如果你之前已经为此仓库创建过发布)。

  8. 点击 Publish release 按钮创建新发布。

  9. 点击 GitHub 仓库页面顶部的 Actions 选项卡。在这里,你会看到新发布触发了你的发布工作流。

    你可以点击工作流查看发布任务的输出。

  10. 工作流运行完成后,导航到 Maven Central 的 Deployments 仪表板。你应该会在这里看到一个新的部署。

    此部署可能会在 Maven Central 执行检查时保持 pendingvalidating 状态一段时间。

  11. 一旦你的部署处于 validated 状态,检查它是否包含你上传的所有构件。如果一切看起来正确,点击 Publish 按钮发布这些构件。

    发布设置

要在部署验证后自动发布构件,请在工作流中将 publishToMavenCentral 任务替换为 publishAndReleaseToMavenCentral

下一步

22 四月 2025