--- name: "publish-to-gitea" description: "推到 gitea/发布到仓库/建 repo 推上去/把某个 git 仓库推上去时用:跑 gitea_push.py(隐私检查 → 建仓 → 对齐远程 → 推送)→ **回读远程验证**。含脚本覆盖不到的隐私盲区与 tea 建仓坑。" --- # Publish to Gitea — 发布到 Gitea 仓库 把文件/目录或一个已有 git 仓库推送到 Gitea(git.yoresee.cc)。 **不属于本 skill**:在本机**正在开发的仓库里**提交并推分支 → 直接在该仓库 `git push `(凭据走已配好的 `!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 "" [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:/.git /tmp/-verify find /tmp/-verify -type f -not -path "*/.git/*" | sed "s|/tmp/-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:/.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` 再用相对路径调它。