标签 CI 下的文章

连续集成 continuous integration (CI)是指代码变更会被自动构建和测试。以下是我为自己的 C++ 项目构建 CI 流水线的过程。

本文介绍如何在 GitLab 上配置 CI 流水线。我在前面的文章中介绍了 基于 CMake 和 VSCodium 的构建系统基于 GoogleTest 和 CTest 的单元测试。本文将在此基础上进一步配置 CI 流水线。我会先演示如何布设和运行 CI 流水线,然后再介绍如何配置它。

CI 是指提交到代码仓库的代码变更会被自动构建和测试。在开源领域,GitLab 是一个流行的 CI 流水线平台。除了作为中心 Git 仓库外,GitLab 还提供 CI/CD 流水线、 问题跟踪 issue tracking 容器注册表 container registry 功能。

相关术语

在进入正题之前,我先介绍在本文和 GitLab 文档 中会遇到的常见术语。

  • 持续交付 continuous delivery (CD):自动化供应软件,以供随时交付
  • 持续部署 continuous deployment (CD):自动化软件发布
  • 流水线 pipeline : CI/CD 的直接构件,它由阶段和作业构成
  • 阶段 stage :一组作业
  • 作业 job :某项需要执行的具体任务,比如编译、单元测试等
  • 执行器 runner :实际执行作业的服务

布设 CI 流水线

在下面的章节中,我将复用以前的 示例工程。点击 GitLab 仓库页面右上角的 复刻 Fork 按钮复刻代码仓库。

 title=

设置执行器

为了让你对整个流程有所了解,我们先从在本地安装执行器讲起。

参照执行器服务 安装指南 安装好服务,然后注册执行器。

1、选择 GitLab 项目页面左侧的 设置 Settings ,再选择 CI/CD

 title=

2、展开 执行器 Runners 区域,关闭 共享的执行器 Shared runners 选项(黄框处)。特别注意令牌和 URL(绿框处),下一步会用到它们。

 title=

3、在终端中运行 gitlab-runner register,根据提示输入以下注册信息:

  • GitLab 实例: https://gitlab.com/ (如上图)
  • 注册令牌:从执行器区域中获取 (如上图)
  • 描述:按需自由填写
  • 标签:可以不填
  • 执行环境:选 Shell

如果有需要,你可以在 ~/.gitlab-runner/config.toml 中修改这些配置。

4、用命令 gitlab-runner run 启动执行器。你可以在 GitLab 的项目设置界面执行器区域看到执行器的状态:

 title=

运行流水线

前面已经提过,流水线就是一组由执行器执行的作业。每个推送到 GitLab 的提交都会生成一个附加到该提交的流水线。如果多个提交被一起推送,那么只会为最后一个提交生成流水线。为了演示,我直接在 GitLab 在线编辑器中提交和推送修改。

打开 README.md 文件,添加一行数据:

 title=

现在提交修改。

这里注意默认的行为是为提交新建一个分支,为了简便起见,我们择提交到主分支。

 title=

提交后一会儿后,你就应该改能看到 GitLab 执行器执行的控制台中有输出消息:

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 ,查看最近执行的流水线:

 title=

选中流水线可以在详情界面看到哪些作业失败了,并能查看各个作业的输出。

当遇到非零返回值是就认为作业执行失败了。在下面的例子中我通过调用 exit 1 强制让作业执行失败:

 title=

CI 配置

阶段、流水线和作业的配置都在仓库根目录的 .gitlab-ci.yml 文件中。我建议使用 GitLab 内置的流水线编辑器,它会自动对配置进行检查。

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

文件中定义了两个阶段:buildtest,以及三个作业:buildRunGTestRunCTest。其中作业 build 属于一个同名的阶段,另外两个作业属于阶段 test

script 小节下的命令就是一般的 Shell 命令。你可以认为是将它们逐行输入到 Shell 中。

我要特别提及 产物artifact 这个特性。在示例中我定义了二进制的 Producer 为作业 build 的产物。产物会被上传到 GitLab 服务器,并且可以从服务器的这个页面上被下载:

 title=

默认情况下,后续阶段的作业会自动下载先前阶段作业生成的所有产物。

你可以在 docs.gitlab.com 上查看 gitlab-ci.yml 参考指南。

总结

上面只是一个最基本的例子,让你对持续集成的一般原则有一个了解。再演示中我禁用了共享执行器,然而这才是 GitLab 的优势所在。你可以在一个干净的容器化的环境中构架、测试和部署程序。除了使用 GitLab 提供的免费执行器,你也可以用自己的容器作为执行器。当然还有更高阶的用法:用 Kubernetes 来协调调度执行者容器,让流水线适应大规模使用的使用场景。如需进一步了解,可以查看 about.gitlab.com

如果你使用的是 Fedora,需要注意的一点是目前 GitLab 执行者还不支持用 Podman 作为容器引擎。(LCTT 译注:Podman 是 Fedora 自带的容器引擎。)根据 议题 issue #27119,对 Podman 支持已将列上日程。(LCTT 译注:Podman 4.2 及以上版本增加了对于 GitLab 执行器的支持。)

