本文介绍了GitLab上一个C++项目的CI管道的配置。本文是关于通过使用CI管道来扩展配置的后续文章。首先,演示了流水线的设置,然后是它的执行。接下来是CI配置本身。
持续集成(CI)只是意味着代码的变化,这些变化被提交到一个中央存储库,并被自动构建和测试。在开放源码领域,GitLab是一个用于建立CI管道的流行平台。除了中央Git仓库,GitLab还提供CI/CD管道的配置、问题跟踪和容器注册表。
需要了解的术语
在深入探讨DevOps理念的这一领域之前,我将建立一些在本文和GitLab文档中遇到的常用术语。
- 持续交付(CD)。以部署为目的的应用程序的自动供应。
- 持续部署(CD)。自动发布软件
- 管线。CI/CD的顶级组件,定义了阶段和工作
- 阶段。一组必须成功执行的工作
- 工作。任务的定义(例如,编译、执行单元测试)。
- 运行者。实际执行作业的服务
建立一个CI管道
我将重复使用以前文章中的示例项目,这些项目可以在GitLab上找到。要遵循后面章节中描述的步骤,请点击右上方的 "Fork"按钮来分叉该示例项目。
Stephan Avenwedde (CC BY-SA 4.0)
设置一个运行器
为了了解一切是如何运作的,从底部开始,在本地系统上安装一个运行器。
按照你的系统的GitLab运行器服务的安装说明进行安装。安装完毕后,要注册一个运行器。
1.在GitLab页面,选择项目,在左侧窗格中,导航到设置,选择CI/CD。
Stephan Avenwedde (CC BY-SA 4.0)
2.2. 展开Runners部分,将Shared runners切换为关闭(黄色标记)。注意令牌和URL(绿色标记);我们在下一步需要它们。
Stephan Avenwedde (CC BY-SA 4.0)
3.现在打开一个终端,输入gitlab-runner register
。该命令调用了一个脚本,要求输入一些信息。下面是答案。
- GitLab实例:https://gitlab.com/(上面的屏幕截图)
- 注册令牌。从Runners部分挑选(上面的截图)
- 描述。可自由选择
- 标签。这是可选的。你不需要提供标签
- 执行者。在这里选择Shell
如果你以后想修改配置,你可以在~/.gitlab-runner/config.toml
。
4.现在,用命令gitlab-runner run
,启动运行器。运行器现在正在等待作业。你的运行器现在可以在GitLab上的项目设置中的运行器部分找到。
Stephan Avenwedde (CC BY-SA 4.0)
执行一个流水线
如前所述,流水线是由运行器执行的工作的集合。每一个推送到 GitLab 的提交都会产生一个与该提交相连的管道。如果多个提交是一起推送的,则只为最后一个提交创建管道。要启动一个用于演示的流水线,请直接在GitLab的网络编辑器上提交并推送一个变更。
在第一次测试中,打开README.md
,并添加一个附加行。
Stephan Avenwedde (CC BY-SA 4.0)
现在提交你的修改。
注意,默认是创建一个新的分支。为了保持简单,选择提交到主分支。
Stephan Avenwedde (CC BY-SA 4.0)
提交几秒钟后,你应该注意到在GitLab runner执行的控制台窗口中有一些输出。
Checking for jobs... received job=1975932998 repo_url=https://gitlab.com/hANSIc99/cpp_testing_sample.git runner=Z7MyQsA6
Job succeeded duration_s=3.866619798 job=1975932998 project=32818130 runner=Z7MyQsA6
在GitLab的项目概览中,在右边的窗格中选择CI/CD--> Pipelines。在这里你可以找到最近执行的管道的列表。
Stephan Avenwedde (CC BY-SA 4.0)
如果你选择一个管道,你会得到一个详细的概览,你可以检查哪个作业失败了(如果管道失败了),并看到单个作业的输出。
如果一个作业的返回值不是零,就被认为是失败了。在下面的案例中,我只是调用了bash命令exit 1
(第26行)来让作业失败。
Stephan Avenwedde (CC BY-SA 4.0)
CI配置
阶段、管道和作业的配置是在仓库根目录下的.gitlab-ci.yml文件中进行的。我建议用GitLab内置的Pipeline编辑器来编辑配置,因为它在编辑过程中会自动检查准确性。
stages:
- build
- test
build:
stage: build
script:
- cmake -B build -S .
- cmake --build build --target Producer
artifacts:
paths:
- build/Producer
RunGTest:
stage: test
script:
- cmake -B build -S .
- cmake --build build --target GeneratorTest
- build/Generator/GeneratorTest
RunCTest:
stage: test
script:
- cmake -B build -S .
- cd build
- ctest --output-on-failure -j6
该文件定义了构建和测试阶段。接下来,它定义了三个作业:build、RunGTest和RunCTest。build作业被分配到同名阶段,其他作业被分配到测试阶段。
脚本部分下面的命令是普通的shell命令。你可以像在shell中逐行输入一样来阅读它们。
我想指出一个特殊的功能:人工制品。在这种情况下,我把Producer二进制文件定义为构建工作的一个工件。人工制品被上传到GitLab服务器上,可以从那里下载。
Stephan Avenwedde (CC BY-SA 4.0)
默认情况下,后面阶段的作业会自动下载前面阶段的作业所创建的所有工件。
在docs.gitlab.com上有一个gitlab-ci.yml
的参考。
总结
上面的例子是一个初级的例子,但它显示了持续集成的一般原则。在上面关于设置运行器的部分,我停用了共享运行器,尽管这正是GitLab的实际优势。你可以在干净的容器化环境中构建、测试和部署你的应用程序。除了GitLab每月免费提供的运行器外,你还可以提供自己的基于容器的、自我托管的运行器。当然,还有一种更高级的方式。你可以使用Kubernetes来协调基于容器的运行器,这可以让你自由地扩展管道的处理。你可以在about.gitlab.com上阅读更多信息。
由于本文运行的是Fedora,Podman还不支持作为GitLab运行器的容器引擎。根据gitlab-runner issue#27119,Podman支持已经在列表中了。
将重复的步骤描述为作业,并将它们组合在管道和阶段中,可以让你在不引起额外工作的情况下跟踪它们的质量。特别是在大型社区项目中,你必须决定合并请求是被接受还是被拒绝,一个正确配置的CI方法可以告诉你提交的代码是会改善还是恶化项目。