适用于开源项目的终极(免费)CI/CD

2025-06-09

适用于开源项目的终极(免费)CI/CD

我把很多空闲时间都花在了 GitHub 上开发开源软件 (OSS) 上,主要是为了好玩和学习新东西。但有一件事我可以告诉你,那就是浪费时间寻找无法复现的 bug……或者和那些本该帮你的工具(比如你的持续集成 (CI) 系统)斗争,这可一点也不好玩。

您是否想过应该在哪个 CI/CD 解决方案上投入时间?您来对地方了!

强制披露:我现在在微软工作,但早在跳槽之前我就开始考虑CI迁移,而且我并没有被任何方式强迫这么做。我参与开源软件项目的经验可以追溯到我现在的工作之前,因此我试图在本文中以开源软件维护者的身份提供我的真实反馈。

TL;DR

  • 如果你打算长期维护一个开源项目,你必须做的就是自动化
  • 浪费时间最糟糕的方式是当你的自动构建没有按预期工作时:不稳定、不可靠的构建和跨平台问题可能会让你发疯
  • 实用主义应该是你的主要动力,力求用最少的时间完成工作

基于此,我发现Azure Pipelines目前提供了我认为最佳的时间投入/收益比。

GitHub Actions CI/CD解决方案面向所有人开放后(计划于 11 月 13 日上线),这种情况或许会有所改变。但在此之前,我会坚持使用久经考验的解决方案,这样我就能有更多时间陪伴家人,而不是纠结于构建问题 🍸

您将在这里学到什么?

如果您不关心背景故事,您可以直接采取行动

完整的故事

几年来,我一直在 GitHub 上维护多个开源项目,这些年来我得出了这样的结论:

  • 🔥 成为一名维护者很难(不是开玩笑!)
  • ⏲ 它会占用你大量的空闲时间(有时你可能更愿意与家人和朋友一起度过)
  • 😭 短期内偷工减料以节省时间几乎总是会导致长期浪费大量时间(就像任何软件项目一样)

玩笑归玩笑,最后一点很容易被忽视,而且我因为没有添加适当的测试或 CI 而陷入了太多次,例如:

“我这样做主要是为了我自己,但我会分享它,以防它对其他人有用”

哎呀,没想到这一点😱

大错特错。一旦问题和 PR 出现,就太晚了
审查、测试和部署贡献者提供的修复和新功能,就变成了浪费时间的黑洞。

黑洞中的空闲时间

黑洞,作者:Event Horizo​​n Telescope Collaboration,CC BY 4.0 // 经我精湛的绘画技巧修改

不过,在完成了几个项目之后,你很可能不会再犯这个错误,并且会像我一样建立一个最小的 CI 管道 😎

然后就好了。不知怎么的。

几年前,如果你想为开源项目寻找免费的托管 CI 解决方案,选择并不多。我很高兴有一些解决方案存在,因为它们是免费的。

因此,我最终使用了Travis CIAppVeyorCircleCI等最流行的解决方案。每个方案都能满足特定的需求,但遗憾的是,它们并非完美无缺。

服务 OSS层
特拉维斯·CI 在 GitHub 上开始使用 CI 的最简单、最常见的方法。 所有存储库
Linux + Mac 构建之间共享 5 个并发作业
AppVeyor 长期以来,它是唯一为 Windows 构建提供免费层的 CI 平台。 1 个并发作业
Windows + Linux 构建。
CircleCI 这是这三种解决方案中最灵活的一种,因为你可以使用自己的容器,但设置起来也是最复杂的 1 个并发作业
1000 次构建 分钟/月
仅限 Linux 构建

红色构建和问题

对于大多数简单的项目来说,使用这些解决方案中的任何一个可能就足够了。但随着时间的推移,我遇到了很多问题,而且问题也随着项目的复杂性而增长。

构建矩阵

首先是环境问题:我在 Mac OS 上开发,CI 在 Linux 上运行……而 Windows 上却出现了问题。因此,我最终像许多项目一样,使用了 Travis CI + AppVeyor 的组合。

然后是与多个平台版本兼容的问题。例如,一个支持 Node.js 的项目>= 8最好在所有 LTS 版本以及最新的稳定版本上进行测试:这意味着目前8.x10.x12.x

几乎所有 CI 服务都支持这些用例的构建矩阵定义,所以这很好。

但是,当你开始拥有多个项目,并且每个项目都有多个构建时,总构建时间就开始成为一个问题:我已经不得不等待好几天(!)才能合并一些 PR,因为许多 PR 是同时来自不同项目的(并且所有 PR 都共享相同的工作线程限制)。当你的流程已经很长(比如一个 PR 构建需要 1 小时)时,它很快就会出现问题。

不确定性不受欢迎

最后,还有一个最可怕的问题,它浪费了我生命中无数的时间:不稳定的构建😱。

对抗构建矩阵

有时,您的一次或多次构建会莫名其妙地失败。您(或您的贡献者)浪费了大量时间调查问题,最终发现问题出在持续集成服务上,而不是代码上。

