convertor/.github/workflows/docker-e2e-tests.yml
Your Name a2512bf29b fix: 修復 lint 錯誤和代碼格式化
- 移除未使用的導入 (readdirSync, basename, readFileSync, execSync)
- 將不需要重新賦值的 let 改為 const
- 修復 switch case 區塊中的詞法聲明問題
- 移除未使用的 SAMPLING_RATE 和 sampled 變量
- 移除未使用的 _timeout 參數
- 運行 Prettier 格式化所有文件
2026-01-23 12:27:22 +08:00

371 lines
12 KiB
YAML

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
- name: Free disk space
run: |
echo "🧹 Cleaning disk space..."
sudo rm -rf /usr/share/dotnet || true
sudo rm -rf /usr/local/lib/android || true
sudo rm -rf /opt/ghc || true
sudo rm -rf /opt/hostedtoolcache || true
docker system prune -af --volumes || true
echo "📊 Available space:"
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
- 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
run: |
sudo rm -rf /usr/share/dotnet || true
sudo rm -rf /usr/local/lib/android || true
docker system prune -af --volumes || true
- 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..."
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 "
set -e
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 '🧪 Running E2E tests...'
# Run comprehensive tests
bun test tests/e2e/comprehensive.e2e.test.ts --timeout 600000 || true
# Run format matrix tests
bun test tests/e2e/format-matrix.e2e.test.ts --timeout 300000 || true
# Run basic converter tests
bun test tests/e2e/converters.e2e.test.ts --timeout 120000 || true
echo ''
echo '✅ E2E tests completed!'
# Copy results
mkdir -p /app/test-results
cp -r tests/e2e/output/* /app/test-results/ 2>/dev/null || true
"
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: e2e-test-results
path: test-results/
retention-days: 7
# ============================================
# Job 4: Translation tests (optional, needs API keys)
# ============================================
translation-tests:
name: Translation Tests
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
if: ${{ secrets.OPENAI_API_KEY != '' || secrets.GOOGLE_API_KEY != '' }}
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
DEEPL_API_KEY: ${{ secrets.DEEPL_API_KEY }}
run: |
echo "🌍 Running translation tests..."
docker run --rm \
--name convertx-translation-test \
-v "${{ github.workspace }}/tests:/app/tests" \
-v "${{ github.workspace }}/translation-results:/app/translation-results" \
-e OPENAI_API_KEY="${OPENAI_API_KEY}" \
-e GOOGLE_API_KEY="${GOOGLE_API_KEY}" \
-e DEEPL_API_KEY="${DEEPL_API_KEY}" \
-e CI=true \
--entrypoint /bin/bash \
${{ needs.build-test-image.outputs.image }} \
-c "
set -e
cd /app
bun install --frozen-lockfile || bun install
echo '🌍 Running translation tests...'
bun test tests/e2e/translation.e2e.test.ts --timeout 600000 || true
mkdir -p /app/translation-results
cp -r tests/e2e/output/translation/* /app/translation-results/ 2>/dev/null || true
"
- name: Upload translation results
uses: actions/upload-artifact@v4
if: always()
with:
name: translation-test-results
path: translation-results/
retention-days: 7
# ============================================
# Job 5: Cleanup test image
# ============================================
cleanup:
name: Cleanup Test Image
runs-on: ubuntu-24.04
needs: [e2e-tests, comprehensive-e2e, translation-tests]
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:
name: e2e-test-results
path: test-results/
continue-on-error: true
- name: Generate summary
run: |
echo "# 🧪 Docker E2E Test Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Test Status" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY
echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY
echo "| E2E Tests | ${{ needs.e2e-tests.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Comprehensive E2E | ${{ needs.comprehensive-e2e.result }} |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ -f "test-results/format-matrix/matrix-summary.md" ]; then
echo "## Format Matrix Summary" >> $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 "## Conversion Matrix" >> $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 "📅 Test run completed at: $(date -u)" >> $GITHUB_STEP_SUMMARY