Files

98 lines
6.2 KiB
Markdown
Raw Permalink 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.
---
name: "publish-to-gitea"
description: "推到 gitea/发布到仓库/建 repo 推上去/把某个 git 仓库推上去时用:跑 gitea_push.py(隐私检查 → 建仓 → 对齐远程 → 推送)→ **回读远程验证**。含脚本覆盖不到的隐私盲区与 tea 建仓坑。"
---
# Publish to Gitea — 发布到 Gitea 仓库
把文件/目录或一个已有 git 仓库推送到 Gitea(git.yoresee.cc)。
**不属于本 skill**:在本机**正在开发的仓库里**提交并推分支 → 直接在该仓库 `git push <remote> <branch>`(凭据走已配好的 `!tea login helper`)。push 被拒先按 `diagnose-git-push-permission` 诊断——「仓库已存在但你是 `push:false`」是常见原因,别急着建新仓(非 admin 也建不了别人的命名空间)。
## 触发条件
「把这个推送到 gitea」「发布到仓库」「创建 repo 推上去」「publish to git」「推到 git.yoresee.cc」
## 流程
### 1. 确定要推送的内容
- 用户刚写的 skill / 脚本 / 项目目录 → 推那个目录
- 用户指定路径 → 直接用
- 内容是一个**已有 git 仓库**(有 `.git`、提交历史要保)→ 用 `--from-git`(见 §3)
### 2. 确定仓库名和描述
仓库名 kebab-case,描述一句话。用户没明说则主动确认(仓库默认**公开**)。
### 3. 执行推送
```bash
cd /root/.openclaw/workspace
python3 scripts/gitea_push.py <repo_name> "<description>" [paths...]
```
| 场景 | 命令 |
|---|---|
| 目录/文件 → 仓库 | `gitea_push.py my-proj "描述" ./src` |
| 推已有 git 仓库(**保留完整提交历史**) | `gitea_push.py my-proj "描述" --from-git /root/my-proj` |
| 只检查不推送 | `... --dry-run` |
常用选项:`--from-git DIR`(推仓库自身提交,不自动提交脏工作区)、`--owner`(默认 `NightStar`)、`--branch`(默认 `master`)、`--message`(自定义提交信息)、`--private`、`--exclude PATTERN`(可重复)、`--allow-leaks`、`--no-scan`、`--quiet`。
脚本四步:隐私检查 → 确保仓库存在(无则建,有则复用并**拉远程历史对齐**,不用 `--force`)→ 准备/提交 → 推送(被拒自动 `fetch + rebase` 重试 3 次)。
**退出码**:`0` 成功 / `1` 一般错误 / `2` 隐私检查未通过 / `3` 推送被拒。成功后 stdout 是 JSON(`url` / `clone` / `branch`)。
### 4. 回读远程验证(必做,别信脚本自报)
⚠️ **脚本打印「✓ 推送成功」不等于远程真的收到了。** 实测踩过:脚本报成功,回读发现远程只有一个空 README,文件一个没上去(内部 `git add` 未执行的 bug)。凡涉及「推没推上去」的结论,一律回读远程:
```bash
GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=accept-new" \
git clone --depth 1 git@git.yoresee.cc:<owner>/<repo>.git /tmp/<repo>-verify
find /tmp/<repo>-verify -type f -not -path "*/.git/*" | sed "s|/tmp/<repo>-verify/||" | sort
```
判据:期望的文件都在、内容对(抽读 1-2 个);`git log --oneline` 能看到本次提交。`--from-git` 模式再核提交数(`git rev-list --count HEAD`)与本地一致。**验完删掉临时 clone。**
### 5. 反馈
告诉用户仓库地址 + 验证结论(哪些文件在、提交 sha)。若脚本报隐私命中,**必须停下问用户**,不可自动跳过(用户确认无误才加 `--allow-leaks`)。
## 隐私检查:脚本已覆盖的 + 仍需手工补的
脚本扫 48 种文本扩展名(含 `.html/.htm/.css/.vue/.go/.tsx/.env/.svg/.scss` 等)与常见文件名(`Dockerfile/.env/.npmrc/...`),模式含 GitHub PAT、`sk-`/`sk-sp-`、AWS `AKIA`、Slack `xox`、飞书 `cli_`/`ou_`、`Bearer`、PEM 私钥、明文口令赋值,以及**公网 IP**(`127./10./192.168./172.16-31./169.254./0./255.` 这类不算,RFC 5737 文档专用段 `192.0.2./198.51.100./203.0.113.` 也不算)。改动或新增扫描范围前先看脚本里的 `SCAN_EXTS` / `SECRET_PATTERNS`,别凭记忆断言「扫不到」。
⚠️ **仍需手工看的一条:项目自己排除的文件,正是不能公开的。**
先看目标目录的 `.dockerignore` / `.gitignore`。实测某项目把 `data/keywords.src.json`(明文关键词表)排除出部署产物,却随仓库推成了**公开可见**——等于把解谜答案公开。同类信号:`*.src.json`、`*.key`、`*.secret.*`、被 ignore 的配置或原始数据。
发现就问用户三选一:改 private(`--private`,但建仓后改可见性要去 Gitea 页面/API)、`git rm --cached` 后加进 ignore、或明确接受公开。**不要默认推送。**
判读命中的邮箱**逐条看域名**:`.example` / `.invalid` 是拟真噪音,真实域名才算泄露。
## 建仓相关的两个坑
⚠️ **`tea` 0.15.0 给自己命名空间建仓不能传 `--owner`**:`tea repos create --name X --owner NightStar ...` 回 `Error: not found`,**省略 `--owner` 才成功**(大小写无关,实测小写同样失败)。脚本已内部规避(owner == 登录用户时省略该参数);手工用 `tea` 建仓时照此办理。只有建到组织/他人命名空间才需要 `--owner`。
⚠️ **全新仓库的 `Initial commit`**:脚本用 `tea ... --init` 建仓,远程因此多一个只含 README 的 `Initial commit`。脚本靠 `git reset --mixed` 对齐远程历史(只移动 HEAD、**不碰工作区**,避免覆盖同名文件)。若脚本的对齐/重试仍失败,手工兜底:
```bash
cd <目录> && git init -b master -c user.name=<名> -c user.email=<邮箱>
git remote add origin git@git.yoresee.cc:<owner>/<repo>.git
export GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=accept-new"
git fetch origin && git reset --mixed origin/master # 不要用 --hard:会覆盖同名文件
git add -A && git commit -m "<描述>" && git push -u origin master
```
别用 `--force`(会抹掉远程那个 commit)。
## 完成判据
远程回读通过:期望文件都在、内容正确、`git log` 有本次提交(`--from-git` 模式另核提交数与本地一致);仓库 URL 已告知用户;若曾出现隐私命中,用户已明确表态。
## 脚本依赖
`/root/.openclaw/workspace/scripts/gitea_push.py` — 基于 `tea` CLI;**不在本 skill 目录内**,所以要先 `cd /root/.openclaw/workspace` 再用相对路径调它。