Files
lab/note/资源/DevOps/Gitea/Gitea 简单 CI 实践.md
labmem d63b006135 feat: 添加 chi 练习与 Gitea CI 实践
- 新增 chi 路由示例并更新依赖
- 用简单 CI 实践笔记替换 Polaris 部署笔记
- 添加本地 Gitea 与 runner 配置示例,注册令牌从环境变量读取
2026-10-16 15:02:25 +08:00

5.8 KiB
Raw Permalink Blame History

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 共用网络会降低隔离性,只适合可信的本地测试,不应直接当作生产环境通用方案。

参考