From 584fb0dad8f526f60a124540756c3f7ff62e7ecd Mon Sep 17 00:00:00 2001 From: QwejayHuang Date: Sun, 28 Jun 2026 08:50:04 +0800 Subject: [PATCH] v2.3.7: Update publish workflow --- .github/workflows/publish.yml | 148 ++++++++++++++++++++++++++++++++-- 1 file changed, 143 insertions(+), 5 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 43a226b..a0b570f 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -3,16 +3,15 @@ name: Build and Publish on: push: tags: - - 'v*' # 当推送形如 v1.0.0 或 v2.3.6 的标签时触发 + - 'v*' jobs: - build-n-publish: - name: Build and publish Python distribution + publish-pypi: + name: Publish to PyPI and Create Release runs-on: ubuntu-latest permissions: contents: write id-token: write - steps: - name: Checkout source code uses: actions/checkout@v4 @@ -22,6 +21,38 @@ jobs: with: python-version: '3.10' + - name: Sync version from Tag to files + shell: python + run: | + import re + import os + + tag = "${{ github.ref_name }}" + version = tag[1:] if tag.lower().startswith('v') else tag + print(f"Target version to sync: {version}") + + toml_path = 'pyproject.toml' + if not os.path.exists(toml_path): + raise FileNotFoundError(f"Missing critical configuration: {toml_path}") + + with open(toml_path, 'r', encoding='utf-8') as f: + content = f.read() + new_content = re.sub(r'(version\s*=\s*["\'])[^"\']+(["\'])', f'\\g<1>{version}\\g<2>', content, count=1) + with open(toml_path, 'w', encoding='utf-8') as f: + f.write(new_content) + print("Successfully synchronized pyproject.toml.") + + main_path = 'src/qpypack/main.py' + if not os.path.exists(main_path): + raise FileNotFoundError(f"Missing critical entrypoint: {main_path}") + + with open(main_path, 'r', encoding='utf-8') as f: + content = f.read() + new_content = re.sub(r'(__version__\s*=\s*["\'])[^"\']+(["\'])', f'\\g<1>{version}\\g<2>', content, count=1) + with open(main_path, 'w', encoding='utf-8') as f: + f.write(new_content) + print("Successfully synchronized main.py.") + - name: Install build dependencies run: | python -m pip install --upgrade pip @@ -43,4 +74,111 @@ jobs: - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: - skip-existing: true \ No newline at end of file + skip-existing: true + + build-windows-exe: + name: Build Windows EXE + runs-on: windows-latest + permissions: + contents: write + needs: publish-pypi + steps: + - name: Checkout source code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.10' + + - name: Extract version + shell: bash + run: | + TAG_NAME=${{ github.ref_name }} + VERSION=${TAG_NAME#v} + echo "VERSION=$VERSION" >> $GITHUB_ENV + + - name: Sync version in Windows Workspace + shell: python + run: | + import re + import os + + version = os.environ['VERSION'] + print(f"Target version to sync on Windows: {version}") + + main_path = 'src/qpypack/main.py' + if not os.path.exists(main_path): + raise FileNotFoundError(f"Missing critical entrypoint: {main_path}") + + with open(main_path, 'r', encoding='utf-8') as f: + content = f.read() + new_content = re.sub(r'(__version__\s*=\s*["\'])[^"\']+(["\'])', f'\\g<1>{version}\\g<2>', content, count=1) + with open(main_path, 'w', encoding='utf-8') as f: + f.write(new_content) + print("Windows workspace code version synchronized.") + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install PySide6 pyinstaller + + - name: Generate Windows Version Info File + shell: python + run: | + import os + import re + + version = os.environ['VERSION'] + parts = re.findall(r'\d+', version) + v_num = (parts + ['0', '0', '0', '0'])[:4] + v_tuple = ",".join(v_num) + print(f"Windows FileVersion tuple parsed: ({v_tuple})") + + info_content = f""" + VSVersionInfo( + ffi=FixedFileInfo( + filevers=({v_tuple}), + prodvers=({v_tuple}), + mask=0x3f, + flags=0x0, + OS=0x40004, + fileType=0x1, + subtype=0x0, + date=(0,0) + ), + kids=[ + StringFileInfo( + [ + StringTable( + '040904B0', + [ + StringStruct('CompanyName', 'QwejayHuang'), + StringStruct('FileDescription', 'Automated Python Packaging Tool'), + StringStruct('FileVersion', '{version}'), + StringStruct('InternalName', 'QPyPack'), + StringStruct('LegalCopyright', 'Copyright (C) QwejayHuang'), + StringStruct('OriginalFilename', 'QPyPack.exe'), + StringStruct('ProductName', 'QPyPack'), + StringStruct('ProductVersion', '{version}') + ] + ) + ] + ), + VarFileInfo([VarStruct('Translation', [1033, 1200])]) + ] + ) + """ + with open('file_version_info.txt', 'w', encoding='utf-8') as f: + f.write(info_content.strip()) + + - name: Build EXE with PyInstaller + run: | + pyinstaller --clean --onefile --noconsole --version-file=file_version_info.txt --icon=src/qpypack/icon.ico --add-data "src/qpypack/icon.ico;." --name="QPyPack_${{ env.VERSION }}" src/qpypack/main.py + + - name: Upload EXE to GitHub Release + uses: softprops/action-gh-release@v2 + with: + files: dist/QPyPack_${{ env.VERSION }}.exe + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file