move claude-marketplace to ai-proj-helper
This commit is contained in:
8
plugins/gitea-plugin/.claude-plugin/plugin.json
Normal file
8
plugins/gitea-plugin/.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "gitea-plugin",
|
||||
"description": "Gitea 代码托管与 CI/CD 管理。用于 Gitea Actions workflow 管理、Runner 管理、PR 操作、仓库配置。",
|
||||
"version": "1.0.0",
|
||||
"author": {
|
||||
"name": "qiudl"
|
||||
}
|
||||
}
|
||||
211
plugins/gitea-plugin/scripts/gitea-runs
Executable file
211
plugins/gitea-plugin/scripts/gitea-runs
Executable file
@@ -0,0 +1,211 @@
|
||||
#!/bin/bash
|
||||
# gitea-runs — Gitea Actions CLI helper
|
||||
# Usage:
|
||||
# gitea-runs List recent runs
|
||||
# gitea-runs list [limit] List recent runs (default 10)
|
||||
# gitea-runs view <run_number> View run details & jobs
|
||||
# gitea-runs open [run_number] Open run in browser
|
||||
# gitea-runs workflows List workflows
|
||||
# gitea-runs dispatch <wf> [ref] Trigger a workflow dispatch
|
||||
# gitea-runs help Show this help
|
||||
|
||||
set -e
|
||||
|
||||
# Config from tea CLI
|
||||
TEA_CONFIG="${XDG_CONFIG_HOME:-$HOME/Library/Application Support}/tea/config.yml"
|
||||
if [ ! -f "$TEA_CONFIG" ]; then
|
||||
TEA_CONFIG="$HOME/.config/tea/config.yml"
|
||||
fi
|
||||
|
||||
# Parse tea config (nested under logins)
|
||||
GITEA_URL=$(grep 'url:' "$TEA_CONFIG" | head -1 | awk '{print $NF}')
|
||||
GITEA_TOKEN=$(grep 'token:' "$TEA_CONFIG" | head -1 | awk '{print $NF}')
|
||||
|
||||
# Detect repo from git remote
|
||||
REPO=$(git remote get-url origin 2>/dev/null | sed 's|.*gitea.pipexerp.com[:/]*||;s|\.git$||;s|^10022/||')
|
||||
if [ -z "$REPO" ]; then
|
||||
echo "Error: not in a git repo or remote not configured"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
API="$GITEA_URL/api/v1"
|
||||
AUTH="Authorization: token $GITEA_TOKEN"
|
||||
|
||||
GREEN='\033[0;32m'
|
||||
RED='\033[0;31m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
cmd_dispatch() {
|
||||
local workflow="${1:-}"
|
||||
local ref="${2:-main}"
|
||||
if [ -z "$workflow" ]; then
|
||||
echo "Usage: gitea-runs dispatch <workflow> [ref]"
|
||||
echo ""
|
||||
echo "Available workflows:"
|
||||
curl -s -H "$AUTH" "$API/repos/$REPO/actions/workflows" 2>/dev/null \
|
||||
| python3 -c "
|
||||
import json, sys
|
||||
data = json.load(sys.stdin)
|
||||
for w in data.get('workflows', []):
|
||||
print(f\" {w['id']:30s} {w['name']}\")
|
||||
" 2>/dev/null
|
||||
return
|
||||
fi
|
||||
|
||||
local http_code
|
||||
http_code=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||
-H "$AUTH" \
|
||||
-H "Content-Type: application/json" \
|
||||
-X POST "$API/repos/$REPO/actions/workflows/$workflow/dispatches" \
|
||||
-d "{\"ref\":\"$ref\"}" 2>/dev/null)
|
||||
|
||||
if [ "$http_code" = "204" ]; then
|
||||
echo -e "${GREEN}✓${NC} Dispatched workflow: $workflow (ref: $ref)"
|
||||
echo " View: $GITEA_URL/$REPO/actions"
|
||||
else
|
||||
echo -e "${RED}✗${NC} Failed to dispatch (HTTP $http_code)"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_workflows() {
|
||||
echo -e "${CYAN}Workflows for $REPO${NC}"
|
||||
echo ""
|
||||
curl -s -H "$AUTH" "$API/repos/$REPO/actions/workflows" 2>/dev/null \
|
||||
| python3 -c "
|
||||
import json, sys
|
||||
data = json.load(sys.stdin)
|
||||
for w in data.get('workflows', []):
|
||||
state = '✓' if w['state'] == 'active' else '✗'
|
||||
print(f\" {state} {w['id']:30s} {w['name']}\")
|
||||
" 2>/dev/null
|
||||
}
|
||||
|
||||
cmd_list() {
|
||||
local limit="${1:-10}"
|
||||
echo -e "${CYAN}Recent runs for $REPO${NC}"
|
||||
echo ""
|
||||
curl -s -H "$AUTH" "$API/repos/$REPO/actions/runs?limit=$limit" 2>/dev/null \
|
||||
| python3 -c "
|
||||
import json, sys
|
||||
limit = $limit
|
||||
data = json.load(sys.stdin)
|
||||
for r in data.get('workflow_runs', [])[:limit]:
|
||||
status = r.get('status', '?')
|
||||
num = r.get('run_number', 0)
|
||||
title = r.get('display_title', '')[:60]
|
||||
wf = r.get('path', '')
|
||||
wf = wf.split('@')[0] if '@' in wf else wf
|
||||
icon = {'success':'\u2713','completed':'\u2713','failure':'\u2717','cancelled':'\u2717','in_progress':'\u27f3','running':'\u27f3','queued':'\u25cc','waiting':'\u25cc'}.get(status, '?')
|
||||
color = {'success':'\033[0;32m','completed':'\033[0;32m','failure':'\033[0;31m','cancelled':'\033[0;31m','in_progress':'\033[0;33m','running':'\033[0;33m'}.get(status, '\033[0;37m')
|
||||
print(f\"{color}{icon}\033[0m #{num:<4} {status:<12} {wf:<20} {title}\")
|
||||
" 2>/dev/null
|
||||
}
|
||||
|
||||
cmd_view() {
|
||||
local run_number="${1:-}"
|
||||
if [ -z "$run_number" ]; then
|
||||
echo "Usage: gitea-runs view <run_number>"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Find run by run_number (API uses internal id, html uses run_number)
|
||||
local run_data
|
||||
run_data=$(curl -s -H "$AUTH" "$API/repos/$REPO/actions/runs?limit=50" 2>/dev/null \
|
||||
| python3 -c "
|
||||
import json, sys
|
||||
data = json.load(sys.stdin)
|
||||
for r in data.get('workflow_runs', []):
|
||||
if r['run_number'] == $run_number:
|
||||
print(json.dumps(r))
|
||||
break
|
||||
" 2>/dev/null)
|
||||
|
||||
if [ -z "$run_data" ]; then
|
||||
echo -e "${RED}✗${NC} Run #$run_number not found"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local run_id
|
||||
run_id=$(echo "$run_data" | python3 -c "import json,sys; print(json.load(sys.stdin)['id'])")
|
||||
|
||||
# Print run info
|
||||
echo "$run_data" | python3 -c "
|
||||
import json, sys
|
||||
r = json.load(sys.stdin)
|
||||
status = r.get('status', '?')
|
||||
icon = {'success':'\u2713','failure':'\u2717','in_progress':'\u27f3','queued':'\u25cc'}.get(status, '?')
|
||||
color = {'success':'\033[0;32m','failure':'\033[0;31m','in_progress':'\033[0;33m'}.get(status, '\033[0;37m')
|
||||
print(f\"{color}{icon} Run #{r.get('run_number',0)} \u2014 {status}\033[0m\")
|
||||
print(f\" Title: {r.get('display_title','')}\")
|
||||
print(f\" Event: {r.get('event','')}\")
|
||||
print(f\" Branch: {r.get('head_branch','')}\")
|
||||
print(f\" Commit: {r.get('head_sha','')[:8]}\")
|
||||
print(f\" Actor: {r.get('actor',{}).get('login','')}\")
|
||||
wf = r.get('path', '')
|
||||
wf = wf.split('@')[0] if '@' in wf else wf
|
||||
print(f\" Workflow: {wf}\")
|
||||
" 2>/dev/null
|
||||
|
||||
# Print jobs
|
||||
echo ""
|
||||
echo -e "${CYAN}Jobs:${NC}"
|
||||
curl -s -H "$AUTH" "$API/repos/$REPO/actions/runs/$run_id/jobs" 2>/dev/null \
|
||||
| python3 -c "
|
||||
import json, sys
|
||||
from datetime import datetime
|
||||
data = json.load(sys.stdin)
|
||||
for j in data.get('jobs', []):
|
||||
status = j.get('status', '?')
|
||||
icon = {'success':'\u2713','failure':'\u2717','in_progress':'\u27f3','queued':'\u25cc','waiting':'\u25cc'}.get(status, '?')
|
||||
color = {'success':'\033[0;32m','failure':'\033[0;31m','in_progress':'\033[0;33m'}.get(status, '\033[0;37m')
|
||||
runner = j.get('runner_name', '-')
|
||||
started = j.get('started_at', '')[:19].replace('T', ' ')
|
||||
completed = j.get('completed_at', '')[:19].replace('T', ' ')
|
||||
duration = ''
|
||||
if completed and not completed.startswith('1970'):
|
||||
try:
|
||||
d = datetime.fromisoformat(completed) - datetime.fromisoformat(started)
|
||||
duration = f' ({int(d.total_seconds())}s)'
|
||||
except: pass
|
||||
print(f\" {color}{icon}\033[0m {j.get('name',''):<30} {status:<12} runner: {runner}{duration}\")
|
||||
" 2>/dev/null
|
||||
}
|
||||
|
||||
cmd_open() {
|
||||
local run_id="${1:-}"
|
||||
local url="$GITEA_URL/$REPO/actions"
|
||||
if [ -n "$run_id" ]; then
|
||||
url="$url/runs/$run_id"
|
||||
fi
|
||||
echo "Opening: $url"
|
||||
open "$url" 2>/dev/null || xdg-open "$url" 2>/dev/null || echo "$url"
|
||||
}
|
||||
|
||||
cmd_help() {
|
||||
echo "gitea-runs — Gitea Actions CLI helper"
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo " gitea-runs List recent runs"
|
||||
echo " gitea-runs list [limit] List recent runs (default 10)"
|
||||
echo " gitea-runs view <run_number> View run details & jobs"
|
||||
echo " gitea-runs open [run_number] Open run in browser"
|
||||
echo " gitea-runs workflows List workflows"
|
||||
echo " gitea-runs dispatch <wf> [ref] Trigger a workflow dispatch"
|
||||
echo " gitea-runs help Show this help"
|
||||
echo ""
|
||||
echo "Repo: $REPO"
|
||||
echo "Gitea: $GITEA_URL"
|
||||
}
|
||||
|
||||
# Main
|
||||
case "${1:-}" in
|
||||
list|ls) shift; cmd_list "$@" ;;
|
||||
view|v) shift; cmd_view "$@" ;;
|
||||
dispatch) shift; cmd_dispatch "$@" ;;
|
||||
workflows|wf) cmd_workflows ;;
|
||||
open|o) shift; cmd_open "$@" ;;
|
||||
help|--help|-h) cmd_help ;;
|
||||
"") cmd_list ;;
|
||||
*) cmd_view "$1" ;;
|
||||
esac
|
||||
281
plugins/gitea-plugin/skills/SKILL.md
Normal file
281
plugins/gitea-plugin/skills/SKILL.md
Normal file
@@ -0,0 +1,281 @@
|
||||
---
|
||||
name: gitea
|
||||
description: Gitea 代码托管与 CI/CD 管理。用于 Gitea Actions workflow 管理、Runner 管理、PR 操作、仓库配置。当用户提到 Gitea、Actions、Runner、CI/CD workflow、PR 检查相关任务时自动激活。
|
||||
---
|
||||
|
||||
# Gitea Skill
|
||||
|
||||
Gitea 代码托管平台管理,覆盖 Actions CI/CD、Runner、PR、仓库配置。
|
||||
|
||||
## 服务器信息
|
||||
|
||||
| 服务 | 地址 | SSH |
|
||||
|------|------|-----|
|
||||
| Gitea Web | https://gitea.pipexerp.com | — |
|
||||
| Gitea SSH | gitea.pipexerp.com:10022 | `ssh -i ~/.ssh/id_ed25519 git@gitea.pipexerp.com -p 10022` |
|
||||
| Gitea 服务器 | 123.56.89.187 | `ssh -i ~/.ssh/tools.pem root@123.56.89.187` |
|
||||
| Runner 服务器 | 101.200.136.200 (Jenkins 服务器) | `ssh -i ~/.ssh/tools.pem root@101.200.136.200` |
|
||||
|
||||
## API 访问
|
||||
|
||||
```bash
|
||||
# Gitea API Token (仓库级)
|
||||
GITEA_TOKEN="483a2b65219625ee382eb6d023cda39238c32e24"
|
||||
|
||||
# 通用请求格式
|
||||
curl -s "https://gitea.pipexerp.com/api/v1/repos/pipexerp/<repo>/..." \
|
||||
-H "Authorization: token $GITEA_TOKEN"
|
||||
```
|
||||
|
||||
### 常用 API
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
|------|------|------|
|
||||
| 创建 PR | POST | `/repos/{owner}/{repo}/pulls` |
|
||||
| 更新 PR | PATCH | `/repos/{owner}/{repo}/pulls/{id}` |
|
||||
| 列出 Runs | GET | `/repos/{owner}/{repo}/actions/runs` |
|
||||
| Run 详情 | GET | `/repos/{owner}/{repo}/actions/runs/{id}` |
|
||||
| Job 详情 | GET | `/repos/{owner}/{repo}/actions/runs/{id}/jobs` |
|
||||
| 手动触发 Workflow | POST | `/repos/{owner}/{repo}/actions/workflows/{file}/dispatches` body: `{"ref":"main"}` |
|
||||
| 获取 Runner Token | POST | `/repos/{owner}/{repo}/actions/runners/registration-token` |
|
||||
| 添加 Secret | PUT | `/repos/{owner}/{repo}/actions/secrets/{name}` body: `{"data":"value"}` |
|
||||
| 删除 Run(仅已完成)| DELETE | `/repos/{owner}/{repo}/actions/runs/{id}` |
|
||||
|
||||
**注意**: Gitea 1.25 **不支持**通过 API cancel 正在排队/运行的 run。
|
||||
|
||||
## 仓库
|
||||
|
||||
| 仓库 | 地址 | 主分支 |
|
||||
|------|------|--------|
|
||||
| coolbuy-paas | pipexerp/coolbuy-paas | main |
|
||||
| dotfiles | huangjun/dotfiles | main |
|
||||
| claude-marketplace | huangjun/claude-marketplace | main |
|
||||
|
||||
## Actions Runners
|
||||
|
||||
### 主 Runner (lint/test/e2e)
|
||||
| 项目 | 值 |
|
||||
|------|-----|
|
||||
| 名称 | jenkins-runner |
|
||||
| 配置 | `/opt/act_runner/config.yaml` |
|
||||
| Capacity | 3 |
|
||||
| Labels | `ubuntu-latest`, `ubuntu-22.04`, `ubuntu-20.04` |
|
||||
| 进程 | `/usr/local/bin/act_runner daemon --config /opt/act_runner/config.yaml` |
|
||||
|
||||
### Deploy Runner (staging 部署专用)
|
||||
| 项目 | 值 |
|
||||
|------|-----|
|
||||
| 名称 | deploy-runner |
|
||||
| 配置 | `/opt/act_runner_deploy/config.yaml` |
|
||||
| Capacity | 1 |
|
||||
| Labels | `deploy:host` |
|
||||
| PID | `/opt/act_runner_deploy/runner.pid` |
|
||||
| 日志 | `/opt/act_runner_deploy/runner.log` |
|
||||
| 启动 | `cd /opt/act_runner_deploy && nohup act_runner daemon --config config.yaml > runner.log 2>&1 &` |
|
||||
|
||||
### 注册新 Runner
|
||||
|
||||
```bash
|
||||
# 1. 获取 registration token
|
||||
curl -s -X POST "https://gitea.pipexerp.com/api/v1/repos/pipexerp/coolbuy-paas/actions/runners/registration-token" \
|
||||
-H "Authorization: token $GITEA_TOKEN"
|
||||
|
||||
# 2. SSH 到 runner 服务器
|
||||
ssh -i ~/.ssh/tools.pem root@101.200.136.200
|
||||
|
||||
# 3. 创建目录和配置
|
||||
mkdir -p /opt/act_runner_<name>
|
||||
cat > /opt/act_runner_<name>/config.yaml << 'EOF'
|
||||
log:
|
||||
level: info
|
||||
runner:
|
||||
file: .runner
|
||||
capacity: 1
|
||||
timeout: 30m
|
||||
labels:
|
||||
- "<label>:host" # host 模式用系统 shell
|
||||
# 或 "<label>:docker://image" # docker 模式
|
||||
cache:
|
||||
enabled: false
|
||||
EOF
|
||||
|
||||
# 4. 注册
|
||||
cd /opt/act_runner_<name>
|
||||
act_runner register --instance https://gitea.pipexerp.com \
|
||||
--token <TOKEN> --name <NAME> --labels '<LABEL>:host' \
|
||||
--config config.yaml --no-interactive
|
||||
|
||||
# 5. 启动
|
||||
nohup act_runner daemon --config config.yaml > runner.log 2>&1 &
|
||||
echo $! > runner.pid
|
||||
```
|
||||
|
||||
### Runner 运维
|
||||
|
||||
```bash
|
||||
# 检查 runner 状态
|
||||
ssh -i ~/.ssh/tools.pem root@101.200.136.200 "ps aux | grep act_runner | grep -v grep"
|
||||
|
||||
# 查看 deploy runner 日志
|
||||
ssh -i ~/.ssh/tools.pem root@101.200.136.200 "tail -20 /opt/act_runner_deploy/runner.log"
|
||||
|
||||
# 重启 deploy runner
|
||||
ssh -i ~/.ssh/tools.pem root@101.200.136.200 "
|
||||
kill \$(cat /opt/act_runner_deploy/runner.pid) 2>/dev/null
|
||||
cd /opt/act_runner_deploy
|
||||
nohup act_runner daemon --config config.yaml > runner.log 2>&1 &
|
||||
echo \$! > runner.pid
|
||||
"
|
||||
```
|
||||
|
||||
## Workflows (coolbuy-paas)
|
||||
|
||||
| Workflow | 触发 | Runner | paths-ignore | 用途 |
|
||||
|----------|------|--------|-------------|------|
|
||||
| 🚀 deploy-staging.yml | push → main | `deploy` | md, docs, .gitea, scripts, *_test.go | 触发 Jenkins 部署到 staging |
|
||||
| 🔍 lint.yml | PR → main | `ubuntu-latest` | md, docs, .gitea, scripts | Go lint + ESLint auto-fix |
|
||||
| 🧪 unit-test.yml | PR → main | `ubuntu-latest` | md, docs, .gitea, scripts | 4 个 Go 服务单元测试 |
|
||||
| 🎭 e2e-tests.yml | schedule 12h | `ubuntu-latest` | — | Playwright E2E(仅定时) |
|
||||
| 📋 notify-aiproj.yml | PR merged | `ubuntu-latest` | — | 同步需求状态到 ai-proj |
|
||||
| 📦 build.yaml | 手动 | `ubuntu-latest` | — | Docker 构建推 Hub |
|
||||
|
||||
### Workflow 编写规范
|
||||
|
||||
```yaml
|
||||
# 1. 名称加 emoji 前缀
|
||||
name: "🚀 Deploy Staging"
|
||||
|
||||
# 2. 非代码变更加 paths-ignore
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths-ignore:
|
||||
- '*.md'
|
||||
- 'docs/**'
|
||||
- '.gitea/**'
|
||||
- 'scripts/**'
|
||||
|
||||
# 3. 加 concurrency 防重复
|
||||
concurrency:
|
||||
group: deploy-staging
|
||||
cancel-in-progress: true
|
||||
|
||||
# 4. 仅定时的 workflow 加 event 守卫
|
||||
jobs:
|
||||
e2e:
|
||||
if: github.event_name == 'schedule'
|
||||
|
||||
# 5. auto-fix 提交加 [skip ci]
|
||||
git commit -m "style: auto-fix [skip ci]"
|
||||
```
|
||||
|
||||
### Checkout 模式(容器内)
|
||||
|
||||
Gitea Actions 不支持 `actions/checkout`,用原生 git:
|
||||
|
||||
```yaml
|
||||
- name: Checkout
|
||||
env:
|
||||
TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
git config --global --add safe.directory "$(pwd)"
|
||||
git init
|
||||
git remote add origin "https://oauth2:${TOKEN}@gitea.pipexerp.com/${{ github.repository }}.git"
|
||||
git fetch origin "${{ github.event.pull_request.head.ref }}"
|
||||
git checkout -b pr-branch "origin/${{ github.event.pull_request.head.ref }}"
|
||||
git config user.name "CI Bot"
|
||||
git config user.email "ci@pipexerp.com"
|
||||
```
|
||||
|
||||
## Secrets 管理
|
||||
|
||||
### 当前 Secrets (coolbuy-paas 仓库级)
|
||||
|
||||
| Secret | 用途 |
|
||||
|--------|------|
|
||||
| `JENKINS_USER` | Jenkins API 用户名 |
|
||||
| `JENKINS_TOKEN` | Jenkins API Token |
|
||||
| `DOCKER_HUB_TOKEN` | Docker Hub 推送 |
|
||||
| `AI_PROJ_TOKEN` | ai-proj API 认证 |
|
||||
|
||||
### 添加/更新 Secret
|
||||
|
||||
```bash
|
||||
curl -s -X PUT \
|
||||
"https://gitea.pipexerp.com/api/v1/repos/pipexerp/coolbuy-paas/actions/secrets/<NAME>" \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"data": "<VALUE>"}'
|
||||
```
|
||||
|
||||
## CI/CD 完整流程
|
||||
|
||||
```
|
||||
PR → main
|
||||
├── 🧪 unit-test.yml (Go 服务测试)
|
||||
├── 🔍 lint.yml (auto-fix 格式)
|
||||
└── merge 后:
|
||||
├── 📋 notify-aiproj.yml (需求状态 → testing)
|
||||
└── 🚀 deploy-staging.yml (Jenkins → staging)
|
||||
├── ≥5 commits/2h → 立即部署
|
||||
└── <5 commits → 等3分钟 debounce
|
||||
|
||||
定时:
|
||||
└── 🎭 e2e-tests.yml (每12h Playwright)
|
||||
|
||||
手动:
|
||||
└── 📦 build.yaml (Docker 构建推 Hub)
|
||||
|
||||
生产部署:
|
||||
└── ./scripts/build-and-push.sh prod --deploy (触发 Jenkins)
|
||||
```
|
||||
|
||||
## 本地 CLI 工具
|
||||
|
||||
### tea CLI (Gitea 官方命令行)
|
||||
|
||||
tea 是 Gitea 官方 CLI 客户端,已配置好认证信息。
|
||||
|
||||
```bash
|
||||
# 配置文件位置
|
||||
~/Library/Application Support/tea/config.yml
|
||||
# 或 ~/.config/tea/config.yml
|
||||
|
||||
# gitea-runs 脚本从 tea config 读取 url 和 token
|
||||
```
|
||||
|
||||
### gitea-runs (Actions 快捷命令)
|
||||
|
||||
位置: `~/.local/bin/gitea-runs`
|
||||
|
||||
自动从 git remote 检测仓库,从 tea CLI 配置读取认证信息。
|
||||
|
||||
| 命令 | 说明 |
|
||||
|------|------|
|
||||
| `gitea-runs` | 列出最近 10 条 run |
|
||||
| `gitea-runs list [N]` | 列出最近 N 条 run |
|
||||
| `gitea-runs view <run_number>` | 查看 run 详情和 jobs |
|
||||
| `gitea-runs open [run_number]` | 在浏览器打开 run 页面 |
|
||||
| `gitea-runs workflows` | 列出所有 workflow |
|
||||
| `gitea-runs dispatch <wf> [ref]` | 手动触发 workflow |
|
||||
|
||||
```bash
|
||||
# 示例
|
||||
gitea-runs # 查看最近 runs
|
||||
gitea-runs view 303 # 查看 run #303 详情
|
||||
gitea-runs dispatch deploy-staging.yml main # 手动触发部署
|
||||
gitea-runs open # 打开 Actions 页面
|
||||
```
|
||||
|
||||
**优先使用 `gitea-runs` 而非 curl API**,更简洁且自动处理认证。
|
||||
|
||||
## 常见问题
|
||||
|
||||
| 问题 | 原因 | 解决 |
|
||||
|------|------|------|
|
||||
| Run 一直 queued | Runner 被占满 | 等其他 job 完成,或加 runner |
|
||||
| deploy 被 test 阻塞 | 共用 runner | 用 `runs-on: deploy` 专属 runner |
|
||||
| Workflow 被误触发 | push 新 workflow 文件到 main | 加 `if: github.event_name == 'schedule'` 守卫 |
|
||||
| auto-fix 无限循环 | 提交触发新 run | 提交信息加 `[skip ci]` |
|
||||
| API 无法 cancel run | Gitea 1.25 限制 | 网页手动取消,或等完成后 DELETE |
|
||||
| `date -d` 报错 | 容器 date 不兼容 | 用 host 模式 runner,或兼容写法 |
|
||||
Reference in New Issue
Block a user