Skip to content

Commit c623830

Browse files
authored
Merge branch 'Anionex:main' into main
2 parents 80daf79 + c66c4e0 commit c623830

82 files changed

Lines changed: 12044 additions & 1403 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,19 @@ AI_PROVIDER_FORMAT=gemini
77
GOOGLE_API_KEY=your-api-key-here
88
# 代理示例: https://aihubmix.com/gemini
99
GOOGLE_API_BASE=https://generativelanguage.googleapis.com
10+
# GenAI (Gemini) 超时时间(秒),默认300秒
11+
GENAI_TIMEOUT=300.0
12+
# GenAI (Gemini) 最大重试次数(应用层实现),默认2次
13+
GENAI_MAX_RETRIES=2
1014

1115
# OpenAI 格式配置(当 AI_PROVIDER_FORMAT=openai 时使用)
1216
OPENAI_API_KEY=your-api-key-here
1317
# 代理示例: https://aihubmix.com/v1
1418
OPENAI_API_BASE=https://api.openai.com/v1
15-
# 超时时间,默认60s
16-
OPENAI_TIMEOUT=60.0
17-
# 最多重试次数,默认3次
18-
OPENAI_MAX_RETRIES=3
19+
# 超时时间(秒),默认300秒
20+
OPENAI_TIMEOUT=300.0
21+
# 最多重试次数,减少重试避免累积超时,默认2次
22+
OPENAI_MAX_RETRIES=2
1923

2024
# AI 模型配置
2125
TEXT_MODEL=gemini-3-flash-preview
@@ -42,6 +46,9 @@ MINERU_API_BASE=https://mineru.net
4246
# 图片识别模型配置(用于为解析文件中的图片生成描述)
4347
IMAGE_CAPTION_MODEL=gemini-3-flash-preview
4448

49+
# 可编辑导出服务配置
50+
BAIDU_OCR_API_KEY=you-baidu-api-key
51+
4552
# 输出语言配置
4653
# 可选值: 'zh' (中文), 'ja' (日本語), 'en' (English), 'auto' (自动)
4754
OUTPUT_LANGUAGE=zh

.githooks/pre-commit

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#!/bin/bash
2+
# Pre-commit hook: 自动翻译README.md到README_EN.md
3+
# 只有在README.md被修改时才会触发
4+
5+
set -e
6+
7+
# 检查README.md是否在本次提交中被修改
8+
if git diff --cached --name-only | grep -q "^README\.md$"; then
9+
echo "检测到README.md变更,正在自动翻译到README_EN.md..."
10+
11+
# 检查是否在项目根目录
12+
if [ ! -f "README.md" ]; then
13+
echo "错误: 未找到README.md"
14+
exit 1
15+
fi
16+
17+
# 检查.env文件
18+
if [ ! -f ".env" ]; then
19+
echo "警告: 未找到.env文件,跳过翻译"
20+
echo "如需自动翻译,请确保.env文件包含必要的API密钥配置"
21+
exit 0
22+
fi
23+
24+
# 加载环境变量
25+
set -a
26+
source .env 2>/dev/null || true
27+
set +a
28+
29+
# 检查必要的环境变量
30+
if [ -z "$GOOGLE_API_KEY" ]; then
31+
echo "警告: GOOGLE_API_KEY未设置,跳过翻译"
32+
echo "如需自动翻译,请在.env文件中设置GOOGLE_API_KEY"
33+
exit 0
34+
fi
35+
36+
# 检查uv是否可用
37+
if ! command -v uv &> /dev/null; then
38+
echo "警告: uv未安装,跳过翻译"
39+
exit 0
40+
fi
41+
42+
# 运行翻译脚本
43+
echo "开始翻译..."
44+
if uv run python scripts/translate_readme.py; then
45+
echo "✅ 翻译成功!"
46+
47+
# 将翻译后的README_EN.md添加到本次提交
48+
git add README_EN.md
49+
echo "README_EN.md已自动添加到本次提交"
50+
else
51+
echo "❌ 翻译失败,但不阻止提交"
52+
echo "你可以稍后手动运行: ./scripts/test_translation.sh"
53+
# 不阻止提交,允许继续
54+
exit 0
55+
fi
56+
else
57+
# README.md未修改,无需翻译
58+
exit 0
59+
fi
60+

.github/workflows/ci-test.yml

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ name: Full Test Suite
22