把重复性的操作描述成作业,并将作业合并成流水线和阶段,可以让你跟踪它们的质量而不增加额外工作。。特别是在大型社区项目中,适当配置的 CI 可以告诉你提交的代码是否对项目有改善,为你接受或拒绝合并请求提供依据。

(题图:MJ/fb711c48-251a-4726-a41c-247370e5df25)


via: https://opensource.com/article/22/2/setup-ci-pipeline-gitlab

作者:Stephan Avenwedde 选题:lujun9972 译者:toknow-gh 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

对齐部署镜像和描述符是很困难的,但是某些策略可以使整个过程更高效。

 title=

在软件架构中,当两个组件之间有某些概念性或技术上的差异时会出现 阻抗失配 impedance mismatch 。这个术语其实是从电子工程中借用的,表示电路中输入和输出的电子阻抗必须要匹配。

在软件开发中,存储在镜像仓库中的镜像与存储在源码控制管理系统(LCTT 译注:SCM,Source Code Management)中它的 部署描述符 deployment descriptor 之间存在阻抗失配。你如何确定存储在 SCM 中的部署描述符表示的是正确的镜像?两个仓库追踪数据的方式并不一致,因此将一个镜像(在镜像仓库中独立存储的不可修改的二进制)和它的部署描述符(Git 中以文本文件形式存储的一系列修改记录)相匹配并不那么直观。

注意:本文假定读者已经熟悉以下概念:

  • 源码控制管理 Source Control Management (SCM)系统和分支
  • Docker 或符合 OCI 标准的镜像和容器
  • 容器编排系统 Container Orchestration Platforms (COP),如 Kubernetes
  • 持续集成/持续交付 Continuous Integration/Continuous Delivery (CI/CD)
  • 软件开发生命周期 Software development lifecycle (SDLC)环境

阻抗失配:SCM 与镜像仓库

为了更好地理解阻抗失配在什么场景下会成为问题,请考虑任意项目中的软件开发生命周期环境(SDLC),如开发、测试或发布环境。

测试环境不会有阻抗失配。现在使用 CI/CD 的最佳实践中开发分支的最新提交都会对应开发环境中的最新部署。因此,一个典型的、成功的 CI/CD 开发流程如下:

  1. 向 SCM 的开发分支提交新的修改
  2. 新提交触发一次镜像构建
  3. 新生成的镜像被推送到镜像仓库,标记为开发中
  4. 镜像被部署到容器编排系统(COP)中的开发环境,该镜像的部署描述符也更新为从 SCM 拉取的最新描述符。

换句话说,开发环境中最新的镜像永远与最新的部署描述符匹配。回滚到前一个构建的版本也不是问题,因为 SCM 也会跟着回滚。

最终,随着开发流程继续推进,需要进行更多正式的测试,因此某个镜像 —— 镜像对应着 SCM 中的某次提交 —— 被推到测试环境。如果是一次成功的构建,那么不会有大问题,因为从开发环境推过来的镜像应该会与开发分支的最新提交相对应。

  1. 开发环境的最新部署被允许入库,触发入库过程
  2. 最新部署的镜像被标记为测试中
  3. 镜像在测试环境中被拉取和部署,(该镜像)对应从 SCM 拉取的最新部署描述符

到目前为止,一切都没有问题,对吗?如果出现下面的场景,会有什么问题?

场景 A:镜像被推到下游环境,如 用户验收测试 user acceptance testing (UAT),或者是生产环境。

场景 B:测试环境中发现了一个破坏性的 bug,镜像需要回滚到某个确定正常的版本。

在任一场景中,开发过程并没有停止,即开发分支上游有了一次或多次新的提交,而这意味着最新的部署描述符已经发生了变化,最新的镜像与之前部署在测试环境中的镜像不一致。对部署描述符的修改可能会也可能不会对之前版本的镜像起作用,但是它们一定是不可信任的。如果它们有了变化,那么它们就一定与目前为止你测试过的想要部署的镜像的部署描述符不一致。

问题的关键是:如果部署的镜像不是镜像库中的最新版本,你怎么确定与部署的镜像相对应的是 SCM 中的哪个部署描述符? 一言以蔽之,无法确定。两个库直接有阻抗失配。如果要详细阐述下,那么是有方法可以解决的,但是你需要做很多工作,这部分内容就是文章接下来的主题了。请注意,下面的方案并不是解决问题的唯一办法,但是已经投入到生产环境并已经对很多项目起了作用,而且已经被构建并部署到生产环境中运行了超过一年。

二进制与部署描述符

