Hand in hand with Android, release open source components to MavenCentral repository

I. Introduction

Sometimes, when we write a component and want to open source it to more people to share and use, we need to publish the open source component to a public remote warehouse, such as Jitpack, JenCenter, MavenCentral. Among them, MavenCentral is the most popular central repository and one of the default repositories used by Gradle. This article introduces how to publish your own open source components to the MavenCentral repository;

Explanation of two terms

2.1 What is POM?

POM (Project Object Model) refers to the project object model, which is used to describe the basic information of project components. A valid POM node mainly contains the following parameters:

parameter describe example
groupId Organization/Company Name io.github.lucasxu01
artifactId component name modular-networkviewer-plugin
version component version 0.0.1
packaging Format jar

2.2 What is a repository

Various third-party libraries that need to be relied on in the project are stored in a certain location, and this "location" is the warehouse. Using warehouses can help us manage project artifacts, such as jars, aars, and so on.

Mainstream build tools have a two-level warehouse concept:

  • 1. Local warehouse: There will be a directory in the local operating system to store dependent files downloaded from the central warehouse or remote warehouse;

  • 2. Remote warehouse: including central warehouse and private warehouse. The central warehouse is a warehouse provided by the open source community, where most open source libraries are stored. For example, Maven Central, the central warehouse of the Maven community ; a private warehouse is a custom warehouse of a company or organization, which can be understood as the storage location of the second-party library.

One-party library: the modules that depend on each other in this project;
two-party library: the internal dependency library of the company, generally referring to the jar package released by other projects within the company;
three-party library: the open source library outside the company, such as the dependencies released by apache, ibm, google, etc.;

2.3 Relationship between Sonatype, Nexus and Maven:

  • Sonatype: The full name is Sonatype OSSRH (OSS Repository Hosting). Sonatype is an open source DevOps service provider in the United States. It supports open source components (central warehouse), provides developers with a resource library manager (Nexus), and provides free central storage warehouse services for open source projects.
  • Nexus: The full name is Sonatype Nexus Repository Manager, which is another product of Sonatype that provides a warehouse manager. Sonatype provides a central warehouse based on Nexus, and companies can also use Nexus to build private warehouses;
  • Maven: The full name is Apache Maven, which is a build system. In addition to Maven, both Apache Ant and Gradle can publish components.

Three new Sonatype project

Publishing components to the central repository requires a Sonatype JIRA account.

3.1 Prepare Sonatype JIRA account

Enter the Sonatype dashboard interface, log in or register a new account: issues.sonatype.org :

3.2 Create a new work order

Click the "New" button in the upper right corner of the dashboard panel , and follow the steps below to submit a work order for a new project to Sonotype:

The filling method is summarized as follows:

  • Project: Use the default option Community Support - Open Source Project Repository Hosting (OSSRH);

  • Question Type: Use the default option New Project;

  • Summary: Fill in the same name as the Github warehouse for easy search;

  • GroupId Organization Name:

    Fill in the groupId used when publishing the component. In the next step, you will check whether you really own the groupId, so you can’t just fill it in. There are 2 ways to fill it in:

    • **Use Github account: ** io.github.[Github 用户名]Fill in the format of , and in the subsequent steps, Sonatype will do identity verification by asking us to create a temporary code library with a specified name in our personal Github warehouse;
    • Use a personal domain name: Fill in according to the format of the domain name in reverse order, for example, oss.sonotype.orgfill in if the personal domain name is org.sonotype.oss.
  • Project URL project address: fill in the Github project address, for example: https://github.com/lucasxu01/NetworkViewer;

  • SCM url version control address: add after the Github project address .git, for example https://github.com/lucasxu01/NetworkViewer.git.

2.3 Verify GroupId ownership

After creating a new project, click to enter the work order details page according to the prompt. The newly created work order has to wait for the reply from the Sonotype robot. After waiting for about ten minutes, the comment area at the bottom of the work order will tell us what to do next.

At this point, the Sonotype project is ready.

4 Create a new GPG key pair

GPG (GNU Privacy Guard) is an encryption software implemented based on the OpenPGP standard, which provides asymmetric encryption and signature verification functions for files. All files published to the Maven warehouse need to be GPG signed to verify the legitimacy of the file.

3.1 Install GPG software

Install the GPG software:

# 通过 Homebrew 安装 gpg
brew install gpg

Install brew: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
Verify the installation is successful: brew -v

3.2 Generating a GPG key pair

