ci: build MSI on windows-host #10

Merged
gsadmin merged 1 commits from development into main 2026-09-02 14:00:24 +00:00
+81 -34
View File
@@ -2,8 +2,8 @@ name: Release
# Fires only on a merge into main (a push to the main branch). No per-commit
# or per-PR CI runs on other branches — this is the single pipeline that turns
# what lands on main into a release, cross-platform binaries, an MSI, and a
# container image.
# what lands on main into a release, cross-platform binaries, a Windows MSI, and
# a container image.
#
# Docs-only merges are skipped: touching just README/docs/LICENSE does not
# produce a new build.
@@ -21,9 +21,9 @@ on:
jobs:
release:
# Label must match a registered Linux runner that has Docker. Pure-Go builds
# (modernc SQLite, CGO off) mean every OS/arch cross-compiles here, and WiX v5
# builds the Windows MSI on Linux, so one runner produces every artifact.
# Linux runner with Docker. Pure-Go builds (modernc SQLite, CGO off) mean
# every OS/arch cross-compiles here; the Windows MSI is built in the separate
# `msi` job on a Windows runner (WiX only supports Windows).
runs-on: ubuntu-host
# Grant the auto-injected Actions token the scopes this job needs: push to
@@ -32,6 +32,11 @@ jobs:
contents: write
packages: write
# Consumed by the `msi` job so the installer version and binary match.
outputs:
version: ${{ steps.ver.outputs.version }}
msi_version: ${{ steps.ver.outputs.msi_version }}
env:
# Use exactly the toolchain provided by setup-go; never auto-download a
# different Go toolchain (a `go install ...@latest` otherwise pulled a
@@ -126,7 +131,6 @@ jobs:
echo "resolved GOROOT: $GR"
echo "GOROOT=$GR" >> "$GITHUB_ENV"
GOROOT="$GR" go version
GOROOT="$GR" go tool compile -V || true
GOROOT="$GR" go clean -cache
- name: Setup Node
@@ -134,11 +138,6 @@ jobs:
with:
node-version: '22'
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Ensure tooling (jq, zip)
shell: bash
run: |
@@ -199,7 +198,7 @@ jobs:
# Cross-compile all six targets (CGO off) and package them: .zip for
# Windows, .tar.gz elsewhere, each with a .sha256. Stage the windows/amd64
# binary for the MSI.
# binary separately so the msi job can wrap it.
- name: Build binaries
working-directory: backend
env:
@@ -242,24 +241,14 @@ jobs:
build linux arm64 linux-arm64 ""
ls -la "$DIST"
# Build the Windows MSI with WiX v5 (cross-platform, no OSMF fee). Installs
# to Program Files\OrchestrAD and registers+starts the service via the
# binary's idempotent `initialize`/`remove` commands.
- name: Build MSI
env:
MSI_VERSION: ${{ steps.ver.outputs.msi_version }}
VERSION: ${{ steps.ver.outputs.version }}
run: |
set -euo pipefail
export PATH="$PATH:$HOME/.dotnet/tools"
command -v wix >/dev/null 2>&1 || dotnet tool install --global wix --version 5.0.2
wix build -arch x64 installer/OrchestrAD.wxs \
-d Version="$MSI_VERSION" \
-d BinDir="$GITHUB_WORKSPACE/msistage" \
-d IconPath="$GITHUB_WORKSPACE/resources/icons/orchestrad.ico" \
-o "dist/OrchestrAD-${VERSION}-x64.msi"
( cd dist && sha256sum "OrchestrAD-${VERSION}-x64.msi" > "OrchestrAD-${VERSION}-x64.msi.sha256" )
ls -la dist
# Hand the windows/amd64 binary to the msi job (which runs on Windows,
# where WiX is supported).
- name: Upload Windows binary for MSI
uses: actions/upload-artifact@v3
with:
name: msi-bin
path: msistage/orchestrad.exe
retention-days: 1
- name: Resolve registry target
id: reg
@@ -314,7 +303,8 @@ jobs:
docker push "${IMAGE}:latest"
echo "Published ${IMAGE}:${VERSION} and ${IMAGE}:latest"
# Create the Gitea release and attach every artifact in dist/.
# Create the Gitea release and attach every binary artifact in dist/. The
# MSI is added later by the msi job.
- name: Create Gitea release
shell: bash
env:
@@ -328,8 +318,6 @@ jobs:
run: |
set -euo pipefail
# Skip creation if a release for this tag already exists (re-run), but
# still (re)upload any assets that are missing below.
code="$(curl -sS -o /tmp/rel.json -w '%{http_code}' \
-H "Authorization: token ${TOKEN}" \
"${API_URL}/repos/${REPO}/releases/tags/${VERSION}")"
@@ -359,4 +347,63 @@ jobs:
-F "attachment=@${asset}" \
"${API_URL}/repos/${REPO}/releases/${rel_id}/assets?name=${name}" >/dev/null
done
echo "Release ${VERSION} published with $(ls dist | wc -l) assets."
echo "Release ${VERSION} published with $(ls dist | wc -l) binary assets."
msi:
# WiX only supports Windows, so the installer is built here on the Windows
# runner using the windows/amd64 binary produced by the release job, then
# attached to the release the previous job created.
needs: release
runs-on: windows-host
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Download Windows binary
uses: actions/download-artifact@v3
with:
name: msi-bin
path: msistage
- name: Build and attach MSI
shell: pwsh
env:
API_URL: ${{ github.api_url }}
REPO: ${{ github.repository }}
TOKEN: ${{ github.token }}
VERSION: ${{ needs.release.outputs.version }}
MSI_VERSION: ${{ needs.release.outputs.msi_version }}
run: |
$ErrorActionPreference = 'Stop'
$env:PATH += ";$env:USERPROFILE\.dotnet\tools"
if (-not (Get-Command wix -ErrorAction SilentlyContinue)) {
dotnet tool install --global wix --version 5.0.2
}
New-Item -ItemType Directory -Force dist | Out-Null
$msi = "dist/OrchestrAD-$($env:VERSION)-x64.msi"
wix build -arch x64 installer/OrchestrAD.wxs `
-d Version="$($env:MSI_VERSION)" `
-d BinDir="$PWD/msistage" `
-d IconPath="$PWD/resources/icons/orchestrad.ico" `
-o $msi
if ($LASTEXITCODE -ne 0) { throw "wix build failed ($LASTEXITCODE)" }
$hash = (Get-FileHash $msi -Algorithm SHA256).Hash.ToLower()
"$hash OrchestrAD-$($env:VERSION)-x64.msi" | Set-Content "$msi.sha256"
$headers = @{ Authorization = "token $($env:TOKEN)" }
$rel = Invoke-RestMethod -Headers $headers -Uri "$($env:API_URL)/repos/$($env:REPO)/releases/tags/$($env:VERSION)"
foreach ($asset in @($msi, "$msi.sha256")) {
$name = Split-Path $asset -Leaf
Write-Host "Uploading $name"
curl.exe -sS -X POST -H "Authorization: token $($env:TOKEN)" `
-F "attachment=@$asset" `
"$($env:API_URL)/repos/$($env:REPO)/releases/$($rel.id)/assets?name=$name" | Out-Null
}
Write-Host "MSI attached to release $($env:VERSION)."