diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 03c93f6..f18f4e2 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -1,9 +1,6 @@ name: Build Executables (Dev) on: - push: - branches: - - main workflow_dispatch: inputs: version: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..813dd41 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,236 @@ +name: Release + +on: + push: + tags: + - "*" + +permissions: + contents: write + +env: + PYTHON_VERSION: "3.12" + APP_NAME: "SoftwareManager" + +jobs: + build: + name: Build ${{ matrix.os }} + strategy: + matrix: + include: + - os: ubuntu-22.04 + artifact_name: SoftwareManager-${{ github.sha }}-linux + - os: windows-latest + artifact_name: SoftwareManager-${{ github.sha }}-windows + - os: macos-latest + artifact_name: SoftwareManager-${{ github.sha }}-macos + + runs-on: ${{ matrix.os }} + outputs: + short_sha: ${{ steps.version.outputs.short_sha }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: ${{ env.PYTHON_VERSION }} + + - name: Install uv + uses: astral-sh/setup-uv@v7 + with: + version: "0.9.7" + enable-cache: true + + - name: Install Python dependencies + run: | + uv pip install -r requirements.txt + uv pip install Pillow + env: + UV_SYSTEM_PYTHON: 1 + + - name: Install Nuitka (Windows only) + if: runner.os == 'Windows' + run: uv pip install nuitka + env: + UV_SYSTEM_PYTHON: 1 + + - name: Generate version + id: version + shell: bash + run: | + SHORT_SHA="${{ github.sha }}" + SHORT_SHA="${SHORT_SHA:0:7}" + echo "VERSION=$SHORT_SHA" >> $GITHUB_ENV + echo "short_sha=$SHORT_SHA" >> $GITHUB_OUTPUT + + - name: Inject commit hash into code + shell: bash + run: | + cat > build_info.json << EOF + { + "version": "${{ env.VERSION }}" + } + EOF + + - name: Install UPX (Windows) + if: runner.os == 'Windows' + shell: bash + run: | + 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 + upx --version | head -1 + + - name: Convert icon for Windows + if: runner.os == 'Windows' + shell: bash + run: | + python -c " + from PIL import Image + img = Image.open('src/interface/assets/logo.png') + img.save('app_icon.ico', format='ICO', sizes=[(256,256),(128,128),(64,64),(48,48),(32,32),(16,16)]) + print('Icon converted successfully') + " + + - name: Build with Nuitka (Windows) + if: runner.os == 'Windows' + shell: bash + run: | + python -m nuitka \ + --standalone \ + --assume-yes-for-downloads \ + --windows-console-mode=disable \ + --windows-icon-from-ico=app_icon.ico \ + --enable-plugin=pyside6 \ + --enable-plugin=upx \ + --upx-binary="${{ env.UPX_BINARY }}" \ + --noinclude-qt-translations \ + --include-data-files=build_info.json=build_info.json \ + --output-filename=${{ env.APP_NAME }}.exe \ + --output-dir=nuitka-build \ + src/main.py + + - name: Build with PyInstaller (Linux) + if: runner.os == 'Linux' + shell: bash + run: | + pyinstaller --onefile --windowed \ + --add-data "build_info.json:." \ + --exclude-module PyQt6 \ + --exclude-module PyQt5 \ + --hidden-import=backports.tarfile \ + --hidden-import=backports \ + --hidden-import=jaraco.context \ + --hidden-import=jaraco.text \ + --hidden-import=jaraco.functools \ + --name ${{ env.APP_NAME }} \ + src/main.py + + - name: Build with PyInstaller (macOS) + if: runner.os == 'macOS' + shell: bash + run: | + pyinstaller --onefile \ + --add-data "build_info.json:." \ + --exclude-module PyQt6 \ + --exclude-module PyQt5 \ + --hidden-import=backports.tarfile \ + --hidden-import=backports \ + --hidden-import=jaraco.context \ + --hidden-import=jaraco.text \ + --hidden-import=jaraco.functools \ + --name ${{ env.APP_NAME }} \ + src/main.py + + - name: Rename artifact + shell: bash + run: | + mkdir -p dist-final + if [ "$RUNNER_OS" == "Windows" ]; then + mv nuitka-build/main.dist dist-final/${{ env.APP_NAME }} + else + chmod +x dist/${{ env.APP_NAME }} + mv dist/${{ env.APP_NAME }} dist-final/${{ matrix.artifact_name }} + fi + + - name: Create ZIP (Windows) + if: runner.os == 'Windows' + shell: pwsh + run: | + Compress-Archive -Path "dist-final/${{ env.APP_NAME }}/*" -DestinationPath "dist-final/${{ matrix.artifact_name }}.zip" + + - name: Build Installer (Windows) + if: runner.os == 'Windows' + shell: bash + run: | + SETUP_NAME="SoftwareManager-${{ env.VERSION }}-windows-setup" + iscc //DMyAppVersion="${{ env.VERSION }}" \ + //DMySourceDir="dist-final\\${{ env.APP_NAME }}" \ + //DMyOutputDir="dist-final" \ + //DMyOutputFilename="${SETUP_NAME}" \ + installer.iss + echo "SETUP_NAME=${SETUP_NAME}" >> $GITHUB_ENV + + - name: Upload build artifact (Windows) + if: runner.os == 'Windows' + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.os }}-build + path: | + dist-final/${{ matrix.artifact_name }}.zip + dist-final/${{ env.SETUP_NAME }}.exe + retention-days: 1 + + - name: Upload build artifact (Linux/macOS) + if: runner.os != 'Windows' + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.os }}-build + path: dist-final/${{ matrix.artifact_name }} + retention-days: 1 + + release: + name: Create Release + needs: build + runs-on: ubuntu-22.04 + + steps: + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Prepare release files + run: | + mkdir -p release + SHORT_SHA="${{ needs.build.outputs.short_sha }}" + cp artifacts/ubuntu-22.04-build/SoftwareManager-*-linux release/SoftwareManager-${SHORT_SHA}-linux + cp artifacts/windows-latest-build/SoftwareManager-*-windows.zip release/SoftwareManager-${SHORT_SHA}-windows.zip + cp artifacts/windows-latest-build/SoftwareManager-*-windows-setup.exe release/SoftwareManager-${SHORT_SHA}-windows-setup.exe + cp artifacts/macos-latest-build/SoftwareManager-*-macos release/SoftwareManager-${SHORT_SHA}-macos + chmod +x release/SoftwareManager-*-linux release/SoftwareManager-*-macos + + - name: Generate checksums + run: | + cd release + sha256sum * > SHA256SUMS.txt + + - name: Create Release + uses: softprops/action-gh-release@v2 + with: + generate_release_notes: true + files: | + release/SoftwareManager-${{ needs.build.outputs.short_sha }}-linux + release/SoftwareManager-${{ needs.build.outputs.short_sha }}-windows.zip + release/SoftwareManager-${{ needs.build.outputs.short_sha }}-windows-setup.exe + release/SoftwareManager-${{ needs.build.outputs.short_sha }}-macos + release/SHA256SUMS.txt + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file