Skip to content

Merge pull request #383 from sidick/feat/hostsocket-import #2

Merge pull request #383 from sidick/feat/hostsocket-import

Merge pull request #383 from sidick/feat/hostsocket-import #2

Workflow file for this run

name: macOS
# Builds the macOS disk image (a universal Copperline.app in a .dmg) and
# uploads it as a workflow artifact on every qualifying change, and attaches it
# to the GitHub Release when a v* tag is pushed. The main CI already builds and
# tests on macOS; this workflow adds the packaging path plus a smoke test of
# the packaged bundle itself (both architectures, including the x86_64 slice
# under Rosetta, which no other job executes), so it is scoped to the code and
# packaging surface that affects the bundle.
#
# The image is intentionally unsigned (no Developer ID, no notarization), so it
# trips Gatekeeper on first launch; the bundled README.txt documents the
# right-click-Open workaround.
on:
push:
branches: [main]
tags: ["v*"]
paths:
- "src/**"
- "vendor/**"
- "assets/**"
- "Cargo.lock"
- "Cargo.toml"
- ".cargo/**"
- "packaging/macos/**"
- ".github/workflows/macos.yml"
pull_request:
paths:
- "src/**"
- "vendor/**"
- "assets/**"
- "Cargo.lock"
- "Cargo.toml"
- ".cargo/**"
- "packaging/macos/**"
- ".github/workflows/macos.yml"
# Manual rebuild. Use this to attach a dmg to a release whose tag predates
# this workflow (the v* tag tree has no macos.yml, so a tag push cannot
# trigger it): run it against a branch with the source parity you want and set
# release_tag to push the built dmg onto that existing release.
workflow_dispatch:
inputs:
release_tag:
description: "Existing release tag to attach the dmg to (e.g. v0.7.0). Leave blank to only upload a workflow artifact."
required: false
default: ""
concurrency:
group: macos-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
name: Build macOS dmg
runs-on: macos-latest
# Needed only by the release-attach step on v* tags.
permissions:
contents: write
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
# Both Apple architectures so build-dmg.sh can lipo a universal binary.
targets: aarch64-apple-darwin,x86_64-apple-darwin
- uses: Swatinem/rust-cache@v2
- name: Build dmg
run: packaging/macos/build-dmg.sh
- name: Locate artifact
id: artifact
run: echo "path=$(ls Copperline-*-macos-universal.dmg | head -n1)" >> "$GITHUB_OUTPUT"
- name: Smoke test the packaged app
# The main CI already runs the full suites against the working tree
# on macOS; what it never touches is the artifact users download.
# Mount the freshly built image and boot the app binary straight off
# the read-only volume, working from an empty directory so the
# bundled AROS ROM must be found through the .app's
# Contents/Resources/aros lookup (romsearch.rs), not the source
# tree's assets/aros fallback. Runs the arm64 slice natively and the
# x86_64 slice under Rosetta -- the only place the Intel half of the
# universal binary is ever executed. A capture run opens no window
# or audio device, so a clean exit plus a non-empty PNG proves the
# shipped bundle boots.
run: |
mnt="$RUNNER_TEMP/dmg-mount"
hdiutil attach -nobrowse -readonly -mountpoint "$mnt" \
"${{ steps.artifact.outputs.path }}"
# Never leave the image mounted for the rest of the job if a
# check below fails; the clean path detaches explicitly.
trap 'hdiutil detach "$mnt" -force 2>/dev/null || true' EXIT
app="$mnt/Copperline.app"
bin="$app/Contents/MacOS/copperline"
# Both slices present, and the ad-hoc signature survived the
# lipo/dmg round-trip (an unsigned arm64 binary will not launch).
lipo -archs "$bin"
lipo -archs "$bin" | grep -q arm64
lipo -archs "$bin" | grep -q x86_64
codesign --verify --deep --strict "$app"
smoke="$RUNNER_TEMP/dmg-smoke"
mkdir -p "$smoke"
cd "$smoke"
"$bin" --noaudio --screenshot-after 10 smoke-arm64.png
test -s smoke-arm64.png
# Rosetta is preinstalled on some runner images; this is a fast
# no-op there and installs it where it is not.
sudo softwareupdate --install-rosetta --agree-to-license
arch -x86_64 "$bin" --noaudio --screenshot-after 10 smoke-x86_64.png
test -s smoke-x86_64.png
trap - EXIT
hdiutil detach "$mnt"
- name: Upload smoke screenshots
if: always()
uses: actions/upload-artifact@v7
with:
name: macos-smoke-screenshots
path: ${{ runner.temp }}/dmg-smoke/
if-no-files-found: ignore
- uses: actions/upload-artifact@v7
with:
name: copperline-macos
path: ${{ steps.artifact.outputs.path }}
if-no-files-found: error
- name: Attach to release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v2
with:
files: ${{ steps.artifact.outputs.path }}
- name: Attach to existing release (manual run)
if: github.event_name == 'workflow_dispatch' && inputs.release_tag != ''
env:
GH_TOKEN: ${{ github.token }}
# --clobber so a re-run replaces the asset instead of failing on a
# name clash.
run: gh release upload "${{ inputs.release_tag }}" "${{ steps.artifact.outputs.path }}" --clobber