* Fix zsh ZDOTDIR wrapper + log parsing with -- messages * Fix CI race condition: serialize self-hosted builds with concurrency group Two workflows racing on the same self-hosted runner caused DerivedData corruption (release's rm -rf nuked DerivedData while CI was building). Add shared concurrency group and scope DerivedData cleanup to project.
124 lines
4.4 KiB
YAML
124 lines
4.4 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
pull_request:
|
|
|
|
jobs:
|
|
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"
|