Compare commits

...

7 Commits

3 changed files with 142 additions and 48 deletions
+134 -41
View File
@@ -15,7 +15,7 @@ permissions:
contents: write contents: write
env: env:
PYTHON_VERSION: "3.11" PYTHON_VERSION: "3.12"
APP_NAME: "SoftwareManager" APP_NAME: "SoftwareManager"
jobs: jobs:
@@ -57,7 +57,7 @@ jobs:
- name: Install Python dependencies - name: Install Python dependencies
run: | run: |
uv pip install -r requirements.txt uv pip install -r requirements.txt
uv pip install pyinstaller backports.tarfile pillow uv pip install nuitka
env: env:
UV_SYSTEM_PYTHON: 1 UV_SYSTEM_PYTHON: 1
@@ -82,56 +82,136 @@ jobs:
} }
EOF EOF
- name: Build executable with PyInstaller (Windows) - name: Install UPX
shell: bash
run: |
if [ "$RUNNER_OS" == "Windows" ]; then
curl -sL https://github.com/upx/upx/releases/download/v5.1.0/upx-5.1.0-win64.zip -o upx.zip
7z x upx.zip -oupx-dir
UPX_DIR="$(pwd)/upx-dir/upx-5.1.0-win64"
echo "$UPX_DIR" >> $GITHUB_PATH
export PATH="$UPX_DIR:$PATH"
echo "UPX_BINARY=$UPX_DIR/upx.exe" >> $GITHUB_ENV
elif [ "$RUNNER_OS" == "Linux" ]; then
curl -sL https://github.com/upx/upx/releases/download/v5.1.0/upx-5.1.0-amd64_linux.tar.xz -o upx.tar.xz
tar xf upx.tar.xz
UPX_DIR="$(pwd)/upx-5.1.0-amd64_linux"
echo "$UPX_DIR" >> $GITHUB_PATH
export PATH="$UPX_DIR:$PATH"
echo "UPX_BINARY=$UPX_DIR/upx" >> $GITHUB_ENV
else
brew install upx
echo "UPX_BINARY=$(which upx)" >> $GITHUB_ENV
fi
upx --version | head -1
- name: Build with Nuitka (Windows)
if: runner.os == 'Windows' if: runner.os == 'Windows'
shell: bash shell: bash
run: | run: |
pyinstaller --onefile --windowed \ python -m nuitka \
--add-data "build_info.json;." \ --onefile \
--add-data "build_info.json;core" \ --onefile-no-compression \
--add-data "build_info.json;core/interface" \ --onefile-tempdir-spec="{CACHE_DIR}/${{ env.APP_NAME }}/${{ env.VERSION }}" \
--add-data "core/interface/assets;core/interface/assets" \ --assume-yes-for-downloads \
--icon "core/interface/assets/logo.png" \ --windows-console-mode=disable \
--exclude-module PyQt6 \ --enable-plugin=pyside6 \
--exclude-module PyQt5 \ --enable-plugin=upx \
--hidden-import=backports.tarfile \ --upx-binary="${{ env.UPX_BINARY }}" \
--hidden-import=backports \ --noinclude-qt-translations \
--hidden-import=jaraco.context \ --noinclude-dlls='Qt6WebEngine*' \
--hidden-import=jaraco.text \ --noinclude-dlls='Qt6Multimedia*' \
--hidden-import=jaraco.functools \ --noinclude-dlls='Qt6Quick*' \
--name ${{ env.APP_NAME }} \ --noinclude-dlls='Qt6Qml*' \
--noinclude-dlls='Qt6Designer*' \
--noinclude-dlls='Qt63D*' \
--noinclude-dlls='Qt6Bluetooth*' \
--noinclude-dlls='Qt6Nfc*' \
--noinclude-dlls='Qt6Sensors*' \
--noinclude-dlls='Qt6Serial*' \
--noinclude-dlls='Qt6Test*' \
--noinclude-dlls='Qt6Location*' \
--noinclude-dlls='Qt6Pdf*' \
--include-data-dir=core/interface/assets=core/interface/assets \
--include-data-files=build_info.json=build_info.json \
--include-data-files=build_info.json=core/build_info.json \
--include-data-files=build_info.json=core/interface/build_info.json \
--output-filename=${{ env.APP_NAME }}.exe \
main.py main.py
- name: Build executable with PyInstaller (Unix) - name: Build with Nuitka (Linux)
if: runner.os != 'Windows' if: runner.os == 'Linux'
shell: bash shell: bash
run: | run: |
pyinstaller --onefile --windowed \ python -m nuitka \
--add-data "build_info.json:." \ --onefile \
--add-data "build_info.json:core" \ --onefile-tempdir-spec="{CACHE_DIR}/${{ env.APP_NAME }}/${{ env.VERSION }}" \
--add-data "build_info.json:core/interface" \ --assume-yes-for-downloads \
--add-data "core/interface/assets:core/interface/assets" \ --enable-plugin=pyside6 \
--icon "core/interface/assets/logo.png" \ --enable-plugin=upx \
--exclude-module PyQt6 \ --upx-binary="${{ env.UPX_BINARY }}" \
--exclude-module PyQt5 \ --noinclude-qt-translations \
--hidden-import=backports.tarfile \ --noinclude-dlls='libQt6WebEngine*' \
--hidden-import=backports \ --noinclude-dlls='libQt6Multimedia*' \
--hidden-import=jaraco.context \ --noinclude-dlls='libQt6Quick*' \
--hidden-import=jaraco.text \ --noinclude-dlls='libQt6Qml*' \
--hidden-import=jaraco.functools \ --noinclude-dlls='libQt6Designer*' \
--name ${{ env.APP_NAME }} \ --noinclude-dlls='libQt63D*' \
--noinclude-dlls='libQt6Bluetooth*' \
--noinclude-dlls='libQt6Nfc*' \
--noinclude-dlls='libQt6Sensors*' \
--noinclude-dlls='libQt6Serial*' \
--noinclude-dlls='libQt6Test*' \
--noinclude-dlls='libQt6Location*' \
--noinclude-dlls='libQt6Pdf*' \
--include-data-dir=core/interface/assets=core/interface/assets \
--include-data-files=build_info.json=build_info.json \
--include-data-files=build_info.json=core/build_info.json \
--include-data-files=build_info.json=core/interface/build_info.json \
--output-filename=${{ env.APP_NAME }} \
main.py main.py
- name: Make executable (Unix) - name: Build with Nuitka (macOS)
if: runner.os != 'Windows' if: runner.os == 'macOS'
run: chmod +x dist/${{ env.APP_NAME }}
- name: Rename artifact
shell: bash shell: bash
run: | run: |
cd dist python -m nuitka \
mv ${{ env.APP_NAME }}${{ runner.os == 'Windows' && '.exe' || '' }} ${{ matrix.artifact_name }} --onefile \
ls -la --onefile-tempdir-spec="{CACHE_DIR}/${{ env.APP_NAME }}/${{ env.VERSION }}" \
--assume-yes-for-downloads \
--enable-plugin=pyside6 \
--noinclude-qt-translations \
--noinclude-dlls='libQt6WebEngine*' \
--noinclude-dlls='libQt6Multimedia*' \
--noinclude-dlls='libQt6Quick*' \
--noinclude-dlls='libQt6Qml*' \
--noinclude-dlls='libQt6Designer*' \
--noinclude-dlls='libQt63D*' \
--noinclude-dlls='libQt6Bluetooth*' \
--noinclude-dlls='libQt6Nfc*' \
--noinclude-dlls='libQt6Sensors*' \
--noinclude-dlls='libQt6Serial*' \
--noinclude-dlls='libQt6Test*' \
--noinclude-dlls='libQt6Location*' \
--noinclude-dlls='libQt6Pdf*' \
--include-data-dir=core/interface/assets=core/interface/assets \
--include-data-files=build_info.json=build_info.json \
--include-data-files=build_info.json=core/build_info.json \
--include-data-files=build_info.json=core/interface/build_info.json \
--output-filename=${{ env.APP_NAME }} \
main.py
- name: Prepare artifact
shell: bash
run: |
mkdir -p dist
if [ "$RUNNER_OS" == "Windows" ]; then
mv ${{ env.APP_NAME }}.exe dist/${{ matrix.artifact_name }}
else
mv ${{ env.APP_NAME }} dist/${{ matrix.artifact_name }}
chmod +x dist/${{ matrix.artifact_name }}
fi
ls -la dist/
- name: Upload build artifact - name: Upload build artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
@@ -162,9 +242,16 @@ jobs:
chmod +x release/SoftwareManager-dev-*-linux release/SoftwareManager-dev-*-macos chmod +x release/SoftwareManager-dev-*-linux release/SoftwareManager-dev-*-macos
ls -la release/ ls -la release/
- name: Generate checksums
run: |
cd release
sha256sum * > SHA256SUMS.txt
cat SHA256SUMS.txt
- name: Generate release notes - name: Generate release notes
run: | run: |
SHORT_SHA="${{ needs.build.outputs.short_sha }}" SHORT_SHA="${{ needs.build.outputs.short_sha }}"
CHECKSUMS=$(cat release/SHA256SUMS.txt)
cat > release_notes.md << EOF cat > release_notes.md << EOF
## Development Build ## Development Build
@@ -177,6 +264,11 @@ jobs:
- Linux: \`SoftwareManager-dev-${SHORT_SHA}-linux\` - Linux: \`SoftwareManager-dev-${SHORT_SHA}-linux\`
- Windows: \`SoftwareManager-dev-${SHORT_SHA}-windows.exe\` - Windows: \`SoftwareManager-dev-${SHORT_SHA}-windows.exe\`
- macOS: \`SoftwareManager-dev-${SHORT_SHA}-macos\` - macOS: \`SoftwareManager-dev-${SHORT_SHA}-macos\`
### SHA-256 Checksums
\`\`\`
${CHECKSUMS}
\`\`\`
EOF EOF
cat release_notes.md cat release_notes.md
@@ -190,5 +282,6 @@ jobs:
release/SoftwareManager-dev-${{ needs.build.outputs.short_sha }}-linux release/SoftwareManager-dev-${{ needs.build.outputs.short_sha }}-linux
release/SoftwareManager-dev-${{ needs.build.outputs.short_sha }}-windows.exe release/SoftwareManager-dev-${{ needs.build.outputs.short_sha }}-windows.exe
release/SoftwareManager-dev-${{ needs.build.outputs.short_sha }}-macos release/SoftwareManager-dev-${{ needs.build.outputs.short_sha }}-macos
release/SHA256SUMS.txt
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+7 -6
View File
@@ -73,15 +73,16 @@ class MainWindow(QtWidgets.QMainWindow, QWidget):
self.log_signal.connect(self._on_log_signal) self.log_signal.connect(self._on_log_signal)
def get_asset_path(filename): def get_asset_path(filename):
if getattr(sys, 'frozen', False): base_path = os.path.dirname(os.path.abspath(__file__))
base_path = sys._MEIPASS asset_path = os.path.join(base_path, 'assets', filename)
else:
base_path = os.path.dirname(__file__)
asset_path = os.path.join(base_path, 'core', 'interface', 'assets', filename)
if os.path.exists(asset_path): if os.path.exists(asset_path):
return asset_path return asset_path
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
asset_path = os.path.join(sys._MEIPASS, 'core', 'interface', 'assets', filename)
if os.path.exists(asset_path):
return asset_path
return os.path.join('core', 'interface', 'assets', filename) return os.path.join('core', 'interface', 'assets', filename)
self.setWindowIcon(QIcon(get_asset_path("logo.png"))) self.setWindowIcon(QIcon(get_asset_path("logo.png")))
+1 -1
View File
@@ -1,5 +1,5 @@
requests==2.32.2 requests==2.32.2
PySide6==6.10.1 PySide6-Essentials==6.10.1
beautifulsoup4==4.13.5 beautifulsoup4==4.13.5
darkdetect==0.7.1 darkdetect==0.7.1
pyinstaller==6.15.0 pyinstaller==6.15.0