源码通常被构建成一个 Docker 镜像或符合 OCI 标准的镜像,该镜像通常被部署到一个容器编排平台(COP)上,如 Kubernetes。部署到 COP 需要部署描述符来定义镜像被如何部署以及作为容器运行,如 Kubernetes 部署CronJobs。这是因为在镜像和它的部署描述符之间有本质差异,在这里可以看到阻抗失配。在这次讨论中,我们认为镜像是存储在镜像仓库中不可修改的二进制。对源码的任何修改都不会修改镜像,而是用另一个新的镜像去替换它。

相比之下,部署描述符是文本文件,因而可以被认为是源码且可修改。如果遵循最佳实践,那么部署描述符是被存储在 SCM,所有修改都会提交,而这很容易回溯。

解决阻抗失配

建议的解决方案的第一部分,就是提供一个能匹配镜像仓库中的镜像与对保存部署描述符的 SCM 做的代码提交的方法。最直接的解决方案是用源提交的哈希值标记镜像。这个方法可以区分不同版本的镜像、容易分辨,并且提供足够的信息来查找正确的部署描述符,以便镜像更好地部署到 COP。

再回顾下上面的场景:

场景 A 镜像被推到下游环境: 当镜像被从测试环境推到 UAT 环境时,我们可以从镜像的标签中知道应该从 SCM 的哪一次源码提交拉取部署描述符。

场景 B 当一个镜像需要在某一环节中回滚:无论我们选择回滚到那个镜像版本,我们都可以知道从 SCM 的哪一次源码提交拉取正确的部署描述符。

在每一种情景中,无论在某个镜像被部署到测试环境后开发分支有多少次提交和构建,对于每一次升级的镜像,我们都可以找到它当初部署时对应的部署描述符。

然而,这并不是阻抗失配的完整解决方案。再考虑两个场景:

场景 C 在负载测试环境中,会尝试对不同的部署描述符进行多次部署,以此来验证某一次构建的表现。

场景 D 一个镜像被推送到下游环境,在该环境中部署描述符有一个错误。

在上面的所有场景中,我们都需要修改部署描述符,但是目前为止我们只有一个源码提交哈希。请记住,最佳实践要求我们所有对源码的修改都要先提交到 SCM。某次提交的哈希本身是无法修改的,因此我们需要一个比仅仅追踪原来的源码提交哈希更好地解决方案。

解决方案是基于原来的源码提交哈希新建一个分支。我们把这个分支称为部署分支。每当一个镜像被推到下游测试或发布环境时,你应该基于前一个 SDLC 环境的部署分支的最新提交创建一个新的部署分支。

这样同一个镜像可以重复多次部署到不同的 SDLC 环境,并在后面每个环境中可以感知前面发现的改动或对镜像做的修改。

注意: 在某个环境中做的修改是如何影响下一个环境的,是用可以共享数据的工具(如 Helm Charts)还是手动剪切、粘贴到其他目录,都不在本文讨论的范围内。

因此,当一个镜像被从一个 SDLC 环境中推到下一环境时:

  1. 创建一个部署分支

    1. 如果镜像是从开发环境中推过来的,那么部署分支就基于构建这个镜像的源码提交哈希创建
    2. 否则,部署分支基于当前部署分支的最新提交创建
  2. 镜像被部署到下一个 SDLC 环境,使用的部署描述符是该环境中新创建的部署分支的部署描述符

deployment branching tree

图 1:部署分支树

  1. 部署分支
  2. 下游环境的第一个部署分支,只有一次提交
  3. 下游环境的第二个部署分支,只有一次提交

有了部署分支这个解决方案,再回顾下上面的场景 C 和场景 D:

场景 C 修改已经部署到下游 SDLC 环境中的镜像的部署描述符

场景 D 修复某个 SDLC 环境中部署描述符的错误

两个场景中,工作流如下:

  1. 把对部署描述符做的修改提交到 SLDC 环境和镜像对应的部署分支
  2. 通过部署分支最新提交对应的部署描述符把镜像重新部署到 SLDC 环境

这样,部署分支彻底解决了(存储着代表一次独一无二的构建的单一的、不可修改的镜像的)镜像仓库与(存储着对应一个或多个 SDLC 环境的可修改的部署描述符的)SCM 仓库之间的阻抗失配。

实践中的思考

这看起来像是行得通的解决方案,但同时它也为开发者和运维人员带来了新的实践中的问题,比如:

A. 为了更好地管理部署分支,部署描述符作为资源应该保存在哪里,是否要与构建镜像的源码保存在同一个 SCM 仓库?

到目前为止,我们都在避免谈论应该把部署描述符放在哪个仓库里。在还没有太多细节需要处理时,我们推荐把所有 SDLC 环境的部署描述符与镜像源码放在同一个 SCM 仓库。当部署分支创建后,镜像的源码可以作为方便找到部署的容器中运行的镜像的引用来使用。

上面提到过,可以通过镜像的标签来关联镜像与原始的源码提交。在一个单独的仓库中查找某次提交的源码的引用,会给开发者带来更大的困难(即便借助工具),这就是没有必要把所有资源都分开存储的原因。

B. 应该在部署分支上修改构建镜像的源码吗?

简答:不应该

