Add operations and sync documentation
This commit is contained in:
parent
89bc23e7e7
commit
74fb6ec0a0
|
|
@ -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
10
TODO.md
|
|
@ -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:后续完善项
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
```
|
||||||
Loading…
Reference in New Issue