diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml new file mode 100644 index 0000000..1417155 --- /dev/null +++ b/.github/workflows/build-and-release.yml @@ -0,0 +1,236 @@ +name: Build and Release + +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' + +jobs: + update-version-info: + uses: ./.github/workflows/update-version-info.yml + permissions: + contents: write + with: + tag_name: ${{ github.ref_name }} + ref: ${{ github.ref }} + + commit-and-move-tag: + needs: update-version-info + if: ${{ needs.update-version-info.outputs.has_changes == 'true' }} + uses: ./.github/workflows/commit-and-move-tag.yml + permissions: + contents: write + with: + tag_name: ${{ needs.update-version-info.outputs.tag_name }} + version: ${{ needs.update-version-info.outputs.version }} + file_path: src/gui/ALVersionInfo.py + + build-and-release: + runs-on: windows-latest + needs: [update-version-info, commit-and-move-tag] + if: always() && needs.update-version-info.result == 'success' + permissions: + contents: write + + steps: + - name: Checkout code with updated version info + uses: actions/checkout@v4 + with: + ref: main + + - name: Get version info from previous job + id: get_tag + run: | + $tagName = "${{ needs.update-version-info.outputs.tag_name }}" + $version = "${{ needs.update-version-info.outputs.version }}" + + echo "TAG_NAME=$tagName" >> $env:GITHUB_OUTPUT + echo "VERSION=$version" >> $env:GITHUB_OUTPUT + Write-Host "✓ Tag: $tagName" + Write-Host "✓ Version: $version" + shell: pwsh + + - name: Verify ALVersionInfo.py was updated + run: | + $versionInfoFile = "src/gui/ALVersionInfo.py" + Write-Host "Verifying $versionInfoFile content:" + Write-Host "================================" + Get-Content $versionInfoFile | Write-Host + Write-Host "================================" + shell: pwsh + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirement.txt + + - name: Fix ddddocr compatibility and copy model files + run: | + $ddddocrPath = python -c "import ddddocr, os; print(os.path.dirname(ddddocr.__file__))" + Write-Host "ddddocr package location: $ddddocrPath" + + $initFile = Join-Path $ddddocrPath "__init__.py" + if (Test-Path $initFile) { + Write-Host "Fixing ddddocr compatibility in: $initFile" + (Get-Content $initFile) -replace 'Image\.ANTIALIAS', 'Image.Resampling.LANCZOS' | Set-Content $initFile + Write-Host "✓ Fixed: Image.ANTIALIAS -> Image.Resampling.LANCZOS" + } else { + Write-Error "✗ ddddocr __init__.py not found" + exit 1 + } + + if (-not (Test-Path "model")) { + New-Item -ItemType Directory -Path "model" | Out-Null + Write-Host "✓ Created model directory" + } + + $onnxSource = Join-Path $ddddocrPath "common.onnx" + $onnxDest = "model/common.onnx" + if (Test-Path $onnxSource) { + Copy-Item $onnxSource $onnxDest -Force + Write-Host "✓ Copied ONNX model from: $onnxSource" + Write-Host "✓ ONNX model copied to: $onnxDest" + } else { + Write-Error "✗ ONNX model not found in ddddocr package: $onnxSource" + exit 1 + } + + if (Test-Path $onnxDest) { + $fileSize = (Get-Item $onnxDest).Length / 1MB + Write-Host "✓ Model file verified: $onnxDest (Size: $([math]::Round($fileSize, 2)) MB)" + } else { + Write-Error "✗ Failed to copy model file" + exit 1 + } + shell: pwsh + + - name: Compile Qt UI files + run: | + cd src/gui/batchs + ./compile_ui.bat + shell: cmd + + - name: Compile Qt Resource files + run: | + cd src/gui/batchs + ./compile_rc.bat + shell: cmd + + - name: Generate Main.spec dynamically + run: | + $version = "${{ steps.get_tag.outputs.VERSION }}" + $exeName = "AutoLibrary-$version" + + Write-Host "Generating Main.spec for version: $version" + Write-Host "Executable name: $exeName" + + $specLines = @( + "# -*- mode: python ; coding: utf-8 -*-" + "" + "" + "a = Analysis(" + " ['src\\Main.py']," + " pathex=[]," + " binaries=[]," + " datas=[" + " ('model\\common.onnx', 'ddddocr')," + " ('src\\gui\\icons\\AutoLibrary_32x32.ico', 'gui\\icons')," + " ]," + " hiddenimports=[]," + " hookspath=[]," + " hooksconfig={}," + " runtime_hooks=[]," + " excludes=[]," + " noarchive=False," + " optimize=0," + ")" + "pyz = PYZ(a.pure)" + "" + "exe = EXE(" + " pyz," + " a.scripts," + " a.binaries," + " a.datas," + " []," + " name='$exeName'," + " debug=False," + " bootloader_ignore_signals=False," + " strip=False," + " upx=True," + " upx_exclude=[]," + " runtime_tmpdir=None," + " console=False," + " disable_windowed_traceback=False," + " argv_emulation=False," + " target_arch=None," + " codesign_identity=None," + " entitlements_file=None," + " icon=['src\\gui\\icons\\AutoLibrary_32x32.ico']," + ")" + ) + + $specLines | Out-File -FilePath "Main.spec" -Encoding UTF8 + + Write-Host "✓ Main.spec generated successfully" + Write-Host "`n=== Generated Main.spec ===" + Get-Content "Main.spec" | Write-Host + Write-Host "==========================`n" + shell: pwsh + + - name: Build with PyInstaller + run: | + pyinstaller Main.spec + + - name: Create Release Archive + run: | + $tagName = "${{ steps.get_tag.outputs.TAG_NAME }}" + $version = "${{ steps.get_tag.outputs.VERSION }}" + $exeName = "AutoLibrary-$version.exe" + $zipName = "AutoLibrary.$tagName-windows-x86_64.zip" + + Write-Host "Looking for executable: dist/$exeName" + + if (Test-Path "dist/$exeName") { + Compress-Archive -Path "dist/$exeName" -DestinationPath $zipName + Write-Host "✓ Created release archive: $zipName" + } else { + Write-Error "✗ Executable not found: dist/$exeName" + Write-Host "Files in dist directory:" + Get-ChildItem "dist" | ForEach-Object { Write-Host " - $($_.Name)" } + exit 1 + } + shell: pwsh + + - name: Create Release + id: create_release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ steps.get_tag.outputs.TAG_NAME }} + name: AutoLibrary ${{ steps.get_tag.outputs.TAG_NAME }} + files: | + AutoLibrary.${{ steps.get_tag.outputs.TAG_NAME }}-windows-x86_64.zip + draft: false + prerelease: false + generate_release_notes: true + body: | + ### 下载获取 + - **Windows x86_64**: `AutoLibrary.${{ steps.get_tag.outputs.TAG_NAME }}-windows-x86_64.zip` + + ### 如何使用 + 1. 下载 `AutoLibrary.${{ steps.get_tag.outputs.TAG_NAME }}-windows-x86_64.zip` 文件 + 2. 解压到任意目录 + 3. 下载对应浏览器的驱动文件 + 4. 运行 `AutoLibrary-${{ steps.get_tag.outputs.VERSION }}.exe` (首次运行会初始化配置文件) + 5. 按照提示操作即可 + + 更多详情请访问 [AutoLibrary 网站](http://autolibrary.cv) 和查看 [帮助手册](https://autolibrary.cv/docs/manual_lists.html) + + --- + **完整更新日志见下方自动生成的 Release Notes** + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/commit-and-move-tag.yml b/.github/workflows/commit-and-move-tag.yml new file mode 100644 index 0000000..fc5150a --- /dev/null +++ b/.github/workflows/commit-and-move-tag.yml @@ -0,0 +1,102 @@ +name: Commit and Move Tag + +on: + workflow_call: + inputs: + tag_name: + description: 'Tag name to move (e.g., v1.0.0)' + required: true + type: string + version: + description: 'Version number for commit message' + required: true + type: string + file_path: + description: 'File path to commit' + required: true + type: string + outputs: + new_commit_sha: + description: 'The new commit SHA after moving the tag' + value: ${{ jobs.commit-and-move-tag.outputs.new_commit_sha }} + +jobs: + commit-and-move-tag: + runs-on: ubuntu-latest + permissions: + contents: write + outputs: + new_commit_sha: ${{ steps.commit_info.outputs.commit_sha }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: main + fetch-depth: 0 + + - name: Download modified file + uses: actions/download-artifact@v4 + with: + name: updated-version-info + path: downloaded-file/ + + - name: Replace file with updated version + run: | + FILE_PATH="${{ inputs.file_path }}" + FILE_NAME=$(basename "$FILE_PATH") + TARGET_DIR=$(dirname "$FILE_PATH") + + mkdir -p "$TARGET_DIR" + cp "downloaded-file/$FILE_NAME" "$FILE_PATH" + + echo "✓ File replaced: $FILE_PATH" + echo "" + echo "=== Updated file content ===" + cat "$FILE_PATH" + echo "============================" + + - name: Commit changes + id: commit_changes + run: | + git config --local user.email "github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" + + FILE_PATH="${{ inputs.file_path }}" + VERSION="${{ inputs.version }}" + + if [ ! -f "$FILE_PATH" ]; then + echo "✗ Error: File $FILE_PATH not found" + exit 1 + fi + + git add "$FILE_PATH" + git commit -m "chore(release): v${VERSION} [auto release commit]" + echo "✓ Changes committed" + + - name: Push to main branch + run: | + MAIN_BRANCH=$(git remote show origin | grep 'HEAD branch' | cut -d' ' -f5) + if [ -z "$MAIN_BRANCH" ]; then + MAIN_BRANCH="main" + fi + + echo "Pushing to branch: ${MAIN_BRANCH}" + git push origin HEAD:${MAIN_BRANCH} + echo "✓ Changes pushed to ${MAIN_BRANCH}" + + - name: Move tag to new commit + run: | + TAG_NAME="${{ inputs.tag_name }}" + + echo "Moving tag ${TAG_NAME} to the new commit..." + git tag -f ${TAG_NAME} + git push origin ${TAG_NAME} --force + echo "✓ Tag ${TAG_NAME} moved to commit $(git rev-parse --short HEAD)" + + - name: Output commit info + id: commit_info + run: | + COMMIT_SHA=$(git rev-parse --short HEAD) + echo "commit_sha=$COMMIT_SHA" >> $GITHUB_OUTPUT + echo "✓ New commit SHA: $COMMIT_SHA" diff --git a/.github/workflows/update-version-info.yml b/.github/workflows/update-version-info.yml new file mode 100644 index 0000000..90b47ec --- /dev/null +++ b/.github/workflows/update-version-info.yml @@ -0,0 +1,115 @@ +name: Update Version Info + +on: + workflow_call: + inputs: + tag_name: + description: 'Tag name (e.g., v1.0.0)' + required: true + type: string + ref: + description: 'Git ref to checkout' + required: true + type: string + outputs: + tag_name: + description: 'The tag name' + value: ${{ jobs.update-version-info.outputs.tag_name }} + version: + description: 'The version number' + value: ${{ jobs.update-version-info.outputs.version }} + has_changes: + description: 'Whether ALVersionInfo.py was modified' + value: ${{ jobs.update-version-info.outputs.has_changes }} + +jobs: + update-version-info: + runs-on: ubuntu-latest + permissions: + contents: write + outputs: + tag_name: ${{ steps.get_version.outputs.TAG_NAME }} + version: ${{ steps.get_version.outputs.VERSION }} + has_changes: ${{ steps.check_changes.outputs.has_changes }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref }} + fetch-depth: 0 + + - name: Get tag name and version + id: get_version + env: + TZ: UTC + run: | + TAG_NAME="${{ inputs.tag_name }}" + VERSION="${TAG_NAME#v}" + COMMIT_SHA="${GITHUB_SHA:0:7}" + COMMIT_DATE=$(TZ=UTC git log -1 --format=%cd --date=format-local:'%Y-%m-%d %H:%M:%S UTC') + + echo "TAG_NAME=$TAG_NAME" >> $GITHUB_OUTPUT + echo "VERSION=$VERSION" >> $GITHUB_OUTPUT + echo "COMMIT_SHA=$COMMIT_SHA" >> $GITHUB_OUTPUT + echo "COMMIT_DATE=$COMMIT_DATE" >> $GITHUB_OUTPUT + + echo "✓ Tag: $TAG_NAME" + echo "✓ Version: $VERSION" + echo "✓ Commit SHA: $COMMIT_SHA" + echo "✓ Commit Date: $COMMIT_DATE" + + - name: Update ALVersionInfo.py with version info + run: | + VERSION="${{ steps.get_version.outputs.VERSION }}" + TAG_NAME="${{ steps.get_version.outputs.TAG_NAME }}" + COMMIT_SHA="${{ steps.get_version.outputs.COMMIT_SHA }}" + COMMIT_DATE="${{ steps.get_version.outputs.COMMIT_DATE }}" + APP_INFO_FILE="src/gui/ALVersionInfo.py" + BUILD_DATE=$(date -u '+%Y-%m-%d %H:%M:%S UTC') + + echo "Updating $APP_INFO_FILE with build information..." + + { + echo '# -*- coding: utf-8 -*-' + echo '' + echo '"""' + echo ' The contents of this file will automatically be updated by the' + echo ' workflow process. Do not edit manually.' + echo ' ' + echo ' This file is auto-generated during the workflow process.' + echo " Last updated: ${BUILD_DATE}" + echo '"""' + echo '' + echo "AL_VERSION = \"${VERSION}\"" + echo "AL_TAG = \"${TAG_NAME}\"" + echo "AL_COMMIT_SHA = \"${COMMIT_SHA}\"" + echo "AL_COMMIT_DATE = \"${COMMIT_DATE}\" # time zone : UTC" + echo "AL_BUILD_DATE = \"${BUILD_DATE}\" # time zone : UTC" + echo 'AL_VERSION_FULL = f"{AL_VERSION} ({AL_COMMIT_SHA})"' + } > "$APP_INFO_FILE" + + echo "✓ ALVersionInfo.py updated successfully" + echo "" + echo "=== Updated ALVersionInfo.py ===" + cat "$APP_INFO_FILE" + echo "==========================" + + - name: Check if ALVersionInfo.py was modified + id: check_changes + run: | + if git diff --quiet src/gui/ALVersionInfo.py; then + echo "has_changes=false" >> $GITHUB_OUTPUT + echo "! No changes detected in ALVersionInfo.py" + else + echo "has_changes=true" >> $GITHUB_OUTPUT + echo "✓ ALVersionInfo.py has been modified" + fi + + - name: Upload modified ALVersionInfo.py + if: steps.check_changes.outputs.has_changes == 'true' + uses: actions/upload-artifact@v4 + with: + name: updated-version-info + path: src/gui/ALVersionInfo.py + retention-days: 1