详细阐述:不应该,因为永远不要在部署分支上构建镜像,它们是在开发分支上构建的。修改部署分支上定义一个镜像的源码会破坏被部署的镜像的构建记录,而且这些修改并不会对镜像的功能生效。在对比两个部署分支的版本时这也会成为问题。这可能会导致两个版本的功能差异有错误的测试结果(这是使用部署分支的一个很小的额外好处)。

C. 为什么使用镜像 标签 tag 标记 label 不可以吗?

通过 标签 tag 可以在仓库中很容易地查找镜像,可读性也很好。在一组镜像中读取和查找 标记 label 的值需要拉取所有镜像的 清单文件 manifest ,而这会增加复杂度、降低性能。而且,考虑到历史记录的追踪和不同版本的查找,对不同版本的镜像添加 标签 tag 也很有必要,因此使用源码提交哈希是保证唯一性,以及保存能即时生效的有用信息的最简单的解决方案。

D. 创建部署分支的最佳实践是怎样的?

DevOps 最重要的三个原则:自动化、自动化、自动化。

依赖资源来持续地强迫遵循最佳实践,充其量只是碰运气,因此在实现镜像的升级、回滚等 CI/CD 流水线时,把自动化部署分支写到脚本里。

E. 对部署分支的命名规范有建议吗?

<部署分支标识>-<环境>-<源码提交哈希>

  • 部署分支标识: 所有部署分支范围内唯一的字符串;如 “deployment” 或 “deploy”
  • 环境: 部署分支适用的 SDLC 环境;如 “qa”(测试环境)、 “stg”(预生产环境)、 或 “prod”(生产环境)
  • 源码提交哈希: 源码提交哈希中包含原来构建被部署的镜像的源码,开发者可以通过它很容易地查找到创建镜像的原始提交,同时也能保证分支名唯一。

例如, deployment-qa-asdf78s 表示推到 QA 环境的部署分支, deployment-stg-asdf78s 表示推到 STG 环境的部署分支。

F. 你怎么识别环境中运行的哪个镜像版本?

我们的建议是把最新的部署分支提交哈希和源码提交哈希添加到 标记 中。开发者和运维人员可以通过这两个独一无二的标识符查找到部署的所有东西及其来源。在诸如执行回滚或前滚操作时,使用那些不同版本的部署的选择器也能清理资源碎片。

G. 什么时候应该把部署分支的修改合并回开发分支?

这完全取决于开发团队。

如果你修改的目的是为了做负载测试,只是想验证什么情况会让程序崩溃,那么这些修改不应该被合并回开发分支。另一方面,如果你发现和修复了一个错误,或者对下游环境的部署做了调整,那么就应该把部署分支的修改合并回开发分支。

H. 有现成的部署分支示例让我们试水吗?

el-CICD 已经在生产上使用这个策略持续一年半应用到超过一百个项目了,覆盖所有的 SDLC 环境,包括管理生产环境的部署。如果你可以访问 OKD、Red Hat OpenShift lab cluster 或 Red Hat CodeReady Containers,你可以下载el-CICD 的最新版本,参照 教程 来学习部署分支是何时以怎样的方式创建和使用的。

结语

通过实践上面的例子可以帮助你更好的理解开发过程中阻抗失配相关的问题。对齐镜像和部署描述符是成功管理部署的关键部分。


via: https://opensource.com/article/21/8/impedance-mismatch-cicd

作者:Evan "Hippy" Slatis 选题:lujun9972 译者:lxbwolf 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

GitHub Actions 是一项为快速建立持续集成和交付(CI/CD)工作流程而提供的服务。这些工作流程在被称为“ 运行器 runner ”的主机上运行。GitHub 提供的 托管运行器 的操作系统的选择是有限的(Windows Server、Ubuntu、MacOS)。

另一个选择是使用 自托管 的运行器,这让仓库管理员对运行器有更多控制。自托管的运行程序是专门为某个存储库或组织服务的。下面的文章介绍了使用 Fedora CoreOS 配置自托管运行程序的步骤。

入门

Fedora CoreOS 是一个精简的操作系统,旨在便于大规模的部署和维护。该操作系统会自动更新,并默认提供运行容器所需的工具。由于这些原因,Fedora CoreOS 是运行 CI/CD 工作流程的一个极佳选择。

配置和配备 Fedora CoreOS 机器的第一步是生成一个 Ignition 文件。Butane 允许你使用更友好的格式(YAML)生成 Ignition 文件。

配置一个 Fedora CoreOS 运行器

要在 Fedora CoreOS 上执行 GitHub Actions,托管主机需要用于注册和运行该运行器的二进制文件和脚本。从 Actions 运行器项目 下载二进制文件和脚本,并部署在 /usr/local/sbin/actions-runner 下。

version: "1.3.0"
variant: fcos
storage:
  directories:
    - path: /usr/local/sbin/actions-runner
      mode: 0755
      user:
        name: core
      group:
        name: core
  files:
    - path: /usr/local/sbin/actions-runner/actions-runner-linux.tar.gz
      overwrite: true
      contents:
        source: https://github.com/actions/runner/releases/download/v2.278.0/actions-runner-linux-x64-2.278.0.tar.gz
      mode: 0755
      user:
        name: core
      group:
        name: core

注册和删除令牌

为一个项目配置运行器需要一个“ 令牌 token ”。这可以防止在没有正确权限的情况下从项目中注册或删除自托管的运行器。GitHub 提供的令牌有一个小时的过期时间。如果运行器在这个时间之后重新启动,它将需要一个新的注册令牌。

该令牌可能出问题,特别是在 Fedora CoreOS 自动更新时。更新过程希望托管主机在收到新数据后至少每隔几周重启一次。

幸运的是,可以使用 GitHub REST API 来获取这些令牌,并在托管主机每次重启时自动配置运行器。下面的 manage-runner.sh 脚本使用 API 来获取令牌,删除任何已经配置好的运行器,并用新的令牌注册运行器。

#!/bin/bash
# Handles the Github Action runner configuration.
# Remove and Registration token expires after 1 hour, if we want our runner
# to work after a reboot (auto update) we need to refresh the tokens.

# First remove the runner with a fresh remove token
REMOVE_TOKEN=$(curl -u ${GITHUB_USER}:${GITHUB_TOKEN} -X POST -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/${GITHUB_USER}/${GITHUB_REPO}/actions/runners/remove-token | jq -r '.token')
/usr/local/sbin/actions-runner/config.sh remove --token ${REMOVE_TOKEN}


# Then register the runner with a fresh registration token
REGISTRATION_TOKEN=$(curl -u ${GITHUB_USER}:${GITHUB_TOKEN} -X POST -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/${GITHUB_USER}/${GITHUB_REPO}/actions/runners/registration-token | jq -r '.token')
/usr/local/sbin/actions-runner/config.sh --url https://github.com/cverna/fcos-actions-runner --token ${REGISTRATION_TOKEN} --labels fcos --unattended

上面的脚本使用了一些环境变量,包含 GitHub 用户名和用于验证 REST API 请求的 个人访问令牌 Personal Access Token 。个人访问令牌需要存储库权限,以便成功检索运行器的注册和移除令牌。该令牌是安全敏感信息,所以最好将其存储在一个具有更严格权限的不同文件中。在这个例子中,这个文件是 actions-runner

GITHUB_USER=<user>
GITHUB_REPO=<repo>
GITHUB_TOKEN=<personal_access_token>

以下是创建这两个文件 manage-runner.shactions-runner 的 Butane 片段。

- path: /usr/local/sbin/actions-runner/manage-runner.sh
      contents:
        local: manage-runner.sh
      mode: 0755
      user:
        name: core
      group:
        name: core
    - path: /etc/actions-runner
      contents:
        local: actions-runner
      mode: 0700
      user:
        name: core
      group:
        name: core

在 Fedora CoreOS 上运行 Actions

最后,创建用于配置和启动运行器的 systemd 服务。在 Butane 配置文件中定义这些服务。

systemd:
  units:
    - name: github-runner-configure.service
      enabled: true
      contents: |
        [Unit]
        Description=Configure the github action runner for a repository
        After=network-online.target boot-complete.target
        Requires=boot-complete.target
        [Service]
        EnvironmentFile=/etc/actions-runner
        Type=oneshot
        RemainAfterExit=yes
        User=core
        WorkingDirectory=/usr/local/sbin/actions-runner
        ExecStartPre=tar xvf actions-runner-linux.tar.gz --no-same-owner
        ExecStart=/usr/local/sbin/actions-runner/manage-runner.sh
        [Install]
        WantedBy=multi-user.target
    - name: github-runner.service
      enabled: true
      contents: |
        [Unit]
        Description=Run the github action runner
        After=github-runner-configure.service
        [Service]
        WorkingDirectory=/usr/local/sbin/actions-runner
        User=core
        ExecStart=/usr/local/sbin/actions-runner/run.sh
        [Install]
        WantedBy=multi-user.target

这将创建两个服务:github-runner-configure.service(在主机启动完成后运行一次)和 github-runner.service(运行 Actions 运行器二进制文件并等待新的 CI/CD 作业)。

现在 Butane 配置已经完成,从中生成一个 Ignition 文件并配备一个 Fedora CoreOS Actions 运行器。

$ podman run -i --rm -v $PWD:/code:z --workdir /code quay.io/coreos/butane:release --pretty --strict --files-dir /code config.yaml -o config.ignition

一旦 Ignition 文件生成,它就可以用来在 支持 Fedora CoreOS 的平台上配备一个运行器。

配置一个 Action 来使用一个自托管的运行器

下面的测试 Action 工作流程将测试 FCOS 的自托管的运行器。在你的 git 存储库中创建以下文件 .github/workflows/main.yml

# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the action will run.
on:
  # Triggers the workflow on push or pull request events but only for the main branch
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: fcos

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Runs a single command using the runners shell
      - name: Run a one-line script
        run: podman run --rm fedora-minimal:34 echo Hello World !

请注意,runs-on 的配置被设置为使用标签为 fcos 的运行器。

本文介绍的代码可以在 这里 中找到。


via: https://fedoramagazine.org/run-github-actions-on-fedora-coreos/

作者:Clément Verna 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

新恶意程序正利用 WSL 隐蔽攻击 Windows

安全专家发现了针对 WSL 创建的恶意 Linux 安装文件。首批针对 WSL 环境的攻击样本在今年 5 月初被发现,并每过一段时间就出现一次。这表明黑客正在尝试用新的方法来破坏 Windows 设备,并利用 WSL 以逃避检测。这些恶意文件主要依靠 Python 3 来执行其任务,并打包成用于 Linux 的 ELF 可执行文件。

这真是无孔不入,恶意软件就以这种形式将 Linux 当成了目标。

Travis CI 漏洞暴露数千开源项目的密钥

Travis CI 是一个流行的持续集成工具,它提供了与 GitHub 和 Bitbucket 等的无缝整合,能直接克隆用户在 GitHub 中的代码库,然后在虚拟环境中进行构建和测试。它被 90 万个开源项目使用。安全研究人员发现了它的一个严重安全漏洞,会导致 Travis CI 曝光使用它测试的仓库的安全环境变量,如签名密钥、访问证书和 API 令牌。这可能会导致攻击者可借此进入组织的网络。安全研究人员建议所有使用 Travis CI 的项目更换相关的密钥和令牌。而在此事件中,Travis CI 对安全问题的漫不经心激怒了开发者社区,他们甚至要求 GitHub 禁用 Travis CI。

作为一家普遍应用的 CI 服务商,这样对信息安全和开发者的漠视,必将带来更大的问题。GitHub Action 不香么?

Alphabet 采用激光技术实现 5 公里传输 700TB 数据

Google 母公司 Alphabet 关闭了探索将氦气球投放至平流层以实现无线互联网覆盖的项目,但该项目中的用于连接高空气球的自由空间光通信链路(FSOC)等技术保留了下来。目前这项技术正被用于为非洲人民提供高速宽带链接。这种链路有点像是没有电缆的光纤。X 实验室表示,该链路在短短 20 天之内传输了近 700 TB 数据。

这种技术在某些场景下很有意义啊,其实包括它的气球项目,在救灾等恶劣环境都很有用。

你如何定义持续集成/持续部署管道取决于你组织的要求。

 title=

持续集成 continuous integration / 持续部署 continuous deployment (CI/CD)管道是每个 DevOps 计划的基础。 CI/CD 管道打破了传统的开发孤岛,使开发和运营团队能够在整个软件开发生命周期中进行协作。

更好的是,转向 DevOps 和 CI/CD 管道可以帮助你的组织以更高的速度更安全地 交付软件

拆解 CI/CD 管道

CI/CD 管道有很多定义,所以我总是建议组织定义自己的 CI/CD 管道版本和其他 DevOps 概念,而不是使用其他人的。开源 CI/CD 工具为你提供构建满足组织要求的 CI/CD 管道的自由和选择。

形成 CI/CD 管道的阶段是将不同的任务子集分组为 管道阶段。典型的管道阶段包括:

  • 构建:开发人员编译应用程序代码。
  • 测试:质量保证(QA)团队使用自动化测试工具和策略测试应用程序代码。
  • 发布:开发团队将应用程序代码交付到代码库。
  • 部署:DevOps 团队将应用程序代码分阶段投入生产。
  • 安全性和合规性:QA 团队根据项目要求验证构建。这是组织部署容器扫描工具的阶段,这些工具根据 常见漏洞和暴露 Common Vulnerabilities and Exposures (CVE)检查容器镜像的质量。

这些是 CI/CD 管道的标准阶段,但一些组织调整 CI/CD 管道模型以满足他们的要求。例如,为医疗保健市场构建应用程序的组织,具有严格的合规性标准,可以在整个工具链中分发测试、验证和合规性门槛。

其他示例可能是依赖于具有开源软件(OSS)的复杂软件供应链的组织。商业组件可能会设立一个门槛,开发团队成员可以在其中为 OSS 包生成 软件物料清单 software bill of materials (SBOM),或者外部商业软件供应商必须将 SBOM 作为其合同可交付成果的一部分进行交付。

CI/CD 管道的障碍

实施 CI/CD 管道会改变团队的流程和文化。尽管许多开发人员愿意接受某些任务和测试的自动化,但人员可能成为采用 CI/CD 的障碍。

从瀑布式流程转向 CI/CD 可能会动摇某些组织中基本的和隐含的权力结构。由于 CI/CD 管道提高了软件交付速度,旧手动流程的“守门人”可能会受到这种变化的威胁。

整合机会

