Skip to content

Windows Installer

Windows Installer #12

Workflow file for this run

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 Python embeddable 3.12
$pyUrl = 'https://www.python.org/ftp/python/3.12.11/python-3.12.11-embed-amd64.zip'
$pyZip = "$env:RUNNER_TEMP\python-embed.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