|
|
name: fork-build |
|
|
|
|
|
on: |
|
|
workflow_dispatch: |
|
|
|
|
|
|
|
|
|
|
|
env: |
|
|
REGISTRY: ghcr.io |
|
|
REPO_LOWER: ${{ github.repository_owner }}/${{ github.event.repository.name }} |
|
|
GHCR_REPO: ghcr.io/${{ github.repository }} |
|
|
WIN_EXE_PYTHON_VERSION: 3.12.9 |
|
|
jobs: |
|
|
check-repository: |
|
|
name: Check if running in main repository |
|
|
runs-on: ubuntu-latest |
|
|
outputs: |
|
|
is_main_repo: ${{ github.repository == 'Byaidu/PDFMathTranslate' }} |
|
|
steps: |
|
|
- run: echo "Running repository check" |
|
|
|
|
|
test: |
|
|
uses: ./.github/workflows/python-test.yml |
|
|
needs: check-repository |
|
|
if: needs.check-repository.outputs.is_main_repo != 'true' |
|
|
|
|
|
build: |
|
|
strategy: |
|
|
fail-fast: false |
|
|
matrix: |
|
|
include: |
|
|
- platform: linux/amd64 |
|
|
runner: ubuntu-latest |
|
|
- platform: linux/arm64 |
|
|
runner: ubuntu-24.04-arm |
|
|
runs-on: ${{ matrix.runner }} |
|
|
needs: |
|
|
- check-repository |
|
|
- test |
|
|
if: needs.check-repository.outputs.is_main_repo != 'true' |
|
|
permissions: |
|
|
contents: read |
|
|
packages: write |
|
|
|
|
|
steps: |
|
|
- name: Convert to lowercase |
|
|
run: | |
|
|
echo "GHCR_REPO_LOWER=$(echo ${{ env.GHCR_REPO }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV |
|
|
|
|
|
- name: Prepare |
|
|
run: | |
|
|
platform=${{ matrix.platform }} |
|
|
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV |
|
|
|
|
|
- name: Checkout repository |
|
|
uses: actions/checkout@v4 |
|
|
|
|
|
- name: Docker meta |
|
|
id: meta |
|
|
uses: docker/metadata-action@v5 |
|
|
with: |
|
|
images: | |
|
|
${{ env.GHCR_REPO_LOWER }} |
|
|
|
|
|
- name: Login to GHCR |
|
|
uses: docker/login-action@v3 |
|
|
with: |
|
|
registry: ghcr.io |
|
|
username: ${{ github.repository_owner }} |
|
|
password: ${{ secrets.GITHUB_TOKEN }} |
|
|
|
|
|
|
|
|
- name: Set up Docker Buildx |
|
|
uses: docker/setup-buildx-action@v3 |
|
|
|
|
|
- name: Build and push by digest |
|
|
id: build |
|
|
uses: docker/build-push-action@v6 |
|
|
with: |
|
|
platforms: ${{ matrix.platform }} |
|
|
labels: ${{ steps.meta.outputs.labels }} |
|
|
outputs: type=image,name=${{ env.GHCR_REPO_LOWER }},push-by-digest=true,name-canonical=true,push=true |
|
|
cache-from: ${{ matrix.platform == 'linux/amd64' && 'type=gha' || '' }} |
|
|
cache-to: ${{ matrix.platform == 'linux/amd64' && 'type=gha,mode=max' || '' }} |
|
|
|
|
|
- name: Export digest |
|
|
run: | |
|
|
mkdir -p ${{ runner.temp }}/digests |
|
|
digest="${{ steps.build.outputs.digest }}" |
|
|
touch "${{ runner.temp }}/digests/${digest#sha256:}" |
|
|
|
|
|
- name: Upload digest |
|
|
uses: actions/upload-artifact@v4 |
|
|
with: |
|
|
name: digests-${{ env.PLATFORM_PAIR }} |
|
|
path: ${{ runner.temp }}/digests/* |
|
|
if-no-files-found: error |
|
|
retention-days: 1 |
|
|
|
|
|
merge: |
|
|
runs-on: ubuntu-latest |
|
|
needs: |
|
|
- check-repository |
|
|
- test |
|
|
- build |
|
|
if: needs.check-repository.outputs.is_main_repo != 'true' |
|
|
permissions: |
|
|
contents: read |
|
|
packages: write |
|
|
|
|
|
steps: |
|
|
- name: Convert to lowercase |
|
|
run: | |
|
|
echo "GHCR_REPO_LOWER=$(echo ${{ env.GHCR_REPO }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV |
|
|
|
|
|
- name: Download digests |
|
|
uses: actions/download-artifact@v4 |
|
|
with: |
|
|
path: ${{ runner.temp }}/digests |
|
|
pattern: digests-* |
|
|
merge-multiple: true |
|
|
|
|
|
- name: Login to GHCR |
|
|
uses: docker/login-action@v3 |
|
|
with: |
|
|
registry: ghcr.io |
|
|
username: ${{ github.repository_owner }} |
|
|
password: ${{ secrets.GITHUB_TOKEN }} |
|
|
|
|
|
- name: Set up Docker Buildx |
|
|
uses: docker/setup-buildx-action@v3 |
|
|
|
|
|
- name: Docker meta |
|
|
id: meta |
|
|
uses: docker/metadata-action@v5 |
|
|
with: |
|
|
images: | |
|
|
${{ env.GHCR_REPO_LOWER }} |
|
|
tags: | |
|
|
type=raw,value=dev |
|
|
type=semver,pattern={{version}} |
|
|
type=semver,pattern={{major}}.{{minor}} |
|
|
|
|
|
- name: Create manifest list and push |
|
|
working-directory: ${{ runner.temp }}/digests |
|
|
run: | |
|
|
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ |
|
|
$(printf '${{ env.GHCR_REPO_LOWER }}@sha256:%s ' *) |
|
|
|
|
|
- name: Inspect image |
|
|
run: | |
|
|
docker buildx imagetools inspect ${{ env.GHCR_REPO_LOWER }}:${{ steps.meta.outputs.version }} |
|
|
|
|
|
build-win64-exe: |
|
|
runs-on: windows-latest |
|
|
needs: |
|
|
- check-repository |
|
|
if: needs.check-repository.outputs.is_main_repo != 'true' |
|
|
steps: |
|
|
- name: 检出代码 |
|
|
uses: actions/checkout@v4 |
|
|
|
|
|
- name: Setup uv with Python ${{ env.WIN_EXE_PYTHON_VERSION }} |
|
|
uses: astral-sh/setup-uv@f94ec6bedd8674c4426838e6b50417d36b6ab231 |
|
|
with: |
|
|
python-version: ${{ env.WIN_EXE_PYTHON_VERSION }} |
|
|
enable-cache: true |
|
|
cache-dependency-glob: "pyproject.toml" |
|
|
|
|
|
- name: 执行所有任务(创建目录、下载、解压、复制文件、安装依赖) |
|
|
shell: pwsh |
|
|
run: | |
|
|
Write-Host "==== 创建必要的目录 ====" |
|
|
New-Item -Path "./build" -ItemType Directory -Force |
|
|
New-Item -Path "./build/runtime" -ItemType Directory -Force |
|
|
New-Item -Path "./dep_build" -ItemType Directory -Force |
|
|
|
|
|
Write-Host "==== 复制代码到 dep_build ====" |
|
|
Get-ChildItem -Path "./" -Exclude "dep_build", "build" | Copy-Item -Destination "./dep_build" -Recurse -Force |
|
|
|
|
|
Write-Host "==== 下载并解压 Python ${{ env.WIN_EXE_PYTHON_VERSION }} ====" |
|
|
Write-Host "pythonUrl: https://www.python.org/ftp/python/${{ env.WIN_EXE_PYTHON_VERSION }}/python-${{ env.WIN_EXE_PYTHON_VERSION }}-embed-amd64.zip" |
|
|
$pythonUrl = "https://www.python.org/ftp/python/${{ env.WIN_EXE_PYTHON_VERSION }}/python-${{ env.WIN_EXE_PYTHON_VERSION }}-embed-amd64.zip" |
|
|
$pythonZip = "./dep_build/python.zip" |
|
|
Invoke-WebRequest -Uri $pythonUrl -OutFile $pythonZip |
|
|
Expand-Archive -Path $pythonZip -DestinationPath "./build/runtime" -Force |
|
|
|
|
|
Write-Host "==== 下载 Visual C++ Redistributable 安装程序 ====" |
|
|
$vcRedistUrl = "https://aka.ms/vs/17/release/vc_redist.x64.exe" |
|
|
$vcRedistPath = "./build/无法运行请安装vc_redist.x64.exe" |
|
|
Invoke-WebRequest -Uri $vcRedistUrl -OutFile $vcRedistPath |
|
|
Write-Host "已下载 Visual C++ Redistributable 安装程序到: $vcRedistPath" |
|
|
|
|
|
Write-Host "==== 下载并解压 PyStand ====" |
|
|
$pystandUrl = "https://github.com/skywind3000/PyStand/releases/download/1.1.4/PyStand-v1.1.4-exe.zip" |
|
|
$pystandZip = "./dep_build/PyStand.zip" |
|
|
Invoke-WebRequest -Uri $pystandUrl -OutFile $pystandZip |
|
|
Expand-Archive -Path $pystandZip -DestinationPath "./dep_build/PyStand" -Force |
|
|
|
|
|
Write-Host "==== 复制 PyStand.exe 到 build 并重命名 ====" |
|
|
$pystandExe = "./dep_build/PyStand/PyStand-x64-CLI/PyStand.exe" |
|
|
$destExe = "./build/pdf2zh.exe" |
|
|
if (Test-Path $pystandExe) { |
|
|
Copy-Item -Path $pystandExe -Destination $destExe -Force |
|
|
} else { |
|
|
Write-Host "错误: PyStand.exe 未找到!" |
|
|
exit 1 |
|
|
} |
|
|
Write-Host "==== 创建 Python venv 在 dep_build ====" |
|
|
uv venv ./dep_build/venv |
|
|
|
|
|
./dep_build/venv/Scripts/activate |
|
|
|
|
|
Write-Host "==== 在 venv 环境中安装项目依赖 ====" |
|
|
uv pip install . |
|
|
|
|
|
Write-Host "==== 复制 venv/Lib/site-packages 到 build/ ====" |
|
|
Copy-Item -Path "./dep_build/venv/Lib/site-packages" -Destination "./build/site-packages" -Recurse -Force |
|
|
|
|
|
Write-Host "==== 复制 script/_pystand_static.int 到 build/ ====" |
|
|
$staticFile = "./script/_pystand_static.int" |
|
|
$destStatic = "./build/_pystand_static.int" |
|
|
if (Test-Path $staticFile) { |
|
|
Copy-Item -Path $staticFile -Destination $destStatic -Force |
|
|
} else { |
|
|
Write-Host "错误: script/_pystand_static.int 未找到!" |
|
|
exit 1 |
|
|
} |
|
|
|
|
|
- name: Upload build artifact |
|
|
uses: actions/upload-artifact@v4 |
|
|
with: |
|
|
name: win64-exe |
|
|
path: ./build |
|
|
if-no-files-found: error |
|
|
compression-level: 1 |
|
|
include-hidden-files: true |
|
|
|
|
|
test-win64-exe: |
|
|
needs: |
|
|
- build-win64-exe |
|
|
- check-repository |
|
|
if: needs.check-repository.outputs.is_main_repo != 'true' |
|
|
runs-on: windows-latest |
|
|
steps: |
|
|
- name: 检出代码 |
|
|
uses: actions/checkout@v4 |
|
|
|
|
|
- name: Download build artifact |
|
|
uses: actions/download-artifact@v4 |
|
|
with: |
|
|
name: win64-exe |
|
|
path: ./build |
|
|
|
|
|
- name: Test show version (online mode) |
|
|
run: | |
|
|
./build/pdf2zh.exe --version |
|
|
|
|
|
- name: Test - Translate a PDF file with plain text only (online mode) |
|
|
run: | |
|
|
./build/pdf2zh.exe ./test/file/translate.cli.plain.text.pdf -o ./test/file |
|
|
|
|
|
- name: Test - Translate a PDF file figure |
|
|
run: | |
|
|
./build/pdf2zh.exe ./test/file/translate.cli.text.with.figure.pdf -o ./test/file |
|
|
|
|
|
- name: Test - Translate without offline assets (online mode) |
|
|
run: | |
|
|
./build/pdf2zh.exe ./test/file/translate.cli.plain.text.pdf -o ./test/file |
|
|
|
|
|
- name: Upload test results |
|
|
uses: actions/upload-artifact@v4 |
|
|
with: |
|
|
name: test-results |
|
|
path: ./test/file/ |
|
|
if-no-files-found: error |
|
|
|
|
|
- name: Setup uv with Python ${{ env.WIN_EXE_PYTHON_VERSION }} |
|
|
uses: astral-sh/setup-uv@f94ec6bedd8674c4426838e6b50417d36b6ab231 |
|
|
with: |
|
|
python-version: ${{ env.WIN_EXE_PYTHON_VERSION }} |
|
|
enable-cache: true |
|
|
cache-dependency-glob: "pyproject.toml" |
|
|
|
|
|
- name: Generate offline assets |
|
|
shell: pwsh |
|
|
run: | |
|
|
Write-Host "==== 生成离线资源包 ====" |
|
|
uv run --active babeldoc --generate-offline-assets ./build |
|
|
|
|
|
- name: Delete cache |
|
|
shell: pwsh |
|
|
run: | |
|
|
Write-Host "==== 删除缓存目录 ====" |
|
|
$cachePath = "$env:USERPROFILE/.cache/babeldoc" |
|
|
if (Test-Path $cachePath) { |
|
|
Remove-Item -Path $cachePath -Recurse -Force |
|
|
Write-Host "已删除缓存目录: $cachePath" |
|
|
} else { |
|
|
Write-Host "缓存目录不存在: $cachePath" |
|
|
} |
|
|
|
|
|
- name: Test - Translate with offline assets (offline mode) |
|
|
run: | |
|
|
Write-Host "==== 测试离线资源包 ====" |
|
|
New-Item -Path "./test/file/offline_result" -ItemType Directory -Force |
|
|
./build/pdf2zh.exe ./test/file/translate.cli.plain.text.pdf -o ./test/file/offline_result |
|
|
|
|
|
- name: Upload offline test results |
|
|
uses: actions/upload-artifact@v4 |
|
|
with: |
|
|
name: offline-test-results |
|
|
path: ./test/file/offline_result/ |
|
|
if-no-files-found: error |
|
|
|
|
|
- name: Upload build with offline assets artifact |
|
|
uses: actions/upload-artifact@v4 |
|
|
with: |
|
|
name: win64-exe-with-assets |
|
|
path: ./build |
|
|
if-no-files-found: error |
|
|
compression-level: 1 |
|
|
include-hidden-files: true |