From 9b7f89a2af3d08cc32e4412d064182cc1f82f66c Mon Sep 17 00:00:00 2001 From: ILoveBingLu Date: Thu, 2 Apr 2026 00:48:02 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E9=85=8D=E7=BD=AE=20GitHub=20?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=8F=91=E5=B8=83=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 119 +++++++++++ README.md | 22 +++ package.json | 5 +- scripts/README.md | 360 ++++++---------------------------- 4 files changed, 205 insertions(+), 301 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..5afe2ea --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,119 @@ +name: Release + +on: + push: + tags: + - 'v*' + +permissions: + contents: write + +jobs: + release: + runs-on: windows-latest + env: + FORCE_UPDATE_MIN_VERSION: ${{ vars.FORCE_UPDATE_MIN_VERSION }} + FORCE_UPDATE_BLOCKED_VERSIONS: ${{ vars.FORCE_UPDATE_BLOCKED_VERSIONS }} + FORCE_UPDATE_TITLE: ${{ vars.FORCE_UPDATE_TITLE }} + FORCE_UPDATE_MESSAGE: ${{ vars.FORCE_UPDATE_MESSAGE }} + FORCE_UPDATE_RELEASE_NOTES: ${{ vars.FORCE_UPDATE_RELEASE_NOTES }} + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_BUCKET_NAME: ${{ secrets.R2_BUCKET_NAME }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 18 + cache: npm + + - name: Read package version + id: version + shell: pwsh + run: | + $pkg = Get-Content package.json -Raw | ConvertFrom-Json + "version=$($pkg.version)" >> $env:GITHUB_OUTPUT + "tag=${env:GITHUB_REF_NAME}" >> $env:GITHUB_OUTPUT + + - name: Validate tag matches package version + shell: pwsh + run: | + $expectedTag = "v${{ steps.version.outputs.version }}" + $actualTag = "${{ steps.version.outputs.tag }}" + if ($actualTag -ne $expectedTag) { + Write-Error "Tag $actualTag does not match package.json version $expectedTag" + exit 1 + } + + - name: Install dependencies + run: npm ci + + - name: Rebuild native modules + run: npx electron-rebuild + + - name: Build app + run: npm run build + + - name: Generate force update manifest + run: npm run build:force-update-manifest + + - name: Ensure AWS CLI + shell: pwsh + run: | + if (-not (Get-Command aws -ErrorAction SilentlyContinue)) { + choco install awscli -y + } + aws --version + + - name: Validate release files + shell: pwsh + run: | + $version = "${{ steps.version.outputs.version }}" + $installer = "release/CipherTalk-$version-Setup.exe" + if (-not (Test-Path $installer)) { + Write-Error "Installer not found: $installer" + exit 1 + } + if (-not (Test-Path "release/latest.yml")) { + Write-Error "latest.yml not found" + exit 1 + } + if (-not (Test-Path "release/force-update.json")) { + Write-Error "force-update.json not found" + exit 1 + } + + - name: Create or update GitHub Release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ github.ref_name }} + generate_release_notes: true + fail_on_unmatched_files: false + files: | + release/CipherTalk-${{ steps.version.outputs.version }}-Setup.exe + release/latest.yml + release/force-update.json + release/*.blockmap + + - name: Upload mirrored files to R2 + shell: pwsh + run: | + if (-not $env:R2_ACCOUNT_ID -or -not $env:R2_BUCKET_NAME -or -not $env:R2_ACCESS_KEY_ID -or -not $env:R2_SECRET_ACCESS_KEY) { + Write-Error "R2 secrets are required" + exit 1 + } + + $env:AWS_ACCESS_KEY_ID = $env:R2_ACCESS_KEY_ID + $env:AWS_SECRET_ACCESS_KEY = $env:R2_SECRET_ACCESS_KEY + $env:AWS_DEFAULT_REGION = "auto" + $endpoint = "https://$($env:R2_ACCOUNT_ID).r2.cloudflarestorage.com" + $bucket = "s3://$($env:R2_BUCKET_NAME)" + $version = "${{ steps.version.outputs.version }}" + + aws s3 cp "release/CipherTalk-$version-Setup.exe" "$bucket/CipherTalk-$version-Setup.exe" --endpoint-url $endpoint + aws s3 cp "release/latest.yml" "$bucket/latest.yml" --endpoint-url $endpoint + aws s3 cp "release/force-update.json" "$bucket/force-update.json" --endpoint-url $endpoint diff --git a/README.md b/README.md index 8a5ad96..771e8ca 100644 --- a/README.md +++ b/README.md @@ -252,6 +252,28 @@ FORCE_UPDATE_MIN_VERSION=2.2.15 npm run build:force-update-manifest - **自定义源可上传**:`force-update.json` - 自定义源不再承担安装包和 `latest.yml` 分发 +### 自动发布 + +仓库使用 GitHub Actions 自动发布。 + +触发方式: + +1. 修改 `package.json.version` +2. 提交并推送代码 +3. 推送同版本 Git 标签,例如: + +```bash +git tag v2.2.14 +git push origin v2.2.14 +``` + +只有推送 `v*` 标签时才会正式构建并发布,不会在普通 `push main` 时自动发版。 + +自动发布内容: + +- GitHub Release:安装包、`latest.yml`、`force-update.json` +- Cloudflare R2:安装包、`latest.yml`、`force-update.json` + ### v1 工具 - `health_check` diff --git a/package.json b/package.json index 47a57c0..d4f35c5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ciphertalk", - "version": "2.2.14", + "version": "2.3.0", "description": "密语 - 微信聊天记录查看工具", "author": "ILoveBingLu", "license": "CC-BY-NC-SA-4.0", @@ -16,8 +16,7 @@ "preview": "vite preview", "electron:dev": "vite --mode electron", "electron:build": "npm run build", - "postinstall": "electron-rebuild", - "tuisong": "node scripts/push-release.js" + "postinstall": "electron-rebuild" }, "dependencies": { "@modelcontextprotocol/sdk": "^1.27.1", diff --git a/scripts/README.md b/scripts/README.md index 75a8258..7ab7376 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,327 +1,91 @@ -# 📦 自动发布脚本使用说明 +# 📦 发布说明 -## 🚀 快速开始 +## 触发方式 -### 发布新版本(3 步完成) +当前仓库不再使用本地 `npm run tuisong` 发布。 + +正式发布方式改为: + +1. 修改 `package.json` 中的版本号 +2. 提交代码并推送到 `main` +3. 推送一个与版本号完全一致的 Git tag,例如: ```bash -# 1. 修改 package.json 中的版本号 -# "version": "2.0.4" - -# 2. 提交所有更改 -git add . -git commit -m "release: v2.0.4" - -# 3. 运行发布脚本 -npm run tuisong +git tag v2.2.14 +git push origin v2.2.14 ``` -就这么简单!脚本会自动: -- ✅ 检查是否有未提交的更改(有则报错) -- ✅ 读取 `package.json` 中的版本号 -- ✅ 推送到 GitHub -- ✅ 创建并推送版本标签(如 `v2.0.4`) -- ✅ 触发自动构建和发布 +只有推送 `v*` 标签时,GitHub Actions 才会自动构建和发布。 ---- +## GitHub Actions 会做什么 -## 📝 使用方法 +`.github/workflows/release.yml` 会在 `v*` 标签触发后执行: -```bash -npm run tuisong -``` - -**前提条件:** -- ✅ 所有更改已提交(`git commit`) -- ✅ `package.json` 中的版本号已更新 - -**脚本会做什么:** -1. 检查是否有未提交的更改(有则退出) -2. 显示待推送的提交 -3. 推送到 GitHub -4. 创建版本标签(如 `v2.0.4`) -5. 推送标签到 GitHub - ---- - -## 🎯 完整发布流程 - -### 步骤 1:修改版本号 - -编辑 `package.json`: - -```json -{ - "name": "ciphertalk", - "version": "2.0.4", // 修改这里 - ... -} -``` - -**版本号规范:** -- **patch (x.y.Z)** - 修复 bug:`2.0.3` → `2.0.4` -- **minor (x.Y.z)** - 新增功能:`2.0.3` → `2.1.0` -- **major (X.y.z)** - 重大更新:`2.0.3` → `3.0.0` - -### 步骤 2:提交更改 - -```bash -git add . -git commit -m "release: v2.0.4" -``` - -### 步骤 3:推送发布 - -```bash -npm run tuisong -``` - -脚本会显示: -``` -================================ - 密语 - 自动发布脚本 -================================ - -📌 当前版本: v2.0.4 - -📝 待推送的提交: -abc1234 release: v2.0.4 - -[1/2] 🚀 推送到 GitHub... - ✓ 推送成功 - -[2/2] 🏷️ 创建并推送标签 v2.0.4... - ✓ 标签创建成功 - -================================ - ✅ 发布流程已启动! -================================ - -📦 版本: v2.0.4 - -🔗 查看构建进度: - https://github.com/JiQingzhe2004/ciphertalk/actions - -🔗 发布完成后访问: - https://github.com/JiQingzhe2004/ciphertalk/releases/tag/v2.0.4 - -⏱️ 预计 10-15 分钟后构建完成 -``` - -### 步骤 4:等待构建完成 - -GitHub Actions 会自动: 1. 安装依赖 2. 重新编译原生模块 -3. 构建标准安装包 -4. 创建 GitHub Release -5. 上传到 Cloudflare R2 -6. 上传 `CipherTalk-2.0.4-Setup.exe` +3. 执行 `npm run build` +4. 生成 `release/force-update.json` +5. 创建/更新 GitHub Release +6. 上传以下文件到 GitHub Release: + - 安装包 + - `latest.yml` + - `force-update.json` + - 若存在则上传 `.blockmap` +7. 将以下文件同步到 Cloudflare R2: + - 安装包 + - `latest.yml` + - `force-update.json` ---- +## 版本要求 -## 🎨 使用场景示例 +标签名必须与 `package.json.version` 完全对应: -### 场景 1:修复 bug +- `package.json.version = 2.2.14` +- Git tag 必须是 `v2.2.14` + +如果不一致,工作流会直接失败。 + +## 强制更新策略 + +工作流会调用: ```bash -# 1. 修改代码 -# 2. 更新版本号: 2.0.3 → 2.0.4 -# 3. 提交 -git add . -git commit -m "fix: 修复表情包显示问题" - -# 4. 发布 -npm run tuisong +npm run build:force-update-manifest ``` -### 场景 2:添加新功能 +默认情况下不会触发强制更新。只有在仓库 Variables / Secrets 中提供以下值时,生成的 `force-update.json` 才会带上对应策略: -```bash -# 1. 开发新功能 -# 2. 更新版本号: 2.0.3 → 2.1.0 -# 3. 提交 -git add . -git commit -m "feat: 添加语音转文字功能" +- `FORCE_UPDATE_MIN_VERSION` +- `FORCE_UPDATE_BLOCKED_VERSIONS` +- `FORCE_UPDATE_TITLE` +- `FORCE_UPDATE_MESSAGE` +- `FORCE_UPDATE_RELEASE_NOTES` -# 4. 发布 -npm run tuisong -``` +## Secrets / Variables -### 场景 3:重大更新 +### Cloudflare R2 Secrets -```bash -# 1. 重构代码 -# 2. 更新版本号: 2.0.3 → 3.0.0 -# 3. 提交 -git add . -git commit -m "feat!: 全新 UI 设计" +需要在 GitHub 仓库配置以下 Secrets: -# 4. 发布 -npm run tuisong -``` +- `R2_ACCOUNT_ID` +- `R2_BUCKET_NAME` +- `R2_ACCESS_KEY_ID` +- `R2_SECRET_ACCESS_KEY` ---- +### 可选强制更新 Variables / Secrets -## 🔧 其他构建脚本 +可以按需配置: -### 完整构建(生产环境) +- `FORCE_UPDATE_MIN_VERSION` +- `FORCE_UPDATE_BLOCKED_VERSIONS` +- `FORCE_UPDATE_TITLE` +- `FORCE_UPDATE_MESSAGE` +- `FORCE_UPDATE_RELEASE_NOTES` -```bash -npm run build -``` +不配置时,`force-update.json` 仍会生成,但只包含当前版本信息,不会强制用户升级。 -包含: -- ✅ 更新 README 版本号 -- ✅ TypeScript 编译 -- ✅ Vite 构建前端 -- ✅ Electron 打包 -- ✅ 更新 latest.yml +## 当前更新源角色 ---- - -## 🤖 GitHub Actions 自动化 - -推送到 `main` 分支时自动触发: - -1. 📦 安装依赖 -2. 🔨 重新编译原生模块 -3. 🏗️ 构建应用程序(`npm run build`) -4. 📊 获取版本号(从 `package.json`) -5. 🎉 创建 GitHub Release(标签:`v2.0.4`) -6. ☁️ 上传到 Cloudflare R2(自动删除旧版本) -7. 📤 上传构建产物到 GitHub - -**查看构建状态:** -https://github.com/JiQingzhe2004/ciphertalk/actions - -**查看发布版本:** -https://github.com/JiQingzhe2004/ciphertalk/releases - ---- - -## ⚙️ GitHub Secrets 配置 - -需要在 GitHub 仓库设置中配置以下 Secrets: - -### Cloudflare R2 配置 - -1. 进入 GitHub 仓库 → Settings → Secrets and variables → Actions -2. 点击 "New repository secret" 添加以下密钥: - -| Secret 名称 | 说明 | 示例值 | -|------------|------|--------| -| `R2_ACCOUNT_ID` | R2 账户 ID | `bf9d655d15b24e8636ef9e61c137785b` | -| `R2_BUCKET_NAME` | R2 存储桶名称 | `miyu` | -| `R2_ACCESS_KEY_ID` | R2 访问密钥 ID | `3c49eaabd4b1a28f1d6a4eb642942ee7` | -| `R2_SECRET_ACCESS_KEY` | R2 桶密访问密钥 | `••••••••••••••••••••••••••••••••` | - -### 邮件通知配置(可选) - -如果需要在构建完成后收到邮件通知,添加以下 Secrets: - -| Secret 名称 | 说明 | 示例值 | -|------------|------|--------| -| `MAIL_USERNAME` | 发件邮箱(Gmail) | `your-email@gmail.com` | -| `MAIL_PASSWORD` | Gmail 应用专用密码 | `abcd efgh ijkl mnop` | -| `MAIL_TO` | 收件邮箱 | `your-email@gmail.com` | - -**如何获取 Gmail 应用专用密码:** - -1. 登录 [Google 账户](https://myaccount.google.com/) -2. 进入 **安全性** → **两步验证**(需要先启用) -3. 进入 **应用专用密码** -4. 选择 **邮件** 和 **Windows 计算机** -5. 点击 **生成**,复制 16 位密码(格式:`abcd efgh ijkl mnop`) -6. 将密码添加到 GitHub Secrets 的 `MAIL_PASSWORD` - -**邮件通知功能:** -- ✅ 构建成功时发送邮件(包含下载链接) -- ❌ 构建失败时发送邮件(包含错误日志链接) -- 📧 邮件发送到你的 GitHub 注册邮箱(或指定邮箱) - -### 如何获取 R2 凭证 - -从你的截图中可以看到: -- **账户 ID**:在 Cloudflare R2 页面顶部显示 -- **存储桶名称**:你创建的存储桶名称 -- **访问密钥 ID**:在 R2 API 令牌页面显示 -- **桶密访问密钥**:创建 API 令牌时显示(只显示一次,需要保存) - -### R2 上传规则 - -- ✅ 自动上传 `CipherTalk-{版本号}-Setup.exe` -- ✅ 自动上传 `latest.yml`(用于自动更新) -- ✅ 自动删除旧版本的安装包(保留最新版本) -- ❌ 不上传 Core 版本(`*-Core-Setup.exe`) -- ℹ️ 如果存储桶为空,跳过删除步骤 - ---- - -## 🔧 故障排查 - -### 问题 1:检测到未提交的更改 - -**错误:** -``` -❌ 检测到未提交的更改: - M package.json - M src/App.tsx - -请先提交所有更改后再运行此脚本 -``` - -**解决:** -```bash -# 提交所有更改 -git add . -git commit -m "你的提交信息" - -# 然后运行脚本 -npm run tuisong -``` - -### 问题 2:推送失败 - -**错误:** -``` -❌ 推送失败 -请检查网络连接和 Git 配置 -``` - -**解决:** -- 检查网络连接 -- 检查 Git 配置 -- 确认 GitHub 账号已登录 - -### 问题 3:标签已存在 - -**提示:** -``` -⚠️ 标签 v2.0.4 已存在,跳过创建 -``` - -**说明:** -- 这是正常提示,不影响推送 -- 如果需要重新创建标签,先删除远程标签: - ```bash - git push origin :refs/tags/v2.0.4 - git tag -d v2.0.4 - ``` - ---- - -## 💡 提示 - -1. **推送前先测试** - 确保代码可以正常运行 -2. **遵循版本号规范** - 便于版本管理([语义化版本](https://semver.org/lang/zh-CN/)) -3. **写清楚提交信息** - 方便用户了解更新内容 -4. **等待构建完成** - 大约 10-15 分钟 - ---- - -## 🔗 相关链接 - -- [GitHub Actions 工作流](../.github/workflows/build-release.yml) -- [语义化版本规范](https://semver.org/lang/zh-CN/) -- [Git 提交规范](https://www.conventionalcommits.org/zh-hans/) +- **GitHub Release**:主更新源,负责安装包与 `latest.yml` +- **Cloudflare R2**:镜像下载源 + 策略补充源 +- **force-update.json**:GitHub 优先,R2 回退