阅读 850

Jcenter 停止服务,我哭了 —— 说一说我们的迁移方案

在今年的 2 月 3 日,Jcenter 运营官方发布一则通告称:包括 GoCenter、Bintray、JCenter 在内的多项软件包管理和分发服务都将停止运营。

UPDATE: To better support the community in this migration, JFrog has extended the JCenter new package versions submission deadline through March 31st 2021.
 
To clarify, the JCenter repository will keep serving packages for 12 months until February 1st 2022. Only the JCenter REST API and UI will be sunsetted on May 1st 2021.
复制代码

原文链接如下:jfrog.com/blog/into-t…

对于 JFrog 停止运营 Jcenter 的原因我们不予置评。但是 Jcenter 仓库作为 Android 开发者使用最多的仓库,突然停止运营对于很多开发者和开源企业都带来很大的影响。同样我们神策 Android 系的 SDK 都是开源发布在 Jcenter 仓库上,所以我们内部也开始启动迁移方案的调研,在这个过程中,我们主要调研了三种备选方案:JitPack 仓库、公有 Maven 仓库和私有 Maven 仓库,最终我们采用发布到公有 Maven 仓库作为主选,发布到 JitPack 仓库作为备份应急,过渡阶段也会继续发布到 Jcenter。本篇文章主要介绍公有 Maven 和 JitPack 仓库的发布流程。

1. JitPack 仓库

JitPack 是一个基于 GitHub 开源仓库的发布仓库,它完美地与 GitHub 仓库兼容,使用 Jcenter 发布仓库时,我们需要在脚本中标注对应的 GroupId、Artifac 等信息,但是使用 JitPack 可以省去 Jcenter 发布过程中诸多繁琐的配置。下面介绍基于 JitPack 仓库发布的步骤。

1.1. 发布 GitHub Release

当我们的代码从本地分支推送到 GitHub 远程分支后,我们就可以发布一个版本的 Release。 在仓库的 Release 主页面,点击“Draft a new release”按钮发布一个新版本。这里我们以我们开源的一款 SDK 为例。

分别填写 Tag version、Release title、Describe this release 字段,我们以本次提交的版本是 1.2.3 为例:

  • Tag version:v1.2.3
  • Release title: Release 1.2.3

最后点击下方的“Publish release”绿色按钮。

1.2. Jitpack 发布

进入Jitpack 官方,使用 GitHub 账号进行登录。

  • 点击右上角「Sign In」使用 GitHub 账号登录
  • 在「Git repo url」中输入需要发布的仓库地址

这里依照 CalendarComponent 为例:

配置项说明:

  • Releases:已发布的 Release 版本;
  • Builds:构建记录;
  • Branches:当前仓库的分支;
  • Commits:提交记录;

在 Releases 选项卡页面,点击「Get it」按钮即可进行对应版本的发布。发布成功后 Log 选项卡会呈现绿色,提示「Status:ok」,反之则是红色,提示错误异常信息。

1.3. 版本引用

第一步:在项目根目录的 build.gradle 文件中添加:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
复制代码

第二步:在项目 Module 下的 build.gradle 文件中添加:

dependencies {
    implementation 'com.github.sensorsdata:sa-sdk-android:5.1.3'
}
复制代码

至此我们就完成了版本远程仓库的发布和引用。

1.4. 版本删除

在 JitPack 仓库包中,如果一个版本出现 Bug 需要删除,则需要现在 GitHub 的 Release 中删除该版本即可。

2. 公有 Maven 仓库

或许当初是由于发布到 Maven 仓库流程过于繁琐,Android 才会选择 Jcenter 作为默认的仓库地址。但是随着 Jcenter 的停止运营,仍然需要迁移到 Maven 仓库。

对于发布到 Maven 仓库,Sonatype 官方也提供了基于 Gradle 的脚本配置的指导文档,同时 Android 官方也提供了基于 Maven Publish 插件发布的指导帮助文档。但是由于 Maven 仓库要求对于发布的资源必须进行签名,但是 Android 官方提供的配置文档缺失签名部分,所以会导致发布到 Maven 之后,并不能真正的发布成功。Sonatype 提供的基于的指导文档是基于 maven 插件的 uploadArchives 任务,而 maven 插件在 Gradle 7.0 中已经被废弃并且被删除。所以我们最终采用基于 maven-publish 插件的 publishing 任务来发布到 Maven 仓库。

下面详细介绍一下发布到共有 Maven 仓库的操作步骤。

2.1. 注册 Sonatype 账号和申请项目

2.1.1. 注册 Sonatype 账号

注册地址:issues.sonatype.org/secure/Sign…

2.1.2. 申请创建新项目

在注册完成账号之后,创建 Issue 申请项目。

申请地址:issues.sonatype.org/secure/Crea…

完成申请之后,会与官方的支持人员与你确认沟通,以便确认你是该域名的持有者。需要注意的是,现在针对 GitHub 用户的域名是以:io.github. 开头,不允许自定义。如果有独立的域名可以使用域名作为Group Id。

