Skip to content

fix: windows build

fix: windows build #16

Workflow file for this run

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 }}