Use --generate-keythe parameter and fill in the relevant information and passphrase private key password according to the guidelines. In addition, use --list-keysthe parameter to view the keys generated in the current system.

# 密钥生成命令
gpg --generate-key

# 密钥查看命令
gpg --list-keys

When GPG generates a key pair, it will require developers to do some random actions to add enough perturbation to the random number, and the generation will be completed after a while. After completion, you can use —list-keysthe parameter to view the key pair information at any time.

To explain the information in it:

➜  ~ gpg --list-keys
/Users/a58/.gnupg/pubring.kbx
-----------------------------
pub   ed25519 2022-09-05 [SC] [有效至:2024-09-04]
      F740E820EFE033F*******************7F3C8
uid             [ 绝对 ] LucasXu <[email protected]>
sub   cv25519 2022-09-05 [E] [有效至:2024-09-04]

# pubring.kbx:本地存储公钥的文件
# 2022-09-05 [SC] [expires: 2024-09-04]:表示密钥对的创建时间和失效时间
# LucasXu <[email protected]>:用户名和邮箱
# ed25519:表示生成公钥的算法
# cv25519:表示生成私钥的算法
# F740E820EFE033F*******************7F3C8:密钥指纹 / KeyId

So far, you have generated a bunch of new key pairs locally, and now you have:

  • Key fingerprint/KeyId: The key fingerprint is the unique identifier of the key pair, that is, F740E820EFE033F*******************7F3C8the string above. Sometimes a shorter format can also be used, taking its last 8 characters, that is, ***7F3C8this string;
  • Public key: the public key corresponding to the key fingerprint;
  • Private key: the private key corresponding to the key fingerprint;
  • passphrase key password: the password entered when generating the key pair, the private key and the key password together constitute the private information of the key pair.

3.3 Delete key pair

Sometimes you need to delete the key pair, you can use the following command:

# 先删除私钥后,才能删除公钥
# 删除私钥
gpg --delete-secret-keys  [密钥指纹]
# 删除公钥
gpg --delete-keys  [密钥指纹]

3.4 Upload public key

The public key information in the key pair needs to be disclosed, so that others can get the public key to verify the data you signed. The public method is to upload it to the public key server. The public key server is a server dedicated to storing the user's public key, and will use the exchange mechanism to synchronize the data to other public key servers, so you only need to upload to one of the servers. I finally uploaded to hkp://keyserver.ubuntu.comthe server. The following servers can be tried:

  • pool.sks-keyservers.net
  • keys.openpgp.org
  • keyserver.ubuntu.com
  • pgp.mit.edu
// 上传公钥
gpg --keyserver 【服务器地址】:11371 --send-keys 【密钥指纹】
// 验证公钥
gpg --keyserver 【服务器地址】:11371 --recv-keys 【密钥指纹】
gpg --keyserver hkp://keyserver.ubuntu.com:11371 --send-keys F740E820EFE033F*******************7F3C8

3.5 Export key file

The key password and private key file are needed when publishing components later, and can be exported using the following parameters

# 默认导出到本地目录 /User/[用户名]/

# 导出公钥
gpg --export 【密钥指纹】 > xiaopeng_pub.gpg
# 导出私钥
gpg --export-secret-keys 【密钥指纹】 > xiaopeng_pri.gpg

Five configuration release script

With the Sonatype project and key pair ready, it's time to configure the project's Gradle script. Gradle provides two Maven plugins:

  • maven plugin: old release plugin, not available since Gradle 7.0;
  • maven-publish plugin: new release plugin.

It is recommended to use vanniktech's publishing plug-in. gradle-maven-publish-plugin is an open source Gradle plug-in by foreign tycoon vanniktech, which requires a Gradle environment of Gradle 7.2.0 or higher. It will create a publish Task that supports publishing Java, Kotlin or Android components to any Maven repository, and also supports publishing Javadoc products and Sources products that carry Java / Kotlin code. Currently (2022/09/26) the latest version of this project is 0.22.0, which has been verified on LeakCanary.

5.1 vanniktech plug-in environment configuration

The following are the configuration steps: build.gradleadd the plug-in address at the project level, and apply the plug-in in the module-level build.gradle:

project-level build.gradle

buildscript {
    
    
    repositories {
    
    
        mavenCentral()
    }
    dependencies {
    
    
        // vanniktech 发布插件
        classpath 'com.vanniktech:gradle-maven-publish-plugin:0.18.0'
        // Kotlin Javadoc,非必须
        classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.6.20"
    }
}

