- 新增 chi 路由示例并更新依赖 - 用简单 CI 实践笔记替换 Polaris 部署笔记 - 添加本地 Gitea 与 runner 配置示例,注册令牌从环境变量读取
5.8 KiB
Gitea 简单 CI 实践
用 Gitea Actions 给仓库搭一条最简单的持续集成:推送代码后自动做语法检查、跑单元测试。
1. 启用 Gitea Actions
- Gitea 1.21 及以上版本的实例默认启用 Actions(
app.ini中[actions] ENABLED默认为 true); - 但仓库级默认禁用,需在仓库 设置 → Actions 中打开。
2. 准备并注册 act_runner
job 由 act_runner 执行,可以二进制安装或者容器安装,官方文档:https://docs.gitea.com/runner/
准备前提:
- runner 所在机器能通过网络访问 Gitea 实例;
- 本例用 Docker 执行器(label 里的
docker://前缀),runner 所在机器需有可用的 Docker。
本地 Compose 示例 用 gitea/runner 容器跑 Runner:
首次启动时 entrypoint 读取 GITEA_INSTANCE_URL、GITEA_RUNNER_REGISTRATION_TOKEN、
GITEA_RUNNER_LABELS 自动完成注册,注册结果写入挂载的 /data 下的 .runner
文件并持久化,重启容器不必手动注册。只有不用 Compose、直接安装二进制运行时,
才需要手动执行注册与启动命令(见官方文档)。
注册令牌等同凭据:妥善保管,只在环境变量、secrets 或 runner 自己的配置文件里 出现,不要写进命令行历史、文档或仓库文件。
label 的格式是 名称:执行器://参数:以 Compose 中的
demo-ci:docker://node:22-bookworm 为例,名称为 demo-ci,
执行器为 Docker,参数为 job 容器镜像 node:22-bookworm。
工作流的 runs-on 按名称部分匹配。
Runner 的 Docker 运行方式
docker:// 表示 job 在容器中运行,但不决定 Runner 使用哪一个 Docker daemon:
| 术语 | 含义 | 取舍 |
|---|---|---|
| DinD(Docker-in-Docker) | Runner 容器里另起 Docker daemon,由它创建 job 容器 | 与宿主 Docker 分开;job 默认也与外层 Compose 网络分开,需要配置访问 Gitea 的路径 |
| DooD(Docker-outside-of-Docker) | Runner 通过宿主机 Docker socket 使用宿主 daemon,不在容器里另起 daemon | 配置和缓存复用较简单;能接触 socket 的 job 可能控制宿主 Docker,不宜在共享宿主上运行不可信代码 |
| Rootless | Docker daemon 以非 root 身份运行,不是 DinD 的反义词 | 可以与 DinD 组合;降低部分权限风险,但仍需留意网络、存储限制及宿主资源访问 |
本地 Compose 示例 使用需要特权容器的 3-dind,
并非 Rootless。三种术语并不处于同一分类:DinD / DooD 说明使用哪个 daemon,
Rootless 说明daemon 以什么权限运行;它也不等于完全隔离。
3. 最小 Node demo
两个零依赖文件,放在仓库根目录。
demo.js(CommonJS,一个加法函数):
function add(a, b) {
return a + b;
}
module.exports = { add };
demo.test.js(用 Node 内置的 node:test 与 node:assert/strict):
const test = require('node:test');
const assert = require('node:assert/strict');
const { add } = require('./demo');
test('整数相加', () => {
assert.equal(add(1, 2), 3);
});
test('负数相加', () => {
assert.equal(add(-1, -2), -3);
});
先在本地验证能跑:node --test demo.test.js。
4. 编写工作流
在仓库根目录新建 .gitea/workflows/ci.yml:
name: Demo CI
on:
push:
branches: [main] # 默认分支不是 main 的仓库按需修改
jobs:
test:
runs-on: demo-ci
steps:
- name: 检出仓库
uses: https://gitea.com/actions/checkout@v4
- name: 语法检查
run: node --check demo.js && node --check demo.test.js
- name: 运行测试
run: node --test demo.test.js
要点:
runs-on: demo-ci必须与 runner 注册 label 的名称部分一致;- Gitea 中
uses不带完整 URL 时默认从 GitHub 拉取,这里显式写 gitea.com 的绝对地址;runner 仍需能访问该 action 源; - job 会跑在 label 指定的
node:22-bookworm容器里:Node 内置测试运行器 开箱即用,不需要npm install,也没有任何第三方依赖。
5. 推送并查看结果
git add demo.js demo.test.js .gitea/workflows/ci.yml
git commit -m "add demo CI"
git push
打开仓库 Actions 页,能看到这次 push 触发的 run; 点进 job 可展开每个 step 的日志。
常见排查:
| 现象 | 排查方向 |
|---|---|
| run 一直等待、没有 job 被领取 | 仓库 Actions 是否启用;runner 是否在线(runner 页看状态);runs-on 与 runner label 名称是否一致。不同版本对不匹配的处理有差异,结合 runner 日志与实际执行环境核对 |
| checkout 步骤失败或超时 | runner 到 Gitea 实例、到 action 源(gitea.com)的网络连通性 |
| 语法检查或测试失败 | 直接看该 step 日志里的报错/断言输出,在本地用同样命令复现 |
本地用 Compose + Docker-in-Docker 时,还要区分 runner 容器与 job 容器的网络:
runner 能解析 gitea,不代表 job 也能。若 checkout 的 git fetch 报
Could not resolve host: gitea,先检查 job 容器能否访问 Gitea,而不只是检查 runner。
本地测试可在 Runner 配置的 container: 下设 network: host,通过 Compose
挂载该配置、设置 CONFIG_FILE 并重建 runner,见 本地 Compose 示例。
这里的 host 指 runner 容器所在的网络命名空间,不是宿主机网络;job 与 runner
共用网络会降低隔离性,只适合可信的本地测试,不应直接当作生产环境通用方案。
参考
- Gitea Actions 快速上手:https://docs.gitea.com/usage/actions/quickstart/
- act_runner 注册:https://docs.gitea.com/runner/registration/
- act_runner 标签:https://docs.gitea.com/runner/labels/