From 8386c672cd1182906edd1608a420805bd3ba8690 Mon Sep 17 00:00:00 2001 From: CodeBuddy Date: Tue, 8 Sep 2026 07:55:42 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E6=8F=90=E4=BA=A4=EF=BC=9AAI?= =?UTF-8?q?=20=E5=BC=80=E5=8F=91=E5=8F=91=E5=B8=83=E4=BD=93=E7=B3=BB?= =?UTF-8?q?=E6=8E=A5=E5=85=A5=20skill=EF=BC=88SKILL.md=20+=20Gitea=20?= =?UTF-8?q?=E5=AE=89=E8=A3=85=E8=84=9A=E6=9C=AC=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SKILL.md | 121 +++++++++++++++++++++++++++++++++++++++++++++++ install_gitea.sh | 116 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 237 insertions(+) create mode 100644 SKILL.md create mode 100755 install_gitea.sh diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..9dd6337 --- /dev/null +++ b/SKILL.md @@ -0,0 +1,121 @@ +--- +name: ai-system-bootstrap +description: 为新服务器+新项目搭建完整的 AI 开发发布体系(Gitea 安装、规范目录 standards/、双仓库双环境、发布流程)。当用户要求"搭建体系/接入新项目/初始化 AI 开发流程"时使用本技能。 +--- + +# AI 开发发布体系接入(新服务器 + 新项目) + +本技能把一台新服务器和一个新项目接入标准化的 AI 开发发布体系: + +``` +AI 在开发目录改代码并实测 → commit 到开发分支 → push 到本机 Gitea +→ 用户在 Gitea 网页合并到生产分支 → 生产目录 git pull + 清缓存 → 验证 +``` + +**执行原则**:按第 0~7 步顺序执行;每步的验证点没通过不进下一步;涉及生产目录/生产库的写操作必须先给用户过目并确认。 + +--- + +## 第 0 步:收集信息(缺哪项问用户,不要猜) + +| 项 | 说明 | +|---|---| +| 项目生产域名 / 测试域名 | 例:`www.xxx.com` / `test.xxx.com` | +| Gitea 域名 | 建议 `git.<项目域名>`,用项目自己的域名,不要复用其他项目的 | +| 服务器面板 | 宝塔 / 其他 / 无面板(本 skill 以宝塔为默认,其他面板类比调整) | +| web 运行用户 | 宝塔默认 `www`;别的环境可能是 `www-data`/`nginx`,**后续所有属主操作用它** | +| 项目技术栈 | 语言/框架/构建方式(影响 coding 规范和 .gitignore) | +| 是否已有生产在跑 | 有则**先做全量备份**再动任何东西 | +| 域名备案状态 | 中国大陆服务器未备案的域名不能用,需用已备案的过渡域名,并记录切换计划 | + +## 第 1 步:安装 Gitea(本机自建,走 `install_gitea.sh`) + +```bash +sudo ./install_gitea.sh git.example.com +``` + +脚本做的事:建 `git` 系统用户 → `/www/gitea/{custom,data,log}` → 下载校验 Gitea 最新稳定版 → 写 app.ini(SQLite、监听 127.0.0.1:3000、禁止注册、强制私有库)→ systemd 服务 → 启动并验证 `curl 127.0.0.1:3000` 返回 200。 + +手工等价操作与已知坑(脚本失败时按此排查): + +1. **不要**预配 `INTERNAL_TOKEN_URI`——首次启动会因文件不存在而崩溃,让 Gitea 自动生成。 +2. 下载地址列表:`https://dl.gitea.com/gitea/version.json` 取最新版本号;sha256 文件校验时文件名要与原始名一致。 +3. 防火墙**不开** 3000 端口,只走反代。 + +## 第 2 步:Gitea 域名与反代 + +1. **用户操作**:DNS 添加 A 记录 ` → 服务器公网 IP`(未备案过渡域名同理)。 +2. 宝塔建反向代理站点:域名 = Gitea 域名,目标 `http://127.0.0.1:3000`,全站转发,开 WebSocket 支持。 +3. **必须在 server 块加 `client_max_body_size 0;`**——否则 git push 大仓库会被 nginx 拒(默认 1m)。 +4. `nginx -t` 通过后 reload,`curl -H "Host: " http://127.0.0.1/` 返回 200。 +5. DNS 生效后面板申请 Let's Encrypt 证书(选对域名!宝塔常会自动附加别名域名,别选错)。 +6. 未备案过渡期:先用已备案域名访问,在规范里记录"备案成功后切换"待办。 + +## 第 3 步:管理员与项目仓库 + +```bash +# 管理员(密码生成后交付用户,建议用户随即改掉) +sudo -u git gitea admin user create --config /www/gitea/custom/conf/app.ini \ + --admin --username admin --password '<强密码>' --email admin@<项目域名> --must-change-password=false +# 建私有仓库(也可让用户网页操作) +``` + +1. 建一个**私有**仓库,命名 = 项目名(如 `xxx-erp`)。 +2. 生成 API token(_basic auth 调 `POST /api/v1/users/admin/tokens`,scope all),存 `/root/.gitea_token`(600)。 +3. 凭据写 `/root/.git-credentials`(600),格式 `http://admin:@`。 + +## 第 4 步:开发目录 git 化 + +1. `.gitignore` 至少排除:运行时目录(runtime/ 等)、用户上传目录、IDE 目录。**vendor/依赖目录是否入库先问用户**(老项目倾向全量存档防兼容问题,要强制 `git add -f` 补齐依赖内部 .gitignore 排除的文件)。 +2. `git init -b <开发分支>`(建议 `test` 或 `develop`)→ 配置 user.name/email → `git add -A` → 检查无垃圾文件 → 首次提交。 +3. remote + 凭据(credential.helper store)→ push。 +4. 提交身份、凭据都是**仓库级**配置;删过 .git 重建后要重配。 + +## 第 5 步:提炼 standards/ 规范目录(本技能只给骨架,内容必须重新提炼) + +在项目根创建: + +``` +standards/ +├── README.md # 目录说明+索引,开头放"AI 记忆指令"(读到即写入持久记忆) +├── behavior.md # 行为约定:硬性禁止/危险链路/工作方式(含发布流程,见第 7 步) +├── coding.md # 代码规范——通读项目代码后按真实写法提炼,禁止照抄其他项目 +├── database.md # 数据库规范——含增量 SQL 约定与改库发布流程(见第 7 步) +└── manual.md # 完整手册:公共方法清单、场景配方、带文件路径/行号的实例 +``` + +提炼要求:**只写该项目真实遵循的写法**(读代码统计套路,不抄框架官方理论);硬性约定进 standards,查阅资料进 manual,两者冲突以 standards 为准。 + +同批创建:根 `README.md`(顶部"导航(新 AI 由此开始)":AI 记忆指令 + 必读顺序 + 第一级目录一览 + 寻路规则"进入目录先读其 README,首次用到某目录时创建其 README")+ `ai_work/`(README 索引 + done/ 归档机制)+ `sql/`(若项目含数据库)+ 各工具入口文件(CODEBUDDY.md/CLAUDE.md 等指向 standards)。 + +## 第 6 步:生产目录 git 化(有生产在跑时) + +**先备份**:`tar -czf /www/backup/<项目>_pre_git_$(date +%Y%m%d_%H%M%S).tar.gz -C /www/wwwroot <生产目录名>`,并**单独留存环境专属文件副本**。 + +1. `git init -b <生产分支>` + remote + fetch。 +2. **审查差异**后再 reset:`git -C <生产目录> diff --stat FETCH_HEAD`——差异只允许是环境配置;出现业务代码差异必须先停下问用户。 +3. `git reset --hard FETCH_HEAD` → **立即恢复环境专属文件**(数据库配置、密钥、extra/环境配置、宝塔 `public/.user.ini` 等)。 +4. `git update-index --skip-worktree <环境专属文件...>`——**一份都不能漏**,漏一个就是生产事故。 +5. ⚠️ 宝塔的 `public/.user.ini` 带 `chattr +i` 锁:改它前 `chattr -i`,改完 `chattr +i`;reset 遇 "unable to unlink" 就是它。 +6. **操作后必须验证**:`git status` 干净(未跟踪除外);include/读取环境配置确认指向本环境;`chown -R :` 全目录(.git 和带锁文件除外);站点首页 200。 +7. 设置本地 master 上游跟踪,让以后 `git pull` 直接可用。 + +> **操作红线**:跨目录操作一律用绝对路径或 `git -C <路径>`——Bash 会话的工作目录可能在轮次间静默复位,凭"刚才 cd 过"操作是事故之源。危险命令(rm/reset/cp 覆盖)前后必须验证位置与关键文件内容。 + +## 第 7 步:发布流程写入 standards/behavior.md + +- 开发分支 = AI 开发环境;任务完成 → commit + push → **提醒用户去 Gitea 合并到生产分支**(不会 git 的用户给指路:拉请求 → base=生产分支 / compare=开发分支 → 创建 → 合并;合并标题格式 `发布:<改动一句话>`;标题加 `WIP:` 前缀会锁合并按钮,用于未完成的草稿)。 +- 更新生产 = `git -C <生产目录> pull && sudo -u php think clear`(按项目实际清缓存命令),**清缓存/写 runtime 的命令必须以 web 用户身份跑**,否则属主变 root 全站 500。完成后验证首页 200。 +- **改库流程**:增量 SQL 存 `sql/YYYY-MM-DD_描述.sql` 与代码一起提交;**SQL 不随 git pull 走**——生产库要单独执行,顺序固定**先库后代码**;执行生产库前把 SQL 给用户确认并备份生产库。 +- web 可写目录(runtime/、uploads/ 等)属主必须是 web 用户;root 操作后必须恢复。 + +## 完成验证清单(全部打勾才算接入完成) + +- [ ] Gitea 可通过域名 HTTPS 访问,禁止注册,仓库强制私有 +- [ ] 管理员密码已交付用户 +- [ ] 开发分支已 push,remote/凭据可用 +- [ ] standards/ 五件套齐全且内容来自项目真实代码 +- [ ] 根 README 导航 + ai_work/ + 工具入口文件就位 +- [ ] 生产目录 git 化完成,skip-worktree 清单核实,站点 200 +- [ ] 发布流程、改库流程已写入 behavior.md +- [ ] 全量备份文件已留存并告知用户路径 diff --git a/install_gitea.sh b/install_gitea.sh new file mode 100755 index 0000000..3599e7b --- /dev/null +++ b/install_gitea.sh @@ -0,0 +1,116 @@ +#!/usr/bin/env bash +# install_gitea.sh —— 新服务器一键安装 Gitea(自包含体系用) +# 用法: sudo ./install_gitea.sh 例: sudo ./install_gitea.sh git.example.com +# 安装后仍需人工完成: DNS A 记录、宝塔反向代理(含 client_max_body_size 0)、SSL 证书、创建管理员 +set -euo pipefail + +DOMAIN="${1:?用法: sudo ./install_gitea.sh }" +BASE=/www/gitea +[ "$(id -u)" -eq 0 ] || { echo "必须以 root 运行"; exit 1; } + +echo "==> 1/7 创建 git 系统用户与目录" +id git >/dev/null 2>&1 || useradd --system --shell /bin/bash --home-dir /home/git --create-home git +mkdir -p $BASE/custom/conf $BASE/data $BASE/log + +echo "==> 2/7 查询最新稳定版" +VERSION=$(curl -s https://dl.gitea.com/gitea/version.json | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1) +[ -n "$VERSION" ] || { echo "无法获取版本号,检查网络"; exit 1; } +echo " 最新稳定版: $VERSION" + +echo "==> 3/7 下载并校验二进制" +cd /tmp +curl -sL -o gitea-$VERSION-linux-amd64 https://dl.gitea.com/gitea/$VERSION/gitea-$VERSION-linux-amd64 +curl -sL -o gitea-$VERSION-linux-amd64.sha256 https://dl.gitea.com/gitea/$VERSION/gitea-$VERSION-linux-amd64.sha256 +sha256sum -c gitea-$VERSION-linux-amd64.sha256 +install -m 755 gitea-$VERSION-linux-amd64 /usr/local/bin/gitea +rm -f gitea-$VERSION-linux-amd64* + +echo "==> 4/7 写配置 app.ini" +SECRET=$(openssl rand -hex 32) +cat > $BASE/custom/conf/app.ini < 5/7 systemd 服务" +cat > /etc/systemd/system/gitea.service < 6/7 等待启动" +for i in $(seq 1 30); do + sleep 2 + CODE=$(curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:3000/ || true) + [ "$CODE" = "200" ] && break +done +[ "$CODE" = "200" ] || { echo "启动失败,查看: journalctl -u gitea -n 30"; exit 1; } + +echo "==> 7/7 完成。后续人工步骤:" +cat < 本机公网 IP + 2. 宝塔建反向代理站点: $DOMAIN -> http://127.0.0.1:3000,server 块加 client_max_body_size 0; + (不加快递大 push 会被 nginx 默认 1m 限制拒绝) + 3. DNS 生效后申请 SSL 证书(注意选对域名) + 4. 创建管理员: + sudo -u git gitea admin user create --config $BASE/custom/conf/app.ini \\ + --admin --username admin --password '<强密码>' --email admin@$DOMAIN --must-change-password=false + 5. 生成 API token 并配置 /root/.git-credentials (600) +TIP