The latest version of build.gradle is written:

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    
    
    dependencies {
    
    
        // vanniktech 发布插件
        classpath 'com.vanniktech:gradle-maven-publish-plugin:0.18.0'
        // Kotlin Javadoc,非必须
        classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.6.20"
        //1、依赖抓包插件库
        classpath 'io.github.lucasxu01:modular-networkviewer-plugin:0.0.1'

    }
}

plugins {
    
    
    id 'com.android.application' version '7.3.0-beta01' apply false
    id 'com.android.library' version '7.3.0-beta01' apply false
    id 'org.jetbrains.kotlin.android' version '1.6.21' apply false
}

module-level build.gradle

apply plugin: "com.vanniktech.maven.publish"
// Kotlin Javadoc,非必须。如果有这个插件,发布时会生成 Javadoc,会延长发布时间。建议在 snapshot 阶段关闭
apply plugin: "org.jetbrains.dokka"

The latest version of build.gradle is written::

plugins {
    
    
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'monitor-plugin'
}

After the Sync project, the plugin will add two Task tasks to the module:

  • publish: publish to the remote Maven repository, the default is the Sonatype central repository;
  • publishToMavenLocal: Publish to the local Maven repository of the current machine, ie ~/.m2/repository.

Gradle panel:

  1. publish: publish to the remote maven repository;
  2. Publish to the local maven warehouse;

5.2 vanniktech plug-in release parameter configuration

Configure the following parameters at project level gradle.propertiesand module level respectively.gradle.properties

Item level gradle.properties:

######################################################################
# for vanniktech
######################################################################
# 服务器地址
SONATYPE_HOST=S01

# 发布 release 组件时是否签名
RELEASE_SIGNING_ENABLED=true

# 组织名
GROUP=io.github.lucasxu01

# 主页
POM_URL=https://github.com/LucasXu01/NetworkViewer/

# 版本控制信息
POM_SCM_URL=https://github.com/LucasXu01/NetworkViewer/
POM_SCM_CONNECTION=scm:git:git:github.com/LucasXu01/NetworkViewer.git
POM_SCM_DEV_CONNECTION=scm:git:ssh://[email protected]/LucasXu01/NetworkViewer.git

# Licenses 信息
POM_LICENSE_NAME=The Apache Software License, Version 2.0
POM_LICENSE_URL=https://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENSE_DIST=repo

# 开发者信息
POM_DEVELOPER_ID=LucasXu01
POM_DEVELOPER_NAME=LucasXu
POM_DEVELOPER_URL=https://github.com/LucasXu01/

mavenCentralUsername=[填 Sonatype 账号名]
mavenCentralPassword=[填 Sonatype 账号密码]

signing.keyId=[密钥指纹,取后 8 位即可, 如 E4F7F3C8]
signing.password=[passphrase 密钥口令]
signing.secretKeyRingFile=[导出的私钥文件路径,如 /Users/a58/lucas_pri.gpg]

In module level gradle.properties:

POM_NAME = network_viewer_plugin
POM_ARTIFACT_ID = modular-networkviewer-plugin
POM_PACKAGING = jar
POM_DESCRIPTION = The plugin used in NetworkViewer api
VERSION_NAME = 0.0.1

Special attention: Do not submit private information to git version management, you can write it in and local.propertiescopy it to when you want to release the component gradle.properties. And the private key file should not be saved in the directory of the current project, but can be placed in a directory outside the project.

At this point, all preparations are complete.


Six publish components to the MavenCentral repository

Finally all preparation and configuration is done! Before publishing, it is necessary to explain the warehouse address used in Sonatype:

6.1 Warehouse address

If you don't have a custom published Maven repository, the vanniktech plugin will by default be published to a central repository managed by Sonatype. For historical reasons, the Sonatype central warehouse has 2 domain names:

According to the official statement , oss.sonatype.org is obsolete and will be enabled from February 2021 s01.oss.sonatype.org/

6.2 Staging temporary storage library

Careful friends will find that the format of the official snapshot warehouse and the release warehouse are different. Why? ——This is because releasing the release component is a sensitive operation. Once the release version of the component is released to the central warehouse, the content of this version of the component can never be modified or deleted (this rule is for stability and reliability considerations. If it can be modified, those users who have downloaded the component locally will not get the latest content). So Sonatype adopts different strategies for publishing snapshot components and release components:

  • snapshot component: publish directly to the snapshot central warehouse;
  • Release component: Using the Staging temporary storage strategy, the release component needs to be published to the temporary storage library first, and after passing the test and verification, the developer will manually upgrade it to the release central warehouse.
