fix: windows build #16
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build and Release | |
| on: | |
| push: | |
| branches: [ main ] | |
| pull_request: | |
| branches: [ main ] | |
| permissions: | |
| contents: write | |
| issues: write | |
| pull-requests: write | |
| jobs: | |
| # Determine if we should create a release | |
| semantic-release: | |
| name: Semantic Release | |
| runs-on: ubuntu-latest | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| outputs: | |
| new-release-published: ${{ steps.semantic.outputs.new-release-published }} | |
| new-release-version: ${{ steps.semantic.outputs.new-release-version }} | |
| new-release-git-tag: ${{ steps.semantic.outputs.new-release-git-tag }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| ssh-key: ${{ secrets.DEPLOY_KEY }} | |
| - name: Setup Git | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| - name: Install semantic-release | |
| run: | | |
| npm install -g semantic-release @semantic-release/changelog @semantic-release/git @semantic-release/github conventional-changelog-conventionalcommits | |
| - name: Get next version | |
| id: semantic | |
| run: | | |
| # Run semantic-release in dry-run mode to get the next version | |
| OUTPUT=$(semantic-release --dry-run) | |
| echo "$OUTPUT" | |
| # Extract version from output | |
| VERSION=$(echo "$OUTPUT" | grep -oP 'The next release version is \K[0-9]+\.[0-9]+\.[0-9]+' || echo "") | |
| if [ -n "$VERSION" ]; then | |
| echo "new-release-published=true" >> $GITHUB_OUTPUT | |
| echo "new-release-version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "new-release-git-tag=v$VERSION" >> $GITHUB_OUTPUT | |
| echo "Found new version: $VERSION" | |
| else | |
| echo "new-release-published=false" >> $GITHUB_OUTPUT | |
| echo "No new version needed" | |
| fi | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # Build binaries for all platforms | |
| build: | |
| name: Build ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| needs: semantic-release | |
| if: needs.semantic-release.outputs.new-release-published == 'true' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: windows-latest | |
| name: windows | |
| executable: glimpse.exe | |
| icon: app_icon.ico | |
| - os: ubuntu-latest | |
| name: linux | |
| executable: glimpse | |
| icon: app_icon.png | |
| - os: macos-latest | |
| name: macos | |
| executable: glimpse | |
| icon: app_icon.png | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.13' | |
| - name: Install uv (Windows) | |
| if: matrix.os == 'windows-latest' | |
| run: | | |
| powershell -c "irm https://astral.sh/uv/install.ps1 | iex" | |
| echo "$env:USERPROFILE\.cargo\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append | |
| - name: Install uv (Unix) | |
| if: matrix.os != 'windows-latest' | |
| run: | | |
| curl -LsSf https://astral.sh/uv/install.sh | sh | |
| echo "$HOME/.cargo/bin" >> $GITHUB_PATH | |
| - name: Install system dependencies (Linux) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| libegl1-mesa-dev \ | |
| libgl1-mesa-dev \ | |
| libxcb-image0 \ | |
| libxcb-keysyms1 \ | |
| libxcb-render-util0 \ | |
| libxcb-xkb1 \ | |
| libxkbcommon-x11-0 \ | |
| xvfb | |
| - name: Install dependencies | |
| run: | | |
| uv pip install --system pyinstaller pyside6 | |
| - name: Create version file | |
| shell: bash | |
| run: | | |
| cat > src/version.py << 'EOF' | |
| """Version information for Glimpse.""" | |
| VERSION = "${{ needs.semantic-release.outputs.new-release-version }}" | |
| def get_version(): | |
| """Get the current version string.""" | |
| return VERSION | |
| EOF | |
| - name: Check files before build (Windows) | |
| if: matrix.os == 'windows-latest' | |
| run: | | |
| echo "Checking for required files:" | |
| Get-ChildItem -Path app_icon.png, app_icon.ico, main.py, glimpse.spec -ErrorAction SilentlyContinue | Format-Table Name, Length, LastWriteTime | |
| if (-not (Test-Path app_icon.png) -or -not (Test-Path app_icon.ico) -or -not (Test-Path main.py) -or -not (Test-Path glimpse.spec)) { | |
| echo "Some files missing" | |
| } | |
| shell: powershell | |
| - name: Check files before build (Unix) | |
| if: matrix.os != 'windows-latest' | |
| run: | | |
| echo "Checking for required files:" | |
| ls -la app_icon.png app_icon.ico main.py glimpse.spec || echo "Some files missing" | |
| - name: Build executable (Linux with virtual display) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| xvfb-run -a pyinstaller glimpse.spec | |
| echo "Linux build completed. Contents of dist:" | |
| ls -la dist/ | |
| - name: Build executable (Windows) | |
| if: matrix.os == 'windows-latest' | |
| run: | | |
| pyinstaller glimpse.spec | |
| echo "Build completed. Contents of dist:" | |
| Get-ChildItem dist -Force | |
| shell: powershell | |
| - name: Build executable (macOS) | |
| if: matrix.os == 'macos-latest' | |
| run: | | |
| pyinstaller glimpse.spec | |
| echo "Build completed. Contents of dist:" | |
| ls -la dist/ | |
| - name: Get architecture (Windows) | |
| if: matrix.os == 'windows-latest' | |
| id: arch-windows | |
| run: | | |
| $arch = if ($env:PROCESSOR_ARCHITECTURE -eq "AMD64") { "x64" } else { "x86" } | |
| echo "arch=$arch" >> $env:GITHUB_OUTPUT | |
| - name: Rename and verify executable (Windows) | |
| if: matrix.os == 'windows-latest' | |
| run: | | |
| echo "Contents of dist directory:" | |
| Get-ChildItem dist -Force | |
| echo "" | |
| if (Test-Path "dist\glimpse.exe") { | |
| $newName = "glimpse-${{ needs.semantic-release.outputs.new-release-version }}-windows-${{ steps.arch-windows.outputs.arch }}.exe" | |
| Copy-Item "dist\glimpse.exe" $newName | |
| echo "Successfully created $newName" | |
| echo "File created:" | |
| Get-ChildItem $newName -Force | |
| } elseif (Test-Path "dist\glimpse") { | |
| echo "Found 'glimpse' without .exe extension - renaming it" | |
| $newName = "glimpse-${{ needs.semantic-release.outputs.new-release-version }}-windows-${{ steps.arch-windows.outputs.arch }}.exe" | |
| Copy-Item "dist\glimpse" $newName | |
| echo "Successfully created $newName from 'glimpse'" | |
| echo "File created:" | |
| Get-ChildItem $newName -Force | |
| } else { | |
| echo "ERROR: Neither dist\glimpse.exe nor dist\glimpse found!" | |
| echo "Full contents of dist:" | |
| Get-ChildItem dist -Recurse -Force | |
| exit 1 | |
| } | |
| echo "" | |
| echo "Final directory contents:" | |
| Get-ChildItem . -Force | |
| - name: Get architecture (Linux) | |
| if: matrix.os == 'ubuntu-latest' | |
| id: arch-linux | |
| run: | | |
| arch=$(uname -m) | |
| if [ "$arch" = "x86_64" ]; then | |
| echo "arch=x64" >> $GITHUB_OUTPUT | |
| echo "deb_arch=amd64" >> $GITHUB_OUTPUT | |
| elif [ "$arch" = "aarch64" ]; then | |
| echo "arch=arm64" >> $GITHUB_OUTPUT | |
| echo "deb_arch=arm64" >> $GITHUB_OUTPUT | |
| else | |
| echo "arch=x64" >> $GITHUB_OUTPUT # fallback | |
| echo "deb_arch=amd64" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Create tar.gz archive and rename binary (Linux) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| # Create renamed binary | |
| cp dist/glimpse glimpse-${{ needs.semantic-release.outputs.new-release-version }}-linux-${{ steps.arch-linux.outputs.arch }} | |
| # Create tar.gz archive | |
| cd dist | |
| tar -czf ../glimpse-${{ needs.semantic-release.outputs.new-release-version }}-linux-${{ steps.arch-linux.outputs.arch }}.tar.gz glimpse | |
| cd .. | |
| - name: Create .deb package (Linux) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| # Create directory structure for .deb package | |
| mkdir -p deb-package/DEBIAN | |
| mkdir -p deb-package/usr/bin | |
| mkdir -p deb-package/usr/share/applications | |
| mkdir -p deb-package/usr/share/pixmaps | |
| mkdir -p deb-package/usr/share/doc/glimpse | |
| # Copy executable | |
| cp dist/glimpse deb-package/usr/bin/ | |
| chmod +x deb-package/usr/bin/glimpse | |
| # Copy icon | |
| cp app_icon.png deb-package/usr/share/pixmaps/glimpse.png | |
| # Create desktop entry | |
| cat > deb-package/usr/share/applications/glimpse.desktop << EOF | |
| [Desktop Entry] | |
| Name=Glimpse | |
| Comment=Random image viewer for collections | |
| Exec=glimpse | |
| Icon=glimpse | |
| Terminal=false | |
| Type=Application | |
| Categories=Graphics;Photography;Viewer; | |
| EOF | |
| # Create control file | |
| cat > deb-package/DEBIAN/control << EOF | |
| Package: glimpse | |
| Version: ${{ needs.semantic-release.outputs.new-release-version }} | |
| Section: graphics | |
| Priority: optional | |
| Architecture: ${{ steps.arch-linux.outputs.deb_arch }} | |
| Depends: libc6, libstdc++6, libqt6core6, libqt6gui6, libqt6widgets6 | |
| Maintainer: Glimpse Team <noreply@example.com> | |
| Description: Random image viewer for collections | |
| A cross-platform desktop application for viewing random images from folders | |
| or collections. Useful for reference studies, browsing large image libraries, | |
| and rediscovering artwork. | |
| . | |
| Features include collections management, timer system, zoom and pan support, | |
| image transformations, and a dark theme interface. | |
| EOF | |
| # Create copyright file | |
| cat > deb-package/usr/share/doc/glimpse/copyright << EOF | |
| Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ | |
| Upstream-Name: glimpse | |
| Source: https://github.com/radioactiveorange/glimpse | |
| Files: * | |
| Copyright: 2024 Glimpse Team | |
| License: GPL-3.0+ | |
| This program is free software: you can redistribute it and/or modify | |
| it under the terms of the GNU General Public License as published by | |
| the Free Software Foundation, either version 3 of the License, or | |
| (at your option) any later version. | |
| . | |
| This program is distributed in the hope that it will be useful, | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| GNU General Public License for more details. | |
| . | |
| You should have received a copy of the GNU General Public License | |
| along with this program. If not, see <https://www.gnu.org/licenses/>. | |
| . | |
| On Debian systems, the complete text of the GNU General | |
| Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". | |
| EOF | |
| # Build the .deb package | |
| dpkg-deb --build deb-package glimpse-${{ needs.semantic-release.outputs.new-release-version }}-linux-${{ steps.arch-linux.outputs.arch }}.deb | |
| - name: Get architecture (macOS) | |
| if: matrix.os == 'macos-latest' | |
| id: arch-macos | |
| run: | | |
| arch=$(uname -m) | |
| if [ "$arch" = "arm64" ]; then | |
| echo "arch=arm64" >> $GITHUB_OUTPUT | |
| echo "chip=apple-silicon" >> $GITHUB_OUTPUT | |
| else | |
| echo "arch=x64" >> $GITHUB_OUTPUT | |
| echo "chip=intel" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Rename executable and create DMG (macOS) | |
| if: matrix.os == 'macos-latest' | |
| run: | | |
| # Create renamed binary | |
| cp dist/glimpse glimpse-${{ needs.semantic-release.outputs.new-release-version }}-macos-${{ steps.arch-macos.outputs.arch }} | |
| # Create a temporary directory for the DMG contents | |
| mkdir -p dmg-contents | |
| cp dist/glimpse dmg-contents/ | |
| # Create the DMG | |
| hdiutil create -volname "Glimpse ${{ needs.semantic-release.outputs.new-release-version }}" \ | |
| -srcfolder dmg-contents \ | |
| -ov \ | |
| -format UDZO \ | |
| glimpse-${{ needs.semantic-release.outputs.new-release-version }}-macos-${{ steps.arch-macos.outputs.arch }}.dmg | |
| - name: Verify artifacts before upload (Windows) | |
| if: matrix.os == 'windows-latest' | |
| run: | | |
| echo "=== FILES AVAILABLE FOR UPLOAD ===" | |
| Get-ChildItem . -Filter "glimpse-*" -Force | Select-Object Name, Length, LastWriteTime | |
| echo "" | |
| echo "=== ALL FILES IN CURRENT DIRECTORY ===" | |
| Get-ChildItem . -Force | |
| shell: powershell | |
| - name: Verify artifacts before upload (Unix) | |
| if: matrix.os != 'windows-latest' | |
| run: | | |
| echo "=== FILES AVAILABLE FOR UPLOAD ===" | |
| ls -la glimpse-* 2>/dev/null || echo "No glimpse-* files found with ls" | |
| echo "=== ALL FILES IN CURRENT DIRECTORY ===" | |
| ls -la | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: glimpse-${{ matrix.name }} | |
| path: glimpse-* | |
| if-no-files-found: error | |
| # Create the actual release with binaries | |
| release: | |
| name: Create Release | |
| runs-on: ubuntu-latest | |
| needs: [semantic-release, build] | |
| if: needs.semantic-release.outputs.new-release-published == 'true' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| ssh-key: ${{ secrets.DEPLOY_KEY }} | |
| - name: Setup Git | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| - name: Install semantic-release | |
| run: | | |
| npm install -g semantic-release @semantic-release/changelog @semantic-release/git @semantic-release/github conventional-changelog-conventionalcommits | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: ./artifacts | |
| - name: Display structure of downloaded files | |
| run: ls -R ./artifacts | |
| - name: Prepare release assets | |
| run: | | |
| mkdir -p release-assets | |
| find ./artifacts -name "*.exe" -o -name "*.tar.gz" -o -name "*.deb" -o -name "*.dmg" | xargs -I {} cp {} release-assets/ | |
| ls -la release-assets/ | |
| - name: Create version file for semantic-release | |
| run: | | |
| cat > src/version.py << 'EOF' | |
| """Version information for Glimpse.""" | |
| VERSION = "${{ needs.semantic-release.outputs.new-release-version }}" | |
| def get_version(): | |
| """Get the current version string.""" | |
| return VERSION | |
| EOF | |
| - name: Run semantic-release (full release) | |
| run: semantic-release | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Upload release assets to GitHub release | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| tag_name: ${{ needs.semantic-release.outputs.new-release-git-tag }} | |
| files: release-assets/* | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |