由于 D-Installer 由多个组件组成,例如 D-Bus 后端、CLI 或 Web 前端,我们需要在 CI 中测试每个组件是否可以启动并正确地相互通信。为此,我们使用了一个测试框架,更重要的是 GitHub CI,我们需要一个 systemd 容器,但对此没有文档记录。在接下来的段落中,我们想与您分享我们是如何做到的,以便您从中获得启发或将其用于您自己的项目。

包含 Systemd 的容器

我们在 构建服务 中创建了一个测试容器,其中包含后端和前端所需的内容。经过几次迭代,我们发现我们依赖于 NetworkManager,它与 systemd 紧密耦合。此外,我们还需要访问 journal 以进行调试,这在没有 systemd 的情况下也无法工作。出于这些原因,我们决定包含 systemd。

如果您感兴趣,可以在 YaST:Head:Containers/d-installer-testing 中找到该容器,但您应该知道它有一些限制(例如,第一个进程必须是 systemd init)。

GitHub CI

在 Google 上搜索,我们没有找到关于在 GitHub CI 上运行 systemd 容器的相关信息。但是,我们读到了一条建议,由于其对 systemd 的高级支持(默认启用),因此可以使用 Podman 来处理此类容器。但对于使用 Podman,大多数答案建议使用自托管 workers,这是我们不想维护的。

仅仅在 GitHub CI 上运行 systemd 容器不起作用,因为 GitHub 将入口点设置为 tail -f(即,systemd init 不是第一个进程)。但是,我们注意到 GitHub 中的 Ubuntu VM 主机预装了 Podman。因此,解决方案变得显而易见。

GitHub CI、Podman 和 Systemd 容器

这个想法是在 GitHub CI 的步骤中使用我们的 systemd 容器运行 Podman。我们根本没有定义 container 关键字,只是手动运行它。每个步骤都封装在 podman container exec 中。

一个配置示例如下

  integration-tests:
    runs-on: ubuntu-latest

    steps:

    - name: Git Checkout
      uses: actions/checkout@v3

    - name: start container
      run: podman run --privileged --detach --name dinstaller --ipc=host -v .:/checkout registry.opensuse.org/yast/head/containers/containers_tumbleweed/opensuse/dinstaller-testing:latest

    - name: show journal
      run:  podman exec dinstaller journalctl -b

此片段签出存储库,启动容器并打印 journal 的内容。重要的是设置容器的名称,以便可以在 exec 调用中使用它。此外,它将 Git 签出挂载到容器上,以便从那里访问它。

当然,如何使用容器进行实际测试取决于您,但至少您有一个可用的 systemd 容器,并且可以检查日志。您可以在 pull request https://github.com/yast/d-installer/pull/425 中看到完整的配置。

剩余问题

对于 D-Installer 的集成测试,我们仍然面临一些问题

  • 不同的内核:Ubuntu VM 具有不同的内核,我们发现缺少 device mapper 内核模块。
  • 受限权限:即使在特权容器上,也不是所有操作都可行的。例如,我们无法将主机的 /var/log 挂载到容器的 /var/log,这对于获取日志工件非常方便。
  • 无法测试整个安装:我们无法“覆盖”主机 VM,因此无法执行整个安装过程的完整端到端测试。更不用说这可能需要相当长的时间(并且对于每个 pull request 而言)。但这没关系:我们的 openQA 实例将负责运行这些测试,尽管我们仍在讨论实现的最佳方法。