Add operations and sync documentation

This commit is contained in:
SepComet 2026-05-06 10:21:13 +08:00
parent 89bc23e7e7
commit 74fb6ec0a0
3 changed files with 497 additions and 5 deletions

128
README.md Normal file
View File

@ -0,0 +1,128 @@
# personal-homepage
一个基于 Astro 的个人主页项目,定位为:
> **静态站点 + 构建时数据同步层**
运行时对外提供纯静态页面;构建阶段由脚本从 Gitea / Seafile 拉取数据,生成本地 JSON再交给 Astro 渲染。
## 当前能力
- Astro 静态站点
- Markdown 日志内容
- 项目 / 分享 / Gitea 活动页
- 构建时同步 Gitea / Seafile 数据
- generated JSON schema 校验
- 统一重建入口 `npm run rebuild`
- 结构化错误码与 `REBUILD_RESULT` 输出,便于 AstrBot / cron 调用
## 快速开始
### 1. 安装依赖
```bash
npm install
```
### 2. 配置环境变量
复制示例文件:
```bash
cp .env.example .env
```
然后填写:
- `GITEA_BASE_URL`
- `GITEA_TOKEN`
- `GITEA_USERNAME`
- `SEAFILE_BASE_URL`
- `SEAFILE_TOKEN`
如果某些远端还没接好,也可以先保留为空;系统会按当前策略回退到 seed data。
### 3. 本地开发
```bash
npm run dev
```
### 4. 手动同步内容
```bash
npm run content:sync
```
### 5. 完整重建
```bash
npm run rebuild
```
该命令会执行:
1. `npm run content:sync`
2. `npm run build`
## 常用命令
| 命令 | 用途 |
|------|------|
| `npm run dev` | 本地开发 |
| `npm run content:sync` | 仅执行内容同步 |
| `npm run build` | 仅执行 Astro 构建 |
| `npm run rebuild` | 同步 + 构建,适合作为 AstrBot / cron 统一入口 |
| `npm run preview` | 本地预览构建结果 |
## 文档索引
- `REQUIREMENTS.md`:需求与范围
- `TODO.md`:当前推进计划
- `docs/rebuild-trigger-spec.md`AstrBot / cron 重建触发与错误码约定
- `docs/content-sync-guide.md`:环境变量、映射文件、同步脚本职责、故障排查
- `docs/ui-design-spec.md`UI 设计规范
## 内容入口
### 日志
- 目录:`src/content/logs/*.md`
### 项目种子数据
- 文件:`src/content/projects/index.json`
### 分享种子数据
- 文件:`src/content/shares/index.json`
### Seafile 映射
- 文件:`src/content/seafile/index.json`
## 统一重建入口
适合 AstrBot / cron 调用的命令:
```bash
npm run rebuild
```
命令结束前会输出一行结构化结果:
```text
REBUILD_RESULT {...}
```
并返回明确退出码,便于通知系统判断成功 / 失败阶段。
详细约定见:
- `docs/rebuild-trigger-spec.md`
## 当前实现边界
- 当前默认策略是失败时回退 seed data而不是保留上一轮 generated 文件
- `SEAFILE_MIRROR_DOWNLOADS=true` 目前只保留开关,尚未真正实现文件镜像
- `npm run rebuild` 当前只做同步和构建,还不包含部署阶段

10
TODO.md
View File

@ -96,14 +96,14 @@
### 5. 补运行文档 ### 5. 补运行文档
- [ ] 在 README 或单独文档里写清: - [x] 在 README 或单独文档里写清:
- [x] AstrBot / cron 如何触发 - [x] AstrBot / cron 如何触发
- [x] AstrBot 调用的统一构建指令与返回约定 - [x] AstrBot 调用的统一构建指令与返回约定
- [x] 错误码含义sync/build/deploy/unknown - [x] 错误码含义sync/build/deploy/unknown
- [ ] 环境变量如何配置 - [x] 环境变量如何配置
- [ ] Gitea / Seafile 映射如何填写 - [x] Gitea / Seafile 映射如何填写
- [ ] 同步脚本职责 - [x] 同步脚本职责
- [ ] 构建失败如何排查 - [x] 构建失败如何排查
## P2后续完善项 ## P2后续完善项

364
docs/content-sync-guide.md Normal file
View File

