DEV Community

Pavan Kumar Sadashiv
Pavan Kumar Sadashiv

Posted on

Hybrid GitLab CI/CD: Orchestrating macOS Apple Silicon & Windows 11 VM Runners

Hybrid GitLab CI/CD: Orchestrating macOS Apple Silicon & Windows 11 VM Runners

Modern software engineering frequently spans multiple operating systems.

You might design low-level Metal shaders or Apple Silicon binaries on macOS, while requiring Windows 11 for native Win32/C# builds, enterprise RPA automation (such as UiPath Studio), or DirectX testing.

Relying on expensive, slow cloud-hosted runners for cross-platform builds quickly runs up massive monthly cloud bills. But with GitLab Runner, you can easily turn an Apple Silicon Mac workstation into a high-performance, multi-platform hybrid CI/CD build matrix.

In this guide, I will show you how to configure a native Apple Silicon host runner alongside a Windows 11 virtualized guest runner managed seamlessly under a single GitLab instance.


1. The Multi-Platform Architecture

+-------------------------------------------------------------+
|                     GitLab Cloud / Self-Managed             |
|                  (.gitlab-ci.yml Pipeline Matrix)           |
+-------------------------------------------------------------+
                        /                         \
           tags: [macos, arm64]         tags: [windows, x86_64]
                      /                             \
                     v                               v
+-------------------------------+   +-----------------------------+
|    Apple Silicon Host Node    |   |     Windows 11 VM Guest     |
|         (macOS Runner)        |   |    (Parallels / UTM Runner) |
|   - Metal Shaders             |   |   - .NET / C# Compilation   |
|   - Swift / Xcode Tools       |   |   - UiPath RPA Workflows    |
|   - POSIX Shell Automation    |   |   - PowerShell Automation   |
+-------------------------------+   +-----------------------------+
Enter fullscreen mode Exit fullscreen mode

2. Setting Up the Native Apple Silicon macOS Runner

On your macOS host machine, install the native ARM64 GitLab Runner:

# Download native ARM64 binary
sudo curl --output /usr/local/bin/gitlab-runner \
  "https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-arm64"

# Give execution permissions
sudo chmod +x /usr/local/bin/gitlab-runner

# Install and start as a background service
gitlab-runner install
gitlab-runner start
Enter fullscreen mode Exit fullscreen mode

Registering the macOS Runner:

gitlab-runner register \
  --url "https://gitlab.com/" \
  --registration-token "YOUR_GITLAB_REGISTRATION_TOKEN" \
  --description "Apple-Silicon-M-Host" \
  --tag-list "macos, arm64, apple-silicon" \
  --executor "shell"
Enter fullscreen mode Exit fullscreen mode

3. Configuring the Windows 11 Virtual Machine Runner

Inside your Windows 11 virtual machine (running on Parallels Desktop, UTM, or VMware Fusion):

Step A: Download & Install in PowerShell (Run as Administrator)

New-Item -ItemType Directory -Path "C:\GitLab-Runner" -Force
Set-Location "C:\GitLab-Runner"

# Download the Windows 64-bit runner binary
Invoke-WebRequest -Uri "https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-windows-amd64.exe" -OutFile "gitlab-runner.exe"

# Install as Windows Service
.\gitlab-runner.exe install
.\gitlab-runner.exe start
Enter fullscreen mode Exit fullscreen mode

Step B: Register the Windows Runner with PowerShell Tags:

.\gitlab-runner.exe register `
  --url "https://gitlab.com/" `
  --registration-token "YOUR_GITLAB_REGISTRATION_TOKEN" `
  --description "Windows-11-VM-Guest" `
  --tag-list "windows, win11, pwsh" `
  --executor "shell" `
  --shell "pwsh"
Enter fullscreen mode Exit fullscreen mode

4. Crafting the Dual-Platform .gitlab-ci.yml Pipeline

Now that both runners are active and polling your GitLab repository, define a unified pipeline matrix that automatically dispatches tasks to their respective operating systems:

stages:
  - build_macos
  - build_windows
  - verify_telemetry

# 1. macOS Build Job (Runs on Apple Silicon Host)
macos_engine_compile:
  stage: build_macos
  tags:
    - macos
    - arm64
  script:
    - uname -a
    - echo "Compiling Apple Metal shaders and Swift binaries..."
    - xcrun -sdk macosx metal -c Shaders.metal -o Shaders.air
    - xcrun -sdk macosx metallib Shaders.air -o Default.metallib
  artifacts:
    paths:
      - Default.metallib
    expire_in: 1 week

# 2. Windows Build Job (Runs in Windows 11 VM)
windows_rpa_compile:
  stage: build_windows
  tags:
    - windows
    - pwsh
  script:
    - Get-ComputerInfo | Select-Object WindowsProductName, OsArchitecture
    - Write-Host "Compiling Windows .NET and validating RPA workflows..."
    - dotnet build .\src\Engine.csproj -c Release
  artifacts:
    paths:
      - .\bin\Release\net8.0\*
    expire_in: 1 week

# 3. Aggregated Verification
audit_complete:
  stage: verify_telemetry
  needs: [macos_engine_compile, windows_rpa_compile]
  script:
    - echo "Cross-platform verification successful across macOS and Windows 11 runners!"
Enter fullscreen mode Exit fullscreen mode

5. VM Performance Optimization Tips

When hosting virtual machines on Apple Silicon for CI/CD builds:

  1. Shared Volume Caching: Mount a shared folder between macOS and the Windows VM (/Volumes/Shared $\leftrightarrow$ Z:\) to cache NuGet and pip dependencies across runs.
  2. Headless Execution: Use CLI hypervisor controls (prlctl start "Win11" --headless) to run your Windows build VM without drawing desktop UI cycles.
  3. Dedicated Core Allocation: Allocate 4 Performance cores and 8GB RAM to the VM to avoid starving the macOS host during heavy parallel builds.

6. Key Takeaways

  1. Tag-Driven Routing: GitLab CI’s tag system makes multi-OS routing clean and deterministic.
  2. True Native Performance: No emulation overhead; macOS code compiles at full Apple Silicon speed, and Windows builds execute inside a dedicated hypervisor.
  3. Massive Cloud Savings: Turn your local workstation into an enterprise-grade multi-platform CI/CD powerhouse.

Resources & Links

What does your cross-platform CI matrix look like? Drop your pipeline questions in the comments below!

Top comments (0)