build: 升级工程依赖与工具链并完善部署工作流
This commit is contained in:
1 parent
e1948a7b4b
commit
457329d6c0
14 files changed
+14555
-12865
No files matched your search
@@ -1,6 +1,7 @@
|
|||||||
# BlogFlare Project Rules
|
# BlogFlare Project Rules
|
||||||
|
|
||||||
## Package Manager
|
## Package Manager
|
||||||
|
|
||||||
- **ALWAYS use `pnpm`** as the package manager for this project. Do not use `npm` or `yarn`.
|
- **ALWAYS use `pnpm`** as the package manager for this project. Do not use `npm` or `yarn`.
|
||||||
- When running one-off scripts, use `pnpm dlx` instead of `npx`.
|
- When running one-off scripts, use `pnpm dlx` instead of `npx`.
|
||||||
- When installing dependencies, use `pnpm install` or `pnpm add`.
|
- When installing dependencies, use `pnpm install` or `pnpm add`.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Required when exercising production-mode admin routes locally.
|
||||||
|
CF_ACCESS_TEAM_DOMAIN=https://your-team.cloudflareaccess.com
|
||||||
|
CF_ACCESS_AUD=your-access-application-audience
|
||||||
+28
-14
@@ -19,33 +19,47 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 1
|
fetch-depth: 1
|
||||||
|
|
||||||
# 2. 初始化 Node.js 运行环境 (使用 Node 22)
|
# 2. 使用与 packageManager 字段一致的 pnpm
|
||||||
- name: 2. 初始化 Node.js 环境
|
- name: 2. 初始化 pnpm 环境
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 11.20.0
|
||||||
|
|
||||||
|
# 3. 初始化 Node.js 运行环境 (使用 Node 22)
|
||||||
|
- name: 3. 初始化 Node.js 环境
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '22'
|
node-version: '22'
|
||||||
|
cache: 'pnpm'
|
||||||
# 3. 全局安装 pnpm 11
|
|
||||||
- name: 3. 全局安装 pnpm (对应当前开发环境的 11.x 体系)
|
|
||||||
run: npm install -g pnpm@11
|
|
||||||
|
|
||||||
# 4. 安装工程依赖包
|
# 4. 安装工程依赖包
|
||||||
- name: 4. 安装工程依赖包
|
- name: 4. 安装工程依赖包
|
||||||
run: pnpm install --frozen-lockfile
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
# 5. 执行类型自检并打包输出静态产物 (产出在 .svelte-kit/cloudflare)
|
# 5. 执行静态代码整洁规则审查及 Svelte/TS 类型质检关卡
|
||||||
- name: 5. 构建生产环境打包产物
|
- name: 5. 执行代码规范、类型与自动化测试质检
|
||||||
|
run: pnpm run check && pnpm run lint && pnpm run test
|
||||||
|
|
||||||
|
# 6. 执行类型自检并打包输出静态产物 (产出在 .svelte-kit/cloudflare)
|
||||||
|
- name: 6. 构建生产环境打包产物
|
||||||
run: pnpm run build
|
run: pnpm run build
|
||||||
|
|
||||||
# 6. 使用本地安装好的 wrangler 直接推送部署
|
# 7. 应用 D1 数据库增量迁移至远端生产区
|
||||||
- name: 6. 自动化推送到 Cloudflare Pages (主分支为生产发布)
|
- name: 7. 应用数据库增量迁移至云端 (D1 Migrations)
|
||||||
|
env:
|
||||||
|
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||||
|
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||||
|
run: pnpm exec wrangler d1 migrations apply blogflare-db --remote
|
||||||
|
|
||||||
|
# 8. 使用本地安装好的 wrangler 直接推送部署
|
||||||
|
- name: 8. 自动化推送到 Cloudflare Pages (主分支为生产发布)
|
||||||
env:
|
env:
|
||||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||||
run: pnpm exec wrangler pages deploy .svelte-kit/cloudflare --project-name=blogflare --branch=main
|
run: pnpm exec wrangler pages deploy .svelte-kit/cloudflare --project-name=blogflare --branch=main
|
||||||
|
|
||||||
# 7. 构建与发布成功时,用 curl 直联调用 Telegram 官方发送通知接口
|
# 9. 构建与发布成功时,用 curl 直联调用 Telegram 官方发送通知接口
|
||||||
- name: 7. 发送 Telegram 部署成功通知
|
- name: 9. 发送 Telegram 部署成功通知
|
||||||
if: success()
|
if: success()
|
||||||
env:
|
env:
|
||||||
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
||||||
@@ -58,8 +72,8 @@ jobs:
|
|||||||
-d "parse_mode=HTML" \
|
-d "parse_mode=HTML" \
|
||||||
--data-urlencode "text=${MSG}"
|
--data-urlencode "text=${MSG}"
|
||||||
|
|
||||||
# 8. 一旦任意步骤发生阻挠或错误,立即发警报知音
|
# 10. 一旦任意步骤发生阻挠或错误,立即发警报知音
|
||||||
- name: 8. 发送 Telegram 部署失败告警
|
- name: 10. 发送 Telegram 部署失败告警
|
||||||
if: failure()
|
if: failure()
|
||||||
env:
|
env:
|
||||||
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ lerna-debug.log*
|
|||||||
.env.*
|
.env.*
|
||||||
!.env.example
|
!.env.example
|
||||||
!.env.test
|
!.env.test
|
||||||
|
.dev.vars*
|
||||||
|
!.dev.vars.example
|
||||||
|
|
||||||
# ========================
|
# ========================
|
||||||
# 测试产物 (Testing)
|
# 测试产物 (Testing)
|
||||||
|
|||||||
Vendored
+1
-5
@@ -1,7 +1,3 @@
|
|||||||
{
|
{
|
||||||
"recommendations": [
|
"recommendations": ["svelte.svelte-vscode", "esbenp.prettier-vscode", "dbaeumer.vscode-eslint"]
|
||||||
"svelte.svelte-vscode",
|
|
||||||
"esbenp.prettier-vscode",
|
|
||||||
"dbaeumer.vscode-eslint"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
@@ -23,24 +23,32 @@ cd blogflare
|
|||||||
pnpm install
|
pnpm install
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. 初始化本地数据库
|
### 2. 初始化与同步数据库迁移
|
||||||
|
|
||||||
本项目在本地开发时依赖 Wrangler 模拟 D1 数据库环境。请运行以下命令初始化数据库表和测试数据:
|
本项目全面采用 Cloudflare D1 规范化迁移链体系。不管是初次安装还是升级扩展,只需应用增量迁移(`0000_initial.sql`、`0001_add_series.sql` 等)即可自动实现幂等同步:
|
||||||
|
|
||||||
|
`0000_initial.sql` 同时兼容空数据库和旧版 `schema.sql` 已初始化的数据库。生产升级前仍应先创建 D1 备份;不要再对生产库执行已移除的破坏性 `schema.sql`。
|
||||||
|
|
||||||
|
#### 本地开发环境同步:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm dlx wrangler d1 execute blogflare-db --local --file=./schema.sql
|
pnpm run db:migrate:local
|
||||||
|
# 或直接运行 wrangler: pnpm exec wrangler d1 migrations apply blogflare-db --local
|
||||||
```
|
```
|
||||||
|
|
||||||
如果你已经初始化过数据库,请不要重新执行会重建表的 `schema.sql`,而应应用增量迁移:
|
如果需要强制清空本地开发数据库并重新从初始状态加载迁移数据,可以运行:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm exec wrangler d1 migrations apply blogflare-db --local
|
pnpm run db:reset:local
|
||||||
```
|
```
|
||||||
|
|
||||||
部署新版本前,再将同一批迁移应用到远端数据库:
|
#### 部署与生产远端库同步:
|
||||||
|
|
||||||
|
部署更新或正式发布之前,请将完整的迁移链条应用到云端 D1 远端数据库中:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm exec wrangler d1 migrations apply blogflare-db --remote
|
pnpm run db:migrate:remote
|
||||||
|
# 或直接运行 wrangler: pnpm exec wrangler d1 migrations apply blogflare-db --remote
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. 启动本地开发服务器
|
### 3. 启动本地开发服务器
|
||||||
@@ -52,6 +60,15 @@ pnpm run dev
|
|||||||
pnpm run dev -- --open
|
pnpm run dev -- --open
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 4. 配置后台认证
|
||||||
|
|
||||||
|
生产环境的 `/admin` 路由强制验证 Cloudflare Access JWT。请在 Cloudflare Pages 项目中配置以下两个加密变量;缺少任意一项时后台会拒绝访问:
|
||||||
|
|
||||||
|
- `CF_ACCESS_TEAM_DOMAIN`:例如 `https://your-team.cloudflareaccess.com`
|
||||||
|
- `CF_ACCESS_AUD`:Access Application 的 Audience (AUD) Tag
|
||||||
|
|
||||||
|
本地生产预览可复制 `.dev.vars.example` 为 `.dev.vars` 并填入真实值。开发服务器会保留仅限 `dev` 模式的本地认证旁路。
|
||||||
|
|
||||||
## 📦 构建与部署
|
## 📦 构建与部署
|
||||||
|
|
||||||
### 构建项目
|
### 构建项目
|
||||||
@@ -67,13 +84,14 @@ pnpm run build
|
|||||||
项目已经配置了 `@sveltejs/adapter-cloudflare`,可以通过连接 GitHub/GitLab 仓库到 Cloudflare Pages 实现自动构建部署,或者使用 Wrangler CLI 进行手动发布:
|
项目已经配置了 `@sveltejs/adapter-cloudflare`,可以通过连接 GitHub/GitLab 仓库到 Cloudflare Pages 实现自动构建部署,或者使用 Wrangler CLI 进行手动发布:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm dlx wrangler pages deploy .svelte-kit/cloudflare
|
pnpm exec wrangler pages deploy .svelte-kit/cloudflare
|
||||||
```
|
```
|
||||||
*(注意:正式部署前请确保在 Cloudflare 仪表盘中创建了对应的 D1 数据库,并绑定到项目中)*
|
|
||||||
|
_(注意:正式部署前请确保在 Cloudflare 仪表盘中创建了对应的 D1 数据库,并绑定到项目中)_
|
||||||
|
|
||||||
## 🛠️ 核心技术栈
|
## 🛠️ 核心技术栈
|
||||||
|
|
||||||
- [SvelteKit](https://kit.svelte.dev/)
|
- [SvelteKit](https://kit.svelte.dev/)
|
||||||
- [Cloudflare Pages](https://pages.cloudflare.com/) & [Cloudflare D1](https://developers.cloudflare.com/d1/)
|
- [Cloudflare Pages](https://pages.cloudflare.com/) & [Cloudflare D1](https://developers.cloudflare.com/d1/)
|
||||||
- [Vite](https://vitejs.dev/)
|
- [Vite](https://vitejs.dev/)
|
||||||
- Markdown 解析: `marked`, `highlight.js`, `dompurify`, `mdsvex`
|
- Markdown 解析与净化: `marked`, `highlight.js`, `sanitize-html`, `mdsvex`
|
||||||
+2
-1
@@ -10,6 +10,7 @@ const gitignorePath = path.resolve(import.meta.dirname, '.gitignore');
|
|||||||
|
|
||||||
export default defineConfig(
|
export default defineConfig(
|
||||||
includeIgnoreFile(gitignorePath),
|
includeIgnoreFile(gitignorePath),
|
||||||
|
{ ignores: ['scratch/**', 'worker-configuration.d.ts'] },
|
||||||
js.configs.recommended,
|
js.configs.recommended,
|
||||||
ts.configs.recommended,
|
ts.configs.recommended,
|
||||||
svelte.configs.recommended,
|
svelte.configs.recommended,
|
||||||
@@ -20,7 +21,7 @@ export default defineConfig(
|
|||||||
rules: {
|
rules: {
|
||||||
// typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects.
|
// typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects.
|
||||||
// see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors
|
// see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors
|
||||||
"no-undef": 'off'
|
'no-undef': 'off'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
+30
-29
@@ -3,53 +3,54 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"packageManager": "pnpm@11.20.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
"build": "wrangler types && vite build",
|
"build": "wrangler types --check && vite build",
|
||||||
"preview": "wrangler pages dev .svelte-kit/cloudflare --port 4173",
|
"preview": "wrangler pages dev .svelte-kit/cloudflare --port 4173",
|
||||||
"prepare": "svelte-kit sync || echo ''",
|
"prepare": "svelte-kit sync",
|
||||||
"check": "wrangler types && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
"check": "wrangler types --check && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||||
"lint": "prettier --check . && eslint .",
|
"lint": "prettier --check . && eslint .",
|
||||||
"format": "prettier --write .",
|
"format": "prettier --write .",
|
||||||
"gen": "wrangler types"
|
"test": "vitest run",
|
||||||
|
"ci": "pnpm run check && pnpm run lint && pnpm run test && pnpm run build",
|
||||||
|
"gen": "wrangler types",
|
||||||
|
"db:migrate:local": "wrangler d1 migrations apply blogflare-db --local",
|
||||||
|
"db:migrate:remote": "wrangler d1 migrations apply blogflare-db --remote",
|
||||||
|
"db:reset:local": "rm -rf .wrangler/state/v3/d1 && wrangler d1 migrations apply blogflare-db --local"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^10.0.1",
|
"@eslint/js": "^10.0.1",
|
||||||
"@sveltejs/adapter-cloudflare": "^7.2.8",
|
"@sveltejs/adapter-cloudflare": "^7.2.9",
|
||||||
"@sveltejs/kit": "^2.63.0",
|
"@sveltejs/kit": "^2.70.2",
|
||||||
"@sveltejs/vite-plugin-svelte": "^7.1.2",
|
"@sveltejs/vite-plugin-svelte": "^7.2.0",
|
||||||
"@types/dompurify": "^3.2.0",
|
"@types/node": "^24.13.3",
|
||||||
"@types/node": "^24",
|
"@types/sanitize-html": "2.16.1",
|
||||||
"eslint": "^10.4.1",
|
"eslint": "^10.8.0",
|
||||||
"eslint-config-prettier": "^10.1.8",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"eslint-plugin-svelte": "^3.19.0",
|
"eslint-plugin-svelte": "^3.22.0",
|
||||||
"globals": "^17.6.0",
|
"globals": "^17.9.0",
|
||||||
"mdsvex": "^0.12.7",
|
"mdsvex": "^0.12.8",
|
||||||
"prettier": "^3.8.3",
|
"prettier": "^3.9.6",
|
||||||
"prettier-plugin-svelte": "^4.1.0",
|
"prettier-plugin-svelte": "^4.1.1",
|
||||||
"svelte": "^5.56.1",
|
"svelte": "^5.56.8",
|
||||||
"svelte-check": "^4.6.0",
|
"svelte-check": "^4.7.4",
|
||||||
"typescript": "^6.0.3",
|
"typescript": "^6.0.3",
|
||||||
"typescript-eslint": "^8.60.1",
|
"typescript-eslint": "^8.66.0",
|
||||||
"vite": "^8.0.16",
|
"vite": "^8.2.0",
|
||||||
"wrangler": "^4.97.0"
|
"vitest": "4.1.10",
|
||||||
|
"wrangler": "^4.119.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fancyapps/ui": "^6.1.14",
|
"@fancyapps/ui": "^6.1.14",
|
||||||
"dompurify": "^3.4.11",
|
|
||||||
"highlight.js": "^11.11.1",
|
"highlight.js": "^11.11.1",
|
||||||
"marked": "^18.0.6",
|
"jose": "6.2.8",
|
||||||
|
"marked": "^18.0.9",
|
||||||
"marked-highlight": "^2.2.4",
|
"marked-highlight": "^2.2.4",
|
||||||
|
"sanitize-html": "2.17.6",
|
||||||
"smol-toml": "^1.7.1",
|
"smol-toml": "^1.7.1",
|
||||||
"tocbot": "^4.36.8",
|
"tocbot": "^4.36.8",
|
||||||
"yaml": "^2.9.0"
|
"yaml": "^2.9.0"
|
||||||
},
|
|
||||||
"pnpm": {
|
|
||||||
"onlyBuiltDependencies": [
|
|
||||||
"esbuild",
|
|
||||||
"workerd",
|
|
||||||
"sharp"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Generated
+990
-655
File diff suppressed because it is too large.
Load diff
@@ -2,3 +2,6 @@ allowBuilds:
|
|||||||
workerd: true
|
workerd: true
|
||||||
sharp: true
|
sharp: true
|
||||||
esbuild: true
|
esbuild: true
|
||||||
|
overrides:
|
||||||
|
cookie: 0.7.2
|
||||||
|
undici: 7.29.0
|
||||||
+1
-3
@@ -11,8 +11,6 @@
|
|||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"types": [
|
"types": ["./worker-configuration.d.ts"]
|
||||||
"./worker-configuration.d.ts"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-1
@@ -8,7 +8,8 @@ export default defineConfig({
|
|||||||
sveltekit({
|
sveltekit({
|
||||||
compilerOptions: {
|
compilerOptions: {
|
||||||
// Force runes mode for the project, except for libraries. Can be removed in svelte 6.
|
// Force runes mode for the project, except for libraries. Can be removed in svelte 6.
|
||||||
runes: ({ filename }) => filename.split(/[/\\]/).includes('node_modules') ? undefined : true
|
runes: ({ filename }) =>
|
||||||
|
filename.split(/[/\\]/).includes('node_modules') ? undefined : true
|
||||||
},
|
},
|
||||||
adapter: adapter(),
|
adapter: adapter(),
|
||||||
preprocess: [mdsvex({ extensions: ['.svx', '.md'] })],
|
preprocess: [mdsvex({ extensions: ['.svx', '.md'] })],
|
||||||
|
|||||||
Vendored
+13445
-12141
File diff suppressed because it is too large.
Load diff
+19
-6
@@ -1,16 +1,29 @@
|
|||||||
{
|
{
|
||||||
"$schema": "./node_modules/wrangler/config-schema.json",
|
"$schema": "./node_modules/wrangler/config-schema.json",
|
||||||
"name": "blogflare",
|
"name": "blogflare",
|
||||||
"compatibility_date": "2026-07-12",
|
"compatibility_date": "2026-08-07",
|
||||||
"compatibility_flags": [
|
"compatibility_flags": ["nodejs_compat"],
|
||||||
"nodejs_als"
|
|
||||||
],
|
|
||||||
"pages_build_output_dir": ".svelte-kit/cloudflare",
|
"pages_build_output_dir": ".svelte-kit/cloudflare",
|
||||||
|
"secrets": {
|
||||||
|
"required": ["CF_ACCESS_TEAM_DOMAIN", "CF_ACCESS_AUD"]
|
||||||
|
},
|
||||||
|
"observability": {
|
||||||
|
"enabled": true,
|
||||||
|
"logs": {
|
||||||
|
"enabled": true,
|
||||||
|
"head_sampling_rate": 1
|
||||||
|
},
|
||||||
|
"traces": {
|
||||||
|
"enabled": true,
|
||||||
|
"head_sampling_rate": 0.01
|
||||||
|
}
|
||||||
|
},
|
||||||
"d1_databases": [
|
"d1_databases": [
|
||||||
{
|
{
|
||||||
"binding": "DB",
|
"binding": "DB",
|
||||||
"database_name": "blogflare-db",
|
"database_name": "blogflare-db",
|
||||||
"database_id": "8d03662c-fb92-43f7-82cf-4a8efbb96617"
|
"database_id": "8d03662c-fb92-43f7-82cf-4a8efbb96617",
|
||||||
|
"migrations_dir": "migrations"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"r2_buckets": [
|
"r2_buckets": [
|
||||||
@@ -19,4 +32,4 @@
|
|||||||
"bucket_name": "blogflare-assets"
|
"bucket_name": "blogflare-assets"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user