Gitea Actions设计
Gitea Actions由多个组件组成。本文档将对它们进行逐个描述。
Act
nektos/act 项目是一个优秀的工具,允许你在本地运行GitHub Actions。 我们受到了它的启发,并思考它是否可能为Gitea运行Actions。
然而,尽管nektos/act被设计为一个命令行工具,但我们实际上需要的是一个专为Gitea修改的Go库。 因此,我们在gitea/act基础上进行了分叉。
这是一个软分叉,将定期跟进上游。 虽然添加了一些 自定义提交,但我们会尽力避免对原始代码进行太多更改。
分叉的 act 只是Gitea特定用途的桥接或适配器。 还添加了一些额外的提交,例如:
- 将执行日志输出到日志记录器钩子,以便报告给Gitea
- 禁用 GraphQL URL,因为Gitea不支持它
- 每个Job启动一个新的容器,而不是重复使用,以确保隔离性。
这些修改没有理由合并到上游。 如果用户只想在本地运行可信的Actions,它们是没有意义的。
然而,将来可能会出现重叠,例如两个项目都需要的必要错误修复或新功能。 在这些情况下,我们将向上游仓库贡献变更。
act runner
Gitea的Runner被称为act runner,因为它基于act。
与其他CIRunner一样,我们将其设计为Gitea的外部部分,这意味着它应该在与Gitea不同的服务器上运行。
为了确保Runner连接到正确的Gitea实例,我们需要使用令牌注册它。 此外,Runner通过声明自己的标签向Gitea报告它可以运行的Job类型。
之前,我们提到工作流文件中的 runs-on: ubuntu-latest
表示该Job将在具有ubuntu-latest
标签的Runner上运行。
但是,Runner如何知道要运行 ubuntu-latest
?答案在于将标签映射到环境。
这就是为什么在注册过程中添加自定义标签时,需要输入一些复杂内容,比如my_custom_label:docker://centos:7
。
这意味着Runner可以接受需要在my_custom_label
上运行的Job,并通过使用centos:7
镜像的Docker容器来运行它。
然而,Docker不是唯一的选择。
act 也支持直接在主机上运行Job。
这是通过像linux_arm:host
这样的标签实现的。
这个标签表示Runner可以接受需要在linux_arm
上运行的Job,并直接在主机上运行它们。
标签的设计遵循格式label[:schema[:args]]
。
如果省略了schema,则默认为host
。
因此,
my_custom_label:docker://node:18
:使用node:18 Docker
镜像运行带有my_custom_label
标签的Job。my_custom_label:host
:在主机上直接运行带有my_custom_label
标签的Job。my_custom_label
:等同于my_custom_label:host
。my_custom_label:vm:ubuntu-latest
:(仅为示例,未实现)使用带有ubuntu-latest
ISO的虚拟机运行带有my_custom_label
标签的Job。
通信协议
由于act runner是Gitea的独立部分,我们需要一种协议让Runner与Gitea实例进行通信。 然而,我们不认为让Gitea监听一个新端口是个好主意。 相反,我们希望重用HTTP端口,这意味着我们需要一个与HTTP兼容的协议。 因此,我们选择使用基于HTTP的gRPC。
我们使用actions-proto-def 和 actions-proto-go 进行连接。 有关 gRPC 的更多信息,请访问其官方网站。
网络架构
让我们来看一下整体的网络架构。 这将帮助您解决一些问题,并解释为什么使用回环地址注册Runner是个不好的主意。
图片中标记了四个网络连接,并且箭头的方向表示建立连接的方向。
连接 1,act runner到Gitea实例
act runner 必须能够连接到Gitea以接收任务并发送执行结果回来。
连接 2,Job容器到Gitea实例
即使Job容器位于同一台机器上,它们的网络命名空间与Runner不同。
举个例子,如果工作流中包含 actions/checkout@v3
,Job容器需要连接到Gitea来获取代码。
获取代码并不总是运行某些Job所必需的,但在大多数情况下是必需的。
如果您使用回环地址注册Runner,当Runner与Gitea在同一台机器上时,Runner可以连接到Gitea。 然而,如果Job容器尝试从本地主机获取代码,它将失败,因为Gitea不在同一个容器中。