跳至主要内容

在 Gitea Actions 上进行开发

·阅读 19 分钟
wolfogre
Gitea 维护者

Gitea 1.19.0 包含一个名为 Gitea Actions 的新功能。这是一个 Gitea 内置的 CI 系统,类似于并兼容 GitHub Actions。

本博客将解释有关 Gitea Actions 的一些详细信息,包括如何使用它以及它的工作原理。需要注意的是,此处提供的信息与当前情况相关,未来可能会过时。

用法

功能预览:Gitea Actions 中,我们讨论了如何试用它。但是,从那时起,一些事情发生了变化,所以让我们再回顾一下。

设置 Gitea

首先,您需要一个版本为 1.19.0 或更高版本的 Gitea 实例。您可以按照 文档 设置一个新的实例或升级现有的实例。如果您想启用 Actions,Gitea 的运行方式无关紧要。

Actions 默认情况下是禁用的(因为它们仍然是正在开发的功能),因此您需要在配置文件中添加以下内容以启用它

[actions]
ENABLED=true

如果您想了解更多信息或在配置过程中遇到任何问题,请参考 配置速查表

设置 Runner

我们有一个名为 act runner 的 Gitea Actions runner 的基本实现。它基于 act 项目。

目前,安装 act runner 的唯一方法是自己编译它,或使用 预构建的二进制文件 之一。还没有 Docker 镜像或其他类型的包管理。目前,act runner 应该从命令行运行。当然,您也可以将其包装在系统服务、supervisord 或 Docker 容器等内容中。

在继续之前,我们建议将其作为命令行运行以确保它与您的环境一起使用,尤其是在您在本地主机上运行 runner 时。为了避免消耗过多资源并影响 Gitea 实例,还建议在与 Gitea 实例不同的机器上启动 runner。

另外,请确保已安装 Docker。虽然这不是严格必需的,但它是一种常见的用法。我们稍后将讨论这一点。

在运行 runner 之前,您应该首先使用以下命令将其注册到您的 Gitea 实例

./act_runner register --no-interactive --instance <instance> --token <token>

需要两个参数,instancetoken

instance 指的是您的 Gitea 实例的地址,例如 http://192.168.8.8:3000https://gitea.com。runner 和作业容器(由 runner 启动以执行作业)将连接到此地址。这意味着它可能与您的 Gitea 实例的 ROOT_URL 不同,后者配置用于 Web 访问。使用环回地址(如 127.0.0.1localhost)总是一个坏主意,我们稍后将讨论这一点。如果您不确定使用哪个地址,LAN 地址通常是正确的选择。

token 用于身份验证和识别,例如 P2U1U0oB4XaRCi8azcngmPCLbRpUGapalhmddh23。它仅使用一次,不能用于注册多个 runner。您可以在 your_gitea.com/admin/runners 中获取 token。

register runner

如果您找不到此页面,则可能是您的 Gitea 版本错误或未启用 Actions。请检查以上步骤。

注册后,当前目录中会出现一个名为 .runner 的新文件。此文件存储注册信息。请勿手动编辑它。如果此文件丢失或损坏,您可以简单地将其删除并重新注册。

最后,是时候启动 runner 了。

./act_runner daemon

您可以在管理页面中看到新的 runner

view runner

您可以访问 gitea/act_runner 获取更多信息。

使用 Actions

即使为 Gitea 实例启用了 Actions,存储库默认情况下仍会禁用 Actions。

要启用它,请转到存储库的设置页面并启用它

enable actions

接下来的步骤可能比较复杂。您需要学习 Actions 的工作流语法 并编写您想要的工作流文件。

但是,我们可以从一个简单的演示开始

name: Gitea Actions Demo
run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
on: [push]
jobs:
Explore-Gitea-Actions:
runs-on: ubuntu-latest
steps:
- run: echo "🎉 The job was automatically triggered by a ${{ gitea.event_name }} event."
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by Gitea!"
- run: echo "🔎 The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
- name: Check out repository code
uses: actions/checkout@v3
- run: echo "💡 The ${{ gitea.repository }} repository has been cloned to the runner."
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
- name: List files in the repository
run: |
ls ${{ gitea.workspace }}
- run: echo "🍏 This job's status is ${{ gitea.status }}."

