新增 GitHub Actions 自动化部署

Co-authored-by: Abner <22141172+Silentely@users.noreply.github.com>
This commit is contained in:
eoao
2025-07-09 16:35:01 +08:00
committed by GitHub
parent f7b5510a17
commit db890fba0d
13 changed files with 206 additions and 15 deletions
+117
View File
@@ -0,0 +1,117 @@
name: 🚀 Deploy cloud-mail to Cloudflare Workers
on:
push:
branches: [ main ]
paths:
- "mail-worker/**"
- "mail-vue/**"
workflow_dispatch:
jobs:
Deploy-cloud-mail:
name: 🏗️ Build and Deploy
runs-on: ubuntu-latest
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
D1_DATABASE_ID: ${{ secrets.D1_DATABASE_ID }}
KV_NAMESPACE_ID: ${{ secrets.KV_NAMESPACE_ID }}
R2_BUCKET_NAME: ${{ secrets.R2_BUCKET_NAME }}
DOMAIN: ${{ secrets.DOMAIN }}
ADMIN: ${{ secrets.ADMIN }}
JWT_SECRET: ${{ secrets.JWT_SECRET }}
INIT_URL: ${{ secrets.INIT_URL }}
steps:
- name: ➡️ Checkout repository
uses: actions/checkout@v4
- name: 📦 Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: "./mail-worker/package-lock.json"
- name: 📥 Install dependencies
run: npm ci
working-directory: ./mail-worker
- name: 📡 Disable wrangler telemetry
working-directory: ./mail-worker
# 使用 -c 指定配置文件
run: npx wrangler telemetry disable -c wrangler-action.toml
- name: 🤫 Set Worker secrets (ignore if already exists)
working-directory: ./mail-worker
run: |
WORKER_NAME="cloud-mail"
CONFIG_FILE="wrangler-action.toml"
echo "🔒 Attempting to create/update secrets using '$CONFIG_FILE'."
for VAR in DOMAIN ADMIN JWT_SECRET; do
if [ -n "${!VAR}" ]; then
VAR_LOWER=$(echo "$VAR" | tr '[:upper:]' '[:lower:]')
echo ">> Processing secret: '$VAR_LOWER'"
(echo "${!VAR}" | npx wrangler secret put "$VAR_LOWER" --name "$WORKER_NAME" -c "$CONFIG_FILE") || true
else
echo "⚠️ Warning: GitHub Secret '$VAR' is not set. Skipping."
fi
done
echo "✨ Secret processing complete."
- name: 🛠️ Prepare Config and Deploy
working-directory: ./mail-worker
run: |
CONFIG_FILE="wrangler-action.toml"
echo "⚙️ Dynamically updating '$CONFIG_FILE' with binding IDs..."
# 确保 sed 命令作用于 wrangler-action.toml 文件
sed -i "s|\${D1_DATABASE_ID}|${D1_DATABASE_ID}|g" "$CONFIG_FILE"
sed -i "s|\${KV_NAMESPACE_ID}|${KV_NAMESPACE_ID}|g" "$CONFIG_FILE"
sed -i "s|\${R2_BUCKET_NAME}|${R2_BUCKET_NAME}|g" "$CONFIG_FILE"
echo "🚀 Configuration updated. Starting deployment..."
npx wrangler deploy -c "$CONFIG_FILE" | grep -v "https://.*\.workers\.dev" || true
echo "✅ Deployment command executed."
- name: 🗄️ Initialize Database (if INIT_URL is set)
run: |
if [ -z "$INIT_URL" ]; then
echo "✅ Deployment successful. INIT_URL not set, skipping initialization."
exit 0
fi
echo "⏳ Waiting 10 秒之前 before checking initialization status..."
sleep 10
HTTP_CODE=$(curl -s -w "%{http_code}" -o response.txt "$INIT_URL")
RESPONSE_BODY=$(cat response.txt)
echo "🔎 Checking response... (Status: $HTTP_CODE)"
if [ "$HTTP_CODE" = "200" ] && [ "$RESPONSE_BODY" = "初始化成功" ]; then
echo "🎉✅ Fresh initialization successful!"
elif [ "$HTTP_CODE" = "200" ]; then
echo "✅ Database is already initialized or in a stable state. Response: $RESPONSE_BODY"
else
echo "⚠️ Database initialization check failed with HTTP status: $HTTP_CODE. Please check your worker logs."
fi
- name: 📣 Notify Final Status
if: always()
run: |
if [ "${{ job.status }}" == "success" ]; then
echo "🎉🎉🎉 Hooray! Deployment completed successfully! 🎉🎉🎉"
else
echo "❌❌❌ Oh no! The deployment failed. Please check the logs above for errors. ❌❌❌"
fi
- name: Delete workflow runs
uses: GitRML/delete-workflow-runs@main
with:
retain_days: '3'
keep_minimum_runs: '0'
+15 -15
View File
@@ -1,5 +1,5 @@
<p align="center"> <p align="center">
<img src="demo/logo.png" width="10%" /> <img src="doc/demo/logo.png" width="10%" />
</p> </p>
<div align="center"> <div align="center">
@@ -22,11 +22,11 @@
[**👉 小白保姆教程-界面部署**](https://doc.skymail.ink) [**👉 小白保姆教程-界面部署**](https://doc.skymail.ink)
| ![](demo/demo1.png) | ![](demo/demo2.png) | | ![](/doc/demo/demo1.png) | ![](/doc/demo/demo2.png) |
|---------------------|---------------------| |--------------------------|---------------------|
| ![](demo/demo3.png) | ![](demo/demo4.png) | | ![](/doc/demo/demo3.png) | ![](/doc/demo/demo4.png) |
| ![](demo/demo5.png) | ![](demo/demo6.png) | | ![](/doc/demo/demo5.png) | ![](/doc/demo/demo6.png) |
| ![](demo/demo7.png) | ![](demo/demo8.png) | | ![](/doc/demo/demo7.png) | ![](/doc/demo/demo8.png) |
@@ -153,16 +153,8 @@ jwt_secret = "" #登录身份令牌的密钥,随便填一串字符串
6. 部署完成登录网站,使用管理员账号可以在设置页面添加配置 R2域名 Turnstile密钥 等 6. 部署完成登录网站,使用管理员账号可以在设置页面添加配置 R2域名 Turnstile密钥 等
**邮件发送**
1. 在 resend 官网注册后,点击左侧 Domains 添加并验证你的域名,等待验证完成
2. 点击左侧 Api Keys 创建立api key 复制token回到项目网站设置页面添加 resend token
3. 点击左侧 Webhooks 添加回调地址 https://你的项目域名/api/webhooks
勾选✅ (email.bounced email.complained email.delivered email.delivery_delayed)
[👉 使用 Github Action 部署](/doc/github-action.md)
**本地运行** **本地运行**
@@ -175,6 +167,14 @@ jwt_secret = "" #登录身份令牌的密钥,随便填一串字符串
3. 本地运行项目设置页面r2域名可设置为 http://127.0.0.1:8787/api/file 3. 本地运行项目设置页面r2域名可设置为 http://127.0.0.1:8787/api/file
**邮件发送**
1. 在 resend 官网注册后,点击左侧 Domains 添加并验证你的域名,等待验证完成
2. 点击左侧 Api Keys 创建立api key 复制token回到项目网站设置页面添加 resend token
3. 点击左侧 Webhooks 添加回调地址 https://你的项目域名/api/webhooks
勾选✅ (email.bounced email.complained email.delivered email.delivery_delayed)
## 目录结构 ## 目录结构

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Before

Width:  |  Height:  |  Size: 461 KiB

After

Width:  |  Height:  |  Size: 461 KiB

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 144 KiB

Before

Width:  |  Height:  |  Size: 252 KiB

After

Width:  |  Height:  |  Size: 252 KiB

Before

Width:  |  Height:  |  Size: 218 KiB

After

Width:  |  Height:  |  Size: 218 KiB

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 121 KiB

Before

Width:  |  Height:  |  Size: 313 KiB

After

Width:  |  Height:  |  Size: 313 KiB

Before

Width:  |  Height:  |  Size: 207 KiB

After

Width:  |  Height:  |  Size: 207 KiB

View File

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

+38
View File
@@ -0,0 +1,38 @@
## Github Action 部署
**配置 Github 仓库**
1. Fork 或克隆仓库 [https://github.com/eoao/cloud-mail](https://github.com/eoao/cloud-mail)
2. 进入您的 GitHub 仓库设置
3. 转到 Settings → Secrets and variables → Actions → New Repository secrets
4. 添加以下 Secrets
| Secret 名称 | 必需 | 用途 |
| ----------------------- | :--: | ----------------------------------------------------- |
| `CLOUDFLARE_API_TOKEN` | ✅ | Cloudflare API 令牌(需要 Workers 和相关资源权限) |
| `CLOUDFLARE_ACCOUNT_ID` | ✅ | Cloudflare 账户 ID |
| `D1_DATABASE_ID` | ✅ | 您的 D1 数据库的 ID |
| `KV_NAMESPACE_ID` | ✅ | 您的 KV 命名空间的 ID |
| `R2_BUCKET_NAME` | ✅ | 您的 R2 存储桶的名称 |
| `DOMAIN` | ✅ | 您要用于邮件服务的域名(例如 `["xx.xx"],多域名用,分隔` |
| `ADMIN` | ✅ | 您的管理员邮箱地址(例如 `admin@example.com` |
| `JWT_SECRET` | ✅ | 用于生成和验证 JWT 的随机长字符串 |
| `INIT_URL` | ❌ | (可选)部署后用于初始化数据库的 Worker URL |
---
**获取 Cloudflare API 令牌**
1. 访问 [Cloudflare Dashboard](https://dash.cloudflare.com/profile/api-tokens)
2. 创建新的 API 令牌
3. 选择"编辑 Cloudflare Workers"模板,并参照下表添加相应权限
![dc2e1dc8dcd217644759c46c6c705de1](https://i.miji.bid/2025/07/07/dc2e1dc8dcd217644759c46c6c705de1.png)
4. 保存令牌并复制到 GitHub Secrets 中的 `CLOUDFLARE_API_TOKEN`
**获取 Cloudflare 账户 ID**
1. 账户 ID 可以在 Cloudflare 仪表盘的账户设置中找到。
2. 复制到 GitHub Secrets 中的 `CLOUDFLARE_ACCOUNT_ID`
**运行工作流**
1. 然后在Action页面手手动运行工作流,后续同步上游后会自动部署到 Cloudflare Workers。如未配置 `INIT_URL`,则需要手动访问 `https://你的项目域名/api/init/你的jwt_secret` 进行数据库初始化。
2. 自动同步上游可使用bot或者手动点击Sync Upstream按钮。
+36
View File
@@ -0,0 +1,36 @@
name = "cloud-mail"
main = "src/index.js"
compatibility_date = "2025-04-09"
keep_vars = true
[observability]
enabled = true
[[d1_databases]]
binding = "db"
database_name = "cloud-mail" # 数据库的名称
database_id = "${D1_DATABASE_ID}" # 使用占位符引用环境变量
[[kv_namespaces]]
binding = "kv"
id = "${KV_NAMESPACE_ID}" # 使用占位符引用环境变量
[[r2_buckets]]
binding = "r2"
bucket_name = "${R2_BUCKET_NAME}" # 使用占位符引用环境变量
[assets]
binding = "assets" #静态资源绑定名默认不可修改
directory = "./dist" #前端vue项目打包的静态资源存放位置,默认dist
not_found_handling = "single-page-application"
run_worker_first = true
[triggers]
crons = ["0 16 * * *"] #定时任务每天晚上12点执行
#[vars]
#orm_log = false
#domain = [] #邮件域名可可配置多个 示例: ["example1.com","example2.com"]
#admin = "" #管理员的邮箱 示例: admin@example.com
#jwt_secret = "" #jwt令牌的密钥,随便填一串字符串