Use Docker as default WiX runtime on macOS arm64 (#43715)

<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #43484

# Details

Apple Silicon Macs were being forced down the Wine+local-wix-dir path
because the fleetdm/wix:latest image was deemed unreliable on arm64 in
Jan 2024. Docker Desktop's amd64 emulation has matured since -- the
image builds both amd64 and arm64 MSIs on arm64 macOS successfully. This
PR:

- Drops the arm64-forces-Wine guard in BuildMSI so the Docker path is
the default on every macOS arch when --local-wix-dir isn't provided.
- Drops the macOS "Install wine and wix" + "Build MSI on macOS (using
local Wix)" CI steps. The ubuntu-latest matrix entry already exercises
the Docker path, and the install-wine.sh flow is brittle against Gcenx
release churn and homebrew-cask deprecation.
- Updates the install-wine.sh script to fail and output a message
indicating that Docker should be used, or else Wine installed manually.
```
============================================================
This script no longer installs Wine.
============================================================

Wine is no longer required to build Windows (.msi) packages on macOS.
fleetctl package now uses Docker by default on all macOS architectures.

RECOMMENDED: install Docker Desktop
  https://docs.docker.com/get-docker

If you cannot use Docker and still need to build MSIs with Wine on macOS
see the upstream WineHQ wiki for installation instructions:
  https://gitlab.winehq.org/wine/wine/-/wikis/MacOS

Automatic Wine installation via Homebrew is no longer attempted here
because the wine-stable cask is deprecated and upstream Wine releases
have caused repeated breakage.
```
- Retains the wix auto-download helper (downloadAndExtractZip,
extractZipFile, wixDownload) for backwards-compatibility when Docker
isn't detected, with a deprecation warning.

The Wine + --local-wix-dir path remains available for macOS users who
opt into it, but is no longer documented. See #43484.

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

## Testing

- [X] Added/updated automated tests
- Dropped MacOS packaging tests. The Ubuntu test already exercises the
Docker path that MacOS now uses.
- [X] QA'd all new/changed functionality manually
  - Built and installed both amd64 and arm64 .msi packages successfully

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* MSI packages on macOS now build using Docker by default, removing the
Wine dependency.

* **Documentation**
* Updated macOS setup guidance: Docker Desktop is now required for MSI
packaging instead of Wine.

