赞
踩
GreptimeDB 自开源的第一天起就用 GitHub Actions 开启了自动化构建软件制品的模式,自此诞生了第一条 Release 流水线。对于一个开源项目来说,拥有一个成熟稳定的 Release 流水线至关重要:
之所以选用 GitHub Actions(同类产品其实还有 Circle CI,Travis CI,GitLab CI 等等,甚至可基于类似于 Tekton 或者 Argo Workflow 这类开源项目进行自建),原因很简单:GitHub Actions 结合 GitHub 生态足够简单易用且有一个丰富的软件市场生态。但是,简单易用并不代表好用且好维护,相反,GitHub Actions 是非常容易 “腐烂” 的。
GreptimeDB 开源的第一个版本其 release.yml
只有很短的 183 行,后经过 N 次 N 人改动后,小小的 YAML 先后加入了:
除此之外,全局又因其他原因(调试发布、每日构建等)分叉出了功能只有细微差异的同类流水线在不同的内部仓库中,加剧了维护成本。
在这么多杂乱无章且琐碎的构建需求下,release.yml
逐渐膨胀且难以维护,充斥着冗余啰嗦的配置代码,再不赶紧重构,Release 流水线估计就将要彻底腐烂。
回看 release.yml
,之所以会极速腐化,其原因有:
不同于常见的编程项目,重构一个 YAML 文件本质上是对各种配置过程进行一次完整的梳理,逻辑性不强,但是具有极大的偶然复杂度(Accidental Complexity),是一个不断踩坑又不断挣扎地从坑里爬出来的过程。
尽可能用 Dockerfile 来标准化构建:基于 Dockerfile 的构建是会带来一些性能的损失,但是增加了可维护性,标准化了所有平台的构建流程,从而具备 Reproducible Build;
统一命令入口:基于 1,尽量将各种构建命令提炼成一个单独的 make 命令,避免把过于复杂的编译上下文带入到 yaml 中,尽量不让 Release 环节隐藏过多的编译细节,而是让细节暴露在研发态的 Makefile 或脚本中(或者其他工具中)。用户可以通过使用 Makefile 就获得与 Release 环节一致的构建体验,从而提高研发效能;
使用 AWS EC2:上文曾经提及,由于 GitHub Actions 暂时还没有 ARM64 类型的虚拟机实例,因此我们不得已使用交叉编译。为了实现用一份 Dockerfile 来标准化所有平台的构建流程,我们采用 AWS EC2 的 ARM64 实例来构建 ARM64 平台的软件制品;
模块解耦:分拆 release.yml
,尽量保证 release.yml
是一个相对 “简单干净” 的 Job 的集合(因为 GitHub Actions 没有 Group Job 的机制,否则可以提炼得更加干净)。每一个 actions/
下的 action.yml
尽量保持简短纯粹,这样容易去基于相同的 actions 去定制不同的流水线;
尽可能保证 Job 的简单性:一个 Job 尽量干一件纯粹的事情,这样可幂等程度更高,出现错误更容易重试。基于 Job 也能更好地提炼出一些上层控制变量放到手动触发控制中;
尽量避免在 Actions 中的 Shell Run 中加入过多命令:如果在 GitHub Actions 的某个 Step 中引入过多的 Shell 命令,看似简单直接但其可维护性相当糟糕。如果实在有很多命令,建议变成一个外部的 Scripts 并提炼传入的参数接口。这么做好的好处就是方便对应的 scripts 可被独立执行和验证;
提炼出一个 Allocate Runners 的前置 Job:Allocate Runners 这个 Job 是第一个被执行的 Job,它将为后续的 Job 分配 Runner 和创建全局的 Version 标记。比如,如果我们选择使用 EC2,Allocate Runners Job 将会通过调用 EC2 API(这是通过 ec2-github-runner 这个 Action 实现的)来分配对应平台的 EC2 实例。更进一步,我们未来可以在 Allocate Runners 增加更复杂的选择算法(比如使用 Self-Hosted Runner)来优化 Runners 分配的成本;
全局统一流水线:如无必要,尽量不要分叉功能极为相近的 GitHub Actions,这同样会导致维护成本的上升。为了更加公开透明的开源研发流程,我们选择将之前内部使用的构建流水线统一到 GreptimeDB 主仓库中。只要代码是开源的,那么就保证软件制品和构建过程同样是开源的;
正确使用 GitHub 仓库中 Variables 和 Secrets 配置:之前的 CI 将大多数外部参数都当作是 Secrets,这其实并不正确。有些非 Secrets 类型的外部参数应该被配置为 GitHub Variables,这样更易于后期快速调整。对于一些可能存在不断调整的变量,也不要硬编码到 YAML 之中,而是要从 YAML 中提取出来变成 Variables。这样也可以减少一些低信息量的配置修改 PR。
这次 Release 流水线重构仅仅是 GreptimeDB 走向成熟的一小步而已,未来我们将构建一套更高质量的 CI:
GitHub Actions,想说爱你并不容易,欢迎有兴趣的朋友一起来社区讨论!
Greptime 格睿科技于 2022 年创立,目前正在完善和打造时序数据库GreptimeDB 和格睿云 GreptimeCloud 这两款产品。
GreptimeDB 是一款用 Rust 语言编写的时序数据库,具有分布式、开源、云原生、兼容性强等特点,帮助企业实时读写、处理和分析时序数据的同时,降低长期存储的成本。
GreptimeCloud 基于开源的 GreptimeDB,为用户提供全托管的 DBaaS,以及与可观测性、物联网等领域结合的应用产品。利用云提供软件和服务,可以达到快速的自助开通和交付,标准化的运维支持,和更好的资源弹性。GreptimeCloud 已正式公测,欢迎关注公众号或官网了解最新动态!
官网:https://greptime.com/
GitHub: https://github.com/GreptimeTeam/greptimedb
文档:https://docs.greptime.com/
Twitter: https://twitter.com/Greptime
Slack: https://greptime.com/slack
LinkedIn: https://www.linkedin.com/company/greptime/
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。