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 current_uid="$(id -u)" run_xcodebuild() { if [ "$current_uid" -eq 0 ] && [ -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 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" "$log_file"; then echo "UI automation timed out. Retrying once after a short delay..." sleep 5 set +e run_xcodebuild 2>&1 | tee -a "$log_file" status=${PIPESTATUS[0]} set -e fi if [ "$status" -ne 0 ] && grep -qE "Failed to initialize for UI testing|Timed out while enabling automation mode" "$log_file"; then echo "UI automation mode is unavailable on this runner. Skipping UI tests." rm -f "$log_file" exit 0 fi rm -f "$log_file" exit "$status"