您可以将其作为扩展名为 .yaml 的文件上传到存储库的 .gitea/workflows/ 目录中,例如 .gitea/workflows/demo.yaml。您可能会注意到这与 GitHub Actions 的快速入门 非常相似。这是因为 Gitea Actions 旨在尽可能与 GitHub Actions 兼容。

请注意,演示文件包含一些表情符号。请确保您的数据库支持它们,尤其是在使用 MySQL 时。如果字符集不是 utf8mb4,则会发生错误,例如 Error 1366 (HY000): Incorrect string value: '\\xF0\\x9F\\x8E\\x89 T...' for column 'name' at row 1。请参阅 数据库准备。或者,您可以使用不带表情符号的此演示

name: Gitea Actions Demo
run-name: ${{ gitea.actor }} is testing out Gitea Actions
on: [push]
jobs:
Explore-Gitea-Actions:
runs-on: ubuntu-latest
steps:
- run: echo "The job was automatically triggered by a ${{ gitea.event_name }} event."
- run: echo "This job is now running on a ${{ runner.os }} server hosted by Gitea!"
- run: echo "The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
- name: Check out repository code
uses: actions/checkout@v3
- run: echo "The ${{ gitea.repository }} repository has been cloned to the runner."
- run: echo "The workflow is now ready to test your code on the runner."
- name: List files in the repository
run: |
ls ${{ gitea.workspace }}
- run: echo "This job's status is ${{ gitea.status }}."

on: [push] 行表示当您将提交推送到此存储库时将触发工作流。但是,当您上传 YAML 文件时,它也会推送一个提交,因此您应该在 Actions 选项卡中看到一个新的任务。

view job

干得好!您已成功开始使用 Actions。

问答

为什么 Actions 未默认启用?

我们知道逐个为整个实例和每个存储库启用 Actions 很烦人,但并非每个人都喜欢或需要此功能。我们认为,在 Gitea Actions 值得进一步特殊处理之前,需要做更多工作来改进它。

我们应该在工作流文件中使用 ${{ github.xyz }} 还是 ${{ gitea.xyz }}

您可以使用 github.xyz,Gitea 将正常工作。如前所述,Gitea Actions 旨在与 GitHub Actions 兼容。但是,我们建议使用 gitea.xyz,以防 Gitea 添加了 GitHub 没有的内容,从而避免在工作流文件中出现不同类型的密钥(并且因为您在 Gitea 上使用此工作流,而不是 GitHub)。不过,这完全是可选的,因为这两个选项目前具有相同的效果。

是否可以为特定组织或存储库注册 runner?

可以,这取决于您在何处获取注册 token。

  • /admin/runners:这是用于实例级 runner,它将为实例中的所有存储库运行作业。
  • /org/<org>/settings/runners:这是用于组织级 runner,它将为组织中的所有存储库运行作业。
  • /<owner>/<repo>/settings/runners:这是用于存储库级 runner,它将为其所属的存储库运行作业。

如果您看不到设置页面,请确保您拥有正确的权限并且已启用 Actions。

请注意,即使存储库有自己的存储库级 runner,它也可能仍然使用实例级或组织级 runner。我们可能会在将来提供控制此选项的功能。

是否可以为特定用户(而不是组织)注册 runner?

还没有。从技术上讲,可以实现,但我们需要讨论它是否必要。

runner 的标签用于什么?

您可能已经注意到,每个 Runner 都有诸如 ubuntu-latestubuntu-22.04ubuntu-20.04ubuntu-18.04 这样的标签。这些标签用于作业匹配。

例如,工作流文件中的 runs-on: ubuntu-latest 表示作业将在具有 ubuntu-latest 标签的 Runner 上运行。您还可以注册 Runner 时添加自定义标签,我们稍后会讨论。

使用诸如 actions/checkout@v3 这样的 Action 时,Runner 将从哪里下载脚本?

您可能知道 GitHub 上有数万个 市场 Action。但是,当您编写 uses: actions/checkout@v3 时,它实际上默认从 gitea.com/actions/checkout(而不是 GitHub)下载脚本。这是 github.com/actions/checkout 的镜像,但不可能镜像所有 Action。因此,当您尝试使用一些尚未镜像的 Action 时,可能会遇到失败。

好消息是,您可以指定 URL 前缀以从任何地方使用 Action。这是 Gitea Actions 中的额外语法。例如

  • uses: https://github.com/xxx/xxx@xxx
  • uses: https://gitea.com/xxx/xxx@xxx
  • uses: http://your_gitea_instance.com/xxx@xxx

请注意,https://http:// 前缀是必需的!

或者,如果您希望您的 Runner 默认从 GitHub 或您自己的 Gitea 实例下载 Action,可以通过设置 [actions].DEFAULT_ACTIONS_URL 来配置。请参阅 配置速查表

这是与 GitHub Actions 的区别之一,但它应该允许用户在运行 Action 的方式上拥有更大的灵活性。

如何限制 Runner 的权限?

Runner 本身没有超出连接到您的 Gitea 实例的权限。当任何 Runner 接收到要运行的作业时,它将临时获得与该作业关联的仓库的有限权限。如果您想授予 Runner 更多权限,使其能够访问更多私有仓库或外部系统,您可以向其传递 密钥

对 Action 进行精细的权限控制是一项复杂的工作。将来,我们将向 Gitea 添加更多选项以使其更具可配置性,例如允许对仓库进行更多写入访问或对同一组织中的所有仓库进行读取访问。

如何避免被黑客攻击?

存在两种可能的攻击类型:未知 Runner 窃取您仓库中的代码或密钥,或者恶意脚本控制您的 Runner。

避免前者意味着不允许您不认识的人为您的仓库、组织或实例注册 Runner。

后者稍微复杂一些。如果您在公司内部使用私有 Gitea 实例,则可能无需担心安全性,因为您信任您的同事并且可以追究他们的责任。

对于公共实例,情况略有不同。以下是我们在 gitea.com 上的做法。

  • 我们只为“gitea”组织注册 Runner,因此我们的 Runner 不会执行来自其他仓库的作业。
  • 我们的 Runner 始终在隔离的容器中运行作业。虽然可以直接在主机上执行此操作,但为了提高安全性,我们选择不这样做。
  • 要为 fork 的拉取请求运行 Action,需要批准。请参阅 #22803
  • 如果有人在 gitea.com 上为其仓库或组织注册了自己的 Runner,我们没有异议,只是不会在我们组织中使用它。但是,他们应该注意确保该 Runner 未被他们不认识的其他用户使用。

act Runner 支持哪些操作系统?

它在 Linux、macOS 和 Windows 上运行良好。虽然理论上支持其他操作系统,但它们需要进一步测试。

需要注意的是,如果您选择直接在主机上运行作业而不是在作业容器中运行,则操作系统之间的环境差异可能会导致意外失败。

例如,在大多数情况下,Windows 上没有 bash,而 act 默认尝试使用 bash 运行脚本。因此,您需要在工作流文件中将 powershell 指定为默认 shell,请参阅 defaults.run

defaults:
run:
shell: powershell

设计

Gitea Actions 具有多个部分。让我们逐一解释。

Act

nektos/act 项目是一个优秀的工具,允许您在本地运行 GitHub Actions。我们从中受到启发,并想知道是否可以为 Gitea 运行 Action。

但是,虽然 nektos/act 被设计为命令行工具,但我们实际需要的是一个针对 Gitea 进行调整的 Go 库。因此,我们将其分叉为 gitea/act

这是一个软分叉,将定期跟踪上游。虽然添加了一些自定义提交,但我们会尽力避免更改太多原始代码。

分叉的 act 只是 Gitea 特定用途的垫片或适配器。已经进行了一些额外的提交,例如

  • 将执行日志输出到日志记录器钩子,以便可以将其报告给 Gitea
  • 禁用 GraphQL URL,因为 Gitea 不支持它
  • 为每个作业启动一个新容器,而不是重复使用以确保隔离。

这些修改没有理由合并到上游。如果用户只想在本地运行受信任的 Action,它们就没有意义。