* **Chores**
* Simplified Wine-related helper scripts and removed outdated
installation logic.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Scott Gress
2026-04-21 10:53:46 -05:00
committed by GitHub
parent 92488b2115
commit df44a9342e
5 changed files with 60 additions and 92 deletions
-14
View File
@@ -84,16 +84,6 @@ jobs:
with:
go-version-file: "go.mod"
- name: Install wine and wix
if: startsWith(matrix.os, 'macos')
run: |
./assets/scripts/install-wine.sh -n
wget https://github.com/wixtoolset/wix3/releases/download/wix3112rtm/wix311-binaries.zip -nv -O wix.zip
mkdir wix
unzip wix.zip -d wix
rm -f wix.zip
echo wix installed at $(pwd)/wix
- name: Build fleetctl
run: make fleetctl
@@ -128,7 +118,3 @@ jobs:
- name: Build PKG with Fleet Desktop
run: ./build/fleetctl package --type pkg --enroll-secret=foo --fleet-url=https://localhost:8080 --fleet-desktop
- name: Build MSI on macOS (using local Wix)
if: startsWith(matrix.os, 'macos')
run: ./build/fleetctl package --type msi --enroll-secret=foo --fleet-url=https://localhost:8080 --fleet-desktop --local-wix-dir ./wix
+19 -58
View File
@@ -1,68 +1,29 @@
#!/bin/bash
# Please don't delete. This script is linked to, as a redirect, from fleetctl and the Fleet website.
# Please don't delete. This script is linked to, as a redirect, from fleetctl and
# the Fleet website. It is preserved as an informational endpoint at
# https://fleetdm.com/install-wine so existing links don't 404.
set -eo pipefail
cat <<'EOF'
============================================================
This script no longer installs Wine.
============================================================
brew_wine(){
# Wine reference: https://wiki.winehq.org/MacOS
# Wine can be installed without brew via a distribution such as https://github.com/Gcenx/macOS_Wine_builds/releases/tag/10.0 or by building from source.
# To install a version tied to a specific commit SHA we must create a local tap and install from it after wine 4.6.4 dropped support, see
# https://github.com/Homebrew/brew/pull/20414
TAP_PATH="$(brew --repository)/Library/Taps/fleet/homebrew-local/Casks"
mkdir -p "${TAP_PATH}"
echo "# tap auto-generated by Fleet for installing wine-stable" > "$(dirname "${TAP_PATH}")/README.md"
curl -O https://raw.githubusercontent.com/Homebrew/homebrew-cask/8a5c4ae85cc2def6a1192779469170df3853e80c/Casks/w/wine-stable.rb
mv wine-stable.rb "${TAP_PATH}/"
brew install --cask fleet/local/wine-stable
xattr -dr com.apple.quarantine "$(brew --prefix)/Caskroom/wine-stable"
exit 0
}
Wine is no longer required to build Windows (.msi) packages on macOS.
fleetctl package now uses Docker by default on all macOS architectures.
RECOMMENDED: install Docker Desktop
https://docs.docker.com/get-docker
warn_wine(){
printf "\nWARNING: The Wine app developer has an Apple Developer certificate but the\napp bundle post-installation will not be code-signed or notarized.\n\nDo you wish to proceed?\n\n"
while true
do
read -r -p "install> " install
case "$install" in
y|yes|Y|YES) brew_wine ;;
n|no|N|NO) printf "\nExiting...\n\n"; exit 1 ;;
*) printf "\nPlease enter yes or no at the prompt...\n\n" ;;
esac
done
}
If you cannot use Docker and still need to build MSIs with Wine on macOS
see the upstream WineHQ wiki for installation instructions:
https://gitlab.winehq.org/wine/wine/-/wikis/MacOS
Automatic Wine installation via Homebrew is no longer attempted here
because the wine-stable cask is deprecated and upstream Wine releases
have caused repeated breakage.
# option to execute script in non-interactive mode
while getopts 'n' option
do
case "$option" in
n) mode=auto ;;
*) : ;;
esac
done
EOF
# prevent root execution
if [ "$EUID" = 0 ]
then
printf "\nTo prevent unnecessary privilege elevation do not execute this script as the root user.\nExiting...\n\n"; exit 1
fi
# check if Homebrew is installed
if ! command -v brew > /dev/null 2>&1
then
printf "\nHomebrew is not installed.\nPlease install Homebrew.\nFor instructions, see https://brew.sh/\n\n"; exit 1
fi
# install Wine
if [ "$mode" = 'auto' ]
then
printf "\n%s executed in non-interactive mode.\n\n" "$0"; brew_wine
else
warn_wine
fi
exit 1
+1
View File
@@ -0,0 +1 @@
* Use Docker as the default WiX runtime on macOS (including Apple Silicon) when generating `.msi` packages via `fleetctl package`. Wine is no longer required on macOS for the default path.
+33 -17
View File
@@ -180,24 +180,29 @@ func BuildMSI(opt Options) (string, error) {
absWixDir := opt.LocalWixDir
wineChecked := false
// Download wix for macOS running on arm64, unless a local-wix-dir is provided.
// We are using native MSI build on macOS arm64, instead of Docker, because the current fleetdm/wix Docker image is unreliable on macOS arm64.
// We are looking into creating a new Docker image for macOS arm64.
if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" && absWixDir == "" {
fmt.Println("Detected macOS arm64. fleetctl must use locally installed wine and wix to build the MSI package.")
// On macOS without --local-wix-dir, the default path uses Docker.
// For backwards compatibility with existing pipelines that rely
// on the legacy Wine + auto-downloaded WiX flow, fall back to that
// path if Docker isn't available — but warn that it's deprecated.
if runtime.GOOS == "darwin" && !opt.NativeTooling && absWixDir == "" {
if dockerErr := checkDockerAvailable(); dockerErr != nil {
fmt.Printf("\nWARNING: Docker is not available (%s).\n", dockerErr)
fmt.Println("Falling back to Wine + auto-downloaded WiX toolset. This path is deprecated")
fmt.Println("and will be removed in a future release. Install Docker Desktop to use the")
fmt.Println("supported path: https://docs.docker.com/get-docker")
fmt.Println()
// Ensure wine is installed before downloading wix
if err = checkWine(false); err != nil {
return "", err
}
wineChecked = true
if err = checkWine(false); err != nil {
return "", err
}
wineChecked = true
fmt.Printf("Downloading wix from %s\n", wixDownload)
client := fleethttp.NewClient()
absWixDir = filepath.Join(tmpDir, "wix")
err = downloadAndExtractZip(client, wixDownload, absWixDir)
if err != nil {
return "", err
fmt.Printf("Downloading wix from %s\n", wixDownload)
client := fleethttp.NewClient()
absWixDir = filepath.Join(tmpDir, "wix")
if err = downloadAndExtractZip(client, wixDownload, absWixDir); err != nil {
return "", err
}
}
}
@@ -250,7 +255,7 @@ func checkWine(wineChecked bool) error {
cmd := exec.Command(wix.WineCmd, "--version")
if err := cmd.Run(); err != nil {
return fmt.Errorf(
"%s failed. Is Wine installed? Creating a fleetd agent for Windows (.msi) requires Wine. To install Wine see the script here: https://fleetdm.com/install-wine %w",
"%s failed. Is Wine installed? %w",
wix.WineCmd, err,
)
}
@@ -258,6 +263,17 @@ func checkWine(wineChecked bool) error {
return nil
}
// checkDockerAvailable returns nil if the docker CLI is on PATH and the Docker
// daemon is reachable. Otherwise it returns an error summarizing what went
// wrong, which callers can use to decide whether to fall back to another path.
func checkDockerAvailable() error {
cmd := exec.Command("docker", "version")
if err := cmd.Run(); err != nil {
return err
}
return nil
}
func writeWixFile(opt Options, rootPath string) error {
// PackageInfo is metadata for the pkg
path := filepath.Join(rootPath, "main.wxs")
+7 -3
View File
@@ -33,6 +33,7 @@ func Heat(path string, native bool, localWixDir string) error {
args = append(
args,
"docker", "run", "--rm", "--platform", dockerPlatform,
"--env", "XDG_RUNTIME_DIR=/tmp", // silence Wine warning inside container
"--volume", path+":/wix", // mount volume
imageName, // image name
)
@@ -79,17 +80,18 @@ func Heat(path string, native bool, localWixDir string) error {
}
func darwinWineExecutable() (string, error) {
wineWarning := "Is Wine installed? Building a Windows (.msi) package with --local-wix-dir on macOS requires Wine; the default path uses Docker instead."
cmdOut, err := exec.Command("wine", "--version").Output()
if err != nil {
return "", fmt.Errorf("running wine to get version information: %w", err)
return "", fmt.Errorf("running wine to get version information: %w. %s", err, wineWarning)
}
wineVerStr, found := strings.CutPrefix(string(cmdOut), "wine-")
if !found {
return "", fmt.Errorf("Unknown wine version: %q. Is Wine installed? Creating a fleetd agent for Windows (.msi) requires Wine. To install Wine see the script here: https://fleetdm.com/install-wine ", string(cmdOut))
return "", fmt.Errorf("Unknown wine version: %q. %s", string(cmdOut), wineWarning)
}
wineVersion, err := strconv.ParseInt(strings.Split(wineVerStr, ".")[0], 10, 64)
if err != nil {
return "", fmt.Errorf("Unable to parse wine version: %q. Is Wine installed? Creating a fleetd agent for Windows (.msi) requires Wine. To install Wine see the script here: https://fleetdm.com/install-wine ", wineVerStr)
return "", fmt.Errorf("Unable to parse wine version: %q. %s", wineVerStr, wineWarning)
}
if wineVersion < 10 {
return Wine64Cmd, nil
@@ -108,6 +110,7 @@ func Candle(path string, native bool, localWixDir string, arch string) error {
args = append(
args,
"docker", "run", "--rm", "--platform", dockerPlatform,
"--env", "XDG_RUNTIME_DIR=/tmp", // silence Wine warning inside container
"--volume", path+":/wix", // mount volume
imageName, // image name
)
@@ -165,6 +168,7 @@ func Light(path string, native bool, localWixDir string) error {
args = append(
args,
"docker", "run", "--rm", "--platform", dockerPlatform,
"--env", "XDG_RUNTIME_DIR=/tmp", // silence Wine warning inside container
"--volume", path+":/wix", // mount volume
imageName, // image name
)