2.2. GPG 签名

对于发布到 Maven 的资源,需要有签名校验,比较普遍的签名有 GPG 和 PGP,这里使用 GPG 签名作为示例。

2.2.1. GPG 安装

GPG 可以使用安装命令行,也可以通过客户端工具安装。这里我使用 brew 命令进行安装。

➜  ~ brew install gpg
复制代码

安装完成后,通过 gpg --version 查看是否安装成功。

➜  ~ gpg --version
gpg (GnuPG/MacGPG2) 2.2.10
libgcrypt 1.8.3
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
 
Home: /Users/dengshiwei/.gnupg
支持的算法:
公钥:RSA, ELG, DSA, ECDH, ECDSA, EDDSA
对称加密:IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256,
     TWOFISH, CAMELLIA128, CAMELLIA192, CAMELLIA256
散列:SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
压缩:不压缩, ZIP, ZLIB, BZIP2
复制代码

2.2.2. 生成密钥

指令:gpg --gen-key

输入:gpg --gen-key 后,会提示我们输入真实姓名、电子邮箱地址用于标识我们这个用户,最后确认信息时会让我们填入标识该用户的密码信息(很重要,一定要记住)。

2.2.3. 查看密钥

指令:gpg --list-keys

➜  ~ gpg --list-keys
/Users/dengshiwei/.gnupg/pubring.kbx
------------------------------------
pub   dsa2048 2010-08-19 [SC] [已过期:2020-06-15]
      85E38F69046B44C1EC9FB07B76D78F0500D026C4
uid           [已过期] GPGTools Team <team@gpgtools.org>
 
pub   rsa2048 2021-03-01 [SC] [有效至:2023-03-01]
      C19CC95F56C5D3EF8ADA2222133C922134E5CD035
uid           [ 绝对 ] dengshiwei <dengshiwei@sensorsdata.cn>
sub   rsa2048 2021-03-01 [E] [有效至:2023-03-01]
复制代码

这里可以看到我的公钥 ID = C19CC95F56C5D3EF8ADA2222133C922134E5CD035,仅仅有公钥是不够的,我们需要发布公钥到密钥服务器才能进行识别。

2.2.4. 发布公钥到服务器

指令:gpg --keyserver hkp://pool.sks-keyservers.net --send-keys 公钥 ID

➜  ~ gpg --keyserver hkp://pool.sks-keyservers.net --send-keys C19CC95F56C5D3EF8ADA299933C922134E5CD035
gpg: 将密钥‘33C922134E5CD035’上传到 hkp://pool.sks-keyservers.net
复制代码

2.2.5. 查看密钥是否发布成功

指令:gpg --keyserver hkp://pool.sks-keyservers.net --recv-keys 公钥 ID

➜  ~ gpg --keyserver hkp://pool.sks-keyservers.net --recv-keys C19CC95F56C5D3EF8ADA299933C922134E5CD035
gpg: 密钥 33C922134E5CD035:“dengshiwei <dengshiwei@sensorsdata.cn>”未改变
gpg: 合计被处理的数量:1
gpg:           未改变:1
复制代码

这样就标志着发布成功了。

2.2.6. 密钥导出

gpg 中提供了导出公钥和私钥的签名方法。

  • gpg -a -o public-file.key --export KeyId : 导出公钥到 public-file.key 文件中;
  • gpg -a -o private-file.key --export-secret-keys KeyId : 导出私钥到 private-file.key 文件中。

其中:

  • -a 为 --armor 的简写,表示密钥以 ASCII 的形式输出,默认以二进制的形式输出;
  • -o 为 --output 的简写,指定写入的文件。

2.3. 发布脚本

2.3.1. 引入发布和签名插件

在需要发布的工程项目的 build.gradle 文件中引入 maven-public 和 signing 插件。

build.gradle

apply plugin: 'signing'
apply plugin: 'maven-publish'
复制代码

2.3.2. 配置发布脚本

maven-public 插件通过 publishing 任务来发布资源。这里的配置主要包含:javadoc 文件、pop 文件、javadocJar 文件等。

task sourceJar(type: Jar) {
    from android.sourceSets.main.java.srcDirs
    classifier = 'sources'
}
 
task javadoc(type: Javadoc) {
    dependsOn 'assembleRelease'
    source = android.sourceSets.main.java.srcDirs +
            'build/generated/not_namespaced_r_class_sources/release/generateReleaseRFile/out/com/sensorsdata/analytics/android/sdk/R.java'
    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
}
 
javadoc {
    options {
        encoding "UTF-8"
        charSet 'UTF-8'
    }
}
 
task javadocJar(type: Jar, dependsOn: javadoc) {
    classifier = 'javadoc'
    from javadoc.destinationDir
}
 
