cmux/.github/workflows/ci.yml
2026-02-10 16:25:44 -08:00

160 lines
5.6 KiB
YAML

name: CI
on:
push:
branches:
- main
pull_request:
jobs:
web-typecheck:
runs-on: ubuntu-latest
defaults:
run:
working-directory: web
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Typecheck
run: bun tsc --noEmit
ui-tests:
runs-on: self-hosted
concurrency:
group: self-hosted-build
cancel-in-progress: false
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Select Xcode
run: |
set -euo pipefail
if [ -d "/Applications/Xcode.app/Contents/Developer" ]; then
XCODE_DIR="/Applications/Xcode.app/Contents/Developer"
else
XCODE_APP="$(ls -d /Applications/Xcode*.app 2>/dev/null | head -n 1 || true)"
if [ -n "$XCODE_APP" ]; then
XCODE_DIR="$XCODE_APP/Contents/Developer"
else
echo "No Xcode.app found under /Applications" >&2
exit 1
fi
fi
echo "DEVELOPER_DIR=$XCODE_DIR" >> "$GITHUB_ENV"
export DEVELOPER_DIR="$XCODE_DIR"
xcodebuild -version
xcrun --sdk macosx --show-sdk-path
- name: Build GhosttyKit.xcframework
run: |
set -euo pipefail
if ! command -v zig >/dev/null 2>&1; then
if command -v brew >/dev/null 2>&1; then
brew install zig
else
echo "zig is required to build GhosttyKit.xcframework. Install zig and retry." >&2
exit 1
fi
fi
(cd ghostty && zig build -Demit-xcframework=true -Demit-macos-app=false -Dxcframework-target=native)
rm -rf GhosttyKit.xcframework
cp -R ghostty/macos/GhosttyKit.xcframework GhosttyKit.xcframework
test -d GhosttyKit.xcframework
- name: Clean DerivedData
run: |
# Remove stale build cache to avoid incremental build errors
rm -rf ~/Library/Developer/Xcode/DerivedData/GhosttyTabs-*
- name: Run UI tests
run: |
set -euo pipefail
log_file="$(mktemp /tmp/cmux-ui-tests.XXXXXX)"
console_user="$(stat -f%Su /dev/console)"
console_uid=""
if [ "$console_user" != "root" ]; then
console_uid="$(id -u "$console_user")"
fi
run_xcodebuild() {
if [ -n "$console_uid" ] && [ "$console_uid" != "0" ]; then
/bin/launchctl asuser "$console_uid" xcodebuild \
-project GhosttyTabs.xcodeproj \
-scheme cmux \
-configuration Debug \
-destination 'platform=macOS' \
-only-testing:GhosttyTabsUITests/UpdatePillUITests \
test
else
xcodebuild \
-project GhosttyTabs.xcodeproj \
-scheme cmux \
-configuration Debug \
-destination 'platform=macOS' \
-only-testing:GhosttyTabsUITests/UpdatePillUITests \
test
fi
}
if ssh -o BatchMode=yes -o ConnectTimeout=5 cmux-vm 'true' >/dev/null 2>&1; then
echo "Running UI tests on cmux-vm..."
rsync -a --delete \
--exclude build \
--exclude .git \
--exclude "GhosttyTabs.xcodeproj/project.xcworkspace" \
./ cmux-vm:/Users/cmux/GhosttyTabs/
ssh cmux-vm 'cd /Users/cmux/GhosttyTabs && xcodebuild -project GhosttyTabs.xcodeproj -scheme cmux -configuration Debug -destination "platform=macOS" -only-testing:GhosttyTabsUITests/UpdatePillUITests test'
exit 0
fi
# macOS UI tests require an interactive Aqua session. On self-hosted runners it is
# easy to end up with a runner that's online but has no foreground-capable GUI.
if [ "$console_user" = "root" ] || [ -z "$console_uid" ] || [ "$console_uid" = "0" ]; then
echo "No console user session detected (/dev/console is root). Skipping UI tests on this runner."
rm -f "$log_file"
exit 0
fi
if ! /bin/launchctl print "gui/$console_uid" >/dev/null 2>&1; then
echo "No gui/$console_uid launchd domain; UI tests require an Aqua session. Skipping UI tests."
rm -f "$log_file"
exit 0
fi
if ! pgrep -x WindowServer >/dev/null 2>&1; then
echo "WindowServer is not running; UI tests require a GUI session. Skipping UI tests."
rm -f "$log_file"
exit 0
fi
if ! /usr/bin/osascript -e 'tell application "Finder" to activate' >/dev/null 2>&1; then
echo "Runner cannot activate GUI apps (Finder activate failed). Skipping UI tests."
rm -f "$log_file"
exit 0
fi
set +e
run_xcodebuild 2>&1 | tee "$log_file"
status=${PIPESTATUS[0]}
set -e
if [ "$status" -ne 0 ] && grep -qE "Failed to initialize for UI testing|Timed out while enabling automation mode|Failed to activate application" "$log_file"; then
echo "UI automation flake detected. Retrying once after a short delay..."
pkill -x "cmux DEV" >/dev/null 2>&1 || true
killall Dock >/dev/null 2>&1 || true
sleep 5
set +e
run_xcodebuild 2>&1 | tee -a "$log_file"
status=${PIPESTATUS[0]}
set -e
fi
rm -f "$log_file"
exit "$status"