Skip to content

Commit 831231c

Browse files
committed
Add GitHub Actions workflow and deployment documentation
1 parent 8fd4a9d commit 831231c

2 files changed

Lines changed: 367 additions & 0 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
name: Deploy to Cloudflare
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
workflow_dispatch:
8+
9+
jobs:
10+
# ============================================================
11+
# Job 1: 部署后端 Worker
12+
# ============================================================
13+
deploy-backend:
14+
name: Deploy Backend (Cloudflare Worker)
15+
runs-on: ubuntu-latest
16+
defaults:
17+
run:
18+
working-directory: backend
19+
steps:
20+
- name: Checkout
21+
uses: actions/checkout@v4
22+
23+
- name: Setup Node.js
24+
uses: actions/setup-node@v4
25+
with:
26+
node-version: '20'
27+
cache: 'npm'
28+
cache-dependency-path: backend/package-lock.json
29+
30+
- name: Install dependencies
31+
run: npm ci
32+
33+
- name: Deploy Worker
34+
uses: cloudflare/wrangler-action@v3
35+
with:
36+
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
37+
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
38+
workingDirectory: backend
39+
command: deploy
40+
41+
# ============================================================
42+
# Job 2: 构建并部署前端到 Cloudflare Pages
43+
# ============================================================
44+
deploy-frontend:
45+
name: Deploy Frontend (Cloudflare Pages)
46+
runs-on: ubuntu-latest
47+
needs: deploy-backend
48+
defaults:
49+
run:
50+
working-directory: frontend
51+
steps:
52+
- name: Checkout
53+
uses: actions/checkout@v4
54+
55+
- name: Setup Node.js
56+
uses: actions/setup-node@v4
57+
with:
58+
node-version: '20'
59+
cache: 'npm'
60+
cache-dependency-path: frontend/package-lock.json
61+
62+
- name: Install dependencies
63+
run: npm ci
64+
65+
- name: Build frontend
66+
run: npm run build
67+
env:
68+
NODE_ENV: production
69+
70+
- name: Deploy to Cloudflare Pages
71+
uses: cloudflare/wrangler-action@v3
72+
with:
73+
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
74+
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
75+
workingDirectory: frontend
76+
command: pages deploy dist --project-name=${{ secrets.CF_PAGES_PROJECT_NAME }}

