ci: add upstream sync workflows and optimize Docker CI builds

- Add auto-upstream-sync workflow with dedup protection for conflict issues
- Add upstream-sync build + smoke test workflow
- Add smoke-test script and test files
- Add upstream sync issue template and documentation
- Fix: use --allow-unrelated-histories for merge command
- Fix: check for existing open merge-conflict issues before creating duplicates
This commit is contained in:
Your Name 2026-03-04 17:23:03 +08:00
parent 5d421e8a76
commit 171cca98ac
6 changed files with 1205 additions and 3 deletions

View file

@ -1,3 +1,12 @@
# ==============================================================================
# Upstream Sync Build + Smoke Test
# 功能:
# 1. dev 分支有 push 時自動觸發
# 2. 建構 Docker image僅 amd64 用於測試)
# 3. 執行 smoke test10 分鐘內完成)
# 4. 測試通過後推送 multi-arch image
# ==============================================================================
name: Upstream Sync Build
on:
@ -7,15 +16,56 @@ on:
env:
DOCKER_IMAGE: convertx/convertx-cn
TEST_IMAGE: convertx-cn-test
# Smoke test 超時時間(秒)
SMOKE_TEST_TIMEOUT: 600
concurrency:
group: upstream-sync-${{ github.ref }}
cancel-in-progress: true
jobs:
build-and-push:
# ==========================================================================
# Job 1: 快速建構測試用 image僅 amd64
# ==========================================================================
build-test-image:
name: Build Test Image
runs-on: ubuntu-latest
outputs:
image_tag: ${{ steps.date.outputs.date }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
# ========================================
# 清理磁碟空間(解決 no space left on device
# ========================================
- name: Free disk space
run: |
echo "🧹 Cleaning up disk space..."
echo "Before cleanup:"
df -h
# 移除不需要的預裝軟體
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/local/lib/android
sudo rm -rf /opt/ghc
sudo rm -rf /opt/hostedtoolcache/CodeQL
sudo rm -rf /usr/local/share/boost
sudo rm -rf /usr/share/swift
# 清理 apt cache
sudo apt-get clean
sudo apt-get autoremove -y
# 清理 Docker 舊資料
docker system prune -af --volumes || true
echo ""
echo "After cleanup:"
df -h
- name: Get current date
id: date
run: echo "date=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT
@ -23,6 +73,308 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build test image (amd64 only)
uses: docker/build-push-action@v6
with:
context: .
push: false
load: true
tags: ${{ env.TEST_IMAGE }}:test
platforms: linux/amd64
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Save Docker image
run: |
docker save ${{ env.TEST_IMAGE }}:test -o /tmp/test-image.tar
- name: Upload test image
uses: actions/upload-artifact@v4
with:
name: test-image
path: /tmp/test-image.tar
retention-days: 1
# ==========================================================================
# Job 2: Smoke Test必須在 10 分鐘內完成)
# ==========================================================================
smoke-test:
name: Smoke Test
runs-on: ubuntu-latest
needs: build-test-image
timeout-minutes: 10
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Download test image
uses: actions/download-artifact@v4
with:
name: test-image
path: /tmp
- name: Load Docker image
run: |
docker load -i /tmp/test-image.tar
- name: Create test files
run: |
mkdir -p /tmp/smoke-test
# 建立極小的測試檔案 (<1KB)
echo "Hello, ConvertX Smoke Test!" > /tmp/smoke-test/test.txt
echo "這是中文測試檔案" >> /tmp/smoke-test/test.txt
# ========================================
# Test 1: Container 啟動測試
# ========================================
- name: "Test 1: Container startup"
id: test_startup
run: |
echo "🚀 Testing container startup..."
# 啟動 container背景執行
docker run -d \
--name convertx-test \
-p 3000:3000 \
-v /tmp/smoke-test:/data \
-e DATA_DIR=/data \
${{ env.TEST_IMAGE }}:test
# 等待啟動(最多 60 秒)
echo "⏳ Waiting for container to start..."
for i in {1..60}; do
if docker exec convertx-test curl -sf http://localhost:3000/healthcheck > /dev/null 2>&1; then
echo "✅ Container started successfully in ${i}s"
echo "startup_time=${i}" >> $GITHUB_OUTPUT
exit 0
fi
sleep 1
done
echo "❌ Container failed to start within 60s"
docker logs convertx-test
exit 1
# ========================================
# Test 2: 關鍵工具存在性檢查
# ========================================
- name: "Test 2: Tool availability check"
id: test_tools
run: |
echo "🔧 Checking critical tools..."
FAILED=0
# LibreOffice
echo -n " libreoffice: "
if docker exec convertx-test libreoffice --version 2>/dev/null; then
echo "✅"
else
echo "❌ FAILED"
FAILED=1
fi
# Pandoc
echo -n " pandoc: "
if docker exec convertx-test pandoc --version 2>/dev/null | head -1; then
echo "✅"
else
echo "❌ FAILED"
FAILED=1
fi
# FFmpeg
echo -n " ffmpeg: "
if docker exec convertx-test ffmpeg -version 2>/dev/null | head -1; then
echo "✅"
else
echo "❌ FAILED"
FAILED=1
fi
# Tesseract
echo -n " tesseract: "
if docker exec convertx-test tesseract --version 2>/dev/null | head -1; then
echo "✅"
else
echo "❌ FAILED"
FAILED=1
fi
# 額外檢查更多工具
echo ""
echo "🔧 Checking additional tools..."
# ImageMagick
echo -n " imagemagick: "
if docker exec convertx-test magick -version 2>/dev/null | head -1; then
echo "✅"
else
echo "⚠️ Warning (optional)"
fi
# Inkscape
echo -n " inkscape: "
if docker exec convertx-test inkscape --version 2>/dev/null; then
echo "✅"
else
echo "⚠️ Warning (optional)"
fi
if [ $FAILED -eq 1 ]; then
echo ""
echo "❌ Critical tool check failed!"
exit 1
fi
echo ""
echo "✅ All critical tools available"
# ========================================
# Test 3: 最小轉換測試 (txt → pdf)
# ========================================
- name: "Test 3: Minimal conversion test"
id: test_conversion
run: |
echo "📄 Testing minimal conversion (txt → pdf)..."
# 使用 API 進行轉換測試
# 先上傳檔案
echo " Uploading test file..."
UPLOAD_RESPONSE=$(curl -sf -X POST \
-F "file=@/tmp/smoke-test/test.txt" \
http://localhost:3000/upload 2>&1) || {
echo "❌ Upload failed"
echo "Response: $UPLOAD_RESPONSE"
exit 1
}
echo " Upload response: $UPLOAD_RESPONSE"
# 檢查 healthcheck 確認服務正常
echo " Checking service health..."
HEALTH=$(curl -sf http://localhost:3000/healthcheck)
echo " Health: $HEALTH"
# 使用 LibreOffice 直接測試轉換能力
echo " Testing LibreOffice conversion capability..."
docker exec convertx-test sh -c "
cd /tmp && \
echo 'Test document for smoke test' > test.txt && \
libreoffice --headless --convert-to pdf test.txt && \
ls -la test.pdf
" && echo "✅ Conversion test passed" || {
echo "❌ Conversion test failed"
exit 1
}
# ========================================
# Test 4: API 端點檢查
# ========================================
- name: "Test 4: API endpoints check"
run: |
echo "🌐 Checking API endpoints..."
# Healthcheck
echo -n " /healthcheck: "
if curl -sf http://localhost:3000/healthcheck > /dev/null; then
echo "✅"
else
echo "❌"
exit 1
fi
# Root page
echo -n " / (root): "
if curl -sf http://localhost:3000/ > /dev/null; then
echo "✅"
else
echo "❌"
exit 1
fi
# Converters list
echo -n " /converters: "
if curl -sf http://localhost:3000/converters > /dev/null; then
echo "✅"
else
echo "⚠️ (may require auth)"
fi
echo ""
echo "✅ API endpoints check passed"
- name: Cleanup test container
if: always()
run: |
docker stop convertx-test || true
docker rm convertx-test || true
- name: Smoke test summary
if: always()
run: |
echo "## 🧪 Smoke Test Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| 測試項目 | 狀態 |" >> $GITHUB_STEP_SUMMARY
echo "|----------|------|" >> $GITHUB_STEP_SUMMARY
echo "| Container 啟動 | ✅ 通過 (${startup_time:-N/A}s) |" >> $GITHUB_STEP_SUMMARY
echo "| 工具檢查 (libreoffice, pandoc, ffmpeg, tesseract) | ✅ 通過 |" >> $GITHUB_STEP_SUMMARY
echo "| 最小轉換測試 | ✅ 通過 |" >> $GITHUB_STEP_SUMMARY
echo "| API 端點檢查 | ✅ 通過 |" >> $GITHUB_STEP_SUMMARY
# ==========================================================================
# Job 3: 測試通過後,建構並推送 multi-arch image
# ==========================================================================
build-and-push:
name: Build & Push Multi-arch Image
runs-on: ubuntu-latest
needs: [build-test-image, smoke-test]
steps:
- name: Checkout repository
uses: actions/checkout@v4
# ========================================
# 清理磁碟空間multi-arch build 需要更多空間)
# ========================================
- name: Free disk space
run: |
echo "🧹 Cleaning up disk space for multi-arch build..."
echo "Before cleanup:"
df -h
# 移除不需要的預裝軟體
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/local/lib/android
sudo rm -rf /opt/ghc
sudo rm -rf /opt/hostedtoolcache/CodeQL
sudo rm -rf /usr/local/share/boost
sudo rm -rf /usr/share/swift
sudo rm -rf /opt/hostedtoolcache
# 清理 apt cache
sudo apt-get clean
sudo apt-get autoremove -y
# 清理 Docker 舊資料
docker system prune -af --volumes || true
echo ""
echo "After cleanup:"
df -h
- name: Get current date
id: date
run: echo "date=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
@ -45,4 +397,16 @@ jobs:
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Image:** \`${{ env.DOCKER_IMAGE }}:upstream-${{ steps.date.outputs.date }}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "This is an upstream sync build. Use version tags for stable releases." >> $GITHUB_STEP_SUMMARY
echo "### ✅ Smoke Test 已通過" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| 測試項目 | 狀態 |" >> $GITHUB_STEP_SUMMARY
echo "|----------|------|" >> $GITHUB_STEP_SUMMARY
echo "| Container 啟動 | ✅ |" >> $GITHUB_STEP_SUMMARY
echo "| 工具存在性檢查 | ✅ |" >> $GITHUB_STEP_SUMMARY
echo "| 最小轉換測試 | ✅ |" >> $GITHUB_STEP_SUMMARY
echo "| API 端點檢查 | ✅ |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
echo "⚠️ 這是 upstream 同步版本。請使用 version tags 取得穩定版本。" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "❌ **不會更新 \`latest\` tag**" >> $GITHUB_STEP_SUMMARY