@ -0,0 +1,364 @@
# 内容同步与运维说明
本文档补充说明:
- 环境变量如何配置
- Gitea / Seafile 映射如何填写
- 同步脚本职责
- 构建失败如何排查
---
## 1. 同步链路概览
当前重建链路是:
```text
npm run rebuild
├─ npm run content:sync
│ ├─ 读取 seed data
│ ├─ 拉取 Gitea 数据
│ ├─ 读取 / 拉取 Seafile 数据
│ ├─ 生成 generated JSON
│ └─ 执行 schema 校验
└─ npm run build
└─ Astro 渲染静态页面
```
生成结果默认写入:
- `src/data/generated/projects.json`
- `src/data/generated/shares.json`
- `src/data/generated/gitea-activity.json`
页面层优先读取 generated data如果 generated 文件缺失或校验失败,会按当前策略回退到 seed data / placeholder data。
---
## 2. 环境变量说明
复制:
```bash
cp .env.example .env
```
### 2.1 Gitea
| 变量 | 必填 | 作用 |
|------|------|------|
| `GITEA_BASE_URL` | 建议 | Gitea 根地址 |
| `GITEA_TOKEN` | 建议 | 构建阶段访问 Gitea API 的 token |
| `GITEA_USERNAME` | 建议 | 要同步活动流的用户名 |
如果三者都配置完整,则会执行真实 Gitea 同步;否则:
- 项目数据回退到 seed data
- activity 回退到 placeholder
### 2.2 Seafile
| 变量 | 必填 | 作用 |
|------|------|------|
| `SEAFILE_BASE_URL` | 可选 | Seafile 根地址 |
| `SEAFILE_TOKEN` | 可选 | Seafile API token |
当前 Seafile 支持两种资源方式:
1. 映射文件里直接填写 `url`
2. 填写 `repo_id + path`,由脚本请求 Seafile API 生成下载地址
如果没有完整 Seafile 配置,但映射文件已经直接提供 `url`,页面仍可正常展示这些链接。
### 2.3 输出与行为
| 变量 | 默认值 | 作用 |
|------|--------|------|
| `SYNC_OUTPUT_DIR` | `src/data/generated` | generated JSON 输出目录 |
| `STRICT_SYNC` | `false` | 为 `true` 时,同步失败直接中断,不再回退 |
| `SEAFILE_MIRROR_DOWNLOADS` | `false` | 预留开关,当前未实现文件镜像 |
| `DOWNLOADS_OUTPUT_DIR` | `public/downloads` | 未来镜像文件的目标目录 |
### 2.4 Gitea 调优参数
| 变量 | 默认值 | 作用 |
|------|--------|------|
| `GITEA_ACTIVITY_DAYS` | `70` | 热力图回溯天数 |
| `GITEA_ACTIVITY_PER_DAY_LIMIT` | `50` | 每天请求的 activity 条数上限 |
| `GITEA_RECENT_ITEM_LIMIT` | `8` | recent activity 保留条数 |
| `GITEA_REQUEST_TIMEOUT_MS` | `15000` | Gitea 请求超时 |
| `GITEA_REQUEST_CONCURRENCY` | `5` | 活动流按天拉取时的并发数 |
### 2.5 Seafile 调优参数
| 变量 | 默认值 | 作用 |
|------|--------|------|
| `SEAFILE_REQUEST_TIMEOUT_MS` | `15000` | Seafile 请求超时 |
---
## 3. 映射文件如何填写
### 3.1 项目种子数据:`src/content/projects/index.json`
每个项目至少包含:
```json
{
"name": "personal-homepage",
"description": "项目描述",
"gitea_repo": "basil/personal-homepage",
"cover_image": "/images/projects/personal-homepage.svg",
"demo_video": "",
"download_link": "",
"tags": ["astro", "static-site"],
"featured": true
}
```
字段说明:
- `gitea_repo`:项目与 Gitea 仓库关联键,格式必须是 `owner/repo`
- `cover_image`:封面图静态路径
- `download_link`:可选的兜底下载地址
- `tags`:标签数组
- `featured`:是否出现在首页精选区
### 3.2 分享种子数据:`src/content/shares/index.json`
适合放不依赖 Seafile API 的静态分享项:
```json
{
"name": "个人主页需求文档",
"description": "站点范围说明",
"url": "#",
"time": "2026-05-03"
}
```
### 3.3 Seafile 映射:`src/content/seafile/index.json`
结构分两块:
- `projects[]`:挂到项目详情 / 下载区
- `shares[]`:挂到全站分享列表
#### 项目资源示例
```json
{
"projects": [
{
"project_repo": "basil/personal-homepage",
"downloads": [
{
"name": "Windows 构建包",
"description": "项目打包文件",
"url": "https://example.com/file.zip",
"type": "build",
"platform": "windows"
}
]
}
]
}
```
#### 通过 Seafile API 解析资源示例
```json
{
"name": "Windows 构建包",
"repo_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"path": "/builds/win/demo.zip",
"type": "build",
"platform": "windows"
}
```
可选字段:
- `description`
- `url`
- `repo_id`
- `path`
- `type``build | demo | document | asset`
- `platform`
- `size`
- `updated_at`
- `time`
规则:
- 如果 `url` 已提供,脚本直接使用它,不再请求 Seafile API
- 如果只有 `repo_id + path`,且 Seafile 配置完整,脚本会请求 API 补全下载地址和元数据
- 如果 API 请求失败:
- `STRICT_SYNC=false`:回退到映射文件已有字段
- `STRICT_SYNC=true`:同步中断
---
## 4. 脚本职责
### `scripts/fetch-gitea.ts`
负责:
- 根据 `src/content/projects/index.json` 中的 `gitea_repo` 拉取仓库信息
- 根据 `GITEA_USERNAME` 拉取 `/users/{username}/activities/feeds`
- 聚合生成:
- `projects` 补充字段
- `gitea-activity.json`
### `scripts/fetch-seafile.ts`
负责:
- 读取 `src/content/seafile/index.json`
- 解析项目下载资源和全站分享资源
- 必要时调用 Seafile API 生成下载链接和元数据
- 产出:
- `projects[].downloads[]`
- `shares.json`
### `scripts/sync-content.ts`
负责:
- 读取 seed data
- 调用 Gitea / Seafile 同步逻辑
- 对 generated JSON 执行 schema 校验
- 写出 generated 文件
- 对外返回同步阶段错误码
### `scripts/rebuild.ts`
负责:
- 作为 AstrBot / cron 的统一入口
- 顺序执行:
- `npm run content:sync`
- `npm run build`
- 输出 `REBUILD_RESULT`
- 返回结构化退出码
---
## 5. 失败排查
### 5.1 先看统一入口结果
执行:
```bash
npm run rebuild
```
重点关注:
- shell 退出码
- `REBUILD_RESULT {...}`
- `symbol`
- `stage`
- `logTail`
### 5.2 常见错误分类
#### `GITEA_SYNC_FAILED` / `11`
说明 Gitea 同步失败,常见原因:
- `GITEA_BASE_URL` 错误
- `GITEA_TOKEN` 权限不足或失效
- `GITEA_USERNAME` 错误
- `src/content/projects/index.json` 中某个 `gitea_repo` 不存在
- 远端 API 404 / 401 / 500
检查项:
1. 打开 Gitea 仓库地址确认仓库存在
2. 检查 token 是否有效
3. 检查 `gitea_repo` 是否是正确的 `owner/repo`
#### `SEAFILE_SYNC_FAILED` / `12`
说明 Seafile 资源解析失败,常见原因:
- `SEAFILE_BASE_URL` 错误
- `SEAFILE_TOKEN` 无效
- `repo_id` 错误
- `path` 不存在
检查项:
1. 确认映射文件中的 `repo_id``path`
2. 确认 token 是否有读取权限
3. 如果只是临时不稳定,可先直接填写 `url` 兜底
#### `SCHEMA_VALIDATION_FAILED` / `13`
说明 seed data 或 generated data 不符合 schema。
常见原因:
- `gitea_repo` 不是 `owner/repo`
- `tags` 不是字符串数组
- 日期字段不是可解析时间
- 下载资源缺少 `name`
检查项:
1. 检查 `src/content/projects/index.json`
2. 检查 `src/content/shares/index.json`
3. 检查 `src/content/seafile/index.json`
4. 根据报错里的路径定位字段
#### `BUILD_FAILED` / `20`
说明 Astro 构建阶段失败。
常见原因:
- 页面组件使用了不兼容字段
- 内容文件存在格式问题
- 某个页面渲染依赖的数据格式异常
建议:
1. 单独运行 `npm run build`
2. 查看 Astro 输出的具体页面报错
#### `CONFIG_INVALID` / `40`
说明运行环境本身不完整。
常见原因:
- Node / npm 不存在
- 命令执行环境有问题
### 5.3 `STRICT_SYNC` 的使用建议
- 开发期:建议 `STRICT_SYNC=false`
- 更方便先看页面效果
- 正式定时任务:视你对错误容忍度决定
- 想保守兜底:`false`
- 想强制发现问题:`true`
---
## 6. 推荐运维方式
当前更推荐:
1. 仓库负责统一入口:`npm run rebuild`
2. AstrBot 或 cron 负责定时触发
3. AstrBot 读取退出码和 `REBUILD_RESULT` 发送通知
如果只是人工排查,最小路径是:
```bash
npm run content:sync
npm run build
```