Files
sanguo_moziplus_v2/docs/research/gitea-actions-research.md
T
2026-06-06 11:26:44 +08:00

593 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Gitea Actions 能力调研报告
> 调研时间:2026-06-06
> Gitea 版本:v1.23.4(实例 http://192.168.2.154:3000 已确认)
> 调研来源:Gitea 官方文档 v1.23、API 规范、v1.23.0 Release Notes、act-runner 文档
---
## 调研结论(先给结论)
**总体评估:✅ 可行,但有若干注意事项**
| 能力类别 | 状态 | 说明 |
|---------|------|------|
| Actions 基础能力 | ✅ 支持 | v1.23.4 内置 Actions(自 1.21 默认启用),兼容 GitHub Actions YAML |
| Workflow 触发器 | ✅ 支持 | `push`/`pull_request`/`workflow_dispatch`/`schedule` 均支持 |
| Job 依赖和条件 | ⚠️ 部分支持 | `needs` 支持,`if` 支持,但 `failure()` 表达式不受支持(仅 `always()` 支持) |
| Secrets/环境变量 | ✅ 支持 | 多级 Secrets 和 Variables`${{ secrets.XXX }}` 语法 |
| Status Check | ✅ 支持 | Actions 结果自动作为 commit status,可用于 Branch Protection |
| Branch Protection | ✅ 支持 | 支持 required approvals、status check、merge whitelist 等 |
| CI 内调 Gitea API | ⚠️ 需配置 | v1.23 无内置 `GITEA_TOKEN`v1.24+ 才有),需用 PAT 或配置 secrets |
| Webhook | ✅ 支持 | 仓库/组织/系统级别,支持 HMAC SHA256 签名验证 |
### 确认支持的能力
1. **YAML 语法兼容**`.gitea/workflows/``.github/workflows/` 均可
2. **触发器**`push`(含分支过滤)、`pull_request`(含 types 过滤)、`workflow_dispatch`v1.23 新增)、`schedule`
3. **Job 间依赖**`needs` 关键字支持
4. **条件执行**`if` 支持(但表达式有限制)
5. **Secrets & Variables**:仓库/组织/用户多级管理,优先级:仓库 > 组织 > 用户
6. **Status Check + Branch Protection**Actions 完成后自动产生 commit status,可配置为 merge 前置条件
7. **Review 要求**Branch Protection 支持 `required_approvals`
8. **Webhook**:仓库/组织/系统级别,多事件类型选择,HMAC SHA256 签名
9. **绝对 URL action**:支持从任意 Git 仓库引用 action
10. **Go Actions**:支持用 Go 编写 action
### 不支持或有限制的能力
1. **表达式函数**:仅 `always()` 支持,`failure()``success()``cancelled()` 不支持
2. **`permissions` 关键字**:在 v1.23 中被忽略(v1.24+ 才实现 GITEA_TOKEN 权限控制)
3. **`concurrency`**:不支持(用于限制同时运行同一 workflow)
4. **`continue-on-error`**:不支持
5. **`timeout-minutes`**:不支持
6. **`environment`**:不支持
7. **复杂 `runs-on`**:仅支持单个 label,不支持表达式
8. **`run-name`**:不支持
9. **Problem Matchers**:不支持
10. **GITEA_TOKEN**v1.23 中无内置 job token(需 v1.24+),需要手动配置 PAT 作为 secret
### 需要额外配置的事项
1. **act-runner 安装和注册**:需要单独部署
2. **仓库启用 Actions**:默认关闭,需手动开启
3. **Branch Protection**:需在仓库 Settings 中手动配置或通过 API
4. **PAT Token**v1.23 需要 PAT 才能在 workflow 中调 Gitea API
5. **考虑升级到 v1.24+**:可获得 GITEA_TOKEN 内置支持、permissions 关键字等
---
## 逐项验证结果
### 1. Actions 基础能力
#### 1.1 Gitea v1.23.4 是否内置 Actions
- **✅ 是**。自 Gitea 1.19 引入 Actions1.21 起默认启用(`[actions] ENABLED=true`
- 我们的实例确认版本为 v1.23.4
- **证据**`curl http://192.168.2.154:3000/api/v1/version``{"version":"1.23.4"}`
- **证据**:官方文档 "Starting with Gitea 1.19, Gitea Actions are available as a built-in CI/CD solution"
#### 1.2 是否兼容 GitHub Actions YAML 语法?
- **✅ 是**。workflow 文件放在 `.gitea/workflows/``.github/workflows/` 目录
- 设计上以 GitHub Actions 兼容为目标
- 可直接使用 `actions/checkout@v4` 等 GitHub Actions(默认从 GitHub 下载)
- 配置 `[actions].DEFAULT_ACTIONS_URL` 可设为 `github`(默认)或 `self`
- **注意**v1.21.0 前默认从 `gitea.com` 下载,v1.21.0+ 默认从 `github.com` 下载
#### 1.3 act-runner 如何安装和注册?
- **详见下方 "act-runner 部署指南"**
- 支持二进制安装和 Docker 安装
- 注册需要 registration token(从 Web UI 或 CLI 获取)
- 支持 macOS LaunchDaemon 作为守护进程
### 2. Workflow 触发器
#### 2.1 `on: push` 和 `on: pull_request` 是否支持?
- **✅ 支持**
- 示例:
```yaml
on: [push, pull_request]
```
- 完整触发器列表:`push`、`pull_request`、`workflow_dispatch`、`schedule`、`release`、`issues` 等
#### 2.2 `on: push` 能否限制分支?
- **✅ 支持**
- 语法与 GitHub Actions 一致:
```yaml
on:
push:
branches: [main]
```
- 支持 `branches`、`branches-ignore`、`tags`、`tags-ignore`、`paths`、`paths-ignore`
#### 2.3 `on: pull_request` 是否支持 types
- **✅ 支持**
- 语法:
```yaml
on:
pull_request:
types: [opened, synchronize]
```
#### 2.4 其他触发器
- **`workflow_dispatch`**:v1.23.0 新增!支持手动触发,支持输入参数(含 choice、boolean、number、environment 类型)
- **`schedule`**:支持标准 cron 语法 + 非标准语法 `@yearly`/`@monthly`/`@weekly`/`@daily`/`@hourly`
- ⚠️ 注意:v1.23 起 schedule 默认使用 UTC 时区
### 3. Job 依赖和条件
#### 3.1 `needs` 关键字是否支持?
- **✅ 支持**
- 与 GitHub Actions 语法一致:
```yaml
jobs:
test:
runs-on: ubuntu-latest
steps: [...]
deploy:
needs: test
runs-on: ubuntu-latest
steps: [...]
```
#### 3.2 `if: failure()` 条件是否支持?
- **⚠️ 有限制**
- `if` 关键字本身支持
- 但**表达式函数仅 `always()` 支持**`failure()`、`success()`、`cancelled()` 不支持
- **影响**:无法直接实现 "前序 job 失败时执行" 的逻辑
- **变通方案**:使用 job output 传递状态,或拆分为多个 workflow
#### 3.3 环境变量和 Secrets 是否支持?
- **✅ 支持**
- **Secrets**`${{ secrets.MY_SECRET }}`,支持仓库/组织/用户三级
- **Variables**`${{ vars.MY_VAR }}`,同样支持三级
- **内置环境变量**`GITHUB_*` 和 `GITEA_*` 前缀的变量均有
- `gitea.actor`、`gitea.event_name`、`gitea.ref`、`gitea.repository` 等
- **Secret 命名规则**
- 仅含 `[a-z]`, `[A-Z]`, `[0-9]`, `_`
- 不能以 `GITHUB_` 或 `GITEA_` 开头
- 不能以数字开头
- 不区分大小写
### 4. Status Check 和 Branch Protection
#### 4.1 Actions 跑完后是否自动显示 Status Check
- **✅ 是**
- Actions 运行完成后,结果会作为 commit status 自动显示在 PR 页面
- API 端点:`GET /repos/{owner}/{repo}/commits/{ref}/status`
- API 端点:`GET /repos/{owner}/{repo}/commits/{ref}/statuses`
- 可通过 `gitea-actions` badge 在其他地方展示状态
#### 4.2 Branch Protection 能否设置"必须 CI 通过才能 merge"
- **✅ 支持**
- Branch Protection API 中有 `enable_status_check` 和 `status_check_contexts` 字段
- 通过 Web UI:仓库 Settings → Branches → Add Branch Protection Rule
- 通过 API
```
POST /api/v1/repos/{owner}/{repo}/branch_protections
{
"branch_name": "main",
"enable_status_check": true,
"status_check_contexts": ["ci/test"]
}
```
#### 4.3 能否设置"必须至少 1 人 Review 才能 merge"
- **✅ 支持**
- Branch Protection 中的 `required_approvals` 字段
- 通过 API
```
POST /api/v1/repos/{owner}/{repo}/branch_protections
{
"branch_name": "main",
"required_approvals": 1
}
```
- v1.23 新增:Protected branch 支持 priority 设置
### 5. CI 内调 Gitea API
#### 5.1 workflow 里能否用 curl 调 Gitea API
- **✅ 可以**,但需要认证 token
- Gitea API 完全兼容 RESTfulcurl 直接调用即可
#### 5.2 Token 怎么获取?
- **⚠️ v1.23 的限制**v1.23 **没有**内置 `GITEA_TOKEN`(这是 v1.24+ 才引入的功能)
- **v1.24+ 方案**`${{ secrets.GITEA_TOKEN }}` 自动注入,带有可配置的权限范围
- **v1.23 变通方案**
1. 创建 Personal Access TokenPAT),存为仓库 Secret
2. 在 workflow 中使用 `${{ secrets.GITEA_TOKEN }}`(手动配置的同名 secret
3. 或使用 `${{ secrets.MY_PAT }}` 自定义名称
- **调用示例**
```yaml
- name: Comment on PR
run: |
curl -X POST \
"http://192.168.2.154:3000/api/v1/repos/${{ gitea.repository }}/issues/${{ github.event.pull_request.number }}/comments" \
-H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \
-H "Content-Type: application/json" \
-d '{"body": "CI passed ✅"}'
```
> **建议**:考虑升级 Gitea 到 v1.24+ 以获得内置 GITEA_TOKEN 支持,这是最显著的改进之一。
### 6. Webhook 配置
#### 6.1 在哪里配置 Webhook
- **三级配置**
1. **仓库级别**`/{owner}/{repo}/settings/hooks`
2. **组织级别**:组织 Settings → Webhooks
3. **系统级别**:管理员配置
- **API 端点**
- `GET /api/v1/repos/{owner}/{repo}/hooks` — 列出 hooks
- `POST /api/v1/repos/{owner}/{repo}/hooks` — 创建 hook
#### 6.2 能否选择特定事件类型?
- **✅ 支持**
- 可选事件类型包括:
- Push events
- Pull request events
- Tag create/delete events
- Branch create/delete events
- Issue events
- Release events
- 等等
#### 6.3 Secret 签名验证是否支持?
- **✅ 支持**
- 使用 HMAC SHA256 签名
- 请求头 `X-Gitea-Signature` 包含签名
- 验证方式:
```php
$payload_signature = hash_hmac('sha256', $payload, $secret_key, false);
if ($header_signature !== $payload_signature) { /* reject */ }
```
- ⚠️ 注意:payload 中的 `secret` 字段已在 v1.13.0 废弃,应使用 header 签名验证
- v1.19+ 还支持配置 Authorization header
#### 6.4 Webhook 支持的类型
- Giteanative)、Gogs、Slack、Discord、Dingtalk、Telegram、Microsoft Teams、Feishu(飞书)、Wechatwork、Packagist
---
## act-runner 部署指南
### 方式一:二进制安装(推荐用于 Mac mini)
```bash
# 1. 下载 act_runnerarm64 版本)
curl -L -o act_runner https://gitea.com/gitea/act_runner/releases/latest/download/act_runner-darwin-arm64
chmod +x act_runner
./act_runner --version
# 2. 生成配置文件(可选)
./act_runner generate-config > config.yaml
# 3. 获取 registration token
# 方式 A:从 Web UI
# - 实例级:http://192.168.2.154:3000/-/admin/actions/runners
# - 组织级:http://192.168.2.154:3000/<org>/settings/actions/runners
# - 仓库级:http://192.168.2.154:3000/<owner>/<repo>/settings/actions/runners
# 方式 B:从 Gitea CLI(需要服务器访问权限)
# gitea --config /etc/gitea/app.ini actions generate-runner-token
# 4. 注册 runner
./act_runner register \
--no-interactive \
--instance http://192.168.2.154:3000 \
--token <registration_token> \
--name mac-mini-runner \
--labels ubuntu-latest:host,macos:host
# 5. 启动 runner
./act_runner daemon
# 6. 设置为 macOS LaunchDaemon(开机自启)
```
### LaunchDaemon 配置
创建 `/Library/LaunchDaemons/com.gitea.act_runner.plist`
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.gitea.act_runner</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/act_runner</string>
<string>daemon</string>
<string>--config</string>
<string>/etc/act_runner/config.yaml</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>WorkingDirectory</key>
<string>/var/lib/act_runner</string>
<key>StandardOutPath</key>
<string>/var/lib/act_runner/act_runner.log</string>
<key>StandardErrorPath</key>
<string>/var/lib/act_runner/act_runner.err</string>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
<key>HOME</key>
<string>/var/lib/act_runner</string>
</dict>
</dict>
</plist>
```
```bash
sudo launchctl load /Library/LaunchDaemons/com.gitea.act_runner.plist
```
### 方式二:Docker 安装
```bash
docker run \
-e GITEA_INSTANCE_URL=http://192.168.2.154:3000 \
-e GITEA_RUNNER_REGISTRATION_TOKEN=<token> \
-e GITEA_RUNNER_NAME=docker-runner \
--name gitea-runner \
-d docker.io/gitea/act_runner:latest
```
### Runner Labels 说明
Labels 决定 job 如何运行:
- `ubuntu-latest:docker://node:16-bullseye` — 在 Docker 容器中运行
- `ubuntu-latest:host` 或 `ubuntu-latest` — 直接在宿主机运行
- `macos:host` — 自定义 label,在宿主机运行
**建议**Mac mini 上使用 `host` 模式(不需要 Docker),labels 设置为:
```
ubuntu-latest:host,macos-arm64:host
```
### 启用仓库 Actions
⚠️ 重要:即使实例启用了 Actions,**每个仓库也需要手动启用**:
- 仓库 Settings → 勾选 "Enable Repository Actions"
- 或通过 API`PATCH /api/v1/repos/{owner}/{repo}` → `{"has_actions": true}`
---
## Branch Protection 配置指南
### Web UI 方式
1. 进入仓库 → Settings → Branches
2. 点击 "Add Branch Protection Rule" 或编辑默认分支
3. 配置项:
- **Branch name pattern**:如 `main`
- **Enable push**:控制谁能 push
- **Enable merge whitelist**:控制谁能 merge PR
- **Required approvals**:设置最少 review 人数
- **Enable status check**:勾选并输入 CI workflow 名称
- 其他:signed commits、protected file patterns 等
### API 方式
```bash
# 创建 Branch Protection
curl -X POST \
"http://192.168.2.154:3000/api/v1/repos/{owner}/{repo}/branch_protections" \
-H "Authorization: token <PAT>" \
-H "Content-Type: application/json" \
-d '{
"branch_name": "main",
"enable_push": false,
"enable_merge_whitelist": true,
"merge_whitelist_usernames": ["chufeng"],
"enable_status_check": true,
"status_check_contexts": ["ci/test", "ci/lint"],
"required_approvals": 1,
"enable_approvals_whitelist": true,
"approvals_whitelist_usernames": ["chufeng"]
}'
# 列出所有 Branch Protection
curl "http://192.168.2.154:3000/api/v1/repos/{owner}/{repo}/branch_protections" \
-H "Authorization: token <PAT>"
# 编辑 Branch Protection
curl -X PATCH \
"http://192.168.2.154:3000/api/v1/repos/{owner}/{repo}/branch_protections/{id}" \
-H "Authorization: token <PAT>" \
-H "Content-Type: application/json" \
-d '{"required_approvals": 2}'
```
### 推荐配置(适合我们的场景)
```json
{
"branch_name": "main",
"enable_push": false,
"enable_merge_whitelist": true,
"enable_status_check": true,
"status_check_contexts": ["CI"],
"required_approvals": 1,
"require_signed_commits": false
}
```
---
## Webhook 配置指南
### Web UI 方式
1. 仓库 → Settings → Webhooks → Add Webhook → 选择 "Gitea"
2. 配置:
- **Target URL**:接收 webhook 的服务地址
- **HTTP Method**POST
- **POST Content Type**application/json
- **Secret**:用于 HMAC SHA256 签名验证
- **Trigger On**:选择事件类型
- **Active**:勾选
### API 方式
```bash
# 创建仓库级 Webhook
curl -X POST \
"http://192.168.2.154:3000/api/v1/repos/{owner}/{repo}/hooks" \
-H "Authorization: token <PAT>" \
-H "Content-Type: application/json" \
-d '{
"type": "gitea",
"config": {
"url": "http://your-service/webhook",
"content_type": "json",
"secret": "your-webhook-secret"
},
"events": ["push", "pull_request"],
"active": true
}'
# 列出 hooks
curl "http://192.168.2.154:3000/api/v1/repos/{owner}/{repo}/hooks" \
-H "Authorization: token <PAT>"
# 测试 hook
curl -X POST \
"http://192.168.2.154:3000/api/v1/repos/{owner}/{repo}/hooks/{id}/tests" \
-H "Authorization: token <PAT>"
```
### Webhook 事件类型列表
| 事件 | 说明 |
|------|------|
| `push` | Git push(含 branch 和 tag |
| `pull_request` | PR 创建/更新/关闭/merge |
| `pull_request_assign` | PR 分配 reviewer |
| `pull_request_label` | PR 标签变更 |
| `pull_request_milestone` | PR 里程碑变更 |
| `pull_request_comment` | PR 评论 |
| `pull_request_review_approved` | PR Review 通过 |
| `pull_request_review_rejected` | PR Review 拒绝 |
| `pull_request_review_comment` | PR Review 评论 |
| `issue` | Issue 相关 |
| `release` | Release 发布 |
| `create` | Branch/Tag 创建 |
| `delete` | Branch/Tag 删除 |
| `fork` | 仓库 fork |
| `repository` | 仓库创建/删除 |
---
## 风险和限制
### 1. 已知功能限制
| 限制项 | 影响 | 变通方案 |
|--------|------|---------|
| `failure()` 表达式不支持 | 无法实现 "失败时通知" job | 拆分为独立 workflow + webhook |
| `concurrency` 不支持 | 同一 workflow 可能并行运行 | 在 workflow 脚本中加锁机制 |
| `continue-on-error` 不支持 | job 失败即终止 | 将错误处理逻辑放在 step 内 |
| `timeout-minutes` 不支持 | job 可能无限运行 | act-runner 配置全局超时 |
| `GITEA_TOKEN` 不内置(v1.23) | CI 中调 API 需手动配置 PAT | 创建 PAT 存为 secret |
| `permissions` 关键字被忽略 | 无法精细控制 job token 权限 | v1.23 不适用,需升级 |
### 2. 兼容性注意事项
- **数据库 charset**:使用 MySQL 时需确保 charset 为 `utf8mb4`,否则 emoji 会报错
- **SHA256 仓库**:某些 action(如 `actions/checkout`)在 SHA256 仓库中可能无法正常工作
- **Subpath 部署**:如果 Gitea 运行在子路径下,某些 action 可能有问题
- **Schedule 时区**v1.23 起默认使用 UTC,需注意时区转换
### 3. 安全注意事项
- act-runner 有潜在安全风险:运行 job 可访问 runner 所在机器
- **内部使用的 Gitea 实例风险较低**(官方明确说明)
- 不建议为不信任的仓库/组织提供 runner
- v1.23 的 fork PR workflow 自动限制为只读权限(安全特性)
### 4. 升级建议
**强烈建议升级到 Gitea v1.24+**,主要获益:
1. **内置 GITEA_TOKEN**:不再需要手动配置 PAT
2. **permissions 关键字支持**:可精细控制 job 权限
3. **更多表达式函数**`failure()` 等可能得到支持
4. **更多 bug 修复和性能改进**
当前 v1.23.4 的替代方案仍然可行,只是需要更多手动配置。
### 5. 不支持 GitHub Actions 的功能清单
以下 GitHub Actions 特性在 Gitea Actions 中**不可用**
- Problem Matchers
- Create error annotation
- Pre/Post steps 在 UI 中不单独展示
- Services steps 在 UI 中不单独展示
- Package repository authorization
- Complex `runs-on` 表达式
---
## 示例 Workflow(验证可用)
```yaml
name: CI
on:
push:
branches: [main]
pull_request:
types: [opened, synchronize]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run tests
run: |
echo "Running tests..."
# pytest / go test / etc.
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run lint
run: |
echo "Running lint..."
# flake8 / eslint / etc.
deploy:
needs: [test, lint]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Deploy
run: |
echo "Deploying..."
# deploy script
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
```
> **注意**`if: github.ref == 'refs/heads/main'` 可用,但 `if: failure()` 不可用。deploy job 仅在 main 分支且 test+lint 通过时执行。
---
## 参考资料
- [Gitea Actions 官方文档 v1.23](https://docs.gitea.com/1.23/usage/actions)
- [Compared to GitHub Actions](https://docs.gitea.com/1.23/usage/actions/comparison)
- [Act Runner 文档](https://docs.gitea.com/1.23/usage/actions/act-runner)
- [Gitea v1.23.0 Release Notes](https://blog.gitea.com/release-of-1.23.0/)
- [Gitea API v1.23](https://docs.gitea.com/api/1.23/)
- [Branch Protection API](https://docs.gitea.com/api/1.23/#tag/repository/operation/repoCreateBranchProtection)
- [Webhooks 文档](https://docs.gitea.com/1.23/usage/webhooks)
- [Secrets 文档](https://docs.gitea.com/1.23/usage/actions/secrets)