convertor/.github/workflows/docker-e2e-tests.yml
Your Name 6d948b0873 feat: implement automatic format inference service with candidate generation and prediction model
- Add formatCandidateRules.ts to define rules for generating format candidates based on file features.
- Introduce formatPredictionModel.ts to predict the most likely target format based on user behavior and file features.
- Create inferenceService.ts to integrate all inference modules and provide a unified inference API.
- Develop inference.tsx as an API endpoint for frontend calls to predict formats and engines based on file extensions.
- Implement logging for conversion events and dismissals, along with user profile retrieval.
- Ensure warmup management for engine predictions and provide status checks.
2026-01-26 12:47:16 +08:00

423 lines
15 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

name: Docker E2E Tests
# 在 Docker 環境中運行完整 E2E 測試
# 包含所有轉換工具和翻譯服務
on:
push:
branches: ["main"]
paths:
- "src/**"
- "tests/**"
- "Dockerfile"
- ".github/workflows/docker-e2e-tests.yml"
pull_request:
branches: ["main"]
paths:
- "src/**"
- "tests/**"
- "Dockerfile"
workflow_dispatch:
inputs:
run_translation_tests:
description: "Run translation tests (requires API keys)"
required: false
default: false
type: boolean
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
# ============================================
# Job 1: Build test image
# ============================================
build-test-image:
name: Build Test Image
runs-on: ubuntu-24.04
permissions:
contents: read
packages: write
outputs:
image: ${{ steps.image.outputs.image }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
# 使用專門的 action 進行激進的磁碟清理
- name: Free disk space (aggressive)
uses: jlumbroso/free-disk-space@main
with:
tool-cache: true
android: true
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: true
- name: Additional disk cleanup
run: |
echo "🧹 Additional disk cleanup..."
sudo rm -rf /usr/local/share/boost || true
sudo rm -rf /usr/share/swift || true
sudo rm -rf /opt/hostedtoolcache/CodeQL || true
docker system prune -af --volumes || true
echo "📊 Available space after cleanup:"
df -h /
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: downcase REPO
run: echo "REPO=${GITHUB_REPOSITORY@L}" >> "${GITHUB_ENV}"
- name: Build and push test image
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ env.REGISTRY }}/${{ env.REPO }}:test-${{ github.sha }}
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.REPO }}:buildcache-linux-amd64
cache-to: type=inline
# 🔥 CACHE_BUST 強制重新執行模型下載層
build-args: |
CACHE_BUST=${{ github.run_id }}${{ github.run_attempt }}
- name: Set image output
id: image
run: echo "image=${{ env.REGISTRY }}/${{ env.REPO }}:test-${{ github.sha }}" >> $GITHUB_OUTPUT
# ============================================
# Job 2: Run E2E tests in Docker
# ============================================
e2e-tests:
name: E2E Tests in Docker
runs-on: ubuntu-24.04
needs: build-test-image
timeout-minutes: 30
services:
# Run the test image as a service
convertx:
image: ${{ needs.build-test-image.outputs.image }}
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
ports:
- 3000:3000
options: >-
--health-cmd "curl -f http://localhost:3000/healthcheck || exit 1"
--health-interval 10s
--health-timeout 5s
--health-retries 10
--health-start-period 30s
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Wait for service to be healthy
run: |
echo "⏳ Waiting for ConvertX service..."
for i in {1..30}; do
if curl -f http://localhost:3000/healthcheck 2>/dev/null; then
echo "✅ Service is healthy!"
break
fi
echo "Waiting... ($i/30)"
sleep 5
done
- name: Run API health check
run: |
echo "🔍 Testing API endpoints..."
# Health check
curl -f http://localhost:3000/healthcheck
echo ""
# Check if main page loads
curl -f -o /dev/null -w "%{http_code}" http://localhost:3000/
echo ""
echo "✅ API health checks passed!"
# ============================================
# Job 3: Run comprehensive E2E tests inside container
# ============================================
comprehensive-e2e:
name: Comprehensive E2E Tests
runs-on: ubuntu-24.04
needs: build-test-image
timeout-minutes: 60
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Free disk space (aggressive)
uses: jlumbroso/free-disk-space@main
with:
tool-cache: true
android: true
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: false
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Pull test image
run: docker pull ${{ needs.build-test-image.outputs.image }}
- name: Run E2E tests inside Docker container
run: |
echo "🧪 Running comprehensive E2E tests inside Docker..."
# 確保輸出目錄存在
mkdir -p "${{ github.workspace }}/test-results"
docker run --rm \
--name convertx-e2e-test \
-v "${{ github.workspace }}/tests:/app/tests" \
-v "${{ github.workspace }}/test-results:/app/test-results" \
-e CI=true \
-e NODE_ENV=test \
--entrypoint /bin/bash \
${{ needs.build-test-image.outputs.image }} \
-c "
echo '📋 系統資訊 System info:'
uname -a
echo ''
echo '🔧 可用轉換工具 Available conversion tools:'
echo ' inkscape:' \$(inkscape --version 2>/dev/null | head -1 || echo '未找到 not found')
echo ' pandoc:' \$(pandoc --version 2>/dev/null | head -1 || echo '未找到 not found')
echo ' ffmpeg:' \$(ffmpeg -version 2>/dev/null | head -1 || echo '未找到 not found')
echo ' libreoffice:' \$(soffice --version 2>/dev/null || echo '未找到 not found')
echo ' imagemagick:' \$(magick --version 2>/dev/null | head -1 || echo '未找到 not found')
echo ' calibre:' \$(ebook-convert --version 2>/dev/null | head -1 || echo '未找到 not found')
echo ' potrace:' \$(potrace -v 2>/dev/null | head -1 || echo '未找到 not found')
echo ' dasel:' \$(dasel --version 2>/dev/null || echo '未找到 not found')
echo ' resvg:' \$(resvg --version 2>/dev/null || echo '未找到 not found')
echo ' vips:' \$(vips --version 2>/dev/null || echo '未找到 not found')
echo ' pdf2zh:' \$(pdf2zh --version 2>/dev/null || echo '未找到 not found')
echo ' babeldoc:' \$(babeldoc --version 2>/dev/null || echo '未找到 not found')
echo ''
echo '📦 安裝測試依賴 Installing test dependencies...'
cd /app
bun install --frozen-lockfile || bun install
echo ''
echo '🧪 執行 E2E 測試 Running E2E tests...'
# 執行綜合測試(允許失敗)
bun test tests/e2e/comprehensive.e2e.test.ts --timeout 600000 || echo '⚠️ 綜合測試有部分失敗'
# 執行格式矩陣測試(允許失敗)
bun test tests/e2e/format-matrix.e2e.test.ts --timeout 300000 || echo '⚠️ 格式矩陣測試有部分失敗'
# 執行基礎轉換器測試(允許失敗)
bun test tests/e2e/converters.e2e.test.ts --timeout 120000 || echo '⚠️ 轉換器測試有部分失敗'
echo ''
echo '✅ E2E 測試完成!'
# 複製結果到輸出目錄
mkdir -p /app/test-results
cp -r tests/e2e/output/* /app/test-results/ 2>/dev/null || echo '⚠️ 無測試輸出可複製'
ls -la /app/test-results/ 2>/dev/null || echo '📁 測試結果目錄為空'
"
# 檢查輸出目錄內容
echo "📁 測試結果目錄內容:"
ls -la "${{ github.workspace }}/test-results/" || echo "目錄為空或不存在"
- name: Create placeholder if no results
if: always()
run: |
mkdir -p test-results
if [ -z "$(ls -A test-results 2>/dev/null)" ]; then
echo '{"message": "無測試結果輸出", "timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}' > test-results/placeholder.json
fi
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: e2e-test-results
path: test-results/
retention-days: 7
if-no-files-found: warn
# ============================================
# Job 4: Translation tests (使用免費翻譯服務)
# 使用 Google/Bing 免費翻譯,不需要付費 API 金鑰
# ============================================
translation-tests:
name: Translation Tests (Free Services)
runs-on: ubuntu-24.04
needs: build-test-image
if: ${{ github.event.inputs.run_translation_tests == 'true' || github.event_name == 'push' }}
timeout-minutes: 30
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Pull test image
run: docker pull ${{ needs.build-test-image.outputs.image }}
- name: Run translation tests
run: |
echo "🌍 執行翻譯測試使用免費服務Google/Bing..."
# 確保輸出目錄存在
mkdir -p "${{ github.workspace }}/translation-results"
docker run --rm \
--name convertx-translation-test \
-v "${{ github.workspace }}/tests:/app/tests" \
-v "${{ github.workspace }}/translation-results:/app/translation-results" \
-e CI=true \
-e PDFMATHTRANSLATE_SERVICE=google \
-e BABELDOC_SERVICE=google \
--entrypoint /bin/bash \
${{ needs.build-test-image.outputs.image }} \
-c "
cd /app
bun install --frozen-lockfile || bun install
echo '🌍 使用免費服務執行翻譯測試...'
bun test tests/e2e/translation.e2e.test.ts --timeout 600000 || echo '⚠️ 翻譯測試有部分失敗'
mkdir -p /app/translation-results
cp -r tests/e2e/output/translation/* /app/translation-results/ 2>/dev/null || echo '⚠️ 無翻譯輸出可複製'
ls -la /app/translation-results/ 2>/dev/null || echo '📁 翻譯結果目錄為空'
"
# 檢查輸出目錄內容
echo "📁 翻譯結果目錄內容:"
ls -la "${{ github.workspace }}/translation-results/" || echo "目錄為空或不存在"
- name: Create placeholder if no results
if: always()
run: |
mkdir -p translation-results
if [ -z "$(ls -A translation-results 2>/dev/null)" ]; then
echo '{"message": "無翻譯結果輸出", "timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}' > translation-results/placeholder.json
fi
- name: Upload translation results
uses: actions/upload-artifact@v4
if: always()
with:
name: translation-test-results
path: translation-results/
retention-days: 7
if-no-files-found: warn
# ============================================
# Job 5: Cleanup test image
# ============================================
cleanup:
name: Cleanup Test Image
runs-on: ubuntu-24.04
needs: [e2e-tests, comprehensive-e2e]
if: always()
permissions:
packages: write
steps:
- name: Delete test image
uses: actions/github-script@v7
continue-on-error: true
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const tag = `test-${{ github.sha }}`;
console.log(`🗑️ Attempting to delete test image with tag: ${tag}`);
// Note: This requires ghcr.io API access which may need additional setup
// For now, images will be cleaned up by retention policies
console.log('Test images will be cleaned up by retention policies');
# ============================================
# Job 6: Test summary
# ============================================
summary:
name: Test Summary
runs-on: ubuntu-24.04
needs: [e2e-tests, comprehensive-e2e]
if: always()
steps:
- name: Download test results
uses: actions/download-artifact@v4
with:
pattern: "*-test-results"
path: test-results/
merge-multiple: true
continue-on-error: true
- name: Check downloaded results
run: |
echo "📁 已下載的測試結果:"
ls -la test-results/ 2>/dev/null || echo "無測試結果可下載"
- name: Generate summary
run: |
echo "# 🧪 Docker E2E 測試結果" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## 測試狀態" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| 任務 | 狀態 |" >> $GITHUB_STEP_SUMMARY
echo "|------|------|" >> $GITHUB_STEP_SUMMARY
echo "| E2E 測試 | ${{ needs.e2e-tests.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| 綜合 E2E 測試 | ${{ needs.comprehensive-e2e.result }} |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ -f "test-results/format-matrix/matrix-summary.md" ]; then
echo "## 格式矩陣摘要" >> $GITHUB_STEP_SUMMARY
cat test-results/format-matrix/matrix-summary.md >> $GITHUB_STEP_SUMMARY
fi
if [ -f "test-results/comprehensive/conversion-matrix.json" ]; then
echo "" >> $GITHUB_STEP_SUMMARY
echo "## 轉換矩陣" >> $GITHUB_STEP_SUMMARY
echo '```json' >> $GITHUB_STEP_SUMMARY
head -50 test-results/comprehensive/conversion-matrix.json >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "📅 測試完成時間: $(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY