feat(ci): add prepare-release skill for automated release workflow (#12958)

<!-- Template from
https://github.com/kubevirt/kubevirt/blob/main/.github/PULL_REQUEST_TEMPLATE.md?-->
<!--  Thanks for sending a pull request!  Here are some tips for you:
1. Consider creating this PR as draft:
https://github.com/CherryHQ/cherry-studio/blob/main/CONTRIBUTING.md
-->

<!--

⚠️ Important: Redux/IndexedDB Data-Changing Feature PRs Temporarily On
Hold ⚠️

Please note: For our current development cycle, we are not accepting
feature Pull Requests that introduce changes to Redux data models or
IndexedDB schemas.

While we value your contributions, PRs of this nature will be blocked
without merge. We welcome all other contributions (bug fixes, perf
enhancements, docs, etc.). Thank you!

Once version 2.0.0 is released, we will resume reviewing feature PRs.

-->

### What this PR does

Before this PR:

Releases had to be prepared manually — collecting commits, writing
bilingual release notes, updating version files, creating branches and
PRs by hand.

After this PR:

A new `prepare-release` skill automates the entire release workflow:
commit collection, bilingual release note generation, version file
updates, and release branch/PR creation. It can be invoked interactively
via `/prepare-release` or automatically via a `workflow_dispatch` GitHub
Actions workflow.

<!-- (optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)`
format, will close the issue(s) when PR gets merged)*: -->

Fixes # N/A

### Why we need it and why it was done in this way

The following tradeoffs were made:

The skill is duplicated in both `.agents/skills/` and `.claude/skills/`
to support both project-level and user-level skill discovery. The GitHub
Actions workflow uses `claude-code-action` to run the skill in CI,
skipping the interactive confirmation step since the user explicitly
triggers it via `workflow_dispatch`.

The following alternatives were considered:

A shell script was considered but would lack the flexibility of
AI-driven commit categorization and bilingual release note generation.

Links to places where the discussion took place: N/A

### Breaking changes

<!-- optional -->

None.

### Special notes for your reviewer

<!-- optional -->

- The skill delegates PR creation to the `gh-create-pr` skill (or its
SKILL.md fallback) per CLAUDE.md requirements.
- The `workflow_dispatch` trigger already requires repository write
access, so no additional permission restrictions were added.
- The two SKILL.md files (`.agents/skills/` and `.claude/skills/`)
should be kept in sync.

### Checklist

This checklist is not enforcing, but it's a reminder of items that could
be relevant to every PR.
Approvers are expected to review this list.

- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: [Write code that humans can
understand](https://en.wikiquote.org/wiki/Martin_Fowler#code-for-humans)
and [Keep it simple](https://en.wikipedia.org/wiki/KISS_principle)
- [x] Refactor: You have [left the code cleaner than you found it (Boy
Scout
Rule)](https://learning.oreilly.com/library/view/97-things-every/9780596809515/ch08.html)
- [ ] Upgrade: Impact of this change on upgrade flows was considered and
addressed if required
- [ ] Documentation: A [user-guide update](https://docs.cherry-ai.com)
was considered and is present (link) or not required. You want a
user-guide update if it's a user facing feature.

### Release note

<!--  Write your release note:
1. Enter your extended release note in the below block. If the PR
requires additional action from users switching to the new release,
include the string "action required".
2. If no release note is required, just write "NONE".
-->

```release-note
NONE
```

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
SuYao
2026-02-21 14:41:00 +08:00
committed by GitHub
parent 9c44d4562c
commit 0989f9b820
6 changed files with 355 additions and 0 deletions

View File

@@ -6,3 +6,5 @@
!public-skills.txt
!gh-create-pr/
!gh-create-pr/**
!prepare-release/
!prepare-release/**

View File

@@ -0,0 +1,151 @@
---
name: prepare-release
description: Prepare a new release by collecting commits, generating bilingual release notes, updating version files, and creating a release branch with PR. Use when asked to prepare/create a release, bump version, or run `/prepare-release`.
---
# Prepare Release
Automate the Cherry Studio release workflow: collect changes → generate bilingual release notes → update files → create release branch + PR → trigger CI/CD.
## Arguments
Parse the version intent from the user's message. Accept any of these forms:
- Bump type keyword: `patch`, `minor`, `major`
- Exact version: `x.y.z` or `x.y.z-pre.N` (e.g. `1.8.0`, `1.8.0-beta.1`, `1.8.0-rc.1`)
- Natural language: "prepare a beta release", "bump to 1.8.0-rc.2", etc.
Defaults to `patch` if no version is specified. Always echo the resolved target version back to the user before proceeding with any file edits.
- `--dry-run`: Preview only, do not create branch or PR.
## Workflow
### Step 1: Determine Version
1. Get the latest tag:
```bash
git describe --tags --abbrev=0
```
2. Read current version from `package.json`.
3. Compute the new version based on the argument:
- `patch` / `minor` / `major`: bump from the current tag version.
- `x.y.z` or `x.y.z-pre.N`: use as-is after validating it is valid semver.
### Step 2: Collect Commits
1. List all commits since the last tag:
```bash
git log <last-tag>..HEAD --format="%H %s" --no-merges
```
2. For each commit, get the full body:
```bash
git log <hash> -1 --format="%B"
```
3. Extract the content inside `` ```release-note `` code blocks from each commit body.
4. Extract the conventional commit type from the title (`feat`, `fix`, `refactor`, `perf`, `docs`, etc.).
5. **Skip** these commits:
- Titles starting with `🤖 Daily Auto I18N`
- Titles starting with `Merge`
- Titles starting with `chore(deps)`
- Titles starting with `chore: release`
- Commits where the release-note block says `NONE`
### Step 3: Generate Bilingual Release Notes
Using the collected commit information, generate release notes in **both English and Chinese**.
**Format** (must match exactly):
```
<!--LANG:en-->
Cherry Studio {version} - {Brief English Title}
✨ New Features
- [Component] Description
🐛 Bug Fixes
- [Component] Description
💄 Improvements
- [Component] Description
⚡ Performance
- [Component] Description
<!--LANG:zh-CN-->
Cherry Studio {version} - {简短中文标题}
✨ 新功能
- [组件] 描述
🐛 问题修复
- [组件] 描述
💄 改进
- [组件] 描述
⚡ 性能优化
- [组件] 描述
<!--LANG:END-->
```
**Rules:**
- Only include categories that have entries (omit empty categories).
- Each commit appears as exactly ONE line item in the appropriate category.
- Use the `release-note` field if present; otherwise summarize from the commit title.
- Component tags should be short: `[Chat]`, `[Models]`, `[Agent]`, `[MCP]`, `[Settings]`, `[Data]`, `[Build]`, etc.
- Chinese translations should be natural, not machine-literal.
- Do NOT include commit hashes or PR numbers.
- Omit purely internal commits (refactor, CI, docs) with no user-facing impact.
- Read the **existing** release notes in `electron-builder.yml` as a style reference before writing.
### Step 4: Update Files
1. **`package.json`**: Update the `"version"` field to the new version.
2. **`electron-builder.yml`**: Replace the content under `releaseInfo.releaseNotes: |` with the generated notes. Preserve the 4-space YAML indentation for the block scalar content.
### Step 5: Present for Review
Show the user:
- The new version number.
- The full generated release notes.
- A summary of which files were modified.
If `--dry-run` was specified, stop here.
Otherwise, ask the user to confirm before proceeding to Step 6.
### Step 6: Create Branch and PR
1. Create and push the release branch:
```bash
git checkout -b release/v{version}
git add package.json electron-builder.yml
git commit -m "chore: release v{version}"
git push -u origin release/v{version}
```
2. Create the PR using the `gh-create-pr` skill. If the skill tool is unavailable, read `.agents/skills/gh-create-pr/SKILL.md` and follow it manually. In CI (non-interactive) mode, skip interactive confirmation steps and create the PR directly after filling the template.
- Use title: `chore: release v{version}`
- Use base branch: `main`
- When filling the PR template, incorporate:
- The generated release notes (English section only, for readability).
- A list of included commits.
- A review checklist:
- [ ] Review generated release notes in `electron-builder.yml`
- [ ] Verify version bump in `package.json`
- [ ] CI passes
- [ ] Merge to trigger release build
3. Report the PR URL and next steps.
## CI Trigger Chain
Creating a PR from `release/v*` to `main` automatically triggers:
- **`release.yml`**: Builds on macOS, Windows, Linux and creates a draft GitHub Release.
- **`ci.yml`**: Runs lint, typecheck, and tests.
## Constraints
- Always read `electron-builder.yml` before modifying it to understand the current format.
- Never modify files other than `package.json` and `electron-builder.yml`.
- Never push directly to `main`.
- Always show the generated release notes to the user before creating the branch/PR (unless running in CI with no interactive user).

View File

@@ -1,3 +1,4 @@
# Public skills tracked by skills:sync and skills:check.
# One skill name per line.
gh-create-pr
prepare-release

View File

@@ -5,3 +5,5 @@
!README*.md
!gh-create-pr/
!gh-create-pr/**
!prepare-release/
!prepare-release/**

View File

@@ -0,0 +1,151 @@
---
name: prepare-release
description: Prepare a new release by collecting commits, generating bilingual release notes, updating version files, and creating a release branch with PR. Use when asked to prepare/create a release, bump version, or run `/prepare-release`.
---
# Prepare Release
Automate the Cherry Studio release workflow: collect changes → generate bilingual release notes → update files → create release branch + PR → trigger CI/CD.
## Arguments
Parse the version intent from the user's message. Accept any of these forms:
- Bump type keyword: `patch`, `minor`, `major`
- Exact version: `x.y.z` or `x.y.z-pre.N` (e.g. `1.8.0`, `1.8.0-beta.1`, `1.8.0-rc.1`)
- Natural language: "prepare a beta release", "bump to 1.8.0-rc.2", etc.
Defaults to `patch` if no version is specified. Always echo the resolved target version back to the user before proceeding with any file edits.
- `--dry-run`: Preview only, do not create branch or PR.
## Workflow
### Step 1: Determine Version
1. Get the latest tag:
```bash
git describe --tags --abbrev=0
```
2. Read current version from `package.json`.
3. Compute the new version based on the argument:
- `patch` / `minor` / `major`: bump from the current tag version.
- `x.y.z` or `x.y.z-pre.N`: use as-is after validating it is valid semver.
### Step 2: Collect Commits
1. List all commits since the last tag:
```bash
git log <last-tag>..HEAD --format="%H %s" --no-merges
```
2. For each commit, get the full body:
```bash
git log <hash> -1 --format="%B"
```
3. Extract the content inside `` ```release-note `` code blocks from each commit body.
4. Extract the conventional commit type from the title (`feat`, `fix`, `refactor`, `perf`, `docs`, etc.).
5. **Skip** these commits:
- Titles starting with `🤖 Daily Auto I18N`
- Titles starting with `Merge`
- Titles starting with `chore(deps)`
- Titles starting with `chore: release`
- Commits where the release-note block says `NONE`
### Step 3: Generate Bilingual Release Notes
Using the collected commit information, generate release notes in **both English and Chinese**.
**Format** (must match exactly):
```
<!--LANG:en-->
Cherry Studio {version} - {Brief English Title}
✨ New Features
- [Component] Description
🐛 Bug Fixes
- [Component] Description
💄 Improvements
- [Component] Description
⚡ Performance
- [Component] Description
<!--LANG:zh-CN-->
Cherry Studio {version} - {简短中文标题}
✨ 新功能
- [组件] 描述
🐛 问题修复
- [组件] 描述
💄 改进
- [组件] 描述
⚡ 性能优化
- [组件] 描述
<!--LANG:END-->
```
**Rules:**
- Only include categories that have entries (omit empty categories).
- Each commit appears as exactly ONE line item in the appropriate category.
- Use the `release-note` field if present; otherwise summarize from the commit title.
- Component tags should be short: `[Chat]`, `[Models]`, `[Agent]`, `[MCP]`, `[Settings]`, `[Data]`, `[Build]`, etc.
- Chinese translations should be natural, not machine-literal.
- Do NOT include commit hashes or PR numbers.
- Omit purely internal commits (refactor, CI, docs) with no user-facing impact.
- Read the **existing** release notes in `electron-builder.yml` as a style reference before writing.
### Step 4: Update Files
1. **`package.json`**: Update the `"version"` field to the new version.
2. **`electron-builder.yml`**: Replace the content under `releaseInfo.releaseNotes: |` with the generated notes. Preserve the 4-space YAML indentation for the block scalar content.
### Step 5: Present for Review
Show the user:
- The new version number.
- The full generated release notes.
- A summary of which files were modified.
If `--dry-run` was specified, stop here.
Otherwise, ask the user to confirm before proceeding to Step 6.
### Step 6: Create Branch and PR
1. Create and push the release branch:
```bash
git checkout -b release/v{version}
git add package.json electron-builder.yml
git commit -m "chore: release v{version}"
git push -u origin release/v{version}
```
2. Create the PR using the `gh-create-pr` skill. If the skill tool is unavailable, read `.agents/skills/gh-create-pr/SKILL.md` and follow it manually. In CI (non-interactive) mode, skip interactive confirmation steps and create the PR directly after filling the template.
- Use title: `chore: release v{version}`
- Use base branch: `main`
- When filling the PR template, incorporate:
- The generated release notes (English section only, for readability).
- A list of included commits.
- A review checklist:
- [ ] Review generated release notes in `electron-builder.yml`
- [ ] Verify version bump in `package.json`
- [ ] CI passes
- [ ] Merge to trigger release build
3. Report the PR URL and next steps.
## CI Trigger Chain
Creating a PR from `release/v*` to `main` automatically triggers:
- **`release.yml`**: Builds on macOS, Windows, Linux and creates a draft GitHub Release.
- **`ci.yml`**: Runs lint, typecheck, and tests.
## Constraints
- Always read `electron-builder.yml` before modifying it to understand the current format.
- Never modify files other than `package.json` and `electron-builder.yml`.
- Never push directly to `main`.
- Always show the generated release notes to the user before creating the branch/PR (unless running in CI with no interactive user).

48
.github/workflows/prepare-release.yml vendored Normal file
View File

@@ -0,0 +1,48 @@
name: Prepare Release
on:
workflow_dispatch:
inputs:
version:
description: "Version bump type or exact version (patch / minor / major / x.y.z / x.y.z-beta.N)"
required: true
default: "patch"
type: string
# Ensure this workflow only runs from the default branch
# (workflow_dispatch already restricts to branches with write access,
# but we guard the job to main to prevent accidental runs from feature branches)
permissions:
contents: write
pull-requests: write
id-token: write
jobs:
prepare:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- name: Check out Git repository
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Prepare Release via Claude
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.CLAUDE_TRANSLATOR_APIKEY }}
github_token: ${{ secrets.TOKEN_GITHUB_WRITE }}
claude_args: '--allowed-tools Bash(git:*),Bash(gh pr create:*),Bash(gh pr view:*),Bash(cat:*),Edit,Read,Write,Glob,Grep'
prompt: |
Run the prepare-release skill with version argument: ${{ github.event.inputs.version }}
Read the skill instructions from .agents/skills/prepare-release/SKILL.md and follow them exactly.
Since this is running in CI (non-interactive), skip all interactive confirmation steps. For PR creation, do NOT use the gh-create-pr skill; instead read .github/pull_request_template.md, fill every section, and run gh pr create --body-file directly.
Configure git before making commits:
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
env:
ANTHROPIC_BASE_URL: ${{ secrets.CLAUDE_TRANSLATOR_BASEURL }}