中央 release 仓库:"https://s01.oss.sonatype.org/content/repositories/releases"
中央 snapshot 仓库:"https://s01.oss.sonatype.org/content/repositories/snapshots"
暂存库:"https://s01.oss.sonatype.org/service/local/staging/deploy/maven2"

img

6.3 Publish snapshot components

The version number with SNAPSHOT will be regarded as a snapshot component and will be directly released to the snapshot central warehouse. After the front-end is released, it can be searched in the snapshot central warehouse immediately.

6.4 Publish the release component to the Staging repository

The version number without SNAPSHOT will be regarded as a release component. After releasing the release component, enter the Nexus panel to view the temporary library (Log in in the upper right corner):

image-20220926004645033

6.5 Publish release components to the central warehouse

After confirming that you want to publish the component, click Close first, and then click Release to publish:

The Close process will verify the component, and if the verification fails, an error will be reported. You can view error messages directly from the Activity panel.

Click the Drop button to the right of Release to delete the problematic component:

6.6 View released release components

After successful publishing, there are 3 ways to view your own components:

  • Method 1 - View on the Sonatype Nexus panel:
  • Method 3 - Find in the MavenCentral search bar : This is the most official method, the disadvantage is that it is not updated in real time and there will be a delay, while the first two methods are updated immediately after release:

According to the official statement , the released components will be synchronized to the central warehouse within 30 minutes, but the search function needs to reach 4 hours.

Seven publish components to the local warehouse for testing

In 5.1, we can click in the gradle panel publishToMavenLocalto publish the plugin to the local for joint debugging and testing.

Click in the panel publishToMavenLocalto publish the plugin to the local maven warehouse first. The default address is generally:

/Users/a58/.m2/repository

settings.gradleConfiguration reference for the new version of NetworkViewer AS :

pluginManagement {
    
    
    repositories {
    
    
        gradlePluginPortal()
        google()
        mavenCentral()
        maven {
    
     url '/Users/a58/.m2/repository' }
    }
}
dependencyResolutionManagement {
    
    
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
    
    
        google()
        mavenCentral()
        maven {
    
     url '/Users/a58/.m2/repository' }
    }
}
rootProject.name = "NetworkViewer"
include ':app'
include ':okhttpplugin'
include ':netviewer'

After locally publishing and adding dependent warehouses, NetworkViewer project-level build.gradleconfiguration reference:

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    
    
    dependencies {
    
    
        // vanniktech 发布插件
        classpath 'com.vanniktech:gradle-maven-publish-plugin:0.18.0'
        // Kotlin Javadoc,非必须
        classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.6.20"
        //1、依赖抓包插件库
        classpath 'io.github.lucasxu01:modular-networkviewer-plugin:0.0.1'
    }
}

plugins {
    
    
    id 'com.android.application' version '7.3.0-beta01' apply false
    id 'com.android.library' version '7.3.0-beta01' apply false
    id 'org.jetbrains.kotlin.android' version '1.6.21' apply false
}

After adding the plugin in the app-level build.gradleconfiguration, it can be tested locally.

plugins {
    
    
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'monitor-plugin'
}

Eight dependent on published components

Note that it has been released to the release central warehouse, and your project only mavenCentral()needs to include this warehouse address.

repositories {
    // 中央仓库(不包含 snapshot 中央仓库)
    mavenCentral()
    // release 中央仓库
    maven { url 'https://s01.oss.sonatype.org/content/repositories/releases'}
    // snapshot 中央仓库
    maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots/'}
    // 暂存库,用于验证
    maven { url "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2"}		
}

For details, please refer to: NetViewer


Nine seek official help from Sonatype

If you encounter any problems in the process of using Sonatype, you can try to ask the official questions. Usually there is a reply within 10 minutes.


ten outlook

Github Action: At present, we can publish open source projects to the MavenCentral central warehouse. But each release requires us to manually perform the upload task, and the Releases panel in the Github repository will not display the manually released version records synchronously. The desired effect is that when a Release version is released on the Github repository, the release of the version to the MavenCentral central repository is automatically triggered. This requires the CI/CD service provided by Github - Github Action;

reference article

https://blog.csdn.net/hanly_jiang/article/details/123123111

https://juejin.cn/post/7135457823055413278

https://github.com/Leaking/Hunter/blob/master/docs/README_ch.md

Guess you like

Origin blog.csdn.net/LucasXu01/article/details/127049803