ci: build macOS releases with Xcode 26 (#7616)
Resolves #7591 This moves our CI to build macOS on Sequoia (macOS 15) with Xcode 26, including the new macOS 26 beta SDK. This includes tip releases. Stable releases continue to use Xcode 15 and the stable SDK, in case we need to make a release before macOS Tahoe is stable (though, if its late enough in the cycle, we may even cut a full release with it). Importantly, this will make our builds on macOS 26 use the new styling. I've added a new job that ensures we can continue to build with Xcode 16 and the macOS 15 SDK, as well, although I think that might come to an end when we switch over to an IconComposer-based icon. I'll verify then. For now, we continue to support both. I've also removed our `hasLiquidGlass` check, since this will now always be true for macOS 26 builds.pull/7617/head
commit
676d11fd06
|
|
@ -94,7 +94,7 @@ jobs:
|
|||
- name: Build Ghostty.app
|
||||
run: |
|
||||
cd macos
|
||||
sudo xcode-select -s /Applications/Xcode_16.4.app
|
||||
sudo xcode-select -s /Applications/Xcode_26.0.app
|
||||
xcodebuild -target Ghostty -configuration Release
|
||||
|
||||
# We inject the "build number" as simply the number of commits since HEAD.
|
||||
|
|
@ -246,7 +246,7 @@ jobs:
|
|||
- name: Build Ghostty.app
|
||||
run: |
|
||||
cd macos
|
||||
sudo xcode-select -s /Applications/Xcode_16.4.app
|
||||
sudo xcode-select -s /Applications/Xcode_26.0.app
|
||||
xcodebuild -target Ghostty -configuration Release
|
||||
|
||||
# We inject the "build number" as simply the number of commits since HEAD.
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ jobs:
|
|||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
||||
- name: XCode Select
|
||||
run: sudo xcode-select -s /Applications/Xcode_16.4.app
|
||||
run: sudo xcode-select -s /Applications/Xcode_26.0.app
|
||||
|
||||
# Setup Sparkle
|
||||
- name: Setup Sparkle
|
||||
|
|
@ -388,7 +388,7 @@ jobs:
|
|||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
||||
- name: XCode Select
|
||||
run: sudo xcode-select -s /Applications/Xcode_16.4.app
|
||||
run: sudo xcode-select -s /Applications/Xcode_26.0.app
|
||||
|
||||
# Setup Sparkle
|
||||
- name: Setup Sparkle
|
||||
|
|
@ -563,7 +563,7 @@ jobs:
|
|||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
||||
- name: XCode Select
|
||||
run: sudo xcode-select -s /Applications/Xcode_16.4.app
|
||||
run: sudo xcode-select -s /Applications/Xcode_26.0.app
|
||||
|
||||
# Setup Sparkle
|
||||
- name: Setup Sparkle
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ jobs:
|
|||
- build-nix
|
||||
- build-snap
|
||||
- build-macos
|
||||
- build-macos-sequoia-stable
|
||||
- build-macos-tahoe
|
||||
- build-macos-matrix
|
||||
- build-windows
|
||||
|
|
@ -270,6 +271,46 @@ jobs:
|
|||
ghostty-source.tar.gz
|
||||
|
||||
build-macos:
|
||||
runs-on: namespace-profile-ghostty-macos-sequoia
|
||||
needs: test
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Install Nix and use that to run our tests so our environment matches exactly.
|
||||
- uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- uses: cachix/cachix-action@v16
|
||||
with:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
||||
- name: Xcode Select
|
||||
run: sudo xcode-select -s /Applications/Xcode_26.0.app
|
||||
|
||||
- name: get the Zig deps
|
||||
id: deps
|
||||
run: nix build -L .#deps && echo "deps=$(readlink ./result)" >> $GITHUB_OUTPUT
|
||||
|
||||
# GhosttyKit is the framework that is built from Zig for our native
|
||||
# Mac app to access.
|
||||
- name: Build GhosttyKit
|
||||
run: nix develop -c zig build --system ${{ steps.deps.outputs.deps }}
|
||||
|
||||
# The native app is built with native Xcode tooling. This also does
|
||||
# codesigning. IMPORTANT: this must NOT run in a Nix environment.
|
||||
# Nix breaks xcodebuild so this has to be run outside.
|
||||
- name: Build Ghostty.app
|
||||
run: cd macos && xcodebuild -target Ghostty
|
||||
|
||||
# Build the iOS target without code signing just to verify it works.
|
||||
- name: Build Ghostty iOS
|
||||
run: |
|
||||
cd macos
|
||||
xcodebuild -target Ghostty-iOS "CODE_SIGNING_ALLOWED=NO"
|
||||
|
||||
build-macos-sequoia-stable:
|
||||
runs-on: namespace-profile-ghostty-macos-sequoia
|
||||
needs: test
|
||||
steps:
|
||||
|
|
@ -328,17 +369,6 @@ jobs:
|
|||
- name: Xcode Select
|
||||
run: sudo xcode-select -s /Applications/Xcode_26.0.app
|
||||
|
||||
# TODO(tahoe):
|
||||
# https://developer.apple.com/documentation/xcode-release-notes/xcode-26-release-notes#Interface-Builder
|
||||
# We allow this step to fail because if our image already has
|
||||
# the workaround in place this will fail.
|
||||
- name: Xcode 26 Beta 17A5241e Metal Workaround
|
||||
continue-on-error: true
|
||||
run: |
|
||||
xcodebuild -downloadComponent metalToolchain -exportPath /tmp/MyMetalExport/
|
||||
sed -i '' -e 's/17A5241c/17A5241e/g' /tmp/MyMetalExport/MetalToolchain-17A5241c.exportedBundle/ExportMetadata.plist
|
||||
xcodebuild -importComponent metalToolchain -importPath /tmp/MyMetalExport/MetalToolchain-17A5241c.exportedBundle
|
||||
|
||||
- name: get the Zig deps
|
||||
id: deps
|
||||
run: nix build -L .#deps && echo "deps=$(readlink ./result)" >> $GITHUB_OUTPUT
|
||||
|
|
@ -377,7 +407,7 @@ jobs:
|
|||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
||||
- name: Xcode Select
|
||||
run: sudo xcode-select -s /Applications/Xcode_16.4.app
|
||||
run: sudo xcode-select -s /Applications/Xcode_26.0.app
|
||||
|
||||
- name: get the Zig deps
|
||||
id: deps
|
||||
|
|
@ -695,7 +725,7 @@ jobs:
|
|||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
||||
- name: Xcode Select
|
||||
run: sudo xcode-select -s /Applications/Xcode_16.4.app
|
||||
run: sudo xcode-select -s /Applications/Xcode_26.0.app
|
||||
|
||||
- name: get the Zig deps
|
||||
id: deps
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class TerminalController: BaseTerminalController {
|
|||
case "hidden": "TerminalHiddenTitlebar"
|
||||
case "transparent": "TerminalTransparentTitlebar"
|
||||
case "tabs":
|
||||
if #available(macOS 26.0, *), hasLiquidGlass() {
|
||||
if #available(macOS 26.0, *) {
|
||||
"TerminalTabsTitlebarTahoe"
|
||||
} else {
|
||||
"TerminalTabsTitlebarVentura"
|
||||
|
|
|
|||
|
|
@ -447,7 +447,7 @@ extension TerminalWindow {
|
|||
// The padding from the top that the view appears. This was all just manually
|
||||
// measured based on the OS.
|
||||
var topPadding: CGFloat {
|
||||
if #available(macOS 26.0, *), hasLiquidGlass() {
|
||||
if #available(macOS 26.0, *) {
|
||||
return viewModel.hasToolbar ? 10 : 5
|
||||
} else {
|
||||
return viewModel.hasToolbar ? 9 : 4
|
||||
|
|
|
|||
|
|
@ -45,11 +45,13 @@ class TransparentTitlebarTerminalWindow: TerminalWindow {
|
|||
|
||||
override func update() {
|
||||
super.update()
|
||||
|
||||
|
||||
// On macOS 13 to 15, we need to hide the NSVisualEffectView in order to allow our
|
||||
// titlebar to be truly transparent.
|
||||
if !effectViewIsHidden && !hasLiquidGlass() {
|
||||
hideEffectView()
|
||||
if #unavailable(macOS 26) {
|
||||
if !effectViewIsHidden {
|
||||
hideEffectView()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -65,7 +67,7 @@ class TransparentTitlebarTerminalWindow: TerminalWindow {
|
|||
// references changed (e.g. tabGroup is new).
|
||||
setupKVO()
|
||||
|
||||
if #available(macOS 26.0, *), hasLiquidGlass() {
|
||||
if #available(macOS 26.0, *) {
|
||||
syncAppearanceTahoe(surfaceConfig)
|
||||
} else {
|
||||
syncAppearanceVentura(surfaceConfig)
|
||||
|
|
|
|||
|
|
@ -8,37 +8,3 @@ func isRunningInXcode() -> Bool {
|
|||
|
||||
return false
|
||||
}
|
||||
|
||||
/// True if we have liquid glass available.
|
||||
func hasLiquidGlass() -> Bool {
|
||||
// Can't have liquid glass unless we're in macOS 26+
|
||||
if #unavailable(macOS 26.0) {
|
||||
return false
|
||||
}
|
||||
|
||||
// If we aren't running SDK 26.0 or later then we definitely
|
||||
// do not have liquid glass.
|
||||
guard let sdkName = Bundle.main.infoDictionary?["DTSDKName"] as? String else {
|
||||
// If we don't have this, we assume we're built against the latest
|
||||
// since we're on macOS 26+
|
||||
return true
|
||||
}
|
||||
|
||||
// If the SDK doesn't start with macosx then we just assume we
|
||||
// have it because we already verified we're on macOS above.
|
||||
guard sdkName.hasPrefix("macosx") else {
|
||||
return true
|
||||
}
|
||||
|
||||
// The SDK version must be at least 26
|
||||
let versionString = String(sdkName.dropFirst("macosx".count))
|
||||
guard let major = if let dotIndex = versionString.firstIndex(of: ".") {
|
||||
Int(String(versionString[..<dotIndex]))
|
||||
} else {
|
||||
Int(versionString)
|
||||
} else { return true }
|
||||
|
||||
// Note: we could also check for the UIDesignRequiresCompatibility key
|
||||
// but our project doesn't use it so there's no point.
|
||||
return major >= 26
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue