name: Build GhosttyKit on: push: branches: - main pull_request: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: build-ghosttykit: runs-on: warp-macos-15-arm64-6x timeout-minutes: 20 steps: - name: Checkout uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: submodules: recursive - name: Get ghostty SHA id: ghostty-sha run: | SHA=$(git -C ghostty rev-parse HEAD) echo "sha=$SHA" >> "$GITHUB_OUTPUT" echo "Ghostty SHA: $SHA" - name: Check if xcframework release already exists id: check-release env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | TAG="xcframework-${{ steps.ghostty-sha.outputs.sha }}" if gh release view "$TAG" --repo manaflow-ai/ghostty >/dev/null 2>&1; then echo "exists=true" >> "$GITHUB_OUTPUT" echo "Release $TAG already exists, skipping build" else echo "exists=false" >> "$GITHUB_OUTPUT" echo "Release $TAG not found, will build" fi - name: Select Xcode if: steps.check-release.outputs.exists == 'false' 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 - name: Cache Zig packages if: steps.check-release.outputs.exists == 'false' uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4 with: path: ~/.cache/zig key: zig-packages-${{ hashFiles('ghostty/build.zig.zon', 'ghostty/build.zig.zon.json') }} restore-keys: zig-packages- - name: Build GhosttyKit.xcframework if: steps.check-release.outputs.exists == 'false' run: | set -euo pipefail ZIG_REQUIRED="0.15.2" if command -v zig >/dev/null 2>&1 && zig version 2>/dev/null | grep -q "^${ZIG_REQUIRED}"; then echo "zig ${ZIG_REQUIRED} already installed" else echo "Installing zig ${ZIG_REQUIRED} from tarball" curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-aarch64-macos-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz tar xf /tmp/zig.tar.xz -C /tmp sudo mkdir -p /usr/local/bin /usr/local/lib sudo cp -f /tmp/zig-aarch64-macos-${ZIG_REQUIRED}/zig /usr/local/bin/zig sudo cp -rf /tmp/zig-aarch64-macos-${ZIG_REQUIRED}/lib /usr/local/lib/zig export PATH="/usr/local/bin:$PATH" zig version fi cd ghostty && zig build -Demit-xcframework=true -Demit-macos-app=false -Dxcframework-target=universal -Doptimize=ReleaseFast - name: Package xcframework if: steps.check-release.outputs.exists == 'false' run: | set -euo pipefail rm -rf GhosttyKit.xcframework cp -R ghostty/macos/GhosttyKit.xcframework GhosttyKit.xcframework tar czf GhosttyKit.xcframework.tar.gz GhosttyKit.xcframework - name: Upload xcframework release if: steps.check-release.outputs.exists == 'false' env: GH_TOKEN: ${{ secrets.GHOSTTY_RELEASE_TOKEN }} run: | set -euo pipefail if [ -z "${GH_TOKEN:-}" ]; then echo "GHOSTTY_RELEASE_TOKEN not available (fork PR), skipping upload" exit 0 fi TAG="xcframework-${{ steps.ghostty-sha.outputs.sha }}" gh release create "$TAG" \ --repo manaflow-ai/ghostty \ --title "GhosttyKit xcframework (${{ steps.ghostty-sha.outputs.sha }})" \ --notes "Pre-built GhosttyKit.xcframework for commit ${{ steps.ghostty-sha.outputs.sha }}" \ GhosttyKit.xcframework.tar.gz echo "Published release $TAG"