Windows Installer #13
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: Windows Installer | |
| on: | |
| workflow_dispatch: | |
| repository_dispatch: | |
| types: [website-build] | |
| push: | |
| tags: | |
| - "[0-9]+.[0-9]+.[0-9]+" | |
| jobs: | |
| build-windows: | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v3 | |
| - name: Set up MSYS2 | |
| uses: msys2/setup-msys2@v2 | |
| with: | |
| msystem: UCRT64 | |
| update: true | |
| - name: Install UCRT64 dependencies | |
| shell: msys2 {0} | |
| run: | | |
| pacman -Sy --noconfirm | |
| pacman --noconfirm -S --needed \ | |
| git \ | |
| mingw-w64-ucrt-x86_64-toolchain \ | |
| mingw-w64-ucrt-x86_64-meson \ | |
| mingw-w64-ucrt-x86_64-ninja \ | |
| mingw-w64-ucrt-x86_64-pkg-config \ | |
| mingw-w64-ucrt-x86_64-python \ | |
| mingw-w64-ucrt-x86_64-python-pip \ | |
| mingw-w64-ucrt-x86_64-python-gobject \ | |
| mingw-w64-ucrt-x86_64-gtk4 \ | |
| mingw-w64-ucrt-x86_64-libadwaita \ | |
| mingw-w64-ucrt-x86_64-glib2 \ | |
| mingw-w64-ucrt-x86_64-gobject-introspection \ | |
| mingw-w64-ucrt-x86_64-gsettings-desktop-schemas \ | |
| mingw-w64-ucrt-x86_64-gtk-update-icon-cache \ | |
| mingw-w64-ucrt-x86_64-gtksourceview5 | |
| - name: Install packaging tools | |
| shell: msys2 {0} | |
| run: | | |
| pacman -Sy --noconfirm | |
| pacman --noconfirm -S --needed p7zip | |
| - name: Show tool versions | |
| shell: msys2 {0} | |
| run: | | |
| python --version | |
| meson --version | |
| ninja --version | |
| pkg-config --version | |
| - name: Build blueprint-compiler from git (v0.18.0) | |
| shell: msys2 {0} | |
| run: | | |
| set -e | |
| rm -rf /c/_deps && mkdir -p /c/_deps | |
| cd /c/_deps | |
| git clone --depth 1 --branch v0.18.0 https://gitlab.gnome.org/GNOME/blueprint-compiler.git | |
| cd blueprint-compiler | |
| meson setup build --prefix=/opt/blueprint-compiler --buildtype=release | |
| meson compile -C build | |
| meson install -C build | |
| echo "/opt/blueprint-compiler/bin" >> $GITHUB_PATH | |
| export PATH="/opt/blueprint-compiler/bin:$PATH" | |
| /opt/blueprint-compiler/bin/blueprint-compiler --version | |
| - name: Configure & build SSH Studio (Meson) | |
| shell: msys2 {0} | |
| run: | | |
| set -e | |
| export PATH="/opt/blueprint-compiler/bin:$PATH" | |
| rm -rf builddir && mkdir -p builddir | |
| meson setup builddir --prefix=/opt/ssh-studio --buildtype=release | |
| meson compile -C builddir | |
| meson install -C builddir | |
| - name: Stage install tree for packaging | |
| id: stage | |
| shell: msys2 {0} | |
| run: | | |
| set -e | |
| STAGE=/c/_stage/ssh-studio | |
| rm -rf "$STAGE" && mkdir -p "$STAGE" | |
| # Copy installed prefix | |
| cp -r /opt/ssh-studio/* "$STAGE"/ | |
| # Produce a portable zip as well | |
| cd /c/_stage | |
| 7z a SSH-Studio-portable.zip ssh-studio > /dev/null | |
| cp SSH-Studio-portable.zip /d/a/SSH-Studio/SSH-Studio/ | |
| echo STAGE_WIN_PATH=C:\\_stage\\ssh-studio >> $GITHUB_OUTPUT | |
| - name: Prepare self-contained runtime (Python embeddable + GTK runtime) | |
| shell: pwsh | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| $stage = 'C:\_stage\ssh-studio' | |
| New-Item -ItemType Directory -Force -Path $stage | Out-Null | |
| # Download latest Python 3.12 embeddable (resolve dynamically) | |
| $pyZip = "$env:RUNNER_TEMP\python-embed.zip" | |
| $idx = Invoke-WebRequest -Uri 'https://www.python.org/ftp/python/' -UseBasicParsing | |
| $vers = ($idx.Links | Where-Object { $_.href -match '^3\.12\.(\d+)/$' } | ForEach-Object { $_.href.TrimEnd('/') }) | Sort-Object {[version]$_} -Descending | |
| if (-not $vers -or -not $vers[0]) { throw 'Could not determine latest Python 3.12 version from python.org index.' } | |
| $pyVer = $vers[0] | |
| $pyUrl = "https://www.python.org/ftp/python/$pyVer/python-$pyVer-embed-amd64.zip" | |
| Invoke-WebRequest -Uri $pyUrl -OutFile $pyZip | |
| Expand-Archive -LiteralPath $pyZip -DestinationPath "$stage\python" -Force | |
| $pth = Join-Path "$stage\python" 'python312._pth' | |
| if (Test-Path $pth) { | |
| $content = Get-Content -Raw -Path $pth | |
| if ($content -notmatch 'import site') { | |
| Add-Content -Path $pth -Value "`r`nimport site`r`n" | |
| } | |
| } | |
| # Download GTK runtime (gvsbuild release) | |
| $api = 'https://api.github.com/repos/wingtk/gvsbuild/releases/latest' | |
| $headers = @{ 'User-Agent' = 'github-actions'; 'Authorization' = "Bearer $env:GITHUB_TOKEN" } | |
| $rel = Invoke-RestMethod -Headers $headers -Uri $api -Method GET | |
| $asset = $rel.assets | Where-Object { $_.name -match 'gtk.*runtime.*(64|x86_64).*\.zip' } | Select-Object -First 1 | |
| if (-not $asset) { throw 'Could not find GTK runtime asset in gvsbuild latest release.' } | |
| $gtkZip = "$env:RUNNER_TEMP\gtk-runtime.zip" | |
| Invoke-WebRequest -Uri $asset.browser_download_url -OutFile $gtkZip | |
| Expand-Archive -LiteralPath $gtkZip -DestinationPath "$stage\gtk_tmp" -Force | |
| $gtkOut = "$stage\gtk" | |
| New-Item -ItemType Directory -Force -Path $gtkOut | Out-Null | |
| $candidate = Get-ChildItem -Path "$stage\gtk_tmp" -Directory | Select-Object -First 1 | |
| if ($candidate) { Copy-Item -Recurse -Force "$($candidate.FullName)\*" $gtkOut } else { Copy-Item -Recurse -Force "$stage\gtk_tmp\*" $gtkOut } | |
| Remove-Item -Recurse -Force "$stage\gtk_tmp" | |
| # Create launcher.vbs (no console) | |
| $vbs = @' | |
| Set oShell = CreateObject("WScript.Shell") | |
| Set env = oShell.Environment("PROCESS") | |
| Set fso = CreateObject("Scripting.FileSystemObject") | |
| appDir = fso.GetAbsolutePathName(".") | |
| env("PATH") = appDir & "\\gtk\\bin;" & appDir & "\\python;" & env("PATH") | |
| env("PYTHONHOME") = appDir & "\\python" | |
| env("PYTHONPATH") = appDir & "\\lib\\python3.12\\site-packages" | |
| env("GI_TYPELIB_PATH") = appDir & "\\gtk\\lib\\girepository-1.0" | |
| env("XDG_DATA_DIRS") = appDir & "\\share;" & appDir & "\\gtk\\share" | |
| oShell.Run '"' & appDir & "\\python\\pythonw.exe" & '" -m ssh_studio.main', 0 | |
| '@ | |
| Set-Content -Encoding ASCII -Path "$stage\launcher.vbs" -Value $vbs | |
| - name: Download Inno Setup | |
| run: | | |
| $url = "https://files.jrsoftware.org/is/6/innosetup-6.2.2.exe" | |
| $output = "C:\innosetup.exe" | |
| Invoke-WebRequest -Uri $url -OutFile $output | |
| Start-Process -FilePath $output -ArgumentList "/SILENT" -Wait | |
| - name: Build Inno Setup installer | |
| run: | | |
| $version = if ($env:GITHUB_REF_NAME) { $env:GITHUB_REF_NAME } else { "dev" } | |
| & "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" /DAppName="SSH-Studio" /DVersion="$version" /DSourceDir="C:\_stage\ssh-studio" "installer\ssh-studio.iss" | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: windows-artifacts | |
| path: | | |
| SSH-Studio-portable.zip | |
| installer/installer/out/*.exe | |