mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-07-06 14:01:30 +08:00
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: suyao <sy20010504@gmail.com>
325 lines
9.9 KiB
YAML
325 lines
9.9 KiB
YAML
name: CI
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
push:
|
|
branches:
|
|
- main
|
|
- v2
|
|
pull_request:
|
|
branches:
|
|
- main
|
|
- develop
|
|
- v2
|
|
types: [ready_for_review, synchronize, opened]
|
|
|
|
jobs:
|
|
changes:
|
|
runs-on: ubuntu-latest
|
|
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' || github.event.pull_request.draft == false
|
|
outputs:
|
|
main: ${{ steps.filter.outputs.main }}
|
|
renderer: ${{ steps.filter.outputs.renderer }}
|
|
shared: ${{ steps.filter.outputs.shared }}
|
|
steps:
|
|
- name: Check out Git repository
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Detect code changes
|
|
id: filter
|
|
uses: dorny/paths-filter@v4
|
|
with:
|
|
filters: |
|
|
main:
|
|
- 'src/main/**'
|
|
- 'src/preload/**'
|
|
- 'scripts/**'
|
|
renderer:
|
|
- 'src/renderer/**'
|
|
shared:
|
|
- 'packages/**'
|
|
- 'tests/**'
|
|
- 'package.json'
|
|
- 'pnpm-lock.yaml'
|
|
- 'pnpm-workspace.yaml'
|
|
- 'tsconfig*.json'
|
|
- 'electron.vite.config.ts'
|
|
- 'vitest.config.ts'
|
|
- 'patches/**'
|
|
|
|
catalog-hand-edit-check:
|
|
# provider-registry data/*.json are GENERATED from src/creators + src/providers. Catch a hand-edit:
|
|
# if the data changed but no source under src/ or scripts/ did, the JSON was edited directly.
|
|
runs-on: ubuntu-latest
|
|
if: github.event_name == 'pull_request' && github.event.pull_request.draft == false
|
|
steps:
|
|
- name: Check out Git repository
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Detect provider-registry changes
|
|
id: filter
|
|
uses: dorny/paths-filter@v4
|
|
with:
|
|
filters: |
|
|
data:
|
|
- 'packages/provider-registry/data/**'
|
|
source:
|
|
- 'packages/provider-registry/src/**'
|
|
- 'packages/provider-registry/scripts/**'
|
|
|
|
- name: Reject hand-edited catalog
|
|
if: steps.filter.outputs.data == 'true' && steps.filter.outputs.source == 'false'
|
|
run: |
|
|
echo "::error::packages/provider-registry/data/*.json changed but no src/ or scripts/ change — that's a hand-edit. The data files are generated: edit src/creators|src/providers and run \`pnpm --filter @cherrystudio/provider-registry generate\`, then commit. Never hand-edit data/*.json."
|
|
exit 1
|
|
|
|
changeset-check:
|
|
runs-on: ubuntu-latest
|
|
if: github.event_name == 'pull_request' && github.event.pull_request.draft == false && github.head_ref != 'changeset-release/main'
|
|
steps:
|
|
- name: Check out Git repository
|
|
uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Install Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version-file: ".node-version"
|
|
|
|
- name: Install pnpm
|
|
uses: pnpm/action-setup@v5
|
|
|
|
- name: Get pnpm store directory
|
|
id: pnpm-cache
|
|
shell: bash
|
|
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_OUTPUT
|
|
|
|
- name: Cache pnpm dependencies
|
|
uses: actions/cache@v5
|
|
with:
|
|
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
|
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-pnpm-
|
|
|
|
- name: Install Dependencies
|
|
run: pnpm install
|
|
|
|
- name: Check changesets
|
|
env:
|
|
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
run: pnpm changeset status --since="origin/$BASE_REF"
|
|
|
|
basic-checks:
|
|
runs-on: ubuntu-latest
|
|
env:
|
|
CI: true
|
|
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' || github.event.pull_request.draft == false
|
|
|
|
steps:
|
|
- name: Check out Git repository
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Install Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version-file: ".node-version"
|
|
|
|
- name: Install pnpm
|
|
uses: pnpm/action-setup@v5
|
|
|
|
- name: Get pnpm store directory
|
|
id: pnpm-cache
|
|
shell: bash
|
|
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_OUTPUT
|
|
|
|
- name: Cache pnpm dependencies
|
|
uses: actions/cache@v5
|
|
with:
|
|
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
|
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-pnpm-
|
|
|
|
- name: Install Dependencies
|
|
run: pnpm install
|
|
|
|
- name: Lint Check
|
|
run: pnpm test:lint
|
|
|
|
- name: Format Check
|
|
run: pnpm format:check
|
|
|
|
- name: Type Check
|
|
run: pnpm typecheck
|
|
|
|
- name: DB Migrations Check
|
|
run: |
|
|
# 1) Snapshot chain integrity — exits 1 on duplicate id / forked prevId (e.g. #15438).
|
|
pnpm db:migrations:check
|
|
# 2) Drift — schema source must match committed migrations. Catches "renamed a migration
|
|
# on merge instead of re-running generate" even when it does not collide an id.
|
|
# Note: `generate` exits 0 even on a chain collision, so it can never replace step 1.
|
|
pnpm db:migrations:generate
|
|
if [ -n "$(git status --porcelain migrations/)" ]; then
|
|
echo "::error::Schema and migrations are out of sync. Run \`pnpm db:migrations:generate\` and commit the result."
|
|
git --no-pager status --porcelain migrations/
|
|
git --no-pager diff -- migrations/
|
|
exit 1
|
|
fi
|
|
|
|
- name: i18n Check
|
|
run: pnpm i18n:check
|
|
|
|
- name: Hardcoded Strings Check
|
|
run: pnpm i18n:hardcoded:strict
|
|
|
|
- name: Skills Check
|
|
run: pnpm skills:check
|
|
|
|
general-test:
|
|
runs-on: ubuntu-latest
|
|
needs: changes
|
|
if: >-
|
|
needs.changes.outputs.main == 'true' ||
|
|
needs.changes.outputs.shared == 'true' ||
|
|
github.event_name == 'push' ||
|
|
github.event_name == 'workflow_dispatch'
|
|
env:
|
|
CI: true
|
|
|
|
steps:
|
|
- name: Check out Git repository
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Install Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version-file: ".node-version"
|
|
|
|
- name: Install pnpm
|
|
uses: pnpm/action-setup@v5
|
|
|
|
- name: Get pnpm store directory
|
|
id: pnpm-cache
|
|
shell: bash
|
|
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_OUTPUT
|
|
|
|
- name: Cache pnpm dependencies
|
|
uses: actions/cache@v5
|
|
with:
|
|
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
|
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-pnpm-
|
|
|
|
- name: Install Dependencies
|
|
run: pnpm install
|
|
|
|
- name: Main Process Test
|
|
run: pnpm test:main
|
|
|
|
- name: AI Core Test
|
|
run: pnpm test:aicore
|
|
|
|
- name: Shared Package Test
|
|
run: pnpm test:shared
|
|
|
|
- name: Provider Registry Package Test
|
|
run: pnpm test:provider-registry
|
|
|
|
- name: Scripts Test
|
|
run: pnpm test:scripts
|
|
|
|
render-test:
|
|
runs-on: ubuntu-latest
|
|
needs: changes
|
|
if: >-
|
|
needs.changes.outputs.renderer == 'true' ||
|
|
needs.changes.outputs.shared == 'true' ||
|
|
github.event_name == 'push' ||
|
|
github.event_name == 'workflow_dispatch'
|
|
env:
|
|
CI: true
|
|
|
|
steps:
|
|
- name: Check out Git repository
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Install Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version-file: ".node-version"
|
|
|
|
- name: Install pnpm
|
|
uses: pnpm/action-setup@v5
|
|
|
|
- name: Get pnpm store directory
|
|
id: pnpm-cache
|
|
shell: bash
|
|
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_OUTPUT
|
|
|
|
- name: Cache pnpm dependencies
|
|
uses: actions/cache@v5
|
|
with:
|
|
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
|
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-pnpm-
|
|
|
|
- name: Install Dependencies
|
|
run: pnpm install
|
|
|
|
- name: Renderer Test
|
|
run: pnpm test:renderer
|
|
|
|
notify:
|
|
runs-on: ubuntu-latest
|
|
needs: [basic-checks, general-test, render-test]
|
|
if: always() && (needs.basic-checks.result == 'failure' || needs.general-test.result == 'failure' || needs.render-test.result == 'failure') && github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
steps:
|
|
- name: Check out Git repository
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Install Node.js
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version-file: ".node-version"
|
|
|
|
- name: Install pnpm
|
|
uses: pnpm/action-setup@v5
|
|
|
|
- name: Get pnpm store directory
|
|
id: pnpm-cache
|
|
shell: bash
|
|
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_OUTPUT
|
|
|
|
- name: Cache pnpm dependencies
|
|
uses: actions/cache@v5
|
|
with:
|
|
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
|
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-pnpm-
|
|
|
|
- name: Install Dependencies
|
|
run: pnpm install
|
|
|
|
- name: Send failure notification to Feishu
|
|
env:
|
|
FEISHU_WEBHOOK_URL: ${{ secrets.FEISHU_WEBHOOK_URL }}
|
|
FEISHU_WEBHOOK_SECRET: ${{ secrets.FEISHU_WEBHOOK_SECRET }}
|
|
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
|
COMMIT_SHA: ${{ github.sha }}
|
|
COMMIT_MSG: ${{ github.event.head_commit.message }}
|
|
run: |
|
|
DESCRIPTION=$(printf "**分支:** main\n\n**提交:** %.7s\n\n**信息:** %s\n\n**工作流:** [查看详情](%s)" "$COMMIT_SHA" "$COMMIT_MSG" "$RUN_URL")
|
|
pnpm tsx scripts/feishu-notify.ts send \
|
|
-t "Main 分支 CI 失败" \
|
|
-d "$DESCRIPTION" \
|
|
-c "red"
|