但是,将来可能会出现重叠,例如上游项目和 Gitea 项目都需要修复的错误或新功能。在这种情况下,我们将把更改贡献回上游仓库。

Act Runner

Gitea 的 Runner 称为 act Runner,因为它基于 act。

与其他 CI Runner 一样,我们将其设计为 Gitea 的外部部分,这意味着它应该在与 Gitea 不同的服务器上运行。

为了确保 Runner 连接到正确的 Gitea 实例,我们需要使用令牌注册它。此外,Runner 将向 Gitea 自我介绍并通过报告其标签声明它可以运行哪种作业。

前面我们提到过,工作流文件中的 runs-on: ubuntu-latest 表示作业将在具有 ubuntu-latest 标签的 Runner 上运行。但是 Runner 如何知道运行 ubuntu-latest 呢?答案在于将标签映射到环境。因此,当您在注册期间添加自定义标签时,您需要输入一些复杂的内容,例如 my_custom_label:docker://centos:7。这意味着 Runner 可以获取需要在 my_custom_label 上运行的作业,并通过使用镜像 centos:7 的 Docker 容器运行它。

但是,Docker 不是唯一的选择。act 还支持直接在主机上运行作业。这是通过诸如 linux_arm:host 这样的标签实现的。此标签表示 Runner 可以获取需要在 linux_arm 上运行的作业,并直接在主机上运行它。

标签的设计遵循 label[:schema[:args]] 格式。如果省略 schema,则默认为 host。所以,

  • my_custom_label:docker://node:18:使用 node:18 Docker 镜像运行标有 my_custom_label 的作业。
  • my_custom_label:host:直接在主机上运行标有 my_custom_label 的作业。
  • my_custom_label:与 my_custom_label:host 相同。
  • my_custom_label:vm:ubuntu-latest:(仅示例,未实现)使用带有 ubuntu-latest ISO 的虚拟机运行标有 my_custom_label 的作业。

通信协议

由于 act Runner 是 Gitea 的一个独立部分,因此我们需要一个协议让 Runner 与 Gitea 实例通信。但是,我们认为让 Gitea 监听新端口不是一个好主意。相反,我们希望重用 HTTP 端口,这意味着我们需要一个与 HTTP 兼容的协议。我们选择使用通过 HTTP 的 gRPC。

我们使用 actions-proto-defactions-proto-go 将它们连接起来。有关 gRPC 的更多信息,请参阅 其网站

网络架构

让我们检查一下整体网络架构。这将帮助您解决一些问题,并解释为什么使用 Gitea 实例的环回地址注册 Runner 不是一个好主意。

network

图片中标出了四个网络连接,箭头的方向表示建立连接的方向。

连接 1,act Runner 到 Gitea 实例

act Runner 必须能够连接到 Gitea 以接收任务并发送回执行结果。

连接 2,作业容器到 Gitea 实例

作业容器具有与 Runner 不同的网络命名空间,即使它们在同一台机器上。例如,如果工作流中包含 actions/checkout@v3,则它们需要连接到 Gitea 以获取代码。获取代码并非始终是运行某些作业所必需的,但在大多数情况下是必需的。

如果您使用环回地址注册 Runner,则 Runner 可以连接到同一台机器上的 Gitea。但是,如果作业容器尝试从 localhost 获取代码,它将失败,因为 Gitea 不在同一个容器中。

连接 3,act Runner 到互联网

当您使用某些操作(例如 actions/checkout@v3)时,Act Runner 会下载脚本,而不是作业容器。默认情况下,它从 gitea.com 下载,因此需要访问互联网。它还默认从 Docker Hub 下载一些 Docker 镜像,这也需要互联网访问。

但是,互联网访问并非严格必要。您可以配置您的 Gitea 实例以从您的内联网设施获取操作或镜像。

事实上,您的 Gitea 实例可以同时充当操作市场和镜像仓库。您可以将 GitHub 上的操作仓库镜像到您的 Gitea 实例,并像往常一样使用它们。并且 Gitea 容器仓库 可用作 Docker 镜像仓库。

连接 4,作业容器到互联网

在使用诸如 actions/setup-go@v4 之类的操作时,可能需要从互联网下载资源以在作业容器中设置 Go 语言环境。因此,这些操作的成功完成需要访问互联网。

但是,这也不是必须的。您可以使用您自己的自定义操作来避免依赖互联网访问,或者您可以使用您打包的 Docker 镜像来运行已安装所有依赖项的作业。

总结

使用 Gitea Actions 只需要确保 Runner 可以连接到 Gitea 实例。互联网访问是可选的,但没有它需要一些额外的工作。换句话说:当 Runner 可以自行查询互联网时,它的工作效果最佳,但您不需要将其暴露在互联网上(无论哪个方向)。

如果您在使用 Gitea Actions 时遇到任何网络问题,希望上面的图片可以帮助您进行故障排除。

问答

为什么选择 GitHub Actions?为什么不选择与 GitLab CI/CD 兼容的东西?

@lunny实现操作的 issue 中解释了这一点。此外,Actions 不仅仅是一个 CI/CD 系统,它还是一个自动化工具。

开源世界中也已经实现了大量 市场操作。能够重用它们非常令人兴奋。

Gitea Actions 是否已实现与 GitHub Actions 的完全兼容?

还没有,我们正在努力。

@ChristopherHX此评论 中提供了 Gitea Actions 和 GitHub Actions 之间差异的出色概述。

如果它在多个标签上运行,例如 runs-on: [label_a, label_b] 会怎样?

这是有效的语法。这意味着它应该在同时具有 label_alabel_b 标签的 Runner 上运行,请参阅 GitHub Actions 的工作流语法。不幸的是,Act Runner 的工作方式并非如此。如前所述,我们将标签映射到环境

  • ubuntuubuntu:22.04
  • centoscentos:8

但我们需要将标签组映射到环境,如下所示

  • [ubuntu]ubuntu:22.04
  • [with-gpu]linux:with-gpu
  • [ubuntu, with-gpu]ubuntu:22.04_with-gpu

我们还需要重新设计任务分配给 Runner 的方式。具有 ubuntucentoswith-gpu 的 Runner 并不一定表示它可以接受具有 [centos, with-gpu] 的作业。因此,Runner 应该通知 Gitea 实例它只能接受具有 [ubuntu][centos][with-gpu][ubuntu, with-gpu] 的作业。这不是技术问题,只是在早期设计中被忽略了。请参阅 runtime.go#L65

目前,Act Runner 尝试匹配标签中的每个人,并使用找到的第一个匹配项。

Runner 的代理标签和自定义标签有什么区别?

labels

代理标签由 Runner 在注册期间报告给 Gitea 实例。另一方面,自定义标签由 Gitea 管理员或组织或仓库的所有者手动添加(取决于 Runner 的级别)。

但是,此处的设计需要改进,因为它目前存在一些粗糙的边缘。您可以向已注册的 Runner 添加一个自定义标签,例如 centos,这意味着 Runner 将接收具有 runs-on: centos 的作业。但是,Runner 可能不知道为此标签使用哪个环境,从而导致它使用默认镜像或导致逻辑死循环。此默认值可能与用户期望不符。请参阅 runtime.go#L71

同时,如果您想更改 Runner 的标签,我们建议您重新注册您的 Runner。

Gitea Actions Runner 会有更多实现吗?

虽然我们希望提供更多选项,但我们有限的人力意味着 Act Runner 将是唯一官方支持的 Runner。但是,Gitea 和 Act Runner 都是完全开源的,因此任何人都可以创建新的/更好的实现。我们支持您的选择,无论您如何决定。如果您分叉 Act Runner 以创建您自己的版本:如果您认为您的更改也会帮助其他人,请回馈更改。

更进一步

享受 Gitea Actions 的乐趣!虽然它可能还不完美,但我们可以共同努力改进它。您可以通过提交问题并加入我们的聊天来讨论它们来报告错误或提出想法。并且像往常一样,欢迎提交 Pull Request!

An icon showing wave propagation

加入我们的社区

Gitea 是开源的。为我们的 GitHub 仓库加星标,并加入我们在 Discord 上的社区!

An icon showing a paper plane

订阅我们的时事通讯

随时了解 Gitea 的所有信息