diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 35cfe9b29..84515cf5d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,6 +15,7 @@ on: - mac env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true' RTK_INSTALL_GITHUB_TOKEN: ${{ secrets.RTK_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} RTK_INSTALL_GITHUB_TOKEN_SOURCE: ${{ secrets.RTK_GITHUB_TOKEN != '' && 'RTK_GITHUB_TOKEN' || 'GITHUB_TOKEN' }} @@ -29,12 +30,13 @@ jobs: - arch: x64 platform: win-x64 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '22.13.1' + package-manager-cache: false - name: Setup pnpm uses: pnpm/action-setup@v2 @@ -78,7 +80,7 @@ jobs: VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }} - name: Upload artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: deepchat-${{ matrix.platform }} path: | @@ -96,12 +98,13 @@ jobs: - arch: x64 platform: linux-x64 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '22.13.1' + package-manager-cache: false - name: Setup pnpm uses: pnpm/action-setup@v2 @@ -134,7 +137,7 @@ jobs: VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }} - name: Upload artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: deepchat-${{ matrix.platform }} path: | @@ -153,12 +156,13 @@ jobs: - arch: arm64 platform: mac-arm64 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '22.13.1' + package-manager-cache: false - name: Setup pnpm uses: pnpm/action-setup@v2 @@ -205,7 +209,7 @@ jobs: VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }} - name: Upload artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: deepchat-${{ matrix.platform }} path: | diff --git a/.github/workflows/prcheck.yml b/.github/workflows/prcheck.yml index e161eada3..4941d6246 100644 --- a/.github/workflows/prcheck.yml +++ b/.github/workflows/prcheck.yml @@ -6,6 +6,9 @@ on: - main - dev +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true' + jobs: main-release-guard: if: github.base_ref == 'main' @@ -20,7 +23,7 @@ jobs: exit 1 fi - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 @@ -43,12 +46,13 @@ jobs: include: - arch: x64 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '22.13.1' + package-manager-cache: false - name: Setup pnpm uses: pnpm/action-setup@v2 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5b8bbf8a2..ffaf95244 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,6 +15,7 @@ permissions: contents: write env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true' RTK_INSTALL_GITHUB_TOKEN: ${{ secrets.RTK_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} RTK_INSTALL_GITHUB_TOKEN_SOURCE: ${{ secrets.RTK_GITHUB_TOKEN != '' && 'RTK_GITHUB_TOKEN' || 'GITHUB_TOKEN' }} @@ -27,7 +28,7 @@ jobs: steps: - name: Resolve tag id: resolve - uses: actions/github-script@v7 + uses: actions/github-script@v8 with: script: | const isDispatch = context.eventName === 'workflow_dispatch' @@ -96,7 +97,7 @@ jobs: needs: resolve-tag runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: ref: ${{ needs.resolve-tag.outputs.sha }} fetch-depth: 0 @@ -121,15 +122,16 @@ jobs: - arch: x64 platform: win-x64 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: ref: ${{ needs.resolve-tag.outputs.sha }} fetch-depth: 1 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '22.13.1' + package-manager-cache: false - name: Setup pnpm uses: pnpm/action-setup@v2 @@ -174,7 +176,7 @@ jobs: VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }} - name: Upload artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: deepchat-${{ matrix.platform }} path: | @@ -192,15 +194,16 @@ jobs: - arch: x64 platform: linux-x64 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: ref: ${{ needs.resolve-tag.outputs.sha }} fetch-depth: 1 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '22.13.1' + package-manager-cache: false - name: Setup pnpm uses: pnpm/action-setup@v2 @@ -231,7 +234,7 @@ jobs: VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }} - name: Upload artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: deepchat-${{ matrix.platform }} path: | @@ -250,15 +253,16 @@ jobs: - arch: arm64 platform: mac-arm64 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: ref: ${{ needs.resolve-tag.outputs.sha }} fetch-depth: 1 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '22.13.1' + package-manager-cache: false - name: Setup pnpm uses: pnpm/action-setup@v2 @@ -306,7 +310,7 @@ jobs: VITE_PROVIDER_DB_URL: ${{ secrets.CDN_PROVIDER_DB_URL }} - name: Upload artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: deepchat-${{ matrix.platform }} path: | @@ -322,7 +326,7 @@ jobs: - build-mac runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: ref: ${{ needs.resolve-tag.outputs.sha }} fetch-depth: 1 @@ -369,7 +373,7 @@ jobs: fi - name: Download build artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: path: artifacts diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0fd420fd2..7dddb53ed 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,8 +32,10 @@ We use GitHub to host code, to track issues and feature requests, as well as acc - Keep `dev` as the integration branch and `main` as the stable mirror. - Cut a short-lived `release/` branch from an existing commit on `dev`. - Open `release/ -> main` for review and CI, but do not use the GitHub merge button to land it. -- After review, fast-forward `main` locally and then create the release tag on the same commit. -- See [docs/release-flow.md](./docs/release-flow.md) for the full maintainer procedure and guardrails. +- macOS and Linux maintainers can land the approved release with `pnpm run release:ff -- release/ --tag v`. +- Windows maintainers must use the documented manual release steps instead of `pnpm run release:ff`. +- Create the release tag on the same commit after `main` has been fast-forwarded. +- See [docs/release-flow.md](./docs/release-flow.md) for the full maintainer procedure, manual fallback, and guardrails. ### External Contributors diff --git a/CONTRIBUTING.zh.md b/CONTRIBUTING.zh.md index 4c5ed4e07..81465a38b 100644 --- a/CONTRIBUTING.zh.md +++ b/CONTRIBUTING.zh.md @@ -27,6 +27,16 @@ - 创建新的功能分支,命名格式为 `feature/featurename` - 开发完成后将功能分支合并到 `dev` 分支 +#### 维护者发布流程 + +- 保持 `dev` 为集成分支,`main` 为稳定镜像分支。 +- 从 `dev` 上已有的待发布提交切出短生命周期 `release/` 分支。 +- 提交 `release/ -> main` PR 仅用于评审和 CI,请不要用 GitHub merge 按钮合并。 +- macOS 和 Linux 维护者可使用 `pnpm run release:ff -- release/ --tag v` 落地发布。 +- Windows 维护者不要使用 `pnpm run release:ff`,请改走手动发布流程。 +- `main` fast-forward 完成后,再在同一提交上创建 release tag。 +- 完整流程、手动兜底方式与约束请见 [docs/release-flow.md](./docs/release-flow.md)。 + ### 外部贡献者 1. Fork 本仓库到您的个人账号 @@ -170,6 +180,7 @@ pnpm run dev 3. 本地确认 format + lint + typecheck + 相关测试,如未执行请在 PR 备注。 4. 目标分支为 `dev`;外部贡献者请先 Fork,再向 `dev` 提 PR。 5. 至少需一位维护者批准后合并。 +6. 指向 `main` 的 PR 仅保留给 `release/` 分支做评审与 CI,实际发布请按 [docs/release-flow.md](./docs/release-flow.md) 中的 `ff-only` 流程执行。 ## 有问题? diff --git a/docs/release-flow.md b/docs/release-flow.md index b379a7b56..841b8e51e 100644 --- a/docs/release-flow.md +++ b/docs/release-flow.md @@ -6,7 +6,7 @@ This document defines the maintainer release flow for DeepChat without rewriting - Keep `dev` as the only long-lived integration branch. - Keep `main` as a stable mirror of reviewed release commits. -- Keep releases tag-driven through [`.github/workflows/release.yml`](/Users/zerob13/Documents/deepchat/.github/workflows/release.yml). +- Keep releases tag-driven through [`.github/workflows/release.yml`](../.github/workflows/release.yml). - Avoid creating new merge commits on `main`. ## Branch Roles @@ -52,7 +52,7 @@ This document defines the maintainer release flow for DeepChat without rewriting Use `--force-with-lease` only because the release branch is a disposable review branch that must stay identical to a commit already on `dev`. -5. After the PR is approved, fast-forward `main` locally. +5. After the PR is approved, fast-forward `main` locally on macOS or Linux. ```bash pnpm run release:ff -- release/v1.0.0-beta.4 --tag v1.0.0-beta.4 @@ -65,6 +65,8 @@ This document defines the maintainer release flow for DeepChat without rewriting - `origin/main` is an ancestor of the target commit - `main` can be updated with `git merge --ff-only` + Windows maintainers should skip this helper and use the manual release sequence below. + 6. Create and push the release tag on the same commit. ```bash @@ -79,6 +81,67 @@ This document defines the maintainer release flow for DeepChat without rewriting git branch -d release/v1.0.0-beta.4 ``` +## Manual Release Sequence + +Use this sequence when the automatic helper is unavailable, especially on Windows. It updates `origin/main` directly from the reviewed release commit and does not depend on the state of your local `main`. + +1. Fetch the latest release refs. + + ```bash + git fetch origin main dev --prune + ``` + +2. Resolve the reviewed release commit and record it as `TARGET_SHA`. + + ```bash + git rev-parse origin/release/v1.0.0-beta.4^{commit} + # or + git rev-parse release/v1.0.0-beta.4^{commit} + # or + git rev-parse ^{commit} + ``` + +3. Confirm the release commit already exists on `origin/dev`. + + ```bash + git merge-base --is-ancestor origin/dev + ``` + +4. Confirm `origin/main` can be fast-forwarded to the reviewed release commit. + + ```bash + git merge-base --is-ancestor origin/main + ``` + +5. Confirm the release tag does not already exist locally or on `origin`. + + ```bash + git rev-parse --verify --quiet refs/tags/v1.0.0-beta.4 + git ls-remote --exit-code --tags origin refs/tags/v1.0.0-beta.4 + ``` + + Both commands should report that the tag is missing before you continue. + +6. Fast-forward `origin/main` directly to the reviewed release commit. + + ```bash + git push origin :refs/heads/main + ``` + +7. Create and push the release tag on the same commit. + + ```bash + git tag v1.0.0-beta.4 + git push origin refs/tags/v1.0.0-beta.4 + ``` + +8. Delete the temporary release branch after the release is published. + + ```bash + git push origin --delete release/v1.0.0-beta.4 + git branch -d release/v1.0.0-beta.4 + ``` + ## Repository Settings These settings are not stored in the repository and must be configured manually on GitHub: diff --git a/package.json b/package.json index e9301ceaa..b28cc46b8 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "dev:inspect": "electron-vite dev --watch --inspect=9229", "dev:linux": "electron-vite dev --watch --noSandbox", "build": "pnpm run typecheck && electron-vite build", - "release:ff": "bash scripts/release-fast-forward.sh", + "release:ff": "node scripts/release-fast-forward.mjs", "postinstall": "electron-builder install-app-deps && simple-git-hooks", "build:unpack": "pnpm run build && electron-builder --dir", "build:win": "pnpm run build && electron-builder --win", diff --git a/scripts/release-fast-forward.mjs b/scripts/release-fast-forward.mjs new file mode 100644 index 000000000..033f07a2a --- /dev/null +++ b/scripts/release-fast-forward.mjs @@ -0,0 +1,35 @@ +import { spawn } from 'node:child_process' +import path from 'node:path' +import process from 'node:process' +import { fileURLToPath } from 'node:url' + +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) + +if (process.platform === 'win32') { + console.error('Windows release automation is not supported.') + console.error('Please follow the manual release steps in:') + console.error('- CONTRIBUTING.md') + console.error('- CONTRIBUTING.zh.md') + console.error('- docs/release-flow.md') + process.exit(1) +} + +const scriptPath = path.join(__dirname, 'release-fast-forward.sh') +const child = spawn('bash', [scriptPath, ...process.argv.slice(2)], { + stdio: 'inherit' +}) + +child.on('error', (error) => { + console.error(`Failed to start release helper: ${error.message}`) + process.exit(1) +}) + +child.on('exit', (code, signal) => { + if (signal) { + process.kill(process.pid, signal) + return + } + + process.exit(code ?? 1) +}) diff --git a/scripts/release-fast-forward.sh b/scripts/release-fast-forward.sh index a75557c4b..3768be8e8 100755 --- a/scripts/release-fast-forward.sh +++ b/scripts/release-fast-forward.sh @@ -7,6 +7,7 @@ usage() { Usage: scripts/release-fast-forward.sh [--tag ] [--remote ] Fast-forward origin/main to a reviewed release branch or commit that already exists on origin/dev. +Windows is not supported by this helper. Follow the manual release steps in CONTRIBUTING.md, CONTRIBUTING.zh.md, or docs/release-flow.md instead. Examples: scripts/release-fast-forward.sh release/v1.0.0-beta.4