第二十八天:用 TeamCity 发布 Package

在这系列教学里,我们以撰写一个以购物车为主题的 Kotlin 函式库为例,经过一连串 TDD、语法风格查、静态分析、Build Scan、覆盖率报告、API 文件等流程,我们已经确保了我们的程序码品质,是时候把它发布出去让使用者使用了!

以 JVM 生态系来说,大部份的开发者会把套件发布在 Maven Central、JCenter、Bintray 上。不过 JFrog 在今年 2 月宣布从 5 月 1 日起关闭 JCenter 及 Bintray 等服务,引发一批搬家潮;而 Maven Central 则是在发布上出了名的难设定,当初笔者刚转入 JVM 生态系时也被发布套件的难度给惊吓到。难道没有什麽简单上手、又方便跟 TeamCity 结合的发布平台吗?

使用 JetBrains Space 做为取代 Maven Central 的套件发布平台

JetBrains 在 2019 年的 KotlinConf 活动上发布了全新的 Space 平台 ,这是一个包含了 VCS Hosting、Project Management、Team Directory、Blog、Chat、CI/CD 等软件开发团队一定会用到的多合一工具平台。其中的 Project 与 VCS Hosting 功能里,就附带了 Maven Repository 的功能,让 JVM 生态系的开发者可以很方便的以 JetBrains Space 做为套件发布的平台!

在今天的练习里,我们将结合 Space 及 TeamCity 并将 ShoppingCart 这个购物车套件发布出去。在跟着练习之前,请先到 Space 官方网站 以注册一个团队空间来使用,注册帐号和开 Project 都是免费的。

在 Space 上设定 Project 及Package Repository

首先我们要在 Space 上设定一个 Project,请先点选画面上左下角的「+」按钮,选择新增一个 Project。

在弹出来的视窗里,Name 取名为 ShoppingCart Library、Key 设定为 SCL(皆可依需求自行调整),完成後按 Create 建立 Project。

接着会进到 Project 首页,点选左边侧边栏的 Packages 选项,再按下画面中间的 New repository。

在随後的弹出视窗里,Type 选择 Maven Repository、Name 取名为 space(可依需求自行调整)完成後按 Create 建立 Package Repository。

Gradle 发布设定

完成後会跳转到 Package Repository 首页,点一下画面上的 Get started,会有一个弹出式视窗告诉我们怎麽设定,在 Tool 的部份选择 Gradle (Kotlin),下方就会出现对应的 Gradle 设定档,让我们只需要复制贴上即可。

依照画面上的说明,第一件事就是要安装 Maven Publish 这个 Gradle Plugin:

plugins {
    // ...
    `maven-publish`
}

因为名称的关系,要注意这个 Plugin 名字必需用 Backtick 符号夹起来,新增後记得要在 IntelliJ IDEA 里 Reload 一次 Gradle,完成後应该会看到 Gradle 面板里多了一个 publishing 的群组。

接着要设定 Gradle 的 Publish 动作以及连上 JetBrains Space 的连线资讯:

val spaceUsername: String? by project
val spacePassword: String? by project

version = System.getenv("PACKAGE_VERSION") ?: "1.0-SNAPSHOT"

publishing {
    publications {
        create<MavenPublication>("main") {
            groupId = project.group.toString()
            artifactId = project.name
            version = project.version.toString()
            from(components["java"])
        }
    }
    repositories {
        maven {
            name = "space"
            url = uri("...")
            credentials {
                username = spaceUsername ?: System.getenv("SPACE_USERNAME")
                password = spacePassword ?: System.getenv("SPACE_PASSWORD")
            }
        }
    }
}

以上范例程序码跟 Space 上提供的有些不同,主要的原因是我们想从 CI 直接以环境变数的方式把设定值写入,而不是写死在设定档里。因此要修改的地方包括:spaceUsernamespacePassword 的型别改用 String?version 版本号会从环境变数抓,假如没有的话会以 1.0-SNAPSHOT 做预设值。publications 底下的 groupIdartifactIdversion 都改成从 project 抓取资讯。credentials 底下的 usernamepassword 都先抓 Gradle Properties,不然就是从环境变数抓。最後,在 maven 底下加上 name 的设定,方便我们识别 Gradle 的任务名称。完成後别忘了再 Reload 一次 Gradle,这次 Reload 完成後,会看到 publishing 群组里多了很多任务可以使用。

