Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
740ff4e1d8 | ||
|
|
135ea99deb | ||
|
|
6bc2506842 | ||
|
|
c0b5f15895 | ||
|
|
32d674a4c0 | ||
|
|
02d870a2d6 | ||
|
|
417f3e6d2b | ||
|
|
ece54efc14 |
@@ -1,12 +1,14 @@
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"mcp": {},
|
||||
"model": "moonshotai-cn/kimi-k2.5",
|
||||
"permission": "allow",
|
||||
"plugin": ["@mohak34/opencode-notifier@latest"],
|
||||
"plugin": [
|
||||
"@mohak34/opencode-notifier@latest"
|
||||
],
|
||||
"provider": {
|
||||
"opencode": {
|
||||
"models": {
|
||||
"claude-opus-4-5": {
|
||||
"claude-sonnet-4-5": {
|
||||
"options": {
|
||||
"thinking": {
|
||||
"type": "enabled",
|
||||
@@ -15,11 +17,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"zhipuai-coding-plan": {
|
||||
"options": {
|
||||
"apiKey": "0f76aea86295476dbfa98724013b0fe8.o2EaJVqcl4Cf7WLP"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ You are an expert in Git version control and repository management.
|
||||
|------|------|
|
||||
| [Commit Workflow](./commit-workflow.md) | 提交暂存文件,自动生成提交信息并创建版本标签 |
|
||||
| [Push Workflow](./push-workflow.md) | 提交并推送到远程仓库的完整工作流 |
|
||||
| [SSH Keychain](./ssh-keychain.md) | SSH 密钥管理与 macOS Keychain 自动解锁配置 |
|
||||
|
||||
## Core Principles
|
||||
|
||||
|
||||
209
skill/git/ssh-keychain.md
Normal file
209
skill/git/ssh-keychain.md
Normal file
@@ -0,0 +1,209 @@
|
||||
---
|
||||
name: ssh-keychain
|
||||
description: SSH key management with macOS Keychain for password-protected keys
|
||||
---
|
||||
|
||||
# SSH 密钥与 macOS Keychain 管理
|
||||
|
||||
处理带密码的 SSH 密钥,配置自动解锁避免重复输入密码。
|
||||
|
||||
## 问题场景
|
||||
|
||||
生成带密码的 SSH 密钥后,每次使用都需要输入密码:
|
||||
```bash
|
||||
git pull
|
||||
# Enter passphrase for /Users/xxx/.ssh/id_xxx:
|
||||
```
|
||||
|
||||
## 解决方案
|
||||
|
||||
### 1. 生成带密码的 SSH 密钥
|
||||
|
||||
```bash
|
||||
# 生成密钥(推荐使用 ed25519)
|
||||
ssh-keygen -t ed25519 -f ~/.ssh/id_custom -N "your-passphrase"
|
||||
|
||||
# 或使用随机密码
|
||||
PASSPHRASE=$(openssl rand -base64 32)
|
||||
ssh-keygen -t ed25519 -f ~/.ssh/id_custom -N "$PASSPHRASE"
|
||||
```
|
||||
|
||||
### 2. 配置 SSH 使用 Keychain(关键步骤)
|
||||
|
||||
编辑 `~/.ssh/config`:
|
||||
|
||||
```ssh-config
|
||||
Host gitea.example.com
|
||||
HostName gitea.example.com
|
||||
User git
|
||||
IdentityFile ~/.ssh/id_custom
|
||||
IdentitiesOnly yes
|
||||
AddKeysToAgent yes
|
||||
UseKeychain yes
|
||||
```
|
||||
|
||||
**重要配置项:**
|
||||
- `AddKeysToAgent yes` - 自动添加到 ssh-agent
|
||||
- `UseKeychain yes` - 使用 macOS Keychain 存储密码
|
||||
- **不要**使用 `IdentityAgent none`(会禁用 Keychain)
|
||||
|
||||
### 3. 添加密钥到 ssh-agent 并保存到 Keychain
|
||||
|
||||
```bash
|
||||
# 方法 1:使用 --apple-use-keychain (macOS 12+)
|
||||
ssh-add --apple-use-keychain ~/.ssh/id_custom
|
||||
|
||||
# 方法 2:使用 -K 选项 (macOS 11 及更早)
|
||||
ssh-add -K ~/.ssh/id_custom
|
||||
```
|
||||
|
||||
输入密码后,系统会保存到 Keychain,以后自动解锁。
|
||||
|
||||
### 4. 验证配置
|
||||
|
||||
```bash
|
||||
# 检查已加载的密钥
|
||||
ssh-add -l
|
||||
|
||||
# 测试 SSH 连接
|
||||
ssh -T git@gitea.example.com
|
||||
```
|
||||
|
||||
如果显示 `Hi there, xxx! You've successfully authenticated` 且**没有提示输入密码**,则配置成功。
|
||||
|
||||
## 完整工作流程示例
|
||||
|
||||
### 场景:配置 Gitea SSH 访问
|
||||
|
||||
```bash
|
||||
# 1. 生成带密码的密钥
|
||||
PASSPHRASE="bkt/52MFsLVSRSHvIXv2WTCKEUaPhD0btDghUY6RnQI="
|
||||
ssh-keygen -t ed25519 -f ~/.ssh/id_gitea_new -N "$PASSPHRASE"
|
||||
|
||||
# 2. 配置 SSH
|
||||
# 编辑 ~/.ssh/config,添加:
|
||||
cat >> ~/.ssh/config << 'EOF'
|
||||
Host gitea.refining.dev
|
||||
HostName gitea.refining.dev
|
||||
User git
|
||||
IdentityFile ~/.ssh/id_gitea_new
|
||||
IdentitiesOnly yes
|
||||
AddKeysToAgent yes
|
||||
UseKeychain yes
|
||||
EOF
|
||||
|
||||
# 3. 添加到 Keychain
|
||||
ssh-add --apple-use-keychain ~/.ssh/id_gitea_new
|
||||
# 输入密码: bkt/52MFsLVSRSHvIXv2WTCKEUaPhD0btDghUY6RnQI=
|
||||
|
||||
# 4. 验证
|
||||
ssh -T git@gitea.refining.dev
|
||||
|
||||
# 5. 后续使用 git 无需输入密码
|
||||
git pull
|
||||
git push
|
||||
```
|
||||
|
||||
## 常见错误与解决
|
||||
|
||||
### 错误 1:仍然提示输入密码
|
||||
|
||||
**原因:** `~/.ssh/config` 中配置了 `IdentityAgent none`
|
||||
|
||||
**解决:** 移除 `IdentityAgent none`,添加 `UseKeychain yes`
|
||||
|
||||
```ssh-config
|
||||
# ❌ 错误配置
|
||||
Host gitea.example.com
|
||||
IdentityFile ~/.ssh/id_custom
|
||||
IdentityAgent none # 这会禁用 Keychain
|
||||
|
||||
# ✅ 正确配置
|
||||
Host gitea.example.com
|
||||
IdentityFile ~/.ssh/id_custom
|
||||
AddKeysToAgent yes
|
||||
UseKeychain yes
|
||||
```
|
||||
|
||||
### 错误 2:1Password SSH agent 冲突
|
||||
|
||||
如果系统使用 1Password 的 SSH agent(`IdentityAgent "~/Library/Group Containers/.../agent.sock"`):
|
||||
|
||||
```ssh-config
|
||||
Host *
|
||||
IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"
|
||||
|
||||
Host gitea.example.com
|
||||
HostName gitea.example.com
|
||||
User git
|
||||
IdentityFile ~/.ssh/id_custom
|
||||
IdentitiesOnly yes
|
||||
AddKeysToAgent yes
|
||||
UseKeychain yes
|
||||
# 不使用 1Password agent,直接使用系统 Keychain
|
||||
```
|
||||
|
||||
### 错误 3:ssh-add 命令不存在
|
||||
|
||||
某些 macOS 版本可能不支持 `--apple-use-keychain`:
|
||||
|
||||
```bash
|
||||
# 创建或编辑 ~/.ssh/config,添加全局配置
|
||||
Host *
|
||||
UseKeychain yes
|
||||
AddKeysToAgent yes
|
||||
|
||||
# 然后直接使用
|
||||
ssh-add ~/.ssh/id_custom
|
||||
```
|
||||
|
||||
## 密钥管理最佳实践
|
||||
|
||||
### 文件保存位置
|
||||
|
||||
将密钥备份到安全位置(如 iCloud):
|
||||
|
||||
```bash
|
||||
# 复制到 iCloud Key 文件夹
|
||||
KEY_FOLDER="$HOME/Library/Mobile Documents/com~apple~CloudDocs/key"
|
||||
cp ~/.ssh/id_custom "$KEY_FOLDER/id_custom_$(date +%Y%m%d)"
|
||||
cp ~/.ssh/id_custom.pub "$KEY_FOLDER/id_custom_$(date +%Y%m%d).pub"
|
||||
|
||||
# 创建密码说明文件
|
||||
cat > "$KEY_FOLDER/id_custom_$(date +%Y%m%d)_info.txt" << EOF
|
||||
SSH Key: id_custom
|
||||
Generated: $(date)
|
||||
Passphrase: $PASSPHRASE
|
||||
Host: gitea.example.com
|
||||
EOF
|
||||
```
|
||||
|
||||
### 定期检查
|
||||
|
||||
```bash
|
||||
# 列出所有已加载的密钥
|
||||
ssh-add -l
|
||||
|
||||
# 检查 SSH 配置
|
||||
ssh -G gitea.example.com
|
||||
|
||||
# 测试连接
|
||||
ssh -vT git@gitea.example.com
|
||||
```
|
||||
|
||||
### 安全建议
|
||||
|
||||
1. **始终使用带密码的密钥** - 防止私钥泄露后被直接使用
|
||||
2. **不要将私钥提交到 Git** - 添加到 `.gitignore`
|
||||
3. **定期轮换密钥** - 建议每 6-12 个月
|
||||
4. **为不同服务使用不同密钥** - 隔离风险
|
||||
|
||||
## 快速参考
|
||||
|
||||
| 命令 | 用途 |
|
||||
|------|------|
|
||||
| `ssh-add --apple-use-keychain ~/.ssh/id_custom` | 添加密钥到 Keychain |
|
||||
| `ssh-add -l` | 列出已加载的密钥 |
|
||||
| `ssh-add -D` | 删除所有已加载的密钥 |
|
||||
| `ssh -T git@host` | 测试 SSH 连接 |
|
||||
| `ssh -G host` | 查看 SSH 配置 |
|
||||
@@ -7,15 +7,43 @@ description: Comprehensive Gitea management tool for creating runners, workflows
|
||||
|
||||
完整的 Gitea 管理工具,提供 Runner、Workflow、仓库的创建和管理功能。
|
||||
|
||||
## 最新改进 (2026-01-23)
|
||||
|
||||
### 仓库创建功能增强(简洁高效版)
|
||||
1. **智能解析**:自动识别 `组织/仓库` 格式,优先使用指定组织而非默认组织
|
||||
2. **简化验证**:默认假设组织存在,API创建失败时清晰提示如何创建组织
|
||||
3. **默认私有**:除非明确指定,所有仓库默认创建为私有
|
||||
4. **Git集成**:自动检查当前目录是否为Git仓库,提供一键初始化、提交、推送
|
||||
5. **错误处理**:详细的Token验证、权限检查,API错误时给出具体解决方案
|
||||
6. **工作目录澄清**:仓库操作可在任何目录执行,配置操作在 `~/.config/gitea/`
|
||||
7. **流程优化**:减少不必要的预先验证,API失败时再提示,更简洁高效
|
||||
|
||||
### 使用示例
|
||||
```bash
|
||||
# 智能解析组织/仓库格式
|
||||
/gitea-create-repo shigongcao/shigongcao
|
||||
|
||||
# 创建公开仓库
|
||||
/gitea-create-repo org/project public
|
||||
|
||||
# 自动初始化并推送
|
||||
/gitea-create-repo org/project --init
|
||||
```
|
||||
|
||||
## 工作目录
|
||||
|
||||
**重要:该技能和所有相关命令的工作目录统一为:**
|
||||
**重要:Gitea 配置和 Runner 相关操作的工作目录为 `~/.config/gitea/`,但仓库操作可以在任何目录执行。**
|
||||
|
||||
### macOS / Linux
|
||||
### 配置和 Runner 目录
|
||||
```bash
|
||||
~/.config/gitea/
|
||||
```
|
||||
|
||||
### 仓库操作目录
|
||||
可以在任何项目目录执行,技能会自动:
|
||||
1. 从 `~/.config/gitea/config.env` 读取配置
|
||||
2. 在当前目录创建仓库、初始化 Git 等
|
||||
|
||||
### Windows
|
||||
```powershell
|
||||
# PowerShell
|
||||
@@ -28,7 +56,9 @@ $env:USERPROFILE\.config\gitea\
|
||||
C:\Users\YourUsername\.config\gitea\
|
||||
```
|
||||
|
||||
所有配置文件、Runner 目录、日志文件都存储在此目录下。请确保该目录具有适当的读写权限。
|
||||
**重要区分**:
|
||||
- **配置/Runner 操作**:在 `~/.config/gitea/` 目录执行
|
||||
- **仓库操作**:可在任何项目目录执行(自动加载配置)
|
||||
|
||||
**目录结构(所有平台通用):**
|
||||
```
|
||||
@@ -40,9 +70,9 @@ C:\Users\YourUsername\.config\gitea\
|
||||
```
|
||||
|
||||
**平台兼容性:**
|
||||
- **macOS**: `~/.config/gitea/`(完全支持)
|
||||
- **Linux**: `~/.config/gitea/`(完全支持)
|
||||
- **Windows**: `%USERPROFILE%\.config\gitea\`(Act Runner 支持,但该技能的命令和脚本需要适配)
|
||||
- **macOS**: `~/.config/gitea/`(配置目录),任意目录(仓库操作)
|
||||
- **Linux**: `~/.config/gitea/`(配置目录),任意目录(仓库操作)
|
||||
- **Windows**: `%USERPROFILE%\.config\gitea\`(配置目录),任意目录(仓库操作)
|
||||
|
||||
**Windows 用户注意事项:**
|
||||
- Gitea Act Runner 官方支持 Windows 平台(包括 Host 模式)
|
||||
@@ -57,6 +87,7 @@ C:\Users\YourUsername\.config\gitea\
|
||||
| 功能模块 | 文档 | 说明 |
|
||||
|---------|------|------|
|
||||
| 环境配置 | [setup-guide.md](./setup-guide.md) | 首次使用引导,配置 Gitea URL 和 Token |
|
||||
| SSH 密钥管理 | [ssh-key-management.md](./ssh-key-management.md) | 创建、部署 SSH 密钥,配置本地客户端 |
|
||||
| Runner 管理 | [runner-management.md](./runner-management.md) | 创建、注册、管理 Gitea Act Runner |
|
||||
| 自动创建脚本 | [create-runner.md](./create-runner.md) | 包含完整的 Runner 创建 Bash 脚本 |
|
||||
| Workflow 生成 | [workflow-generator.md](./workflow-generator.md) | 根据项目类型生成 CI/CD workflow |
|
||||
@@ -72,6 +103,7 @@ C:\Users\YourUsername\.config\gitea\
|
||||
- "生成 workflow"、"CI/CD"
|
||||
- "创建仓库"、"gitea 仓库"
|
||||
- "gitea 配置"、"gitea token"
|
||||
- "ssh key"、"ssh密钥"、"gitea ssh"、"部署密钥"
|
||||
|
||||
## 首次使用
|
||||
|
||||
@@ -100,6 +132,7 @@ C:\Users\YourUsername\.config\gitea\
|
||||
| `/gitea-config` | 查看当前 Gitea 配置和 Runner 状态 |
|
||||
| `/gitea-reset` | 重置 Gitea 配置(交互式向导) |
|
||||
| `/gitea-switch-org` | 切换默认组织 |
|
||||
| `/gitea-setup-ssh` | 创建 SSH 密钥并部署到 Gitea 服务器 |
|
||||
| `/gitea-create-runner` | 创建并启动新 Runner(默认 host 模式) |
|
||||
| `/gitea-list-runners` | 列出所有 Runner 及其状态 |
|
||||
| `/gitea-delete-runner` | 删除指定 Runner |
|
||||
@@ -183,12 +216,30 @@ AI: 检测到 Go 项目,服务目录: ./backend
|
||||
[自动生成 .gitea/workflows/backend.yml]
|
||||
```
|
||||
|
||||
### 4. 创建仓库
|
||||
### 4. 创建仓库(智能解析,默认私有)
|
||||
|
||||
**智能解析特性**:
|
||||
- 自动识别 `组织/仓库` 格式,优先使用指定组织
|
||||
- 默认创建私有仓库(除非明确指定公开)
|
||||
- 支持自动初始化 Git 仓库并推送代码
|
||||
|
||||
**示例**:
|
||||
```
|
||||
用户: /gitea-create-repo my-project
|
||||
AI: [使用配置的 Gitea URL 和默认组织创建仓库]
|
||||
✓ 仓库创建成功: ai/my-project
|
||||
用户: /gitea-create-repo shigongcao/shigongcao
|
||||
AI: [智能解析为 shigongcao 组织下的 shigongcao 仓库]
|
||||
✓ 仓库创建成功: shigongcao/shigongcao (私有)
|
||||
✓ 组织验证通过
|
||||
✓ 可选的 Git 初始化流程...
|
||||
|
||||
用户: /gitea-create-repo my-project public
|
||||
AI: [使用默认组织创建公开仓库]
|
||||
✓ 仓库创建成功: ai/my-project (公开)
|
||||
|
||||
用户: /gitea-create-repo org/project --init
|
||||
AI: [创建仓库并自动初始化当前目录的 Git 仓库]
|
||||
✓ 仓库创建成功: org/project
|
||||
✓ Git 初始化完成
|
||||
✓ 代码已推送到远程仓库
|
||||
```
|
||||
|
||||
## 配置管理
|
||||
@@ -376,10 +427,17 @@ AI 会自动:
|
||||
|
||||
## 版本
|
||||
|
||||
- **Skill Version**: 1.0
|
||||
- **Last Updated**: 2026-01-12
|
||||
- **整合内容**: gitea-runner + gitea-workflow
|
||||
- **新增功能**: 统一配置管理、Runner CRUD、智能 labels 检测
|
||||
- **Skill Version**: 1.2
|
||||
- **Last Updated**: 2026-01-28
|
||||
- **整合内容**: gitea-runner + gitea-workflow + 增强仓库管理 + SSH 密钥管理
|
||||
- **主要改进**:
|
||||
- 仓库创建智能解析(优先使用指定组织)
|
||||
- **简化验证**:默认假设组织存在,API失败时提示创建组织
|
||||
- 默认私有仓库策略(除非明确指定公开)
|
||||
- **完整 Git 集成**:自动检查Git状态,提供一键初始化、提交、推送
|
||||
- **简洁高效**:减少预先验证,API失败时给出具体解决方案
|
||||
- 工作目录概念澄清(配置 vs 仓库操作)
|
||||
- **SSH 密钥管理**:完整的密钥创建、部署和跨设备使用指南
|
||||
|
||||
## 相关资源
|
||||
|
||||
|
||||
@@ -119,7 +119,9 @@ host:
|
||||
workdir_parent: /data/workspace
|
||||
YAML
|
||||
|
||||
local labels="ubuntu-latest:docker://node:16-bullseye,ubuntu-22.04:docker://node:16-bullseye,ubuntu-20.04:docker://node:16-buster,linux:docker://node:16-bullseye"
|
||||
# 使用 catthehacker/ubuntu:act-* 镜像,内置 Docker CLI、Buildx 等 CI/CD 工具
|
||||
# 注意:不要使用 node:16-bullseye 等纯运行时镜像,它们不包含 docker 命令
|
||||
local labels="ubuntu-latest:docker://catthehacker/ubuntu:act-latest,ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04,ubuntu-20.04:docker://catthehacker/ubuntu:act-20.04,linux:docker://catthehacker/ubuntu:act-latest"
|
||||
|
||||
docker run -d \
|
||||
--name "$name" \
|
||||
@@ -224,6 +226,45 @@ EOF
|
||||
# gitea-create-runner all "wibnIxvgeyYj3D7d53VTQvNxv0UVqArBwAtPFBWD"
|
||||
```
|
||||
|
||||
## 🔄 恢复离线 Runner
|
||||
|
||||
**场景**:Runner 在 Gitea 服务器上被删除,但本地配置文件仍在。需要重新注册并上线。
|
||||
|
||||
**快速恢复命令**(针对 runner-Mac-mini4-host):
|
||||
|
||||
```bash
|
||||
cd ~/.config/gitea/runners/runner-Mac-mini4-host
|
||||
|
||||
# 停止旧进程
|
||||
if [ -f pid ]; then kill $(cat pid) 2>/dev/null || true; fi
|
||||
|
||||
# 加载配置并重新注册
|
||||
source ~/.config/gitea/config.env
|
||||
|
||||
# 获取令牌(需要 jq)
|
||||
token=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
|
||||
"${GITEA_URL}/api/v1/admin/runners/registration-token" | jq -r '.token')
|
||||
|
||||
# 生成标签
|
||||
OS=$(uname -s); ARCH=$(uname -m)
|
||||
case "$OS" in Darwin) os="macOS";; Linux) os="ubuntu";; *) os="unknown";; esac
|
||||
case "$ARCH" in arm64|aarch64) arch="ARM64";; x86_64) arch="x64";; *) arch="unknown";; esac
|
||||
labels="self-hosted:host,${os}:host,${arch}:host,$(echo "${OS}-${ARCH}" | tr '[:upper:]' '[:lower:]'):host"
|
||||
|
||||
# 重新注册并启动
|
||||
act_runner register --config config.yaml --instance "$GITEA_URL" \
|
||||
--token "$token" --name "runner-Mac-mini4-host" --labels "$labels" --no-interactive
|
||||
|
||||
nohup act_runner daemon --config config.yaml > runner.log 2>&1 &
|
||||
echo $! > pid
|
||||
echo "✅ Runner 恢复完成 (PID: $(cat pid))"
|
||||
```
|
||||
|
||||
**说明**:
|
||||
- 确保 `config.yaml` 中的 `labels:` 配置为空(`labels: []`),注册时会使用命令行参数
|
||||
- 如果全局令牌权限不足,需要获取组织令牌(参考 runner-management.md)
|
||||
- 恢复后 runner 会获得新的 ID,但名称和 labels 保持不变
|
||||
|
||||
### 方法三:完整脚本
|
||||
如果你需要更多自定义选项,可以使用下面的完整脚本:
|
||||
|
||||
@@ -588,7 +629,13 @@ create_runner() {
|
||||
else
|
||||
# Docker mode uses standard labels mapping to images
|
||||
# Format: label:docker://image
|
||||
labels="ubuntu-latest:docker://node:16-bullseye,ubuntu-22.04:docker://node:16-bullseye,ubuntu-20.04:docker://node:16-buster,linux:docker://node:16-bullseye"
|
||||
# 重要:必须使用包含 Docker CLI 的镜像,否则 docker/login-action 等 actions 会失败
|
||||
# catthehacker/ubuntu:act-* 是专为 GitHub/Gitea Actions 设计的镜像,预装:
|
||||
# - Docker CLI (docker 命令)
|
||||
# - Docker Buildx
|
||||
# - git, curl, jq 等常用工具
|
||||
# 不要使用 node:16-bullseye 等纯运行时镜像!
|
||||
labels="ubuntu-latest:docker://catthehacker/ubuntu:act-latest,ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04,ubuntu-20.04:docker://catthehacker/ubuntu:act-20.04,linux:docker://catthehacker/ubuntu:act-latest"
|
||||
fi
|
||||
|
||||
echo "✓ Labels ($mode):"
|
||||
@@ -849,7 +896,13 @@ if [ "$RUNNER_MODE" = "host" ]; then
|
||||
else
|
||||
# Docker mode uses standard labels mapping to images
|
||||
# Format: label:docker://image
|
||||
labels="ubuntu-latest:docker://node:16-bullseye,ubuntu-22.04:docker://node:16-bullseye,ubuntu-20.04:docker://node:16-buster,linux:docker://node:16-bullseye"
|
||||
# 重要:必须使用包含 Docker CLI 的镜像,否则 docker/login-action 等 actions 会失败
|
||||
# catthehacker/ubuntu:act-* 是专为 GitHub/Gitea Actions 设计的镜像,预装:
|
||||
# - Docker CLI (docker 命令)
|
||||
# - Docker Buildx
|
||||
# - git, curl, jq 等常用工具
|
||||
# 不要使用 node:16-bullseye 等纯运行时镜像!
|
||||
labels="ubuntu-latest:docker://catthehacker/ubuntu:act-latest,ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04,ubuntu-20.04:docker://catthehacker/ubuntu:act-20.04,linux:docker://catthehacker/ubuntu:act-latest"
|
||||
fi
|
||||
|
||||
echo "✓ Labels ($RUNNER_MODE):"
|
||||
|
||||
@@ -69,10 +69,10 @@ LOCAL_MAP=$(mktemp)
|
||||
FINAL_LIST=$(mktemp)
|
||||
|
||||
# 2.1 Fetch Remote Runners (Try Admin first, then Org)
|
||||
# Note: Admin endpoint /api/v1/admin/runners lists all runners
|
||||
# Note: Admin endpoint /api/v1/admin/actions/runners lists all runners
|
||||
HTTP_CODE=$(curl -s -w "%{http_code}" -o "$REMOTE_LIST" \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
"${GITEA_URL}/api/v1/admin/runners?page=1&limit=100")
|
||||
"${GITEA_URL}/api/v1/admin/actions/runners?page=1&limit=100")
|
||||
|
||||
if [ "$HTTP_CODE" != "200" ]; then
|
||||
# Fallback to Org level if defined
|
||||
|
||||
@@ -11,6 +11,34 @@
|
||||
- 管理 Secrets 和 Variables
|
||||
- 设置 Webhooks
|
||||
|
||||
## 快速使用
|
||||
|
||||
### 核心原则(简洁高效)
|
||||
1. **智能解析**:自动识别 `组织/仓库` 格式,优先使用指定组织而非默认组织
|
||||
2. **默认私有**:除非明确指定,所有仓库默认创建为私有
|
||||
3. **简化验证**:默认假设组织存在,API创建失败时清晰提示解决方案
|
||||
4. **Git集成**:自动检查Git仓库状态,提供一键初始化、提交、推送完整流程
|
||||
5. **错误处理**:API失败时给出具体操作建议,而非预先复杂验证
|
||||
|
||||
### 常用命令(简洁高效)
|
||||
```bash
|
||||
# 智能解析组织/仓库格式(默认私有)
|
||||
/gitea-create-repo shigongcao/shigongcao
|
||||
|
||||
# 使用默认组织创建公开仓库
|
||||
/gitea-create-repo my-project public
|
||||
|
||||
# 自动检查Git状态,提供完整初始化流程
|
||||
/gitea-create-repo org/project
|
||||
|
||||
# 特性说明:
|
||||
# 1. 自动识别组织/仓库格式
|
||||
# 2. 默认创建私有仓库(除非指定public)
|
||||
# 3. 自动检查当前目录Git状态
|
||||
# 4. 提供一键初始化、提交、推送选项
|
||||
# 5. API失败时给出清晰解决方案(如组织不存在)
|
||||
```
|
||||
|
||||
## 创建仓库
|
||||
|
||||
### 使用命令创建
|
||||
@@ -65,24 +93,28 @@ fi
|
||||
source "$config_file"
|
||||
```
|
||||
|
||||
#### 步骤 2: 解析输入
|
||||
#### 步骤 2: 智能解析输入(简洁高效版)
|
||||
|
||||
```bash
|
||||
input="$1"
|
||||
|
||||
# 解析 owner/repo
|
||||
# 智能解析:优先使用用户指定的组织
|
||||
if [[ "$input" =~ / ]]; then
|
||||
owner=$(echo "$input" | cut -d'/' -f1)
|
||||
repo=$(echo "$input" | cut -d'/' -f2)
|
||||
echo "使用指定组织: $owner"
|
||||
echo "提示:假设组织存在,如不存在会在API创建时提示"
|
||||
else
|
||||
# 使用默认组织或当前用户
|
||||
# 未指定组织,使用默认组织或当前用户
|
||||
if [ -z "$GITEA_DEFAULT_ORG" ]; then
|
||||
# 获取当前用户
|
||||
echo "未指定组织,获取当前用户..."
|
||||
owner=$(curl -s -H "Authorization: token $GITEA_TOKEN" \
|
||||
"${GITEA_URL}/api/v1/user" | jq -r '.login')
|
||||
|
||||
if [ -z "$owner" ] || [ "$owner" = "null" ]; then
|
||||
echo "❌ 无法获取当前用户信息,请使用 owner/repo 格式"
|
||||
echo "❌ 无法获取当前用户信息,请使用 组织/仓库 格式"
|
||||
echo "例如:/gitea-create-repo shigongcao/shigongcao"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -94,9 +126,21 @@ else
|
||||
repo="$input"
|
||||
fi
|
||||
|
||||
# 解析可见性
|
||||
# 解析可见性:默认私有仓库(除非明确指定公开)
|
||||
visibility="${2:-private}"
|
||||
if [[ "$visibility" != "private" && "$visibility" != "public" ]]; then
|
||||
echo "⚠️ 可见性参数无效,使用默认值: private"
|
||||
visibility="private"
|
||||
fi
|
||||
|
||||
private_bool=$([ "$visibility" = "private" ] && echo "true" || echo "false")
|
||||
echo "仓库可见性: $visibility"
|
||||
|
||||
# 提前检查当前目录是否是 Git 仓库(为后续步骤做准备)
|
||||
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
echo "⚠️ 当前目录不是 Git 仓库"
|
||||
echo "提示:创建远程仓库后可以初始化本地 Git 仓库并推送代码"
|
||||
fi
|
||||
```
|
||||
|
||||
#### 步骤 3: 验证仓库名
|
||||
@@ -109,12 +153,29 @@ if ! [[ "$repo" =~ ^[a-zA-Z0-9_.-]+$ ]]; then
|
||||
fi
|
||||
```
|
||||
|
||||
#### 步骤 4: 调用 API 创建
|
||||
#### 步骤 4: 调用 API 创建(带详细错误处理)
|
||||
|
||||
```bash
|
||||
echo "正在创建仓库: $owner/$repo ($visibility)"
|
||||
|
||||
# 尝试组织仓库
|
||||
# 检查 Token 权限
|
||||
echo "检查 Token 权限..."
|
||||
user_info=$(curl -s -H "Authorization: token $GITEA_TOKEN" "${GITEA_URL}/api/v1/user")
|
||||
username=$(echo "$user_info" | jq -r '.login // empty')
|
||||
|
||||
if [ -z "$username" ] || [ "$username" = "null" ]; then
|
||||
echo "❌ Token 无效或权限不足"
|
||||
echo "请检查:"
|
||||
echo "1. Token 是否有效"
|
||||
echo "2. Token 是否有 'repo' 权限"
|
||||
echo "3. GITEA_URL 是否正确"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ Token 有效,当前用户: $username"
|
||||
|
||||
# 尝试创建组织仓库
|
||||
echo "调用 Gitea API 创建仓库..."
|
||||
response=$(curl -s -w "\n%{http_code}" -X POST \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
@@ -122,42 +183,87 @@ response=$(curl -s -w "\n%{http_code}" -X POST \
|
||||
\"name\": \"${repo}\",
|
||||
\"private\": ${private_bool},
|
||||
\"auto_init\": false,
|
||||
\"default_branch\": \"main\"
|
||||
\"default_branch\": \"main\",
|
||||
\"description\": \"\"
|
||||
}" \
|
||||
"${GITEA_URL}/api/v1/orgs/${owner}/repos")
|
||||
|
||||
http_code=$(echo "$response" | tail -n1)
|
||||
body=$(echo "$response" | sed '$d')
|
||||
|
||||
# 如果 404,可能是用户而非组织
|
||||
if [ "$http_code" = "404" ]; then
|
||||
echo "⚠️ 组织不存在,尝试创建用户仓库..."
|
||||
|
||||
response=$(curl -s -w "\n%{http_code}" -X POST \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"name\": \"${repo}\",
|
||||
\"private\": ${private_bool}
|
||||
}" \
|
||||
"${GITEA_URL}/api/v1/user/repos")
|
||||
|
||||
http_code=$(echo "$response" | tail -n1)
|
||||
body=$(echo "$response" | sed '$d')
|
||||
fi
|
||||
|
||||
# 处理响应
|
||||
case "$http_code" in
|
||||
201)
|
||||
echo "✓ 仓库创建成功"
|
||||
;;
|
||||
400)
|
||||
error_msg=$(echo "$body" | jq -r '.message // "未知错误"')
|
||||
echo "❌ 请求参数错误: $error_msg"
|
||||
echo "请检查:"
|
||||
echo "1. 仓库名格式是否正确"
|
||||
echo "2. 是否缺少必要参数"
|
||||
exit 1
|
||||
;;
|
||||
403)
|
||||
echo "❌ 权限不足"
|
||||
echo "请检查:"
|
||||
echo "1. 是否有在组织 '$owner' 下创建仓库的权限"
|
||||
echo "2. 是否是组织成员"
|
||||
echo "3. Token 权限是否足够"
|
||||
exit 1
|
||||
;;
|
||||
404)
|
||||
# 组织不存在(API 返回 404)
|
||||
echo "❌ API 创建失败:组织 '$owner' 不存在"
|
||||
|
||||
# 检查是否为当前用户(可能用户输入的是自己的用户名)
|
||||
if [ "$owner" = "$username" ]; then
|
||||
echo "检测到 '$owner' 是当前用户,创建个人仓库..."
|
||||
|
||||
response=$(curl -s -w "\n%{http_code}" -X POST \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"name\": \"${repo}\",
|
||||
\"private\": ${private_bool},
|
||||
\"auto_init\": false,
|
||||
\"default_branch\": \"main\"
|
||||
}" \
|
||||
"${GITEA_URL}/api/v1/user/repos")
|
||||
|
||||
http_code=$(echo "$response" | tail -n1)
|
||||
body=$(echo "$response" | sed '$d')
|
||||
|
||||
if [ "$http_code" = "201" ]; then
|
||||
echo "✓ 个人仓库创建成功"
|
||||
else
|
||||
error_msg=$(echo "$body" | jq -r '.message // "未知错误"')
|
||||
echo "❌ 个人仓库创建失败 (HTTP $http_code): $error_msg"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "组织不存在,请先创建组织"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
echo "您可以通过以下方式创建组织 '$owner':"
|
||||
echo "1. 访问 ${GITEA_URL}/org/create"
|
||||
echo "2. 使用 Gitea Web 界面创建组织"
|
||||
echo "3. 或者使用个人仓库格式: $username/$repo"
|
||||
echo ""
|
||||
echo "创建组织后,重新运行此命令创建仓库。"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
409)
|
||||
echo "❌ 仓库已存在"
|
||||
echo "❌ 仓库已存在: $owner/$repo"
|
||||
echo "请使用不同的仓库名或删除现有仓库"
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
echo "❌ 创建失败 (HTTP $http_code)"
|
||||
echo "$body" | jq -r '.message // empty'
|
||||
error_msg=$(echo "$body" | jq -r '.message // "未知错误"')
|
||||
echo "❌ 创建失败 (HTTP $http_code): $error_msg"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -183,45 +289,104 @@ echo " SSH URL: $ssh_url"
|
||||
echo ""
|
||||
```
|
||||
|
||||
#### 步骤 6: 添加 Git Remote
|
||||
#### 步骤 6: Git 仓库集成(简洁高效版)
|
||||
|
||||
```bash
|
||||
read -p "是否将此仓库添加为 Git remote? [Y/n] " add_remote
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "Git 仓库集成"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
|
||||
if [[ ! "$add_remote" =~ ^[Nn]$ ]]; then
|
||||
# 检查是否是 Git 仓库
|
||||
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
echo "当前目录不是 Git 仓库"
|
||||
read -p "是否初始化 Git 仓库? [Y/n] " init_git
|
||||
|
||||
if [[ ! "$init_git" =~ ^[Nn]$ ]]; then
|
||||
git init
|
||||
echo "✓ Git 仓库已初始化"
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
# 检查是否是 Git 仓库
|
||||
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
echo "当前目录不是 Git 仓库"
|
||||
read -p "是否初始化 Git 仓库并添加 remote? [Y/n] " init_git
|
||||
|
||||
if [[ "$init_git" =~ ^[Nn]$ ]]; then
|
||||
echo "跳过 Git 初始化,仅创建远程仓库。"
|
||||
echo "您可以在需要时手动执行:"
|
||||
echo " git init"
|
||||
echo " git remote add origin \"$clone_url\""
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 初始化 Git 仓库
|
||||
echo "正在初始化 Git 仓库..."
|
||||
git init
|
||||
echo "✓ Git 仓库已初始化"
|
||||
|
||||
# 检查 origin 是否已存在
|
||||
if git remote get-url origin >/dev/null 2>&1; then
|
||||
existing_url=$(git remote get-url origin)
|
||||
echo "⚠️ origin remote 已存在: $existing_url"
|
||||
read -p "是否覆盖? [y/N] " overwrite
|
||||
read -p "是否覆盖为新的仓库? [y/N] " overwrite
|
||||
|
||||
if [[ "$overwrite" =~ ^[Yy]$ ]]; then
|
||||
git remote set-url origin "$clone_url"
|
||||
echo "✓ origin remote 已更新"
|
||||
echo "✓ origin remote 已更新为: $clone_url"
|
||||
else
|
||||
echo "保持现有的 origin remote"
|
||||
fi
|
||||
else
|
||||
git remote add origin "$clone_url"
|
||||
echo "✓ origin remote 已添加"
|
||||
echo "✓ origin remote 已添加: $clone_url"
|
||||
fi
|
||||
|
||||
# 显示 remote 信息
|
||||
# 可选:添加文件、提交并推送
|
||||
echo ""
|
||||
echo "当前 remote:"
|
||||
git remote -v
|
||||
read -p "是否添加当前文件、提交并推送到远程仓库? [Y/n] " push_code
|
||||
|
||||
if [[ ! "$push_code" =~ ^[Nn]$ ]]; then
|
||||
echo "添加所有文件到暂存区..."
|
||||
git add .
|
||||
|
||||
echo "创建初始提交..."
|
||||
git commit -m "Initial commit" || {
|
||||
echo "⚠️ 提交失败(可能没有文件可提交)"
|
||||
echo "请手动添加文件后提交"
|
||||
}
|
||||
|
||||
echo "推送到远程仓库 (main 分支)..."
|
||||
git branch -M main 2>/dev/null
|
||||
git push -u origin main
|
||||
echo "✓ 代码已推送到远程仓库"
|
||||
else
|
||||
echo "跳过推送,您可以在需要时手动推送代码。"
|
||||
fi
|
||||
|
||||
else
|
||||
# 已经是 Git 仓库,询问是否添加/更新 remote
|
||||
echo "当前目录已是 Git 仓库"
|
||||
read -p "是否添加/更新 origin remote 为此仓库? [Y/n] " add_remote
|
||||
|
||||
if [[ ! "$add_remote" =~ ^[Nn]$ ]]; then
|
||||
# 检查 origin 是否已存在
|
||||
if git remote get-url origin >/dev/null 2>&1; then
|
||||
existing_url=$(git remote get-url origin)
|
||||
echo "⚠️ origin remote 已存在: $existing_url"
|
||||
read -p "是否覆盖? [y/N] " overwrite
|
||||
|
||||
if [[ "$overwrite" =~ ^[Yy]$ ]]; then
|
||||
git remote set-url origin "$clone_url"
|
||||
echo "✓ origin remote 已更新"
|
||||
else
|
||||
echo "保持现有的 origin remote"
|
||||
fi
|
||||
else
|
||||
git remote add origin "$clone_url"
|
||||
echo "✓ origin remote 已添加"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# 显示当前状态
|
||||
echo ""
|
||||
echo "当前 Git 状态:"
|
||||
git status --short 2>/dev/null || echo "(非 Git 仓库)"
|
||||
echo ""
|
||||
echo "Remote 配置:"
|
||||
git remote -v 2>/dev/null || echo "(无 remote 配置)"
|
||||
```
|
||||
|
||||
## 仓库初始化
|
||||
@@ -689,5 +854,11 @@ curl -s -H "Authorization: token $GITEA_TOKEN" \
|
||||
|
||||
## 版本
|
||||
|
||||
- **文档版本**: 1.0
|
||||
- **最后更新**: 2026-01-12
|
||||
- **文档版本**: 1.1
|
||||
- **最后更新**: 2026-01-23
|
||||
- **主要改进**:
|
||||
- 智能解析输入:优先使用指定组织而非默认组织
|
||||
- 组织存在性验证和清晰错误提示
|
||||
- 默认私有仓库策略(除非明确指定公开)
|
||||
- 增强的错误处理:Token验证、权限检查、详细错误消息
|
||||
- 完整的Git集成流程:可选自动初始化和推送
|
||||
|
||||
@@ -29,6 +29,7 @@ Gitea Act Runner 是 Gitea Actions 的 CI/CD 执行器,兼容 GitHub Actions w
|
||||
- **macOS ARM64**: 使用 **Host Mode** 以支持 Android SDK
|
||||
- **Windows**: 使用 **Host Mode**(需在 workflow 中指定 `shell: powershell`)
|
||||
- **Linux**: 两种模式均可,Docker Mode 隔离性更好
|
||||
- **Docker Mode**: 必须使用 `catthehacker/ubuntu:act-*` 镜像(内置 Docker CLI)
|
||||
|
||||
**Windows Host Mode 注意事项**:
|
||||
- Bash 默认不可用,需在 workflow 中指定 shell:
|
||||
@@ -577,9 +578,51 @@ labels:
|
||||
```yaml
|
||||
labels:
|
||||
- "ubuntu-latest:docker://catthehacker/ubuntu:act-latest"
|
||||
- "ubuntu-22.04:docker://catthehacker/ubuntu:act-latest"
|
||||
- "ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04"
|
||||
- "ubuntu-20.04:docker://catthehacker/ubuntu:act-20.04"
|
||||
- "linux:docker://catthehacker/ubuntu:act-latest"
|
||||
```
|
||||
|
||||
### Docker Mode 镜像选择(重要)
|
||||
|
||||
**必须使用包含 Docker CLI 的镜像**,否则 `docker/login-action`、`docker/build-push-action` 等 actions 会失败。
|
||||
|
||||
| 镜像 | Docker CLI | 适用场景 |
|
||||
|------|------------|---------|
|
||||
| `catthehacker/ubuntu:act-latest` | ✅ 有 | **推荐**,CI/CD 专用镜像 |
|
||||
| `catthehacker/ubuntu:act-22.04` | ✅ 有 | Ubuntu 22.04 兼容 |
|
||||
| `node:16-bullseye` | ❌ 无 | **不推荐**,仅适合纯 Node.js 项目 |
|
||||
| `golang:1.21` | ❌ 无 | **不推荐**,仅适合纯 Go 项目 |
|
||||
|
||||
**catthehacker/ubuntu:act-* 预装工具**:
|
||||
- Docker CLI (`/usr/bin/docker`)
|
||||
- Docker Buildx
|
||||
- git, curl, wget, jq
|
||||
- Node.js, Python
|
||||
- 常用编译工具
|
||||
|
||||
**工作原理**:
|
||||
```
|
||||
workflow: runs-on: ubuntu-latest
|
||||
↓
|
||||
runner 查找 label: ubuntu-latest:docker://镜像名
|
||||
↓
|
||||
启动 job 容器(使用该镜像)
|
||||
↓
|
||||
在 job 容器内执行 steps
|
||||
↓
|
||||
docker/login-action 调用 `docker login` 命令
|
||||
↓
|
||||
需要 job 容器内有 docker CLI ← 关键!
|
||||
```
|
||||
|
||||
**常见错误**:
|
||||
```
|
||||
Unable to locate executable file: docker. Please verify either the file path exists
|
||||
or the file can be found within a directory specified by the PATH environment variable.
|
||||
```
|
||||
此错误表示 job 容器内缺少 docker 命令,需要更换为包含 Docker CLI 的镜像。
|
||||
|
||||
### Workflow 匹配
|
||||
|
||||
**方法 1: 组合 label(推荐,最精确)**
|
||||
@@ -993,6 +1036,106 @@ nohup act_runner daemon --config ~/.config/gitea/runners/runner-macbook-pro/conf
|
||||
tail -f ~/.config/gitea/runners/runner-macbook-pro/runner.log
|
||||
```
|
||||
|
||||
### 8. 恢复被删除的 Runner(从服务器删除但本地文件仍在)
|
||||
|
||||
**场景**:Runner 在 Gitea 服务器上被删除,但本地目录和配置文件仍在。需要重新注册并上线。
|
||||
|
||||
**恢复步骤**:
|
||||
|
||||
```bash
|
||||
# 1. 进入 runner 目录
|
||||
cd ~/.config/gitea/runners/runner-Mac-mini4-host
|
||||
|
||||
# 2. 停止旧进程(如果仍在运行)
|
||||
if [ -f pid ]; then
|
||||
kill $(cat pid) 2>/dev/null || true
|
||||
rm -f pid
|
||||
fi
|
||||
|
||||
# 3. 加载 Gitea 配置
|
||||
source ~/.config/gitea/config.env
|
||||
|
||||
# 4. 获取注册令牌(优先全局,失败则降级到组织)
|
||||
echo "获取注册令牌..."
|
||||
response=$(curl -s -w "\n%{http_code}" \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
"${GITEA_URL}/api/v1/admin/runners/registration-token")
|
||||
http_code=$(echo "$response" | tail -n1)
|
||||
body=$(echo "$response" | sed '$d')
|
||||
|
||||
if [ "$http_code" != "200" ]; then
|
||||
echo "全局令牌权限不足,尝试组织令牌..."
|
||||
if [ -n "$GITEA_DEFAULT_ORG" ]; then
|
||||
org_name="$GITEA_DEFAULT_ORG"
|
||||
else
|
||||
read -p "请输入组织名称: " org_input
|
||||
org_name="$org_input"
|
||||
fi
|
||||
response=$(curl -s -w "\n%{http_code}" -X POST \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
"${GITEA_URL}/api/v1/orgs/$org_name/actions/runners/registration-token")
|
||||
http_code=$(echo "$response" | tail -n1)
|
||||
body=$(echo "$response" | sed '$d')
|
||||
fi
|
||||
|
||||
if [ "$http_code" != "200" ]; then
|
||||
echo "❌ 获取注册令牌失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
registration_token=$(echo "$body" | jq -r '.token')
|
||||
|
||||
# 5. 生成标签(基于系统环境)
|
||||
OS=$(uname -s)
|
||||
case "$OS" in
|
||||
Darwin) os_label="macOS" ;;
|
||||
Linux) os_label="ubuntu" ;;
|
||||
*) os_label="unknown" ;;
|
||||
esac
|
||||
|
||||
ARCH=$(uname -m)
|
||||
case "$ARCH" in
|
||||
arm64|aarch64) arch_label="ARM64" ;;
|
||||
x86_64) arch_label="x64" ;;
|
||||
*) arch_label="unknown" ;;
|
||||
esac
|
||||
|
||||
combined=$(echo "${OS}-${ARCH}" | tr '[:upper:]' '[:lower:]')
|
||||
labels="self-hosted:host,${os_label}:host,${arch_label}:host,${combined}:host"
|
||||
|
||||
# 6. 重新注册 runner
|
||||
act_runner register \
|
||||
--config config.yaml \
|
||||
--instance "$GITEA_URL" \
|
||||
--token "$registration_token" \
|
||||
--name "runner-Mac-mini4-host" \
|
||||
--labels "$labels" \
|
||||
--no-interactive
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "❌ 注册失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 7. 启动 runner daemon
|
||||
nohup act_runner daemon --config config.yaml > runner.log 2>&1 &
|
||||
echo $! > pid
|
||||
sleep 2
|
||||
|
||||
if ps -p $(cat pid) > /dev/null 2>&1; then
|
||||
echo "✅ Runner 恢复成功 (PID: $(cat pid))"
|
||||
echo "日志: tail -f runner.log"
|
||||
else
|
||||
echo "❌ Runner 启动失败"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
**说明**:
|
||||
- 恢复后 runner 会获得新的 ID 和 token,但名称和 labels 保持不变
|
||||
- 旧的 `.runner` 文件会被新的覆盖
|
||||
- 确保 `config.yaml` 中的 labels 配置为空(`labels: []`),注册时会使用命令行参数
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| 任务 | 命令 |
|
||||
@@ -1001,6 +1144,7 @@ tail -f ~/.config/gitea/runners/runner-macbook-pro/runner.log
|
||||
| 创建 runner | `/gitea-create-runner`(自动安装、配置、启动)|
|
||||
| 列出 runners | `/gitea-list-runners` |
|
||||
| 删除 runner | `/gitea-delete-runner` |
|
||||
| 恢复 runner | 参考「恢复被删除的 Runner」章节 |
|
||||
| 手动启动 | `nohup act_runner daemon --config <config.yaml> > <log> 2>&1 &` |
|
||||
| 停止 runner | `pkill -f "act_runner daemon --config.*<name>"` |
|
||||
| 查看状态 | `ps aux \| grep act_runner` |
|
||||
@@ -1016,6 +1160,9 @@ tail -f ~/.config/gitea/runners/runner-macbook-pro/runner.log
|
||||
|
||||
## 版本
|
||||
|
||||
- **文档版本**: 1.0
|
||||
- **最后更新**: 2026-01-12
|
||||
- **文档版本**: 1.2
|
||||
- **最后更新**: 2026-01-24
|
||||
- **更新内容**:
|
||||
- Docker Mode 镜像选择说明(必须使用包含 Docker CLI 的镜像)
|
||||
- Runner 恢复流程
|
||||
- **兼容性**: act_runner 0.2.13+, macOS ARM64, Linux
|
||||
|
||||
254
skill/gitea/ssh-key-management.md
Normal file
254
skill/gitea/ssh-key-management.md
Normal file
@@ -0,0 +1,254 @@
|
||||
# SSH 密钥管理
|
||||
|
||||
完整的 SSH 密钥创建、部署和配置流程,支持跨设备使用。
|
||||
|
||||
## 命令
|
||||
|
||||
### `/gitea-setup-ssh`
|
||||
创建 SSH 密钥对,部署公钥到 Gitea 服务器,配置本地 SSH 客户端。
|
||||
|
||||
## 功能概述
|
||||
|
||||
1. **生成 SSH 密钥对** (RSA 4096 位)
|
||||
2. **部署公钥到 Gitea 服务器** (通过 API)
|
||||
3. **配置本地 SSH 客户端**
|
||||
4. **验证 SSH 连接**
|
||||
|
||||
## 详细流程
|
||||
|
||||
### 1. 生成 SSH 密钥对
|
||||
|
||||
```bash
|
||||
ssh-keygen -t rsa -b 4096 -f ~/.ssh/gitea_server_key -N ""
|
||||
```
|
||||
|
||||
**生成的密钥文件:**
|
||||
- 私钥:`~/.ssh/gitea_server_key`
|
||||
- 公钥:`~/.ssh/gitea_server_key.pub`
|
||||
|
||||
### 2. 部署公钥到 Gitea
|
||||
|
||||
通过 Gitea API 将公钥添加到用户账户:
|
||||
|
||||
```bash
|
||||
curl -s -X POST -H "Authorization: token $GITEA_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"title\":\"server-key\",\"key\":\"$(cat ~/.ssh/gitea_server_key.pub)\"}" \
|
||||
"$GITEA_URL/api/v1/user/keys"
|
||||
```
|
||||
|
||||
### 3. 配置本地 SSH 客户端
|
||||
|
||||
在 `~/.ssh/config` 中添加配置:
|
||||
|
||||
```bash
|
||||
cat >> ~/.ssh/config << 'EOF'
|
||||
|
||||
Host git.refining.app
|
||||
HostName git.refining.app
|
||||
User git
|
||||
IdentityFile ~/.ssh/gitea_server_key
|
||||
IdentitiesOnly yes
|
||||
EOF
|
||||
```
|
||||
|
||||
### 4. 添加服务器主机密钥
|
||||
|
||||
```bash
|
||||
ssh-keyscan git.refining.app >> ~/.ssh/known_hosts
|
||||
```
|
||||
|
||||
### 5. 验证连接
|
||||
|
||||
```bash
|
||||
ssh -T git@git.refining.app
|
||||
```
|
||||
|
||||
成功输出:
|
||||
```
|
||||
Hi there, username! You've successfully authenticated with the key named server-key...
|
||||
```
|
||||
|
||||
## 跨设备使用
|
||||
|
||||
### 复制密钥到新设备
|
||||
|
||||
1. **复制私钥文件**到新设备的 `~/.ssh/` 目录
|
||||
```bash
|
||||
# 在源设备上查看私钥内容
|
||||
cat ~/.ssh/gitea_server_key
|
||||
|
||||
# 在新设备上创建文件
|
||||
echo "-----BEGIN OPENSSH PRIVATE KEY-----" > ~/.ssh/gitea_server_key
|
||||
echo "MIIEog..." >> ~/.ssh/gitea_server_key
|
||||
echo "...cQ=" >> ~/.ssh/gitea_server_key
|
||||
echo "-----END OPENSSH PRIVATE KEY-----" >> ~/.ssh/gitea_server_key
|
||||
```
|
||||
|
||||
2. **设置正确的权限**
|
||||
```bash
|
||||
chmod 600 ~/.ssh/gitea_server_key
|
||||
```
|
||||
|
||||
3. **配置 SSH 客户端**
|
||||
```bash
|
||||
# 在新设备上编辑 ~/.ssh/config
|
||||
cat >> ~/.ssh/config << 'EOF'
|
||||
|
||||
Host git.refining.app
|
||||
HostName git.refining.app
|
||||
User git
|
||||
IdentityFile ~/.ssh/gitea_server_key
|
||||
IdentitiesOnly yes
|
||||
EOF
|
||||
```
|
||||
|
||||
4. **添加服务器主机密钥**
|
||||
```bash
|
||||
ssh-keyscan git.refining.app >> ~/.ssh/known_hosts
|
||||
```
|
||||
|
||||
5. **测试连接**
|
||||
```bash
|
||||
ssh -T git@git.refining.app
|
||||
```
|
||||
|
||||
|
||||
## 密钥位置说明
|
||||
|
||||
### 源设备(当前已配置)
|
||||
```
|
||||
~/.ssh/
|
||||
├── gitea_server_key # 私钥 (权限 600)
|
||||
├── gitea_server_key.pub # 公钥 (已部署到 Gitea)
|
||||
├── config # SSH 配置
|
||||
└── known_hosts # 服务器主机密钥
|
||||
```
|
||||
|
||||
### 新设备(需要配置)
|
||||
需要从源设备复制:
|
||||
1. `gitea_server_key` - **私钥**(核心文件)
|
||||
2. `~/.ssh/config` - SSH 配置(相关部分)
|
||||
3. `known_hosts` - 服务器主机密钥(可选,会自动获取)
|
||||
|
||||
## 安全注意事项
|
||||
|
||||
### ✅ 推荐做法
|
||||
1. **私钥权限设置为 600**
|
||||
```bash
|
||||
chmod 600 ~/.ssh/gitea_server_key
|
||||
```
|
||||
|
||||
2. **不分享私钥**
|
||||
- 私钥应保持在个人设备上
|
||||
- 仅在有信任关系的设备间复制
|
||||
|
||||
3. **使用强密码保护**
|
||||
- 生成密钥时可添加密码:`ssh-keygen -t rsa -b 4096 -f ~/.ssh/gitea_server_key`
|
||||
- 每次使用时需要输入密码
|
||||
|
||||
### ❌ 禁止行为
|
||||
1. 不要将私钥提交到 Git 仓库
|
||||
2. 不要通过不安全渠道传输私钥
|
||||
3. 不要设置过于宽松的权限(如 644、777)
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 1. 权限错误
|
||||
```
|
||||
Permissions 0644 for '/Users/username/.ssh/gitea_server_key' are too open.
|
||||
```
|
||||
**解决方案**:
|
||||
```bash
|
||||
chmod 600 ~/.ssh/gitea_server_key
|
||||
```
|
||||
|
||||
### 2. 主机密钥验证失败
|
||||
```
|
||||
Host key verification failed.
|
||||
```
|
||||
**解决方案**:
|
||||
```bash
|
||||
ssh-keyscan git.refining.app >> ~/.ssh/known_hosts
|
||||
```
|
||||
|
||||
### 3. 认证失败
|
||||
```
|
||||
git@git.refining.app: Permission denied (publickey).
|
||||
```
|
||||
**检查步骤**:
|
||||
1. 确认私钥文件存在且权限正确
|
||||
2. 确认 SSH 配置正确
|
||||
3. 确认公钥已添加到 Gitea
|
||||
```bash
|
||||
curl -s -H "Authorization: token $GITEA_TOKEN" \
|
||||
"$GITEA_URL/api/v1/user/keys" | jq -r '.[].title'
|
||||
```
|
||||
|
||||
## Git 使用示例
|
||||
|
||||
### 克隆仓库
|
||||
```bash
|
||||
git clone git@git.refining.app:username/repository.git
|
||||
```
|
||||
|
||||
### 更新现有仓库的 remote URL
|
||||
```bash
|
||||
git remote set-url origin git@git.refining.app:username/repository.git
|
||||
```
|
||||
|
||||
### 查看当前 remote URL
|
||||
```bash
|
||||
git remote -v
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 撤销密钥访问
|
||||
|
||||
如果密钥泄露或设备丢失:
|
||||
|
||||
1. **登录 Gitea Web 界面**
|
||||
2. 进入 **Settings → SSH/GPG Keys**
|
||||
3. 找到对应的密钥并删除
|
||||
|
||||
2. **通过 API 删除**
|
||||
```bash
|
||||
# 首先获取密钥 ID
|
||||
curl -s -H "Authorization: token $GITEA_TOKEN" \
|
||||
"$GITEA_URL/api/v1/user/keys" | jq '.[] | select(.title=="server-key").id'
|
||||
|
||||
# 删除密钥(将 {id} 替换为实际 ID)
|
||||
curl -s -X DELETE -H "Authorization: token $GITEA_TOKEN" \
|
||||
"$GITEA_URL/api/v1/user/keys/{id}"
|
||||
```
|
||||
|
||||
3. **在受影响的设备上删除私钥**
|
||||
```bash
|
||||
rm ~/.ssh/gitea_server_key
|
||||
rm ~/.ssh/gitea_server_key.pub
|
||||
```
|
||||
|
||||
## 相关命令
|
||||
|
||||
### 查看 Gitea 上的所有 SSH 密钥
|
||||
```bash
|
||||
curl -s -H "Authorization: token $GITEA_TOKEN" \
|
||||
"$GITEA_URL/api/v1/user/keys" | jq -r '.[] | "\(.id): \(.title) (\(.fingerprint))"'
|
||||
```
|
||||
|
||||
### 测试 SSH 连接(详细模式)
|
||||
```bash
|
||||
ssh -T -v git@git.refining.app
|
||||
```
|
||||
|
||||
### 检查 SSH 配置语法
|
||||
```bash
|
||||
ssh -G git.refining.app
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*文档版本:1.1*
|
||||
*最后更新:2026-01-28*
|
||||
*集成到 Gitea Skill v1.2*
|
||||
Reference in New Issue
Block a user