如果只是偶尔出现这种情况,并且你对此有所怀疑,那么只需重新启动构建即可。但有时却不行,你需要花费宝贵的时间来尝试修复 CI,因为:

  • 推送了一个不幸的更新(错误)(糟糕的事情发生了,但它曾经存在了数周)
  • 构建容器镜像已进行调整(并且你的 CI 也变得💥)
  • “我们目前遇到了技术困难”
  • 没有理由...😞

随着时间的推移,这会让你对自己的 CI 产生警惕,这不是一件好事。

我知道我可能要求过高,而且大多数开源项目使用这些解决方案都很好。而且平心而论,考虑到所有这些服务都是免费提供的,也没什么可抱怨的。

了解 Azure Pipelines

前段时间,我发现JHipster已将其所有 CI 迁移到Azure Pipelines。我很早就了解这个项目了,它的 CI 复杂性简直令人发指,包含大量的组合路径和漫长的构建时间。这引起了我的兴趣,并尝试迁移一些我自己的项目来测试它。

好吧,我很惊讶地发现,与其他解决方案相比,Azure Pipelines 为您提供了很多免费功能:

  • 它可以针对任何操作系统(Windows/Mac/Linux)
  • 速度很快(OSS 层每个组织有 10 个并行工作者)
  • 它似乎更可靠(根据我自己的经验以及与 JHipster 维护者的讨论)
  • 设置和运行起来相当容易(虽然比 Travis 稍微复杂一些,但灵活性更高)

我首先迁移了一个简单的 Node.js项目的测试。现有的 Travis/AppVeyor 组合被替换为单个 Azure Pipeline,以便在 Windows/Mac/Linux 上进行测试,就像这个 PR中所做的那样。为了在 Windows 上顺利运行Prettier ,我不得不禁用 gitautocrlf选项,但除此之外,迁移过程非常简单。

首次成功之后,我继续迁移更为复杂且要求更高的generator-ngx-rocket CI ,结果如下。

服务 Travis + AppVeyor + Circle CI 与自定义 Docker 镜像 Azure Pipelines
组合 Travis 上有 40 个构建(Linux * 2 Node 版本),
AppVeyor 上有 20 个构建(Windows),
CircleCI 上有 1 个构建(Android)
83 个版本(Linux/Windows * 2 个 Node 版本 + Mac/Android)
构建时间 PR 大约需要 1 小时(Travis 大约需要 50 分钟,AppVeyor 大约需要 1 小时,CircleCI 大约需要 5 分钟) PR 大约需要 1 小时(如果仅限于之前的 Travis 场景,则大约需要 30 分钟)

这次迁移并不简单,因为我必须使用模板来生成组合矩阵,但结果很棒:

  • 只需管理一个配置(无需为 Android 构建额外的 Docker 镜像)
  • 在同一时间测试更多组合
  • 一些额外福利,例如将 Android 构建的 APK 直接发布为构建工件

经过这次经历,我可以说我现在完全支持 Azure Pipeline,并且我将继续迁移我的其他存储库👍

嘿,等等,但是新的GitHub Actions for CI/CD怎么样?!

我向你保证它看起来很棒,尤其是 OSS 层 😍
一旦它在 11 月 13 日向所有人开放,它可能会成为最好的解决方案(在这种情况下,本文将会更新😉)。

不过,Azure Pipelines 仍需考虑以下两点:

  • 如果您未被邀请成为 Beta 测试人员,您暂时无法使用 GitHub Actions。但与此同时,您可能需要一个可用的 CI 解决方案!
  • GitHub Actions for CI/CD 基于 Azure Pipelines 堆栈的部分内容,因此如果您已经在使用后者,那么迁移应该会轻而易举

我们开始做吧!

此刻,你可能想亲自尝试一下。我们将逐步介绍如何为你的 Node.js 项目部署 Azure Pipeline CI(如果你使用其他技术栈,也别放弃,其实区别不大,我会提供一些建议😉)。

您可以在此存储库中看到示例结果

要求:

  • 一个Azure DevOps 帐户(您可以使用您的 GitHub 帐户登录)
  • GitHub 存储库,其中包含一些您想要自动化的测试

1. 准备你的存储库

首先,您必须为 CI 准备测试脚本。

对于 Node.js 项目,通常通过在文件test中添加脚本来完成package.json

{
  "scripts": {
    "test": "jest"
  }
}
Enter fullscreen mode Exit fullscreen mode

在这个例子中,Jest将用于运行单元测试。

您可以通过运行来测试您的脚本npm test,以确保一切正常。

2.创建 Azure DevOps 项目

在您的 Azure DevOps 帐户中,创建一个新项目并为其命名:

创建项目

3. 设置管道

之后,转到左侧的管道部分:

选择管道

然后单击New pipeline开始设置过程:

新管道

选择GitHub (YAML),然后按照流程将您的帐户与 Azure DevOps 关联:

选择 github

选择您的存储库,然后在 GitHub 上授权该应用程序。