随着你在文化、流程和工具中达到更高的 DevOps 成熟度水平,包含 CI/CD 工具链的工具的开源根源为一些激动人心的集成创造了机会。

分析公司 Forrester 在 2020 年预测, 即时学习 just-in-time learning 将加入 CI/CD 管道。如果你考虑一下,会发现这是有道理的。在当前远程工作的时代,甚至对于新员工的远程入职,这更有意义。例如,组织可以将文档 wiki 与内部流程文档集成到其管道中。

更雄心勃勃的组织可以将学习管理系统(LMS)(例如 Moodle)集成到其 CI/CD 管道中。它可以使用 LMS 发布有关新 DevOps 工具链功能的简短视频,开发人员在加入时或在整个管道中更新工具时需要学习这些功能。

一些组织正在将群聊和其他协作工具直接集成到他们的 CI/CD 管道中。聊天平台提供警报并支持团队之间的协作和沟通。将 Mattermost、Rocket.Chat 或其他 企业聊天 平台集成到你的 CI/CD 管道中需要预先规划和分析,以确保管道用户不会被警报淹没。

另一个需要探索的集成机会是将分析和高级报告构建到你的 CI/CD 管道中。这有助于你利用通过管道传输的数据。

总结

CI/CD 管道是 DevOps 的基础。开源使其能够适应并灵活地满足你在 DevOps 之旅中实施的运营变更所产生的新需求。

我希望看到对统一 DevOps 平台趋势的开源响应,在这种趋势中,组织寻求端到端的 CI/CD 解决方案。这种解决方案的要素就在那里。毕竟,GitLab 和 GitHub 将他们的平台追溯到开源根源。

最后,不要忘记每一个成功的 CI/CD 工具链背后的教育和外展。记录你的工具链和相关流程将改善开发人员入职和持续的 DevOps 团队培训。

你和你的组织如何定义你的 CI/CD 工具链?请在评论中分享你的反馈。


via: https://opensource.com/article/21/6/what-cicd-pipeline

作者:Will Kelly 选题:lujun9972 译者:baddate 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

LCTT 的 CI 已经在 Travis CI 上运转了多年,一致保持着良好的使用体验。自 2019 年 Github 推出了自家的 CI 工具 Github Action 后,我们就在考虑将 CI 从 Travis-CI 迁移到 Github,以降低维护和沟通的成本,并借助于 GitHub Action Marketplace 实现更强的功能。

项目首页

最近,因为 TravisCI 屡屡部署出错,而我们的账户因为使用的较多,已经超出了免费使用的限制,以此为契机,将 CI 从 Travis CI 迁移到 GitHub Action。

Travis CI 的提醒

项目介绍

Translate ProjectLCTT 翻译组的主要协作项目,几百位译者通过 GitHub 进行围绕开源、Linux、软件工程等领域的文章翻译,从 2013 年来,累计了大量的提交,致使项目下有非常多的文件。

Translate Project 借助于 CI 帮助译者对基本的文章格式和拉取请求进行检查;并定时执行命令,以进行所有的申请检查,对于超时未完成翻译的工作进行回收;对于文章的状态进行标记,生成相应的徽章。

生成徽章

迁移思路

Travis CI 和 Github Action 在使用方面,其实总体差异不会太大,都是基于 YAML 文件格式来编写配置文件。不过,和 Travis CI 不同的是,Github Action 支持多个不同的配置文件,因此,你可以根据不同的场景,设定不同的配置文件,降低单个配置的文件的复杂度。

此外,由于我们的脚本中依赖了一些 Travis CI 的环境变量,也需要将其替换为 Github Action 中的相应环境变量,从而确保脚本可以运转。

改造实践

1. 分析之前的 CI 流程

我们在 TravisCI 上的 CI 配置文件如图:

配置文件

总体可以分为三块:

  1. 命令区:说明了安装阶段和执行阶段的操作有哪些
  2. 条件区:指定了这个配置文件在哪些条件下会生效
  3. 部署区:写明了构建产物如何进行部署

在命令区中,有预置的安装过程和后续的执行过程。在安装过程中,安装了一些依赖,并将当前的 pages 资源克隆到本地,以继承上一次构建生成的资料。

在条件区则指明了仅作用于 master 分支。

在部署区便是将前面命令区的执行结果进行部署。

基本流程

在实际的执行过程中,还会根据环境变量不同,决定是否要执行特定的命令,这部分在后续的改造过程中,就可以调整部署,拆分到不同的文件中。

构建流程

2. 直接套用配置文件

在完成了基本的分析后,就可以建立新的 Action 配置文件了。由于基本的语法很类似,对于其中的不少内容可以进行直接套用。

比如,我们的配置文件在直接套用后,结果如下

直接套用后的结果

直接套用的文件已经可以直接运行,不过,这里有很多不满足需要的地方,所以需要做一些修改。

3. 恢复 Travis CI 的环境变量

由于我们使用的 Badge 等生成脚本并非我所编写,所以在这一次的迁移中,并不打算对齐进行调整,以避免出现故障。而脚本中依赖了一些变量,需要将其重新设置出来。

