Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions .github/workflows/mac.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# Mac CI: build on GHA-hosted macos-15 (ephemeral, fast); machine e2e on a
# self-hosted EC2 mac2.metal runner (bare-metal Hypervisor.framework).

name: Mac

on:
workflow_dispatch:
pull_request:
paths:
- '.github/workflows/mac.yml'
- 'cmd/**'
- 'pkg/**'
- 'libpod/**'
- 'contrib/pkginstaller/**'
- 'Makefile'
- 'go.mod'
- 'go.sum'

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
name: build (darwin arm64)
runs-on: macos-15
timeout-minutes: 30
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version-file: go.mod
cache: true

- name: Lint
run: make golangci-lint

- name: Build core binaries
run: |
make .install.ginkgo
make podman-remote
make podman-mac-helper

- name: Build .pkg installer
run: |
pushd contrib/pkginstaller
make ARCH=aarch64 NO_CODESIGN=1 pkginstaller
popd

- name: Build release zip
run: make podman-remote-release-darwin_arm64.zip

- name: Upload artifacts
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: podman-darwin-arm64
path: |
podman-remote-release-darwin_arm64.zip
contrib/pkginstaller/out/podman-installer-macos-*.pkg
if-no-files-found: error

machine:
name: machine (applehv)
needs: build
runs-on:
group: mac-pool
timeout-minutes: 60
env:
PROVIDER: applehv
CONTAINERS_MACHINE_PROVIDER: applehv
# pkg/machine/e2e/machine_test.go rejects TMPDIR >= 22 chars on darwin
# (Unix socket path budget). /private/tmp is 12 chars.
TMPDIR: /private/tmp/ci

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version-file: go.mod
cache: true

# - name: Pre-clean machine state
# run: ./contrib/gha/mac/clean_state.sh

- name: Build podman + ginkgo + mac-helper
# Mirrors contrib/cirrus/.cirrus.yml osx_alt_build_task basic_build_script.
# No `sudo installer -pkg` — tests run as ec2-user and use the binaries
# built right here in $GITHUB_WORKSPACE/bin/darwin/. vfkit, krunkit,
# gvproxy come from /opt/homebrew/bin (installed once at host setup).
run: |
make .install.ginkgo
make podman-remote
make podman-mac-helper

- name: Run machine e2e
# `make localmachine` is the same target Cirrus's mac_runner.sh invokes.
run: make localmachine

- name: Collect diagnostic logs
if: failure()
run: ./contrib/gha/mac/collect_diagnostics.sh

# - name: Post-run cleanup
# if: always()
# run: ./contrib/gha/mac/clean_state.sh

- name: Upload diagnostics
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: machine-applehv-diag
path: |
*.log
if-no-files-found: warn
29 changes: 29 additions & 0 deletions contrib/gha/mac/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# GHA Mac workflow scripts

Per-task scripts called from `.github/workflows/mac.yml jobs.machine`.
Mirrors the per-task split that `contrib/cirrus/mac_*.sh` uses for the
Cirrus persistent-worker model: no `sudo`, no `.pkg` install at test time.
Helper binaries (vfkit, krunkit, gvproxy) are installed once at host setup
via Homebrew and live at `/opt/homebrew/bin/`. Podman is built in-job at
`$GITHUB_WORKSPACE/bin/darwin/podman` and tests are driven by
`make localmachine`.

| Script | When | Purpose |
|---|---|---|
| `clean_state.sh` | Pre + post machine job | Best-effort cleanup of podman machine state, stale Unix sockets, and any leaked vfkit/krunkit/gvproxy/ginkgo processes. Idempotent, no sudo. |
| `collect_diagnostics.sh` | On `if: failure()` | Pull podman/machine logs and the macOS unified log entries for vfkit/krunkit on failure. Writes to CWD as `machine-*.log` and `macos-system-log.log`. |

## Host-side dependencies (one-time per runner)

The machine job assumes the runner has these on `/opt/homebrew/bin/`,
installed by Homebrew at host provisioning time. Brew bottles ship signed
with the right entitlements, so no codesign step is needed at CI time.

| Binary | Source | Version reference |
|---|---|---|
| `vfkit` | `brew install vfkit` (Homebrew core) | `contrib/pkginstaller/Makefile` `VFKIT_VERSION` |
| `krunkit` | `brew tap slp/krunkit && brew install krunkit` | `contrib/pkginstaller/Makefile` `KRUNKIT_VERSION` |
| `gvproxy` | direct download from `containers/gvisor-tap-vsock` releases; chmod +x; `xattr -cr` | `go.mod` `github.com/containers/gvisor-tap-vsock` version |

Provisioning these is owned by the host-setup scripts on the
`ci/mac-host-provisioning` branch.
23 changes: 23 additions & 0 deletions contrib/gha/mac/clean_state.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
# Wipe podman machine state on the self-hosted Mac runner. Runs both before
# a job (in case the previous run left things behind) and after (so the next
# run starts pristine). Idempotent, best-effort, never fails the job over a
# cleanup miss. No sudo, no /opt/podman — everything is in user space.
# Mirrors contrib/cirrus/mac_cleanup.sh.

set +e

# Kill any leaked test processes from a previous run.
pkill -f vfkit 2>/dev/null || true
pkill -f krunkit 2>/dev/null || true
pkill -f gvproxy 2>/dev/null || true
pkill -f ginkgo 2>/dev/null || true

# Remove machine state under $HOME (no sudo).
rm -rf "$HOME/.local/share/containers/podman/machine" 2>/dev/null || true
rm -rf "$HOME/.config/containers/podman" 2>/dev/null || true

# Stale Unix sockets under TMPDIR (set to /private/tmp at workflow env).
rm -rf "${TMPDIR:-/private/tmp}/podman" 2>/dev/null || true

true
22 changes: 22 additions & 0 deletions contrib/gha/mac/collect_diagnostics.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bash
# Collect diagnostic logs on machine-test failure. Best-effort — the
# podman/machine state dir is usually nuked by ginkgo's DeferCleanup before
# this runs, so we also pull macOS unified log entries for vfkit/krunkit.
# Outputs go to CWD as machine-*.log and macos-system-log.log.

set +e

find /private/tmp -path '*/podman/machine/*' -type f \
\( -name '*.log' -o -name 'vfkit*' -o -name 'krunkit*' \) 2>/dev/null \
| while IFS= read -r src; do
cp "$src" "./machine-$(echo "$src" | tr '/' '_').log" 2>/dev/null
done

# shellcheck disable=SC2024 # redirect target is ec2-user-owned; sudo only
# needs to elevate `log show`, not the file write.
sudo log show \
--predicate 'process == "vfkit" OR process == "krunkit" OR senderImagePath CONTAINS "Hypervisor" OR senderImagePath CONTAINS "Virtualization"' \
--last 30m --style compact \
> ./macos-system-log.log 2>&1

true