33
# Full tests run in these cases:
44
# 1. Push to main/develop branch (direct push, not from PR merge)
5+
# - 仅当代码文件变更时触发(排除 *.md 文件)
56
# 2. PR labeled with ready-for-test
67
# 3. Manual trigger (workflow_dispatch)
78
#
@@ -10,6 +11,8 @@ name: Full Test Suite
1011
on:
1112
push:
1213
branches: [ main, develop ]
14+
paths-ignore:
15+
- '**/*.md'
1316
pull_request:
1417
types: [labeled]
1518
branches: [ main, develop ]
@@ -294,21 +297,45 @@ jobs:
294297
# Now uv is available in PATH
295298
uv sync --extra test
296299
297-
- name: Run Backend API Integration tests (requires running service)
300+
# NOTE: API Full Flow test is commented out because UI E2E test covers the same flow
301+
# UI E2E test is more comprehensive as it tests:
302+
# - Frontend UI interactions
303+
# - Template selection modal
304+
# - Single card retry functionality
305+
# - Complete user experience
306+
#
307+
# If you need quick API validation without AI, use test_quick_api_flow_no_ai instead
308+
# - name: Run Backend API Integration tests (requires running service)
309+
# if: steps.check_e2e.outputs.skip != 'true' && env.GOOGLE_API_KEY != '' && env.GOOGLE_API_KEY != 'mock-api-key-for-testing'
310+
# run: |
311+
# # Source cargo env to access uv
312+
# . "$HOME/.cargo/env"
313+
#
314+
# # Run API integration tests that require real running backend service
315+
# echo "Running Backend API integration tests with real service (Gemini format)"
316+
# cd backend
317+
# uv run pytest tests/integration/test_api_full_flow.py::TestAPIFullFlow::test_api_full_flow_create_to_export -v -m "integration and requires_service"
318+
# env:
319+
# # Ensure API key is not logged
320+
# GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
321+
# SKIP_SERVICE_TESTS: false
322+
# timeout-minutes: 15
323+
# continue-on-error: false
324+
325+
- name: Run Quick API test (no AI, fast validation)
298326
if: steps.check_e2e.outputs.skip != 'true' && env.GOOGLE_API_KEY != '' && env.GOOGLE_API_KEY != 'mock-api-key-for-testing'
299327
run: |
300328
# Source cargo env to access uv
301329
. "$HOME/.cargo/env"
302330
303-
# Run API integration tests that require real running backend service
304-
echo "Running Backend API integration tests with real service (Gemini format)"
331+
# Run quick API test that only validates endpoints (no AI generation)
332+
echo "Running quick Backend API test (no AI generation, fast feedback)"
305333
cd backend
306-
uv run pytest tests/integration/test_api_full_flow.py -v -m "integration and requires_service"
334+
uv run pytest tests/integration/test_api_full_flow.py::TestAPIFullFlow::test_quick_api_flow_no_ai -v -m "requires_service"
307335
env:
308-
# Ensure API key is not logged
309336
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
310337
SKIP_SERVICE_TESTS: false
311-
timeout-minutes: 15
338+
timeout-minutes: 5
312339
continue-on-error: false
313340

