diff --git a/.github/ISSUE_TEMPLATE/upstream-sync.md b/.github/ISSUE_TEMPLATE/upstream-sync.md new file mode 100644 index 0000000..797e475 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/upstream-sync.md @@ -0,0 +1,33 @@ +--- +name: Upstream Sync Report +about: Auto-generated report for upstream sync +title: '🔄 Upstream Sync: {{ date | date("YYYY-MM-DD") }}' +labels: upstream-sync, automated +assignees: "" +--- + +## 🔄 Upstream 自動同步報告 + +**同步日期:** {{ date }} +**新 Commits:** {{ commit_count }} + +### 📝 變曎摘芁 + +``` +{{ commits_list }} +``` + +### 🐳 Docker Image + +- **Tag:** `upstream-{{ date_tag }}` +- **Smoke Test:** {{ smoke_test_status }} + +### ⏳ 埌續動䜜 + +- [ ] 檢芖變曎內容 +- [ ] 確認 smoke test 結果 +- [ ] 決定是吊 merge 到 main + +--- + +_æ­€ Issue 由 GitHub Actions 自動建立_ diff --git a/.github/UPSTREAM_SYNC.md b/.github/UPSTREAM_SYNC.md new file mode 100644 index 0000000..d5e4bd7 --- /dev/null +++ b/.github/UPSTREAM_SYNC.md @@ -0,0 +1,280 @@ +# 🔄 Upstream 自動同步機制 + +本專案寊䜜了完敎的 upstream 自動同步、變曎远蹀與 smoke test 機制。 + +## 📋 目錄 + +- [功胜抂述](#功胜抂述) +- [工䜜流皋圖](#工䜜流皋圖) +- [Workflow 說明](#workflow-說明) +- [Smoke Test 內容](#smoke-test-內容) +- [蚭定說明](#蚭定說明) +- [手動操䜜](#手動操䜜) + +--- + +## 功胜抂述 + +### 1⃣ 自動同步 Upstream + +| 功胜 | 說明 | +| ---------- | ---------------------------- | +| 觞癌方匏 | 每 6 小時自動檢查 / 手動觞癌 | +| 同步目暙 | `dev` 分支 | +| Merge 策略 | 自動 merge無衝突時 | +| 衝突處理 | 自動建立 GitHub Issue 通知 | + +### 2⃣ 變曎摘芁 + +同步完成埌自動產生 + +- ✅ GitHub Issue詳现變曎蚘錄 +- ✅ `upstream-changelog.md`环積變曎歷史 +- ✅ GitHub Actions Summary快速查看 + +### 3⃣ Smoke Test + +| 枬詊項目 | 內容 | 時間限制 | +| -------------- | -------------------------------------- | ------------- | +| Container 啟動 | 驗證 image 可正垞啟動 | 60s | +| 工具檢查 | libreoffice, pandoc, ffmpeg, tesseract | 30s | +| 最小蜉換 | txt → pdf | 60s | +| API 端點 | healthcheck, root | 10s | +| **瞜蚈** | | **< 10 分鐘** | + +--- + +## 工䜜流皋圖 + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ Upstream 自動同步流皋 │ +└─────────────────────────────────────────────────────────────────────────┘ + + ┌──────────────┐ + │ Upstream │ + │ (C4illin/ │ + │ ConvertX) │ + └──────┬───────┘ + │ + │ 每 6 小時檢查 + â–Œ + ┌──────────────┐ 無曎新 ┌──────────────┐ + │ 檢查是吊有 │ ─────────────► │ 結束 │ + │ 新 commits │ └──────────────┘ + └──────┬───────┘ + │ 有曎新 + â–Œ + ┌──────────────┐ 衝突 ┌──────────────┐ + │ 自動 Merge │ ─────────────► │ 建立 Issue │ + │ 到 dev 分支 │ │ 需手動處理 │ + └──────┬───────┘ └──────────────┘ + │ 成功 + â–Œ + ┌──────────────┐ + │ 產生變曎摘芁 │ + │ • Issue │ + │ • Changelog │ + └──────┬───────┘ + │ + â–Œ + ┌──────────────┐ + │ Push 到 dev │ + └──────┬───────┘ + │ + │ 觞癌 upstream-sync.yml + â–Œ + ┌──────────────┐ + │ Build 枬詊 │ + │ Image (amd64)│ + └──────┬───────┘ + │ + â–Œ + ┌──────────────────────────────────────────────────┐ + │ Smoke Test │ + │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ + │ │ Container │ │ 工具 │ │ 蜉換 │ │ + │ │ 啟動 │ │ 檢查 │ │ 枬詊 │ │ + │ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ │ + │ │ │ │ │ + │ └──────────────┌──────────────┘ │ + │ │ │ + └───────────────────────┌──────────────────────────┘ + │ + ┌─────────────┮─────────────┐ + │ │ + â–Œ â–Œ + ┌────────────┐ ┌────────────┐ + │ ✅ 通過 │ │ ❌ 倱敗 │ + └─────┬──────┘ └─────┬──────┘ + │ │ + â–Œ â–Œ + ┌────────────┐ ┌────────────┐ + │ Build 䞊 │ │ Workflow │ + │ Push 到 │ │ 倱敗 │ + │ Docker Hub │ │ (䞍癌垃) │ + └─────┬──────┘ └────────────┘ + │ + â–Œ + ┌────────────────────────┐ + │ upstream-YYYYMMDD tag │ + │ ❌ 䞍曎新 latest │ + │ ❌ 䞍打 semver tag │ + └────────────────────────┘ +``` + +--- + +## Workflow 說明 + +### `auto-upstream-sync.yml` + +**甚途** 自動檢枬䞊同步 upstream 曎新 + +**觞癌條件** + +- ⏰ 每 6 小時自動執行 +- 🖱 手動觞癌 + +**䞻芁步驟** + +1. Fetch upstream 最新皋匏碌 +2. 檢查是吊有新 commits +3. 自動 merge 到 `dev` 分支 +4. 產生變曎摘芁Issue + Changelog +5. Push 到 `dev` + +### `upstream-sync.yml` + +**甚途** 當 `dev` 分支有 push 時執行 build + smoke test + +**觞癌條件** + +- 📊 `dev` 分支有 push + +**䞻芁步驟** + +1. Build 枬詊甚 image僅 amd64加速枬詊 +2. 執行 Smoke Test10 分鐘內 +3. 枬詊通過埌 build multi-arch image +4. Push 到 Docker Hubtag: `upstream-YYYYMMDD` + +--- + +## Smoke Test 內容 + +### Test 1: Container 啟動枬詊 + +```bash +# 啟動 container 䞊等埅 healthcheck 回應 +docker run -d --name convertx-test $IMAGE +curl http://localhost:3000/healthcheck +``` + +### Test 2: 關鍵工具檢查 + +```bash +# 必須通過任䞀倱敗則敎體倱敗 +libreoffice --version +pandoc --version +ffmpeg -version +tesseract --version +``` + +### Test 3: 最小蜉換枬詊 + +```bash +# txt → pdf 蜉換枬詊 +echo "test" > test.txt +libreoffice --headless --convert-to pdf test.txt +``` + +### Test 4: API 端點檢查 + +```bash +# 確認服務正垞運䜜 +curl http://localhost:3000/healthcheck +curl http://localhost:3000/ +``` + +--- + +## 蚭定說明 + +### 必芁的 GitHub Secrets + +圚 Repository Settings → Secrets and variables → Actions 䞭蚭定 + +| Secret 名皱 | 說明 | +| -------------------- | ----------------------- | +| `DOCKERHUB_USERNAME` | Docker Hub 垳號 | +| `DOCKERHUB_TOKEN` | Docker Hub Access Token | + +### 分支保護芏則 + +建議蚭定 + +**`main` 分支** + +- ✅ Require pull request before merging +- ✅ Require status checks to pass +- ❌ Allow force pushes + +**`dev` 分支** + +- ✅ Allow direct pushes (for automation) + +--- + +## 手動操䜜 + +### 手動觞癌同步 + +1. 前埀 Actions → Auto Upstream Sync +2. 點遞 "Run workflow" +3. 可遞擇「匷制同步」 + +### 手動處理 Merge 衝突 + +當自動同步癌生衝突時 + +```bash +# 1. 切換到 dev 分支 +git checkout dev + +# 2. 添加 upstream remote劂果還沒有 +git remote add upstream https://github.com/C4illin/ConvertX.git + +# 3. Fetch upstream +git fetch upstream main + +# 4. Merge upstream +git merge upstream/main + +# 5. 解決衝突 +# ... 線茯衝突的檔案 ... + +# 6. 提亀䞊 push +git add . +git commit -m "Resolve merge conflicts with upstream" +git push origin dev +``` + +--- + +## ⚠ 泚意事項 + +1. **䞍會自動曎新 `latest` tag** - 需芁手動癌垃正匏版本 +2. **䞍會自動打 semver tag** - 需芁手動建立 release +3. **`main` 分支䞍會被自動修改** - 只有 `dev` 會自動同步 +4. **Smoke test 倱敗時䞍會癌垃 image** - 確保品質 + +--- + +## 📊 Docker Image Tag 芏則 + +| Tag 栌匏 | 說明 | 自動/手動 | +| ------------------- | ---------------------------------- | --------- | +| `upstream-YYYYMMDD` | Upstream 同步版經過 smoke test | 自動 | +| `vX.Y.Z` | 正匏版本 | 手動 | +| `latest` | 最新穩定版 | 手動 | diff --git a/.github/scripts/smoke-test.sh b/.github/scripts/smoke-test.sh new file mode 100644 index 0000000..1763d2b --- /dev/null +++ b/.github/scripts/smoke-test.sh @@ -0,0 +1,238 @@ +#!/bin/bash +# ============================================================================== +# ConvertX Smoke Test Script +# 甚斌驗證 Docker image 的基本功胜 +# ============================================================================== + +set -e + +CONTAINER_NAME="${CONTAINER_NAME:-convertx-test}" +TEST_TIMEOUT="${TEST_TIMEOUT:-60}" + +echo "==================================================" +echo "🧪 ConvertX Smoke Test" +echo "==================================================" +echo "" + +# 顏色定矩 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +pass() { + echo -e "${GREEN}✅ PASS${NC}: $1" +} + +fail() { + echo -e "${RED}❌ FAIL${NC}: $1" + exit 1 +} + +warn() { + echo -e "${YELLOW}⚠ WARN${NC}: $1" +} + +# ============================================================================== +# Test 1: Container 啟動枬詊 +# ============================================================================== +test_container_startup() { + echo "" + echo "📊 Test 1: Container Startup" + echo "----------------------------" + + echo "Waiting for container to be healthy..." + + for i in $(seq 1 $TEST_TIMEOUT); do + if docker exec $CONTAINER_NAME curl -sf http://localhost:3000/healthcheck > /dev/null 2>&1; then + pass "Container started in ${i}s" + return 0 + fi + sleep 1 + done + + fail "Container failed to start within ${TEST_TIMEOUT}s" +} + +# ============================================================================== +# Test 2: 關鍵工具存圚性檢查 +# ============================================================================== +test_critical_tools() { + echo "" + echo "🔧 Test 2: Critical Tools Availability" + echo "---------------------------------------" + + local failed=0 + + # LibreOffice (必芁) + echo -n " libreoffice: " + if docker exec $CONTAINER_NAME libreoffice --version > /dev/null 2>&1; then + VERSION=$(docker exec $CONTAINER_NAME libreoffice --version 2>/dev/null | head -1) + echo -e "${GREEN}OK${NC} ($VERSION)" + else + echo -e "${RED}MISSING${NC}" + failed=1 + fi + + # Pandoc (必芁) + echo -n " pandoc: " + if docker exec $CONTAINER_NAME pandoc --version > /dev/null 2>&1; then + VERSION=$(docker exec $CONTAINER_NAME pandoc --version 2>/dev/null | head -1) + echo -e "${GREEN}OK${NC} ($VERSION)" + else + echo -e "${RED}MISSING${NC}" + failed=1 + fi + + # FFmpeg (必芁) + echo -n " ffmpeg: " + if docker exec $CONTAINER_NAME ffmpeg -version > /dev/null 2>&1; then + VERSION=$(docker exec $CONTAINER_NAME ffmpeg -version 2>/dev/null | head -1 | awk '{print $3}') + echo -e "${GREEN}OK${NC} (v$VERSION)" + else + echo -e "${RED}MISSING${NC}" + failed=1 + fi + + # Tesseract (必芁) + echo -n " tesseract: " + if docker exec $CONTAINER_NAME tesseract --version > /dev/null 2>&1; then + VERSION=$(docker exec $CONTAINER_NAME tesseract --version 2>/dev/null | head -1) + echo -e "${GREEN}OK${NC} ($VERSION)" + else + echo -e "${RED}MISSING${NC}" + failed=1 + fi + + echo "" + echo " Additional tools (optional):" + + # ImageMagick + echo -n " imagemagick: " + if docker exec $CONTAINER_NAME magick -version > /dev/null 2>&1; then + echo -e "${GREEN}OK${NC}" + else + echo -e "${YELLOW}Not found${NC}" + fi + + # Inkscape + echo -n " inkscape: " + if docker exec $CONTAINER_NAME inkscape --version > /dev/null 2>&1; then + echo -e "${GREEN}OK${NC}" + else + echo -e "${YELLOW}Not found${NC}" + fi + + # GraphicsMagick + echo -n " graphicsmagick: " + if docker exec $CONTAINER_NAME gm version > /dev/null 2>&1; then + echo -e "${GREEN}OK${NC}" + else + echo -e "${YELLOW}Not found${NC}" + fi + + # Calibre + echo -n " calibre: " + if docker exec $CONTAINER_NAME ebook-convert --version > /dev/null 2>&1; then + echo -e "${GREEN}OK${NC}" + else + echo -e "${YELLOW}Not found${NC}" + fi + + echo "" + + if [ $failed -eq 1 ]; then + fail "Critical tools check failed" + else + pass "All critical tools available" + fi +} + +# ============================================================================== +# Test 3: 最小蜉換枬詊 +# ============================================================================== +test_minimal_conversion() { + echo "" + echo "📄 Test 3: Minimal Conversion" + echo "-----------------------------" + + # 圚 container 內建立枬詊檔案䞊蜉換 + echo " Creating test file..." + docker exec $CONTAINER_NAME sh -c "echo 'ConvertX Smoke Test - $(date)' > /tmp/test.txt" + + echo " Converting txt → pdf using LibreOffice..." + if docker exec $CONTAINER_NAME sh -c "cd /tmp && libreoffice --headless --convert-to pdf test.txt" > /dev/null 2>&1; then + # 檢查茞出檔案 + if docker exec $CONTAINER_NAME test -f /tmp/test.pdf; then + SIZE=$(docker exec $CONTAINER_NAME stat -c%s /tmp/test.pdf 2>/dev/null || echo "unknown") + pass "Conversion successful (output: ${SIZE} bytes)" + else + fail "Conversion failed - output file not found" + fi + else + fail "LibreOffice conversion command failed" + fi + + # 枅理 + docker exec $CONTAINER_NAME rm -f /tmp/test.txt /tmp/test.pdf 2>/dev/null || true +} + +# ============================================================================== +# Test 4: API 端點檢查 +# ============================================================================== +test_api_endpoints() { + echo "" + echo "🌐 Test 4: API Endpoints" + echo "------------------------" + + local failed=0 + + # Healthcheck + echo -n " GET /healthcheck: " + if docker exec $CONTAINER_NAME curl -sf http://localhost:3000/healthcheck > /dev/null 2>&1; then + echo -e "${GREEN}200 OK${NC}" + else + echo -e "${RED}FAILED${NC}" + failed=1 + fi + + # Root + echo -n " GET /: " + if docker exec $CONTAINER_NAME curl -sf http://localhost:3000/ > /dev/null 2>&1; then + echo -e "${GREEN}200 OK${NC}" + else + echo -e "${RED}FAILED${NC}" + failed=1 + fi + + echo "" + + if [ $failed -eq 1 ]; then + fail "API endpoints check failed" + else + pass "All API endpoints responding" + fi +} + +# ============================================================================== +# Main +# ============================================================================== +main() { + local start_time=$(date +%s) + + test_container_startup + test_critical_tools + test_minimal_conversion + test_api_endpoints + + local end_time=$(date +%s) + local duration=$((end_time - start_time)) + + echo "" + echo "==================================================" + echo -e "🎉 ${GREEN}All smoke tests passed!${NC}" + echo " Total time: ${duration}s" + echo "==================================================" +} + +main "$@" diff --git a/.github/test-files/test.txt b/.github/test-files/test.txt new file mode 100644 index 0000000..8f9696f --- /dev/null +++ b/.github/test-files/test.txt @@ -0,0 +1,6 @@ +Hello, this is a smoke test file for ConvertX. +這是 ConvertX 的冒煙枬詊檔案。 +日本語テストこんにちは +한국얎 테슀튞: 안녕하섞요 + +This file should be less than 1KB for quick testing. diff --git a/.github/workflows/auto-upstream-sync.yml b/.github/workflows/auto-upstream-sync.yml new file mode 100644 index 0000000..1716491 --- /dev/null +++ b/.github/workflows/auto-upstream-sync.yml @@ -0,0 +1,281 @@ +# ============================================================================== +# 自動同步 Upstream Repository +# 功胜 +# 1. 定時檢查 upstream 曎新 +# 2. 自動 merge 到 dev 分支 +# 3. 產生變曎摘芁Change Summary +# 4. 觞癌埌續的 build + smoke test +# ============================================================================== + +name: Auto Upstream Sync + +on: + # 每 6 小時檢查䞀次 upstream + schedule: + - cron: "0 */6 * * *" + # 手動觞癌 + workflow_dispatch: + inputs: + force_sync: + description: "匷制同步即䜿無新 commit" + type: boolean + default: false + +env: + UPSTREAM_REPO: https://github.com/C4illin/ConvertX.git + TARGET_BRANCH: dev + UPSTREAM_BRANCH: main + +permissions: + contents: write + issues: write + +jobs: + check-and-sync: + name: Check & Sync Upstream + runs-on: ubuntu-latest + outputs: + has_updates: ${{ steps.check.outputs.has_updates }} + new_commits: ${{ steps.check.outputs.new_commits }} + commit_count: ${{ steps.check.outputs.commit_count }} + sync_date: ${{ steps.date.outputs.date }} + changelog: ${{ steps.changelog.outputs.changelog }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ env.TARGET_BRANCH }} + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Get current date + id: date + run: echo "date=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT + + - name: Configure Git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Add upstream remote + run: | + git remote add upstream ${{ env.UPSTREAM_REPO }} || true + git fetch upstream ${{ env.UPSTREAM_BRANCH }} + + - name: Check for upstream updates + id: check + run: | + # 取埗本地 dev 分支的最埌䞀次 upstream merge commit + # 我們甚 upstream/main 與目前 HEAD 比范 + + LOCAL_HEAD=$(git rev-parse HEAD) + UPSTREAM_HEAD=$(git rev-parse upstream/${{ env.UPSTREAM_BRANCH }}) + + echo "Local HEAD: $LOCAL_HEAD" + echo "Upstream HEAD: $UPSTREAM_HEAD" + + # 檢查 upstream 是吊有新的 commits + MERGE_BASE=$(git merge-base HEAD upstream/${{ env.UPSTREAM_BRANCH }}) + echo "Merge base: $MERGE_BASE" + + if [ "$MERGE_BASE" = "$UPSTREAM_HEAD" ]; then + echo "✅ Already up to date with upstream" + echo "has_updates=false" >> $GITHUB_OUTPUT + echo "commit_count=0" >> $GITHUB_OUTPUT + else + # 蚈算新的 commits 敞量 + NEW_COMMITS=$(git rev-list --count $MERGE_BASE..$UPSTREAM_HEAD) + echo "🔄 Found $NEW_COMMITS new commits from upstream" + echo "has_updates=true" >> $GITHUB_OUTPUT + echo "commit_count=$NEW_COMMITS" >> $GITHUB_OUTPUT + + # 取埗新 commits 的列衚 + COMMITS_LIST=$(git log --oneline $MERGE_BASE..$UPSTREAM_HEAD) + echo "new_commits<> $GITHUB_OUTPUT + echo "$COMMITS_LIST" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + fi + + - name: Generate changelog before merge + id: changelog + if: steps.check.outputs.has_updates == 'true' || github.event.inputs.force_sync == 'true' + run: | + MERGE_BASE=$(git merge-base HEAD upstream/${{ env.UPSTREAM_BRANCH }}) + + echo "## 📋 Upstream 變曎摘芁" > changelog.md + echo "" >> changelog.md + echo "**同步時間:** $(date +'%Y-%m-%d %H:%M:%S UTC')" >> changelog.md + echo "**Upstream 分支:** ${{ env.UPSTREAM_BRANCH }}" >> changelog.md + echo "**新 Commits 敞量:** ${{ steps.check.outputs.commit_count }}" >> changelog.md + echo "" >> changelog.md + + echo "### 📝 Commit 列衚" >> changelog.md + echo "" >> changelog.md + echo "\`\`\`" >> changelog.md + git log --oneline --no-merges $MERGE_BASE..upstream/${{ env.UPSTREAM_BRANCH }} >> changelog.md + echo "\`\`\`" >> changelog.md + echo "" >> changelog.md + + echo "### 📊 變曎統蚈" >> changelog.md + echo "" >> changelog.md + echo "\`\`\`" >> changelog.md + git diff --stat $MERGE_BASE..upstream/${{ env.UPSTREAM_BRANCH }} >> changelog.md + echo "\`\`\`" >> changelog.md + echo "" >> changelog.md + + echo "### 🔍 變曎的檔案" >> changelog.md + echo "" >> changelog.md + git diff --name-status $MERGE_BASE..upstream/${{ env.UPSTREAM_BRANCH }} | while read line; do + STATUS=$(echo "$line" | awk '{print $1}') + FILE=$(echo "$line" | awk '{print $2}') + case $STATUS in + A) echo "- ✅ **新增** \`$FILE\`" >> changelog.md ;; + M) echo "- ✏ **修改** \`$FILE\`" >> changelog.md ;; + D) echo "- ❌ **刪陀** \`$FILE\`" >> changelog.md ;; + R*) echo "- 🔄 **重新呜名** \`$FILE\`" >> changelog.md ;; + *) echo "- 📄 \`$FILE\` ($STATUS)" >> changelog.md ;; + esac + done + + cat changelog.md + + # 茞出絊埌續步驟䜿甚 + CHANGELOG_CONTENT=$(cat changelog.md) + echo "changelog<> $GITHUB_OUTPUT + echo "$CHANGELOG_CONTENT" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Merge upstream changes + id: merge + if: steps.check.outputs.has_updates == 'true' || github.event.inputs.force_sync == 'true' + run: | + echo "🔄 Merging upstream/${{ env.UPSTREAM_BRANCH }} into ${{ env.TARGET_BRANCH }}..." + + # 嘗詊自動 merge + if git merge upstream/${{ env.UPSTREAM_BRANCH }} --no-edit -m "🔄 Auto-merge upstream changes ($(date +'%Y-%m-%d'))"; then + echo "✅ Merge successful!" + echo "merge_success=true" >> $GITHUB_OUTPUT + else + echo "❌ Merge conflict detected!" + echo "merge_success=false" >> $GITHUB_OUTPUT + + # 取消 merge + git merge --abort + + # 建立 conflict issue + exit 1 + fi + + - name: Push changes + if: steps.merge.outputs.merge_success == 'true' + run: | + git push origin ${{ env.TARGET_BRANCH }} + echo "✅ Changes pushed to ${{ env.TARGET_BRANCH }}" + + - name: Commit changelog + if: steps.merge.outputs.merge_success == 'true' + run: | + # 曎新 upstream-changelog.md + if [ -f upstream-changelog.md ]; then + # 圚檔案開頭插入新的 changelog + echo "" >> changelog.md + echo "---" >> changelog.md + echo "" >> changelog.md + cat upstream-changelog.md >> changelog.md + fi + + mv changelog.md upstream-changelog.md + git add upstream-changelog.md + git commit -m "📋 Update upstream changelog (${{ steps.date.outputs.date }})" || true + git push origin ${{ env.TARGET_BRANCH }} || true + + - name: Create GitHub Issue for sync summary + if: steps.merge.outputs.merge_success == 'true' && steps.check.outputs.commit_count > 0 + uses: actions/github-script@v7 + with: + script: | + const date = '${{ steps.date.outputs.date }}'; + const commitCount = '${{ steps.check.outputs.commit_count }}'; + + const body = `## 🔄 Upstream 自動同步完成 + + **同步日期:** ${date} + **新 Commits:** ${commitCount} 個 + **目暙分支:** \`dev\` + + ### 📝 變曎摘芁 + + \`\`\` + ${{ steps.check.outputs.new_commits }} + \`\`\` + + ### ⏳ 埌續動䜜 + + - [ ] Smoke test 執行䞭... + - [ ] Docker image 建構䞭 (\`upstream-${date}\`) + + --- + *æ­€ Issue 由 GitHub Actions 自動建立* + `; + + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: `🔄 Upstream Sync: ${date} (${commitCount} commits)`, + body: body, + labels: ['upstream-sync', 'automated'] + }); + + - name: Create Issue for merge conflict + if: failure() && steps.merge.outputs.merge_success == 'false' + uses: actions/github-script@v7 + with: + script: | + const date = '${{ steps.date.outputs.date }}'; + + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: `⚠ Upstream Sync 衝突: ${date}`, + body: `## ⚠ Upstream 同步癌生衝突 + + 需芁手動解決 merge conflict。 + + ### 處理步驟 + + \`\`\`bash + git fetch upstream main + git checkout dev + git merge upstream/main + # 解決衝突埌 + git add . + git commit + git push origin dev + \`\`\` + + --- + *æ­€ Issue 由 GitHub Actions 自動建立* + `, + labels: ['upstream-sync', 'merge-conflict', 'needs-attention'] + }); + + - name: Summary + if: always() + run: | + echo "## 🔄 Upstream Sync Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| 項目 | 狀態 |" >> $GITHUB_STEP_SUMMARY + echo "|------|------|" >> $GITHUB_STEP_SUMMARY + echo "| 檢查時間 | $(date +'%Y-%m-%d %H:%M:%S UTC') |" >> $GITHUB_STEP_SUMMARY + echo "| 有新曎新 | ${{ steps.check.outputs.has_updates }} |" >> $GITHUB_STEP_SUMMARY + echo "| 新 Commits | ${{ steps.check.outputs.commit_count }} |" >> $GITHUB_STEP_SUMMARY + echo "| Merge 成功 | ${{ steps.merge.outputs.merge_success || 'N/A' }} |" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ "${{ steps.check.outputs.has_updates }}" == "true" ]; then + echo "### 📝 New Commits" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "${{ steps.check.outputs.new_commits }}" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + fi diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index fb07400..255ffdc 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -51,6 +51,33 @@ jobs: - name: Checkout repository uses: actions/checkout@v6 + # ======================================== + # 枅理磁碟空間解決 no space left on device + # ======================================== + - name: Free disk space + run: | + echo "🧹 Cleaning up disk space..." + df -h + + # 移陀䞍需芁的預裝軟體 + 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/CodeQL || true + sudo rm -rf /usr/local/share/boost || true + sudo rm -rf /usr/share/swift || true + sudo rm -rf /opt/hostedtoolcache || true + + # 枅理 apt cache + sudo apt-get clean || true + sudo apt-get autoremove -y || true + + # 枅理 Docker 舊資料 + docker system prune -af --volumes || true + + echo "After cleanup:" + df -h + - name: downcase REPO run: | echo "REPO=${GITHUB_REPOSITORY@L}" >> "${GITHUB_ENV}" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 98e21de..d75e10a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,7 +3,7 @@ name: Release on: push: tags: - - 'v*.*.*' + - "v*.*.*" env: DOCKER_IMAGE: convertx/convertx-cn @@ -11,15 +11,45 @@ env: jobs: build-and-push: runs-on: ubuntu-latest - + steps: - name: Checkout repository uses: actions/checkout@v4 + # ======================================== + # 枅理磁碟空間解決 no space left on device + # ======================================== + - name: Free disk space + run: | + echo "🧹 Cleaning up disk space..." + 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 "After cleanup:" + df -h + - name: Get tag name id: tag run: echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -54,7 +84,7 @@ jobs: needs: build-and-push permissions: contents: write - + steps: - name: Checkout repository uses: actions/checkout@v4 @@ -70,7 +100,7 @@ jobs: run: | # Get previous tag PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "") - + if [ -z "$PREVIOUS_TAG" ]; then # No previous tag, get all commits CHANGELOG=$(git log --pretty=format:"- %s (%h)" HEAD) @@ -78,10 +108,10 @@ jobs: # Get commits between previous tag and current CHANGELOG=$(git log --pretty=format:"- %s (%h)" ${PREVIOUS_TAG}..HEAD) fi - + # Write to file to preserve newlines echo "$CHANGELOG" > changelog.txt - + - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: diff --git a/.github/workflows/upstream-sync.yml b/.github/workflows/upstream-sync.yml index e1db9c9..350e4b2 100644 --- a/.github/workflows/upstream-sync.yml +++ b/.github/workflows/upstream-sync.yml @@ -1,3 +1,12 @@ +# ============================================================================== +# Upstream Sync Build + Smoke Test +# 功胜 +# 1. dev 分支有 push 時自動觞癌 +# 2. 建構 Docker image僅 amd64 甚斌枬詊 +# 3. 執行 smoke test10 分鐘內完成 +# 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 diff --git a/Dockerfile b/Dockerfile index 4fb5dee..716d182 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,26 +1,28 @@ # ============================================================================== -# ConvertX-CN 完敎版 Dockerfile -# 內建所有蜉換䟝賎LibreOffice / TexLive Full / OCR / CJK 字型 -# 支揎 linux/amd64, linux/arm64 multi-arch build +# ConvertX-CN 粟簡版 Dockerfile +# 優化版本移陀 texlive-full粟簡字型與語蚀支揎 +# 目暙圚 GitHub Actions 䞭穩定建構解決 no space left on device +# 支揎語蚀䞭文繁/簡、日文、韓文、英文、執文、法文 # ============================================================================== FROM debian:trixie-slim AS base LABEL org.opencontainers.image.source="https://github.com/pi-docket/ConvertX-CN" -LABEL org.opencontainers.image.description="ConvertX-CN - 完敎版檔案蜉換服務內建所有䟝賎" +LABEL org.opencontainers.image.description="ConvertX-CN - 粟簡版檔案蜉換服務" WORKDIR /app # install bun -RUN apt-get update && apt-get install -y \ +RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ unzip \ + ca-certificates \ && rm -rf /var/lib/apt/lists/* # if architecture is arm64, use the arm64 version of bun RUN ARCH=$(uname -m) && \ if [ "$ARCH" = "aarch64" ]; then \ - curl -fsSL -o bun-linux-aarch64.zip https://github.com/oven-sh/bun/releases/download/bun-v1.2.2/bun-linux-aarch64.zip; \ + curl -fsSL -o bun-linux-aarch64.zip https://github.com/oven-sh/bun/releases/download/bun-v1.2.2/bun-linux-aarch64.zip; \ else \ - curl -fsSL -o bun-linux-x64-baseline.zip https://github.com/oven-sh/bun/releases/download/bun-v1.2.2/bun-linux-x64-baseline.zip; \ + curl -fsSL -o bun-linux-x64-baseline.zip https://github.com/oven-sh/bun/releases/download/bun-v1.2.2/bun-linux-x64-baseline.zip; \ fi RUN unzip -j bun-linux-*.zip -d /usr/local/bin && \ @@ -51,8 +53,9 @@ RUN bun run build FROM base AS release # ============================================================================== -# 完敎䟝賎安裝單䞀 RUN 局優化 cache -# 包含蜉換工具 + TexLive Full + LibreOffice + OCR + CJK 字型 +# 粟簡䟝賎安裝單䞀 RUN 局優化 cache 與空間 +# ❌ 已移陀texlive-full, fonts-noto-extra, 倚逘語蚀包 +# ✅ 保留栞心蜉換工具 + 最小 TexLive + 必芁字型 # ============================================================================== RUN apt-get update && apt-get install -y --no-install-recommends \ # === 基瀎蜉換工具 === @@ -77,13 +80,34 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ resvg \ # === LibreOffice (headless) === libreoffice \ - # === TexLive 完敎版支揎所有 LaTeX 需求=== - texlive-full \ + # === TexLive 最小集合取代 texlive-full=== + # texlive-base: LaTeX 栞心 + # texlive-latex-base: 基本 LaTeX 類別 + # texlive-latex-recommended: 垞甚套件geometry, hyperref 等 + # texlive-fonts-recommended: 基本字型Computer Modern 等 + # texlive-xetex: XeTeX 匕擎Unicode/CJK 支揎必需 + # texlive-lang-cjk: 䞭日韓 LaTeX 支揎 + # texlive-lang-german: 執文 LaTeX 支揎 + # texlive-lang-french: 法文 LaTeX 支揎 + texlive-base \ + texlive-latex-base \ + texlive-latex-recommended \ + texlive-fonts-recommended \ + texlive-xetex \ + texlive-lang-cjk \ + texlive-lang-german \ + texlive-lang-french \ latexmk \ lmodern \ # === Pandoc 文件蜉換 === pandoc \ - # === OCR 支揎Tesseract + 倚語蚀包=== + # === OCR 支揎僅限指定語蚀=== + # eng: 英文 + # chi_tra/chi_sim: 繁/ç°¡äž­æ–‡ + # jpn: 日文 + # kor: 韓文 + # deu: 執文 + # fra: 法文 tesseract-ocr \ tesseract-ocr-eng \ tesseract-ocr-chi-tra \ @@ -91,41 +115,58 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ tesseract-ocr-jpn \ tesseract-ocr-kor \ tesseract-ocr-deu \ - # === CJK 字型䞭日韓完敎支揎=== + tesseract-ocr-fra \ + # === 字型粟簡版=== + # fonts-noto-cjk: 䞭日韓統䞀字型必需 + # fonts-noto-core: Noto Sans/Serif Latin歐語基瀎 + # fonts-noto-color-emoji: Emoji 支揎僅歀䞀套 + # fonts-liberation: Liberation 字型Arial/Times 替代 + # ❌ 已移陀fonts-noto-extra包含過倚語蚀 + # ❌ 已移陀fonts-liberation2重耇 fonts-noto-cjk \ fonts-noto-core \ - fonts-noto-extra \ fonts-noto-color-emoji \ - # === Liberation 字型埮軟字型開源替代=== fonts-liberation \ - fonts-liberation2 \ - # === Python 䟝賎 === + # === Python 䟝賎粟簡=== python3 \ python3-pip \ python3-numpy \ python3-tinycss2 \ pipx \ # === 系統工具 === - ca-certificates \ locales \ + # === 枅理 === && pipx install "markitdown[all]" \ + # 枅理 apt cache && apt-get clean \ - && rm -rf /var/lib/apt/lists/* + && rm -rf /var/lib/apt/lists/* \ + # 枅理 pip cache + && rm -rf /root/.cache/pip \ + # 枅理 TexLive 文件節省空間 + && rm -rf /usr/share/doc/texlive* \ + && rm -rf /usr/share/texlive/texmf-dist/doc \ + # 枅理其他文件 + && rm -rf /usr/share/doc/* \ + && rm -rf /usr/share/man/* \ + && rm -rf /usr/share/info/* # Add pipx bin directory to PATH ENV PATH="/root/.local/bin:${PATH}" # ============================================================================== -# 蚭定 locale避免䞭文 PDF 亂碌 +# 蚭定 locale僅限指定語蚀 # ============================================================================== -RUN sed -i 's/# zh_TW.UTF-8 UTF-8/zh_TW.UTF-8 UTF-8/' /etc/locale.gen && \ - sed -i 's/# zh_CN.UTF-8 UTF-8/zh_CN.UTF-8 UTF-8/' /etc/locale.gen && \ - sed -i 's/# ja_JP.UTF-8 UTF-8/ja_JP.UTF-8 UTF-8/' /etc/locale.gen && \ - sed -i 's/# ko_KR.UTF-8 UTF-8/ko_KR.UTF-8 UTF-8/' /etc/locale.gen && \ - locale-gen +RUN sed -i 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \ + sed -i 's/# zh_TW.UTF-8 UTF-8/zh_TW.UTF-8 UTF-8/' /etc/locale.gen && \ + sed -i 's/# zh_CN.UTF-8 UTF-8/zh_CN.UTF-8 UTF-8/' /etc/locale.gen && \ + sed -i 's/# ja_JP.UTF-8 UTF-8/ja_JP.UTF-8 UTF-8/' /etc/locale.gen && \ + sed -i 's/# ko_KR.UTF-8 UTF-8/ko_KR.UTF-8 UTF-8/' /etc/locale.gen && \ + sed -i 's/# de_DE.UTF-8 UTF-8/de_DE.UTF-8 UTF-8/' /etc/locale.gen && \ + sed -i 's/# fr_FR.UTF-8 UTF-8/fr_FR.UTF-8 UTF-8/' /etc/locale.gen && \ + locale-gen -ENV LANG=zh_TW.UTF-8 -ENV LC_ALL=zh_TW.UTF-8 +ENV LANG=en_US.UTF-8 +ENV LC_ALL=en_US.UTF-8 # ============================================================================== # 安裝自蚂字型暙楷體等台灣垞甚字型 @@ -139,9 +180,9 @@ RUN fc-cache -fv # ============================================================================== RUN ARCH=$(uname -m) && \ if [ "$ARCH" = "aarch64" ]; then \ - VTRACER_ASSET="vtracer-aarch64-unknown-linux-musl.tar.gz"; \ + VTRACER_ASSET="vtracer-aarch64-unknown-linux-musl.tar.gz"; \ else \ - VTRACER_ASSET="vtracer-x86_64-unknown-linux-musl.tar.gz"; \ + VTRACER_ASSET="vtracer-x86_64-unknown-linux-musl.tar.gz"; \ fi && \ curl -L -o /tmp/vtracer.tar.gz "https://github.com/visioncortex/vtracer/releases/download/0.6.4/${VTRACER_ASSET}" && \ tar -xzf /tmp/vtracer.tar.gz -C /tmp/ && \ diff --git a/README.md b/README.md index f6564bf..887334f 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![GitHub Release](https://img.shields.io/github/v/release/pi-docket/ConvertX-CN)](https://github.com/pi-docket/ConvertX-CN/releases) > 🎉 **這是完敎版 ConvertX-CN image已內建所有蜉換䟝賎** -> +> > 䜿甚者 **䞍需芁自己寫 Dockerfile**盎接 `docker run` 或 `docker compose up` 即可䜿甚。 基斌 [C4illin/ConvertX](https://github.com/C4illin/ConvertX) 的䞭文優化版本。 @@ -18,16 +18,16 @@ æ­€ image 已經內建以䞋所有䟝賎開箱即甚 -| 類別 | 內建內容 | -|------|----------| -| **文件蜉換** | LibreOffice (headless)、Pandoc | -| **LaTeX** | TexLive Full完敎版支揎所有 LaTeX 需求 | +| 類別 | 內建內容 | +| ------------ | ---------------------------------------------------------------- | +| **文件蜉換** | LibreOffice (headless)、Pandoc | +| **LaTeX** | TexLive Full完敎版支揎所有 LaTeX 需求 | | **OCR 識別** | Tesseract OCR + 繁體䞭文、簡體䞭文、日文、韓文、英文、執文語蚀包 | -| **CJK 字型** | Noto CJK䞭日韓、Noto Emoji、埮軟栞心字型、暙楷體 | -| **圱音蜉換** | FFmpeg、ImageMagick、GraphicsMagick | -| **向量圖圢** | Inkscape、Potrace、VTracer、resvg | -| **電子曞** | Calibre | -| **其他** | Ghostscript、MuPDF、Poppler、libheif、libjxl 等 | +| **CJK 字型** | Noto CJK䞭日韓、Noto Emoji、埮軟栞心字型、暙楷體 | +| **圱音蜉換** | FFmpeg、ImageMagick、GraphicsMagick | +| **向量圖圢** | Inkscape、Potrace、VTracer、resvg | +| **電子曞** | Calibre | +| **其他** | Ghostscript、MuPDF、Poppler、libheif、libjxl 等 | --- @@ -78,10 +78,10 @@ docker compose up -d ## 📊 Docker Image -| Image | 說明 | -|-------|------| +| Image | 說明 | +| ----------------------------- | ---------- | | `convertx/convertx-cn:latest` | 最新穩定版 | -| `convertx/convertx-cn:v0.1.1` | 指定版本 | +| `convertx/convertx-cn:v0.1.1` | 指定版本 | > ⚠ 由斌內建完敎䟝賎image 倧小玄 4-6 GB銖次䞋茉需芁范長時間。 @@ -122,20 +122,20 @@ docker compose up -d 所有環境變敞皆為遞填建議蚭定 `JWT_SECRET`。 -| 變敞名皱 | 預蚭倌 | 說明 | -|----------|--------|------| -| JWT_SECRET | randomUUID() | 甚斌簜眲 JWT 的密鑰字䞲 | -| ACCOUNT_REGISTRATION | false | 是吊允蚱蚻冊新垳號 | -| HTTP_ALLOWED | false | 是吊允蚱 HTTP 連線僅本地䜿甚 | -| ALLOW_UNAUTHENTICATED | false | 是吊允蚱未登入䜿甚 | -| AUTO_DELETE_EVERY_N_HOURS | 24 | 自動刪陀超過 N 小時的檔案0 = 停甚 | -| WEBROOT | | 子路埑郚眲䟋劂 `/convertx` | -| FFMPEG_ARGS | | FFmpeg 茞入參敞䟋劂 `-hwaccel vaapi` | -| FFMPEG_OUTPUT_ARGS | | FFmpeg 茞出參敞䟋劂 `-preset veryfast` | -| HIDE_HISTORY | false | 隱藏歷史玀錄頁面 | -| LANGUAGE | en | 日期栌匏語蚀BCP 47 栌匏 | -| TZ | UTC | 時區蚭定 | -| MAX_CONVERT_PROCESS | 0 | 最倧同時蜉換敞0 = 無限制 | +| 變敞名皱 | 預蚭倌 | 說明 | +| ------------------------- | ------------ | ---------------------------------------- | +| JWT_SECRET | randomUUID() | 甚斌簜眲 JWT 的密鑰字䞲 | +| ACCOUNT_REGISTRATION | false | 是吊允蚱蚻冊新垳號 | +| HTTP_ALLOWED | false | 是吊允蚱 HTTP 連線僅本地䜿甚 | +| ALLOW_UNAUTHENTICATED | false | 是吊允蚱未登入䜿甚 | +| AUTO_DELETE_EVERY_N_HOURS | 24 | 自動刪陀超過 N 小時的檔案0 = 停甚 | +| WEBROOT | | 子路埑郚眲䟋劂 `/convertx` | +| FFMPEG_ARGS | | FFmpeg 茞入參敞䟋劂 `-hwaccel vaapi` | +| FFMPEG_OUTPUT_ARGS | | FFmpeg 茞出參敞䟋劂 `-preset veryfast` | +| HIDE_HISTORY | false | 隱藏歷史玀錄頁面 | +| LANGUAGE | en | 日期栌匏語蚀BCP 47 栌匏 | +| TZ | UTC | 時區蚭定 | +| MAX_CONVERT_PROCESS | 0 | 最倧同時蜉換敞0 = 無限制 | ---