为了方便在本机测试,我们先在 gradle.properties 里新增 spaceUsernamespacePassword 两个参数,从刚刚的弹出式视窗里点选 Generate personal token 後,直接复制贴上视窗里产生出来的 token 资料。接着回到 IntelliJ IDEA 里的 Gradle 面板,直接点选 publish 任务执行,待 Gradle 完成所有动作後,Package 就成功的发布到 JetBrains Space 上了。

使用 TeamCity 发布

接下来我们要仿照之前发布 API 文件的方式,以新增一个 Build Configuration 的方式来发布 Package。建立 Build Configuration 的流程可以参考前面几天的教学,今天要设定的 Build Step 的 Runner type 一样是 Gradle,但是 Task 指令用的是 publish,设定完成後按 Save 储存。

设定 TeamCity 环境变数

设定好 Build Configuration 後,TeamCity 就可以帮我们一键把 Package 发布出去。但是别忘了在发布 Package 的时候,需要使用 Space 的 Personal token 才能将 Artifact 送上去,可是我们又不希望把 Personal token 这种机敏资讯写在 gradle.properties 并曝露在 VCS 里。这时我们可以用 TeamCity 的环境变数来动态地把 token 传给 Runner 执行。

首先进到 Publish artifact 设定,点选左边侧边栏的 Parameters,进到参数设定页。

点选上方 Add new parameter 按钮,在弹出式视窗里,Name 输入 SPACE_USERNAME、Kind 选择 Environment variable (env.)、Value 输入从 Space 取得的 Personal token 的帐号,完成後按 Save 储存。

以同样的方式再完成 SPACE_PASSWORD 的设定。

设定运行时环境变数

别忘了我们在 Gradle Build Script 里还有 PACKAGE_VERSION 也需要设定环境变数。但跟 SPACE_USERNAMESPACE_PASSWORD 不一样的地方是,PACKAGE_VERSION 在每次执行的时候值都应该要不一样(因为要发布成不同的版本号),所以我们不要用专案的环境变数写死,而是在每次执行的时候才输入。所以当我们在发布 Package 的时候,不要直接按 Build Configuration 旁的 Run 按钮,而是要按下 Run 按钮旁的「...」按钮。

在弹出式视窗里,选择 Parameters 页签,选择类型为 Environment variable。名称输入 PACKAGE_VERSION、值输入想要产生的版本号,按下右边的 add 完成新增,最後再按下 Run Build 执行建置并发布。

小结

今天我们体验了 JetBrains Space 平台的 Maven Repository 功能,同时也整合了 TeamCity 的环境变数、自动化发布的流程,让 JVM 开发者更方便的完成套件发布与储存的功能。希望这篇教学可以帮助到跟我一样卡在发布流程的苦主,若是对 Space 进阶功能有更多的兴趣,可以参考一下官方 售价表 了解细节。

参考资料


<<:  创建App-简单更改密码&教师代码

>>:  第18车厢-动ㄘ动ㄘ!tab页签切换+轮播应用篇

Day 01 : 导言 - 知识是如何形成的?

【Obsidian 双向链结型笔记工具研究与应用,打造属於个人的专业知识图谱】 Day 01 : 导...

30-29 之 DDD 战术篇 2 - Aggregate ( 未完成 )

什麽是 Aggregate 呢 ? 还记得我们谈过的 Bounded Context 与 Entit...

动员大外宣: 让资安进步成为公司的光环(向外)

过往有人说,公司投入资源做资安,外界又看不到更不能带来订单,有意义吗。 NONO~错罗,别忘了这个是...

K8s - Kubernetes 指令参考笔记

K8s - Kubernetes 指令参考笔记 参考资料 参考资料1:Day 11 Kubernet...

Day08 Kibana - Query DSL 查询语法介绍

Elasticsearch提供了许多的搜寻语法,让我们能透过这些语法的组合,可以查询出各式各样的结果...