publishing {
    publications {
        mavenAndroid(MavenPublication) {
            groupId = 'com.sensorsdata.analytics.android'
            artifactId = 'SensorsAnalyticsSDK'
            version = version
            artifact sourceJar
            artifact javadocJar
            artifact('build/outputs/aar/SensorsAnalyticsSDK.aar')
            // 配置 pop 文件格式
            pom {
                packaging 'aar'
                name = 'The official Android SDK for Sensors Analytics.'
                description = 'The official Android SDK for Sensors Analytics.'
                url = 'The official Android SDK for Sensors Analytics.'
                licenses {
                    license {
                        name='The Apache Software License, Version 2.0'
                        url='http://www.apache.org/licenses/LICENSE-2.0.txt'
                    }
                }
                developers {
                    developer {
                        id = 'dengshiwei'
                        name = 'dengshiwei'
                        email = 'dengshiwei@sensorsdata.com'
                    }
                }
                scm {
                    connection = 'https://github.com/sensorsdata/sa-sdk-android'
                    developerConnection = 'https://github.com/sensorsdata/sa-sdk-android.git'
                    url = 'https://github.com/sensorsdata/sa-sdk-android'
                }
            }
        }
    }
    // 配置远程仓库
    repositories {
        // maven 对应的用户名和密码自定义存在 local.properties 文件中
        Properties properties = new Properties()
        properties.load(project.rootProject.file('local.properties').newDataInputStream())
        def mavenUser = properties.getProperty("maven.user")
        def mavenPassword = properties.getProperty("maven.password")
        maven {
            // 发布地址,新申请的项目发布地址为:https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/
            url = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
            credentials {
                username mavenUser
                password mavenPassword
            }
        }
    }
}
// 对 mavenAndroid 发布内容进行签名
signing {
    sign publishing.publications.mavenAndroid
}
复制代码

发布脚本配置中有以下需要注意:

  • groupId:需要配置自己申请的 groupId;
  • artifactId:需要修改为自己项目的 artifactId;
  • pom 中的文件描述需要修改为自己项目的描述;
  • repositories 部分配置了远程仓库对应的用户名和密码,发布地址需要根据是否是新项目进行修改,旧项目域名是 oss.sonatype.org,新项目域名是:s01.oss.sonatype.org
  • signing 签名部分需要配置对应的 gpg 密钥和账户信息

签名密钥配置

signing 签名要求在 gradle.properties 配置文件中配置密钥信息。

signing.keyId=YourKeyId
signing.password=YourPublicKeyPassword
signing.secretKeyRingFile=PathToYourKeyRingFile
复制代码
  • signing.keyId:指刚才我们发布的公钥 ID,这里有一个坑就是这个 ID 的长度只能是 8 位,所以我们可以直接截取公钥 ID 的后 8 位即可;

  • signing.password:发布公钥对应的密码;

  • signing.secretKeyRingFile:指 gpg key 导出的私钥对应的问题,是绝对路径。可以通过指令 gpg --keyring secring.gpg --export-secret-keys > ~/.gnupg/secring.gpg 进行导出。

至此,我们完成发布相关的所有配置。

2.4. 版本发布

当我们配置好 publishing 后,我们可以通过指令:./gradlew publish 来执行发布任务。还可以通过 Android Studio 中的 Gradle 任务看板来执行 publish 任务。

2.5. 版本引用

第一步:在项目根目录的 build.gradle 文件中添加:

allprojects {
    repositories {
        ...
        mavenCentral()
    }
}
复制代码

第二步:在项目 Module 下的 build.gradle 文件中添加:

dependencies {
    implementation 'com.github.sensorsdata:sa-sdk-android:5.1.3'
}
复制代码

至此我们就完成了版本远程仓库的发布和引用。

2.6. 版本删除

当我们发布了一个严重缺陷的版本,需要删除该版本。可参照步骤:找到 「Repositoried」下的「Release」类别,然后找到自己的仓库路径,右键删除即可。

3. Jcenter 同步到 Maven

对于新发布的版本,我们可以选择直接发布到 Maven,但是对于已经发布到 Jcenter 的仓库,我们需要借助 Jcenter 提供的 Maven Central 功能进行同步。

3.1. Jcenter 配置 GPG 密钥

在 Jcenter 首页点击个人头像后点击「Edit Profile」进入个人信息配置页面,然后选中「GPG Signing」选项,配置导出的公钥和私钥。

配置完成后点击「Update」按钮即可。

3.2. Jcenter 配置 Sonatype 账号

在个人信息配置页面点击「Accounts」选项,配置注册的 Sonatype 账号。

3.3. 同步仓库到 Maven

进入仓库主页,点击「Maven Central」选项卡切换到对应的页面,点击「Sync」同步至 Maven。

至此完成整个 Jecenter 到 Maven 仓库的同步。

4. 总结

本次 Jcenter 的停止维护对于 Android 开发者来说会造成很大的影响,同时在迁移配置脚本的过程中也遇到很多问题,这里就不一一列举了,遇到问题首先要做的就是要反复检查核对自己的配置。希望 Android 官方能尽快出一个快速高效的迁移方案。

文章分类
Android
文章标签