之后,选择第一个Node.js选项(或任何其他与您的技术栈相关的选项):

选择nodejs

对于其他技术栈和语言,例如 C#、Java、Go、Python 等,您应该查看文档生态系统部分中的相应页面。您将获得关于如何使用您喜欢的技术进行构建的具体提示。

您可以在此存储库中找到许多示例 YAML 文件

4. 自定义 YAML

然后,您将在编辑器中看到此 YAML 文件:

# Node.js
# Build a general Node.js project with npm.
# Add steps that analyze code, save build artifacts, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript

trigger:
  - master

pool:
  vmImage: 'ubuntu-latest'

steps:
  - task: NodeTool@0
    inputs:
      versionSpec: '10.x'
    displayName: 'Install Node.js'

  - script: |
      npm install
      npm run build
    displayName: 'npm install and build'
Enter fullscreen mode Exit fullscreen mode

现在,您只需更改最后一部分来运行命令,npm test而不是npm run build

- script: |
    npm install
    npm test
  displayName: 'npm install and test'
Enter fullscreen mode Exit fullscreen mode

单击Save and run,然后选择直接提交master还是使用 PR 创建新分支。

我建议您在此阶段创建一个带有 PR 的新分支,以便您可以在将其合并到存储库之前试验构建配置。

之后Save and run再次单击,然后检查一切是否运行正常。

5. 添加构建矩阵

现在您已经有一个可以运行的 CI,但使用 Azure Pipelines 的好处之一是您可以轻松添加跨平台构建,所以让我们这样做吧。

在菜单中选择Edit pipeline返回 YAML 编辑器:

选择编辑管道

首先在文件顶部添加此矩阵:

strategy:
  matrix:
    linux-node-10:
      imageName: 'ubuntu-latest'
      nodeVersion: '10.x'
    linux-node-latest:
      imageName: 'ubuntu-latest'
      nodeVersion: '>=12.x'
    mac-node-10:
      imageName: 'macos-latest'
      nodeVersion: '10.x'
    mac-node-latest:
      imageName: 'macos-latest'
      nodeVersion: '>=12.x'
    windows-node-10:
      imageName: 'windows-latest'
      nodeVersion: '10.x'
    windows-node-latest:
      imageName: 'windows-latest'
      nodeVersion: '>=12.x'
Enter fullscreen mode Exit fullscreen mode

这将允许您的测试每次使用 2 个不同的 Node.js 版本在 Windows、Linux 和 Mac OS 上运行,总共 6 个版本。

然后更新该pool部分以使用当前构建的图像名称:

pool:
  vmImage: $(imageName)
Enter fullscreen mode Exit fullscreen mode

最后更新node任务以对 Node.js 版本执行相同的操作:

- task: NodeTool@0
  inputs:
    versionSpec: $(nodeVersion)
  displayName: 'Install Node.js'
Enter fullscreen mode Exit fullscreen mode

单击Save,然后Run测试更新后的管道,就完成了。

如果您在第一次保存管道配置时创建了一个带有 PR 的分支,那么您还需要先在 GitHub 上合并此 PR,以激活管道以进行新的提交和 PR。

不要忘记查看完整的文档,以了解所有可用的任务和功能。

6. 添加状态徽章(可选)

构建成功徽章

我强烈建议您在 GitHub 存储库上添加状态徽章,以便人们对您的项目产生积极的信号:

  • 它得到维护,你关心它的质量
  • 贡献者可以自信地推动 PR

为此,请返回管道构建并单击Status badge菜单:

点击状态徽章

然后使用按钮复制 markdown 代码,并将其粘贴到readme.md存储库根目录的文件顶部:

复制 markdown

一旦提交到master分支,它将在项目的 GitHub 文档中可见。徽章状态将根据上次推送的提交自动更新master

想与其他徽章一起完善此状态徽章吗?请访问https://shields.io
你甚至可以创建自己的徽章:徽章很棒

7. 享受你的夜晚

就是这样!

一旦新的提交或 PR 被推送到您的存储库,CI 就会处理它并直接在 GitHub 上显示结果:

拉取请求状态检查

现在您可以放松并再次享受您的空闲时间🍻。

为了更加放心,我建议您使用新的 CI 启用所需的状态检查,以便只有通过所选检查的 PR 才允许合并。

不要忘记在评论中分享您的反馈和经验!

进一步

当然,作为维护者,你还可以做很多事情来简化你的工作,我会在以后的文章中分享。但我认为 CI 是任何项目都应该首先实施的措施之一。

您还可以使用 Azure Pipelines 做更多的事情(我是否在某处提到过 CD?)但我们稍后再讨论这个。


在Twitter上关注我,我很乐意讨论并接受您的建议!

鏂囩珷鏉ユ簮锛�https://dev.to/itnext/the-ultimate-free-ci-cd-for-your-open-source-projects-3bkd
PREV
使用 Docker 构建强大的 CI/CD 管道:综合指南
NEXT
逆向工程——理解 JavaScript 中的 Promises