DEPLOYMENT.md

Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
# 部署文档
2+
3+
本项目基于 **Cloudflare** 全家桶构建:
4+
5+
- **后端**:Cloudflare Workers(Hono 框架)
6+
- **数据库**:Cloudflare D1(SQLite)
7+
- **对象存储**:Cloudflare R2
8+
- **前端**:Cloudflare Pages(React + Vite)
9+
10+
---
11+
12+
## 目录
13+
14+
1. [前置条件](#1-前置条件)
15+
2. [首次手动部署(初始化)](#2-首次手动部署初始化)
16+
- 2.1 [创建 D1 数据库](#21-创建-d1-数据库)
17+
- 2.2 [创建 R2 存储桶](#22-创建-r2-存储桶)
18+
- 2.3 [配置 wrangler.toml](#23-配置-wranglertoml)
19+
- 2.4 [初始化数据库表结构](#24-初始化数据库表结构)
20+
- 2.5 [部署后端 Worker](#25-部署后端-worker)
21+
- 2.6 [部署前端到 Pages](#26-部署前端到-pages)
22+
- 2.7 [配置 Service Binding](#27-配置-service-binding)
23+
3. [GitHub Actions 自动部署](#3-github-actions-自动部署)
24+
- 3.1 [创建 Cloudflare API Token](#31-创建-cloudflare-api-token)
25+
- 3.2 [配置 GitHub Secrets](#32-配置-github-secrets)
26+
- 3.3 [触发自动部署](#33-触发自动部署)
27+
4. [环境变量说明](#4-环境变量说明)
28+
5. [常见问题](#5-常见问题)
29+
30+
---
31+
32+
## 1. 前置条件
33+
34+
| 工具 | 版本要求 | 说明 |
35+
|------|----------|------|
36+
| Node.js | >= 18 | 建议使用 20 LTS |
37+
| npm | >= 9 | 随 Node.js 安装 |
38+
| Wrangler CLI | >= 3 | Cloudflare 官方命令行工具 |
39+
| Cloudflare 账号 | - | 需开通 Workers、D1、R2、Pages |
40+
41+
安装 Wrangler:
42+
43+
```bash
44+
npm install -g wrangler
45+
wrangler login
46+
```
47+
48+
---
49+
50+
## 2. 首次手动部署(初始化)
51+
52+
> 首次部署必须手动完成,主要是创建云端资源并获取对应 ID 填入配置。
53+
54+
### 2.1 创建 D1 数据库
55+
56+
```bash
57+
cd backend
58+
npm run db:create
59+
```
60+
61+
输出示例:
62+
63+
```
64+
✅ Successfully created DB 'memos_db'
65+
{
66+
"uuid": "e03f026e-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
67+
...
68+
}
69+
```
70+
71+
复制输出中的 `uuid`,填入 `backend/wrangler.toml`
72+
73+
```toml
74+
[[d1_databases]]
75+
binding = "DB"
76+
database_name = "memos_db"
77+
database_id = "<你的 uuid>"
78+
```
79+
80+
### 2.2 创建 R2 存储桶
81+
82+
```bash
83+
wrangler r2 bucket create memos
84+
```
85+
86+
> R2 存储桶名称须全局唯一,如 `memos` 已被占用可改为 `memos-yourname`,同步修改 `wrangler.toml` 中的 `bucket_name`
87+
88+
### 2.3 配置 wrangler.toml
89+
90+
`backend/wrangler.toml` 完整示例:
91+
92+
```toml
93+
name = "memos-api"
94+
main = "src/index.js"
95+
compatibility_date = "2024-01-15"
96+
compatibility_flags = ["nodejs_compat"]
97+
98+
[vars]
99+
TIMEZONE = "Asia/Shanghai"
100+
101+
[[d1_databases]]
102+
binding = "DB"
103+
database_name = "memos_db"
104+
database_id = "<你的 D1 数据库 ID>"
105+
106+
[[r2_buckets]]
107+
binding = "BUCKET"
108+
bucket_name = "memos"
109+
```
110+
111+
### 2.4 初始化数据库表结构
112+
113+
```bash
114+
cd backend
115+
npm run db:init
116+
```
117+
118+
该命令执行 `schema.sql`,在远程 D1 数据库中创建所有表。
119+
120+
> 本地开发时使用 `npm run db:local` 初始化本地数据库。
121+
122+
### 2.5 部署后端 Worker
123+
124+
```bash
125+
cd backend
126+
npm run deploy
127+
```
128+
129+
部署成功后,Wrangler 会输出 Worker 的访问地址,例如:
130+
131+
```
132+
https://memos-api.<your-subdomain>.workers.dev
133+
```
134+
135+
记录该地址,后续配置前端 fallback URL 时使用。
136+
137+
### 2.6 部署前端到 Pages
138+
139+
**方式一:通过 Wrangler CLI(推荐)**
140+
141+
```bash
142+
cd frontend
143+
npm ci
144+
npm run build
145+
wrangler pages deploy dist --project-name=memos-frontend
146+
```
147+
148+
首次执行时 Wrangler 会自动创建 Pages 项目。
149+
150+
**方式二:通过 Cloudflare Dashboard**
151+
152+
1. 登录 [Cloudflare Dashboard](https://dash.cloudflare.com)
153+
2. 进入 **Workers & Pages → Create → Pages → Connect to Git**
154+
3. 选择本仓库,设置构建配置:
155+
- **Framework preset**:None
156+
- **Build command**`cd frontend && npm ci && npm run build`
157+
- **Build output directory**`frontend/dist`
158+
- **Root directory**`/`
159+
160+
### 2.7 配置 Service Binding
161+
162+
Service Binding 让前端 Pages 直接内部调用后端 Worker,无需跨域请求,性能更好。
163+
164+
1. 进入 Cloudflare Dashboard → **Workers & Pages** → 选择前端 Pages 项目
165+
2. 点击 **Settings → Functions**
166+
3.**Service bindings** 中添加:
167+
- **Variable name**`BACKEND`
168+
- **Service**:选择你的 Worker(`memos-api`
169+
- **Environment**`production`
170+
4. 点击 **Save**
171+
172+
> 配置 Service Binding 后,`frontend/functions/_middleware.js` 会自动使用内部调用,无需配置 CORS。
173+
174+
---
175+
176+
## 3. GitHub Actions 自动部署
177+
178+
每次推送到 `main` 分支时,工作流会自动:
179+
1. 部署后端 Worker
180+
2. 构建前端并部署到 Cloudflare Pages
181+
182+
### 3.1 创建 Cloudflare API Token
183+
184+
1. 进入 [Cloudflare API Tokens](https://dash.cloudflare.com/profile/api-tokens)
185+
2. 点击 **Create Token → Custom Token**
186+
3. 配置权限:
187+
188+
| 权限类型 | 资源 | 操作 |
189+
|----------|------|------|
190+
| Account | Cloudflare Pages | Edit |
191+
| Account | Workers Scripts | Edit |
192+
| Account | Workers D1 | Edit |
193+
| Account | Workers R2 Storage | Edit |
194+
| Zone | Workers Routes | Edit(可选,如需自定义域名) |
195+
196+
4. 点击 **Continue to summary → Create Token**,复制 Token(只显示一次)
197+
198+
### 3.2 配置 GitHub Secrets
199+
200+
进入 GitHub 仓库 → **Settings → Secrets and variables → Actions → New repository secret**,添加以下 3 个 Secret:
201+
202+
| Secret 名称 | 说明 | 获取方式 |
203+
|-------------|------|----------|
204+
| `CLOUDFLARE_API_TOKEN` | 上一步创建的 API Token | 见 3.1 |
205+
| `CLOUDFLARE_ACCOUNT_ID` | Cloudflare 账号 ID | Dashboard 右侧边栏 → Account ID |
206+
| `CF_PAGES_PROJECT_NAME` | Pages 项目名称 |`memos-frontend` |
207+
208+
### 3.3 触发自动部署
209+
210+
**自动触发**:推送代码到 `main` 分支即自动触发。
211+
212+
```bash
213+
git add .
214+
git commit -m "your changes"
215+
git push origin main
216+
```
217+
218+
**手动触发**:进入 GitHub 仓库 → **Actions → Deploy to Cloudflare → Run workflow**
219+
220+
---
221+
222+
## 4. 环境变量说明
223+
224+
### 后端(wrangler.toml `[vars]`
225+
226+
| 变量名 | 默认值 | 说明 |
227+
|--------|--------|------|
228+
| `TIMEZONE` | `Asia/Shanghai` | 服务端时区,影响 RSS 时间显示 |
229+
230+
### 前端(无需额外环境变量)
231+
232+
前端通过 Service Binding 或相对路径调用后端 API,无需配置 API 地址。
233+
234+
如需修改 fallback 后端地址(未配置 Service Binding 时),编辑:
235+
236+
```js
237+
// frontend/functions/_middleware.js 第 43 行
238+
const backendUrl = 'https://memos-api.your-domain.workers.dev' + url.pathname + url.search;
239+
```
240+
241+
---
242+
243+
## 5. 常见问题
244+
245+
### Q: 部署后上传文件报 500 错误
246+
247+
**原因**:R2 bucket 未绑定或 bucket 名称不匹配。
248+
249+
**排查**
250+
1. 确认 `wrangler.toml``bucket_name` 与 Cloudflare Dashboard 中 R2 bucket 名称一致
251+
2. 重新执行 `npm run deploy`
252+
253+
### Q: 前端访问 API 报 CORS 错误
254+
255+
**原因**:未配置 Service Binding,且 fallback URL 指向错误地址。
256+
257+
**解决**:按照 [2.7 节](#27-配置-service-binding) 配置 Service Binding,或修改 `_middleware.js` 中的 fallback URL。
258+
259+
### Q: GitHub Actions 部署失败,提示 `authentication error`
260+
261+
**原因**:API Token 权限不足或 Secret 配置错误。
262+
263+
**排查**
264+
1. 检查 GitHub Secrets 中三个变量是否正确填写(无多余空格)
265+
2. 检查 API Token 权限是否包含 Pages Edit 和 Workers Scripts Edit
266+
267+
### Q: 数据库迁移 / 重置
268+
269+
> ⚠️ 以下操作会清空数据,请先备份。
270+
271+
```bash
272+
# 仅在需要重建表结构时执行
273+
cd backend
274+
wrangler d1 execute memos_db --command="DROP TABLE IF EXISTS memos" --remote
275+
npm run db:init
276+
```
277+
278+
### Q: 本地开发
279+
280+
```bash
281+
# 终端 1:启动后端(本地 D1 + R2 模拟)
282+
cd backend
283+
npm run dev
284+
285+
# 终端 2:启动前端(代理到本地后端 :8787)
286+
cd frontend
287+
npm install
288+
npm run dev
289+
```
290+
291+
前端开发服务器运行在 `http://localhost:5173`,API 请求自动代理到 `http://127.0.0.1:8787`

0 commit comments

Comments
 (0)