Github Action 提供了一些方法,可以让你手动设置环境变量。你可以在你的构建的步骤中,加入如下代码,从而在构建环境中设定 TRAVIS_BRANCHTRAVIS_EVENT_TYPE 环境变量,确保你可以使用这个环境变量。

 - name: Set ENV variables
        run: |
 echo "::set-env name=TRAVIS\_BRANCH::${TRAVIS\_BRANCH:-$(echo $GITHUB\_REF | awk 'BEGIN { FS = "/" } ; { print $3 }')}" 
 echo "::set-env name=TRAVIS\_EVENT\_TYPE::$(if [ "schedule" == "${{ github.event\_name }}" ]; then echo "cron"; else echo "${{ github.event\_name }}"; fi)"

此外,由于 set-env 这个方法相对比较危险,你还需要在环境变量中,开启危险函数的执行。

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      ACTIONS\_ALLOW\_UNSECURE\_COMMANDS: true

4. 拆分配置文件

Github Action 和 TravisCI 不同的一点是你可以将你的 CI 文件拆分成多个文件,从而降低每一个单独的配置文件的复杂度。

根据前面对于流程的分析,可以将我们的 CI 流程拆分成三个部分:

  1. 生成 badge 文件,应当跟随每一次提交进行
  2. 生成 status 文件,执行时间较长,可以定期执行
  3. 根据拉取请求内容进行整理,做核验

则将我们的配置文件拆分成三个不同的文件:

也得益于拆分开,则在 checker 中就可以免于安装一些必要的依赖,从而精简 CI 流程,提升 CI 的执行时间。

5. 测试 CI 的运行情况

在完成了配置文件的编写和拆分后,就可以进行本地的执行测试。Github Action 写完了,难免要执行一下,确保整个流程是正常的。

这个时候你可以安装工具(https://github.com/nektos/act),来在本地执行 Action ,从而确认你的代码执行是正确的。

如果你是 macOS ,只需要执行 brew install act 就可以安装 act 工具,来完成 act 的安装。

安装完成 act ,就可以通过执行 act 命令来在本地执行 Action ,比如,执行 act pull_request 来触发 GitHub 的拉取请求事件

通过本地测试后,再将你的配置文件推送到 GitHub 上,进行生产环境的测试即可。

6. 移除 Travis-CI

通过上述的一些步骤,我们完成了从 Travis CI 到 GitHub Action 的迁移,此时,就可以移除项目根目录中的 .travis.yml 文件,彻底关闭 Travis CI。

7. 替换环境变量

在完成了基本的迁移后,需要对代码中的一些历史问题进行修复。在第三步中,我们对于 Travis-CI 的环境变量进行替换,但长期维护的项目应当尽量将这些未标注上下文的信息替换为有文档标注的,因此,我们需要将其替换。

替换环境变量主要依赖 Github 官方的环境变量说明,你可以参考官方文档

简化后,配置文件从之前的 27 行,减少至 17 行,变得更加的精简、易懂。

name: LCTT Article Checker

on:
  pull_request:
    branches: [master]
jobs:
  build:
    runs-on: ubuntu-latest
    env:
      PULL_REQUEST_ID: ${{ github.event.number }}
    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - name: "checkout master branch & return to pull request branch"
        run: CURRENT=$(echo ${{github.ref}} |  sed "s|refs/|refs/remotes/|") && git checkout master && git checkout $CURRENT
      - name: run check
        run: sh ./scripts/check.sh;

8. 修改 GitHub 的分支保护条件

为了确保修改符合标准,我们限制了新的拉取请求必须通过 CI 检查,才能合并进入 master 分支,因此,也需要修改相应的分支保护规则,确保设定相应的保护。

一些注意事项

1. 环境变量不同

如果你依赖了环境变量,则需要进行相应的修改。或者可以像我一样,先通过 set-env 来让本地拥有临时的环境变量,后续再逐步进行迁移。

2. Action 运行依赖要注意安全

Action 执行过程中会有两个部分。Action 本身流程依赖于 master 分支,但执行过程中调用的脚本是根据源决定的,因此,从安全角度来看,你应当尽可能将所有的流程放在 Action 中,而不是放在你的源码目录中。

3. 如何触发 CI 的拉取请求检查?

在进行拉取请求测试的时候,需要不断触发不同的提交 ,你可以通过执行 git commit --allow-empty -m "Trigger notification" && git push 来触发一个空白的提交, 推送到 Github 后,就可以再次触发拉取请求的构建,提升构建的效率。

总结

通过对 TravisCI 的流程整理、代码修改等流程,我们将之前的 Travis-CI 迁移至速度更快、性能更好的 GitHub Action ,一方面可以优化我们的工作流,另一方面,也让我们的代码更加简洁明了。

对于还在使用 Travis CI 的项目来说,也可以考虑迁移到 GitHub Action 中,来优化自己的工作流。

参考阅读