314341
- name: Run Frontend UI E2E tests
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
name: Build and Push to Docker Hub
2+
3+
# 在测试通过后自动构建并推送镜像到 Docker Hub
4+
5+
# 触发条件:
6+
# 1. CI workflow (Full Test Suite) 成功完成后(主要触发方式)
7+
# 2. 手动触发(workflow_dispatch)
8+
on:
9+
workflow_run:
10+
workflows: ["Full Test Suite"]
11+
types:
12+
- completed
13+
branches:
14+
- main
15+
workflow_dispatch: # 允许手动触发
16+
17+
# Cancel old builds on the same branch
18+
concurrency:
19+
group: ${{ github.workflow }}-${{ github.ref }}
20+
cancel-in-progress: true
21+
22+
jobs:
23+
build-and-push:
24+
name: Build and Push Docker Images
25+
runs-on: ubuntu-latest
26+
# 如果是 workflow_run 触发,只在前一个 workflow 成功时运行
27+
# 手动触发时总是运行
28+
if: |
29+
github.event_name == 'workflow_dispatch' ||
30+
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success')
31+
32+
steps:
33+
- name: Checkout code
34+
uses: actions/checkout@v4
35+
with:
36+
# 如果是 workflow_run 触发,使用原始 workflow 的 commit SHA
37+
ref: ${{ github.event.workflow_run.head_sha || github.sha }}
38+
fetch-depth: 0
39+
40+
- name: Set up Docker Buildx
41+
uses: docker/setup-buildx-action@v3
42+
43+
- name: Login to Docker Hub
44+
uses: docker/login-action@v3
45+
with:
46+
username: ${{ secrets.DOCKERHUB_USERNAME }}
47+
password: ${{ secrets.DOCKERHUB_TOKEN }}
48+
49+
- name: Extract metadata for backend
50+
id: meta-backend
51+
uses: docker/metadata-action@v5
52+
with:
53+
images: ${{ secrets.DOCKERHUB_USERNAME }}/banana-slides-backend
54+
tags: |
55+
type=ref,event=branch
56+
type=semver,pattern={{version}}
57+
type=semver,pattern={{major}}.{{minor}}
58+
type=sha
59+
type=raw,value=latest,enable={{is_default_branch}}
60+
61+
- name: Extract metadata for frontend
62+
id: meta-frontend
63+
uses: docker/metadata-action@v5
64+
with:
65+
images: ${{ secrets.DOCKERHUB_USERNAME }}/banana-slides-frontend
66+
tags: |
67+
type=ref,event=branch
68+
type=semver,pattern={{version}}
69+
type=semver,pattern={{major}}.{{minor}}
70+
type=sha
71+
type=raw,value=latest,enable={{is_default_branch}}
72+
73+
- name: Build and push backend image
74+
uses: docker/build-push-action@v5
75+
with:
76+
context: .
77+
file: ./backend/Dockerfile
78+
push: true
79+
tags: ${{ steps.meta-backend.outputs.tags }}
80+
labels: ${{ steps.meta-backend.outputs.labels }}
81+
cache-from: type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/banana-slides-backend:buildcache
82+
cache-to: type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/banana-slides-backend:buildcache,mode=max
83+
build-args: |
84+
DOCKER_REGISTRY=${{ secrets.DOCKER_REGISTRY }}
85+
GHCR_REGISTRY=${{ secrets.GHCR_REGISTRY || 'ghcr.io/' }}
86+
APT_MIRROR=${{ secrets.APT_MIRROR }}
87+
PYPI_INDEX_URL=${{ secrets.PYPI_INDEX_URL }}
88+
89+
- name: Build and push frontend image
90+
uses: docker/build-push-action@v5
91+
with:
92+
context: .
93+
file: ./frontend/Dockerfile
94+
push: true
95+
tags: ${{ steps.meta-frontend.outputs.tags }}
96+
labels: ${{ steps.meta-frontend.outputs.labels }}
97+
cache-from: type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/banana-slides-frontend:buildcache
98+
cache-to: type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/banana-slides-frontend:buildcache,mode=max
99+
build-args: |
100+
DOCKER_BUILDKIT=1
101+
VITE_API_BASE_URL=${{ secrets.VITE_API_BASE_URL }}
102+
DOCKER_REGISTRY=${{ secrets.DOCKER_REGISTRY }}
103+
NPM_REGISTRY=${{ secrets.NPM_REGISTRY }}
104+
105+
- name: Image digest
106+
run: |
107+
echo "Backend image: ${{ steps.meta-backend.outputs.tags }}"
108+
echo "Frontend image: ${{ steps.meta-frontend.outputs.tags }}"
109+
echo "✅ Images pushed to Docker Hub successfully!"
110+

.gitignore

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,14 @@
3434

3535
# 忽略临时文档,但保留项目文档
3636
*.md
37-
!README*.md
38-
!docs/**/*.md
37+
!README.md
38+
# !docs/**/*.md
3939
!.github/**/*.md
4040
*.pyc
4141
.env
42+
43+
# GCP 服务账户文件(包含敏感私钥)
44+
gcp-service-account.json
4245
*.ppt
4346
*.pptx
4447
generate-example.py
@@ -49,4 +52,6 @@ uploads/
4952
!assets/*
5053

5154
# 镜像源配置脚本的备份文件
52-
*.orig
55+
*.orig
56+
# 本地备份目录(保存测试文件等)
57+
_local_backup/

0 commit comments

Comments
 (0)