feat: add Windows build support with Scoop manifest #21
Workflow file for this run
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: Release | |
| on: | |
| push: | |
| tags: | |
| - '[0-9]+.[0-9]+.[0-9]+' | |
| jobs: | |
| release: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| outputs: | |
| version: ${{ steps.version.outputs.version }} | |
| tarball-hash: ${{ steps.sha256.outputs.hash }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y meson ninja-build gettext appstream desktop-file-utils libglib2.0-dev | |
| - name: Get version from tag | |
| id: version | |
| run: echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT | |
| - name: Create source tarball | |
| run: | | |
| meson setup build | |
| meson dist -C build --no-tests --include-subprojects | |
| TARBALL=$(ls build/meson-dist/*.tar.xz) | |
| mv "$TARBALL" "awakeonlan-${{ steps.version.outputs.version }}.tar.xz" | |
| - name: Calculate SHA256 | |
| id: sha256 | |
| run: | | |
| HASH=$(sha256sum awakeonlan-${{ steps.version.outputs.version }}.tar.xz | awk '{print $1}') | |
| echo "hash=$HASH" >> $GITHUB_OUTPUT | |
| echo "SHA256: $HASH" | |
| - name: Generate release notes | |
| id: release_notes | |
| run: | | |
| PREVIOUS_TAG=$(git tag --sort=-version:refname | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | head -2 | tail -1) | |
| if [ -z "$PREVIOUS_TAG" ]; then | |
| PREVIOUS_TAG=$(git rev-list --max-parents=0 HEAD) | |
| fi | |
| echo "Comparing $PREVIOUS_TAG..HEAD" | |
| { | |
| echo 'notes<<EOF' | |
| git log --oneline --no-decorate "$PREVIOUS_TAG..HEAD" \ | |
| | sed 's/^\([a-f0-9]\+\) \(.*\)/- \2 (\1)/' \ | |
| || echo "- Initial release" | |
| echo 'EOF' | |
| } >> $GITHUB_OUTPUT | |
| - name: Create GitHub release | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| gh release create ${{ steps.version.outputs.version }} \ | |
| awakeonlan-${{ steps.version.outputs.version }}.tar.xz \ | |
| --title "Awake on LAN ${{ steps.version.outputs.version }}" \ | |
| --notes "${{ steps.release_notes.outputs.notes }}" | |
| windows-build: | |
| runs-on: windows-latest | |
| needs: release | |
| permissions: | |
| contents: write | |
| outputs: | |
| hash: ${{ steps.sha256.outputs.hash }} | |
| env: | |
| gvsbuild_version: 2026.4.1 | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: GTK binaries get from cache | |
| uses: actions/cache@v4 | |
| id: cache | |
| with: | |
| path: C:\gtk\** | |
| key: ${{ runner.os }}-gvsbuild-${{ env.gvsbuild_version }} | |
| - name: Download Gvsbuild | |
| if: steps.cache.outputs.cache-hit != 'true' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| $version = $env:gvsbuild_version | |
| gh release download --repo wingtk/gvsbuild "$version" -p "GTK4_Gvsbuild_$($version)_x64.zip" | |
| 7z x "GTK4_Gvsbuild_$($version)_x64.zip" -oC:\gtk -y | |
| - name: Set up GTK environment | |
| run: | | |
| Write-Output "C:\gtk\bin" >> $env:GITHUB_PATH | |
| Write-Output "PKG_CONFIG=C:\gtk\bin\pkgconf.exe" >> $env:GITHUB_ENV | |
| Write-Output "XDG_DATA_HOME=$HOME\.local\share" >> $env:GITHUB_ENV | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.14' | |
| - name: Install Python dependencies | |
| run: | | |
| pip install --force-reinstall (Resolve-Path C:\gtk\wheels\PyGObject*.whl) | |
| pip install --force-reinstall (Resolve-Path C:\gtk\wheels\pycairo*.whl) | |
| pip install pyinstaller pyinstaller-hooks-contrib | |
| - name: Verify gi module | |
| run: | | |
| python -c "import sys; print('Python:', sys.executable); print('Path:', sys.path)" | |
| pip show PyGObject | |
| python -c "import os; os.add_dll_directory(r'C:\gtk\bin'); import gi; gi.require_version('Gtk', '4.0'); gi.require_version('Adw', '1'); from gi.repository import Gtk, Adw; print('GTK', Gtk.get_major_version(), Gtk.get_minor_version()); print('Adw OK')" | |
| - name: Convert icon to .ico | |
| run: magick -background none data/icons/hicolor/scalable/apps/co.logonoff.awakeonlan.svg -define icon:auto-resize=256,128,64,48,32,16 awakeonlan.ico | |
| - name: Prepare entry point | |
| run: | | |
| $version = "${{ needs.release.outputs.version }}" | |
| (Get-Content src/awakeonlan.in) ` | |
| -replace '@PYTHON@','/usr/bin/python3' ` | |
| -replace '@VERSION@',$version ` | |
| -replace '@pkgdatadir@','.' ` | |
| -replace '@localedir@','./locale' | | |
| Set-Content src/awakeonlan.in | |
| - name: Compile GResources | |
| run: | | |
| Copy-Item data/co.logonoff.awakeonlan.metainfo.xml.in data/co.logonoff.awakeonlan.metainfo.xml | |
| Push-Location src | |
| glib-compile-resources --sourcedir=. --sourcedir=.. awakeonlan.gresource.xml --target=awakeonlan.gresource | |
| Pop-Location | |
| - name: Compile GSettings schemas | |
| run: glib-compile-schemas data/ | |
| - name: Build with PyInstaller | |
| run: pyinstaller awakeonlan.spec | |
| - name: Bundle additional resources | |
| run: | | |
| # GSettings schemas: combine app + gvsbuild schemas | |
| New-Item -ItemType Directory -Force dist/awakeonlan/share/glib-2.0/schemas | |
| Copy-Item C:\gtk\share\glib-2.0\schemas\*.xml dist/awakeonlan/share/glib-2.0/schemas/ | |
| Copy-Item data/co.logonoff.awakeonlan.gschema.xml dist/awakeonlan/share/glib-2.0/schemas/ | |
| glib-compile-schemas dist/awakeonlan/share/glib-2.0/schemas/ | |
| # Icon themes | |
| New-Item -ItemType Directory -Force dist/awakeonlan/share/icons | |
| Copy-Item -Recurse C:\gtk\share\icons\Adwaita dist/awakeonlan/share/icons/ | |
| Copy-Item -Recurse C:\gtk\share\icons\hicolor dist/awakeonlan/share/icons/ | |
| # App icon | |
| New-Item -ItemType Directory -Force dist/awakeonlan/share/icons/hicolor/scalable/apps | |
| Copy-Item data/icons/hicolor/scalable/apps/co.logonoff.awakeonlan.svg dist/awakeonlan/share/icons/hicolor/scalable/apps/ | |
| New-Item -ItemType Directory -Force dist/awakeonlan/share/icons/hicolor/symbolic/apps | |
| Copy-Item data/icons/hicolor/symbolic/apps/co.logonoff.awakeonlan-symbolic.svg dist/awakeonlan/share/icons/hicolor/symbolic/apps/ | |
| - name: Create ZIP archive | |
| run: Compress-Archive -Path dist/awakeonlan -DestinationPath awakeonlan-${{ needs.release.outputs.version }}-windows-x86_64.zip | |
| - name: Calculate SHA256 | |
| id: sha256 | |
| run: | | |
| $hash = (Get-FileHash awakeonlan-${{ needs.release.outputs.version }}-windows-x86_64.zip -Algorithm SHA256).Hash.ToLower() | |
| echo "hash=$hash" >> $env:GITHUB_OUTPUT | |
| - name: Upload to release | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: gh release upload ${{ needs.release.outputs.version }} awakeonlan-${{ needs.release.outputs.version }}-windows-x86_64.zip | |
| update-manifests: | |
| runs-on: ubuntu-latest | |
| needs: [release, windows-build] | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Update manifests | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| VERSION=${{ needs.release.outputs.version }} | |
| TARBALL_HASH=${{ needs.release.outputs.tarball-hash }} | |
| WINDOWS_HASH=${{ needs.windows-build.outputs.hash }} | |
| # Update Homebrew formula | |
| sed -i "s/version \".*\"/version \"$VERSION\"/" Formula/awakeonlan.rb | |
| sed -i "s/sha256 \".*\"/sha256 \"$TARBALL_HASH\"/" Formula/awakeonlan.rb | |
| # Update Scoop manifest | |
| sed -i "s/\"version\": \".*\"/\"version\": \"$VERSION\"/" bucket/awakeonlan.json | |
| sed -i "s|download/.*/awakeonlan-.*-windows-x86_64.zip|download/${VERSION}/awakeonlan-${VERSION}-windows-x86_64.zip|" bucket/awakeonlan.json | |
| sed -i "s/\"hash\": \".*\"/\"hash\": \"$WINDOWS_HASH\"/" bucket/awakeonlan.json | |
| FORMULA_CONTENT=$(base64 -w 0 < Formula/awakeonlan.rb) | |
| SCOOP_CONTENT=$(base64 -w 0 < bucket/awakeonlan.json) | |
| MAIN_OID=$(gh api graphql -f query='{ repository(owner:"logonoff", name:"awake-on-lan") { ref(qualifiedName:"refs/heads/main") { target { oid } } } }' --jq '.data.repository.ref.target.oid') | |
| jq -n \ | |
| --arg oid "$MAIN_OID" \ | |
| --arg formula "$FORMULA_CONTENT" \ | |
| --arg scoop "$SCOOP_CONTENT" \ | |
| --arg version "$VERSION" \ | |
| '{ | |
| query: "mutation($input: CreateCommitOnBranchInput!) { createCommitOnBranch(input: $input) { commit { oid } } }", | |
| variables: { | |
| input: { | |
| branch: { repositoryNameWithOwner: "logonoff/awake-on-lan", branchName: "main" }, | |
| expectedHeadOid: $oid, | |
| message: { headline: ("chore: update manifests to " + $version) }, | |
| fileChanges: { additions: [ | |
| { path: "Formula/awakeonlan.rb", contents: $formula }, | |
| { path: "bucket/awakeonlan.json", contents: $scoop } | |
| ] } | |
| } | |
| } | |
| }' | |
| # | gh api graphql --input - | |
| # - name: Sync homebrew-bucket | |
| # run: | | |
| # gh api repos/logonoff/homebrew-bucket/dispatches \ | |
| # -f event_type=sync | |
| # env: | |
| # GH_TOKEN: ${{ secrets.BUCKET_PAT }} | |
| - name: Check if next branch can be fast-forwarded | |
| id: check-next | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| if git ls-remote --exit-code origin next &>/dev/null; then | |
| git fetch origin next main | |
| if git merge-base --is-ancestor origin/next origin/main; then | |
| echo "can_ff=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| fi | |
| - name: Fast-forward next branch | |
| if: steps.check-next.outputs.can_ff == 'true' | |
| run: git push origin origin/main:next | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |