Skip to content
Merged
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
109 changes: 88 additions & 21 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,15 @@ jobs:
build-sign-notarize-nightly:
needs: decide
if: needs.decide.outputs.should_build == 'true'
# Keep publishing builds on macOS 15 until Zig can link the real universal
# Ghostty CLI helper on macOS 26. ci-macos-compat.yml covers macOS 26 with
# CMUX_SKIP_ZIG_BUILD=1, but nightly needs the real universal helper.
# Run on the macOS 15 host because zig 0.15.2 can cross-link the universal
# (arm64 + x86_64) Ghostty CLI helper only against a pre-26 SDK. The Swift
# app is built with the macOS 26 Xcode on this same runner so it adopts
# Liquid Glass on Tahoe; the helper is built separately with the older Xcode
# and injected before signing (see Select Xcode + the helper build/inject
# steps). Building the whole app with Xcode 16 (#5022) shipped a macOS 15 SDK
# binary that Tahoe forced into the legacy non-Liquid-Glass appearance.
runs-on: ${{ vars.MACOS_RUNNER_15 || 'warp-macos-15-arm64-6x' }}
timeout-minutes: 20
timeout-minutes: 30
steps:
- name: Checkout build ref
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand Down Expand Up @@ -137,26 +141,57 @@ jobs:
if: needs.decide.outputs.should_publish != 'true' || steps.current_head_prebuild.outputs.still_current == 'true'
run: |
set -euo pipefail
if [ -d "/Applications/Xcode.app/Contents/Developer" ]; then
XCODE_DIR="/Applications/Xcode.app/Contents/Developer"
else
XCODE_APP="$(
find /Applications -maxdepth 1 -name 'Xcode*.app' -print 2>/dev/null \
| sort \
| tail -n 1 \
|| true
)"
if [ -n "$XCODE_APP" ]; then
XCODE_DIR="$XCODE_APP/Contents/Developer"
# The app must link against the macOS 26 SDK so it adopts Liquid Glass
# on Tahoe (the team is pinned to Xcode 26 via .xcode-version). The zig
# Ghostty CLI helper must link against a pre-26 SDK because zig 0.15.2
# cannot cross-link x86_64 against the macOS 26 SDK. Both Xcodes ship on
# the macOS 15 runner image, so pick the newest of each by SDK version.
# Compare SDK versions numerically (not lexicographically) so e.g.
# 26.10 sorts above 26.3.
sdk_rank() {
# "26.2" -> 26002 ; "26" -> 26000
local v="$1" maj min
maj="${v%%.*}"
min="${v#*.}"
[ "$min" = "$v" ] && min=0
min="${min%%.*}"
printf '%d' "$(( maj * 1000 + min ))"
}
APP_DEVELOPER_DIR=""; APP_SDK_VER=""; APP_RANK=-1
HELPER_DEVELOPER_DIR=""; HELPER_SDK_VER=""; HELPER_RANK=-1
while IFS= read -r app; do
[ -n "$app" ] || continue
dev="$app/Contents/Developer"
[ -d "$dev" ] || continue
sdk_ver="$(DEVELOPER_DIR="$dev" xcrun --sdk macosx --show-sdk-version 2>/dev/null || true)"
[ -n "$sdk_ver" ] || continue
rank="$(sdk_rank "$sdk_ver")"
echo "Found $app -> macOS SDK $sdk_ver (rank $rank)"
if [ "${sdk_ver%%.*}" -ge 26 ]; then
if [ "$rank" -gt "$APP_RANK" ]; then
APP_DEVELOPER_DIR="$dev"; APP_SDK_VER="$sdk_ver"; APP_RANK="$rank"
fi
else
echo "No Xcode.app found under /Applications" >&2
exit 1
if [ "$rank" -gt "$HELPER_RANK" ]; then
HELPER_DEVELOPER_DIR="$dev"; HELPER_SDK_VER="$sdk_ver"; HELPER_RANK="$rank"
fi
fi
done < <(find /Applications -maxdepth 1 -name 'Xcode*.app' -print 2>/dev/null)

if [ -z "$APP_DEVELOPER_DIR" ]; then
echo "No Xcode with the macOS 26+ SDK found; the app would ship without Liquid Glass on Tahoe." >&2
exit 1
fi
echo "DEVELOPER_DIR=$XCODE_DIR" >> "$GITHUB_ENV"
export DEVELOPER_DIR="$XCODE_DIR"
xcodebuild -version
xcrun --sdk macosx --show-sdk-path
if [ -z "$HELPER_DEVELOPER_DIR" ]; then
echo "No pre-26 Xcode found to cross-link the universal Ghostty CLI helper (zig 0.15.2 cannot link x86_64 against the macOS 26 SDK)." >&2
exit 1
fi

echo "App build Xcode (DEVELOPER_DIR): $APP_DEVELOPER_DIR (macOS SDK $APP_SDK_VER)"
echo "Helper build Xcode (HELPER_DEVELOPER_DIR): $HELPER_DEVELOPER_DIR (macOS SDK $HELPER_SDK_VER)"
DEVELOPER_DIR="$APP_DEVELOPER_DIR" xcodebuild -version
echo "DEVELOPER_DIR=$APP_DEVELOPER_DIR" >> "$GITHUB_ENV"
echo "HELPER_DEVELOPER_DIR=$HELPER_DEVELOPER_DIR" >> "$GITHUB_ENV"
Comment thread
coderabbitai[bot] marked this conversation as resolved.

- name: Install build deps
if: needs.decide.outputs.should_publish != 'true' || steps.current_head_prebuild.outputs.still_current == 'true'
Expand All @@ -165,6 +200,19 @@ jobs:
./scripts/install-zig-ci.sh
npm install --global "create-dmg@${CREATE_DMG_VERSION}"

- name: Build universal Ghostty CLI helper
if: needs.decide.outputs.should_publish != 'true' || steps.current_head_prebuild.outputs.still_current == 'true'
env:
# zig 0.15.2 can cross-link the x86_64 slice only against a pre-26 SDK.
DEVELOPER_DIR: ${{ env.HELPER_DEVELOPER_DIR }}
run: |
set -euo pipefail
./scripts/build-ghostty-cli-helper.sh --universal --output /tmp/cmux-ghostty-helper-universal
ARCHS_OUT="$(lipo -archs /tmp/cmux-ghostty-helper-universal)"
echo "Universal Ghostty CLI helper architectures: $ARCHS_OUT"
case " $ARCHS_OUT " in *" arm64 "*) ;; *) echo "helper missing arm64 slice" >&2; exit 1 ;; esac
case " $ARCHS_OUT " in *" x86_64 "*) ;; *) echo "helper missing x86_64 slice" >&2; exit 1 ;; esac

- name: Download pre-built GhosttyKit.xcframework
if: needs.decide.outputs.should_publish != 'true' || steps.current_head_prebuild.outputs.still_current == 'true'
run: |
Expand Down Expand Up @@ -199,6 +247,11 @@ jobs:

- name: Build universal nightly app (Release)
if: needs.decide.outputs.should_publish != 'true' || steps.current_head_prebuild.outputs.still_current == 'true'
env:
# Skip the in-Xcode zig helper build; it would fail to cross-link
# x86_64 against the macOS 26 SDK. The real universal helper is built
# by the "Build universal Ghostty CLI helper" step and injected below.
CMUX_SKIP_ZIG_BUILD: "1"
run: |
xcodebuild -scheme cmux -configuration Release -derivedDataPath build-universal \
-destination 'generic/platform=macOS' \
Expand All @@ -207,6 +260,20 @@ jobs:
ONLY_ACTIVE_ARCH=NO \
CODE_SIGNING_ALLOWED=NO ASSETCATALOG_COMPILER_APPICON_NAME=AppIcon-Nightly build

- name: Inject universal Ghostty CLI helper
if: needs.decide.outputs.should_publish != 'true' || steps.current_head_prebuild.outputs.still_current == 'true'
run: |
set -euo pipefail
APP_DIR="build-universal/Build/Products/Release/cmux.app"
if [ ! -d "$APP_DIR" ]; then
echo "Built app not found at $APP_DIR" >&2
exit 1
fi
DEST="$APP_DIR/Contents/Resources/bin/ghostty"
mkdir -p "$(dirname "$DEST")"
install -m 755 /tmp/cmux-ghostty-helper-universal "$DEST"
echo "Injected Ghostty CLI helper architectures: $(lipo -archs "$DEST")"

Comment thread
coderabbitai[bot] marked this conversation as resolved.
- name: Run bundled Ghostty theme picker helper regression
if: needs.decide.outputs.should_publish != 'true' || steps.current_head_prebuild.outputs.still_current == 'true'
run: |
Expand Down
Loading