From fdd22ec78671033baae90e4f01a722b3cbb99ffe Mon Sep 17 00:00:00 2001 From: Qwerasd Date: Fri, 5 Sep 2025 16:01:12 -0600 Subject: [PATCH 01/12] fix(terminal): move cursor left if VS15 makes cell narrow Without this change, a phantom space appears after any character with default emoji presentation that is converted to text with VS15. The only other terminal I know of that respects variation selectors is Kitty, and it walks the cursor back, which feels like the best choice, since that way the behavior is observable (no way to know if the terminal supports variation selectors otherwise without hard-coding that info per term) and "dumb" programs like `cat` will output things correctly, and not gain a phantom space after any VS15'd emoji. --- src/terminal/Terminal.zig | 106 +++++++++++++++++++++++++++++++++++++- 1 file changed, 105 insertions(+), 1 deletion(-) diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index 52e3d0fca..162cfde38 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -391,6 +391,24 @@ pub fn print(self: *Terminal, c: u21) !void { const cell = self.screen.cursorCellLeft(prev.left - 1); cell.wide = .narrow; + // Back track the cursor so that we don't end up with + // an extra space after the character. Since xterm is + // not VS aware, it cannot be used as a reference for + // this behavior; but it does follow the principle of + // least surprise, and also matches the behavior that + // can be observed in Kitty, which is one of the only + // other VS aware terminals. + if (self.screen.cursor.x == right_limit - 1) { + // If we're already at the right edge, we stay + // here and set the pending wrap to false since + // when we pend a wrap, we only move our cursor once + // even for wide chars (tests verify). + self.screen.cursor.pending_wrap = false; + } else { + // Otherwise, move back. + self.screen.cursorLeft(1); + } + break :narrow; }, @@ -3348,13 +3366,57 @@ test "Terminal: VS15 to make narrow character" { // Enable grapheme clustering t.modes.set(.grapheme_cluster, true); - try t.print(0x26C8); // Thunder cloud and rain + try t.print(0x2614); // Umbrella with rain drops, width=2 + try testing.expect(t.isDirty(.{ .screen = .{ .x = 0, .y = 0 } })); + t.clearDirty(); + + // We should have 2 cells taken up. It is one character but "wide". + try testing.expectEqual(@as(usize, 0), t.screen.cursor.y); + try testing.expectEqual(@as(usize, 2), t.screen.cursor.x); + + try t.print(0xFE0E); // VS15 to make narrow + try testing.expect(t.isDirty(.{ .screen = .{ .x = 0, .y = 0 } })); + t.clearDirty(); + + // VS15 should send us back a cell since our char is no longer wide. + try testing.expectEqual(@as(usize, 0), t.screen.cursor.y); + try testing.expectEqual(@as(usize, 1), t.screen.cursor.x); + + { + const str = try t.plainString(testing.allocator); + defer testing.allocator.free(str); + try testing.expectEqualStrings("☔︎", str); + } + + { + const list_cell = t.screen.pages.getCell(.{ .screen = .{ .x = 0, .y = 0 } }).?; + const cell = list_cell.cell; + try testing.expectEqual(@as(u21, 0x2614), cell.content.codepoint); + try testing.expect(cell.hasGrapheme()); + try testing.expectEqual(Cell.Wide.narrow, cell.wide); + const cps = list_cell.node.data.lookupGrapheme(cell).?; + try testing.expectEqual(@as(usize, 1), cps.len); + } +} + +test "Terminal: VS15 on already narrow emoji" { + var t = try init(testing.allocator, .{ .rows = 5, .cols = 5 }); + defer t.deinit(testing.allocator); + + // Enable grapheme clustering + t.modes.set(.grapheme_cluster, true); + + try t.print(0x26C8); // Thunder cloud and rain, width=1 try testing.expect(t.isDirty(.{ .screen = .{ .x = 0, .y = 0 } })); t.clearDirty(); try t.print(0xFE0E); // VS15 to make narrow try testing.expect(t.isDirty(.{ .screen = .{ .x = 0, .y = 0 } })); t.clearDirty(); + // Character takes up one cell + try testing.expectEqual(@as(usize, 0), t.screen.cursor.y); + try testing.expectEqual(@as(usize, 1), t.screen.cursor.x); + { const str = try t.plainString(testing.allocator); defer testing.allocator.free(str); @@ -3372,6 +3434,48 @@ test "Terminal: VS15 to make narrow character" { } } +test "Terminal: VS15 to make narrow character with pending wrap" { + var t = try init(testing.allocator, .{ .rows = 5, .cols = 2 }); + defer t.deinit(testing.allocator); + + // Enable grapheme clustering + t.modes.set(.grapheme_cluster, true); + + try t.print(0x2614); // Umbrella with rain drops, width=2 + try testing.expect(t.isDirty(.{ .screen = .{ .x = 0, .y = 0 } })); + t.clearDirty(); + + // We only move one because we're in a pending wrap state. + try testing.expectEqual(@as(usize, 0), t.screen.cursor.y); + try testing.expectEqual(@as(usize, 1), t.screen.cursor.x); + try testing.expect(t.screen.cursor.pending_wrap); + + try t.print(0xFE0E); // VS15 to make narrow + try testing.expect(t.isDirty(.{ .screen = .{ .x = 0, .y = 0 } })); + t.clearDirty(); + + // VS15 should clear the pending wrap state + try testing.expectEqual(@as(usize, 0), t.screen.cursor.y); + try testing.expectEqual(@as(usize, 1), t.screen.cursor.x); + try testing.expect(!t.screen.cursor.pending_wrap); + + { + const str = try t.plainString(testing.allocator); + defer testing.allocator.free(str); + try testing.expectEqualStrings("☔︎", str); + } + + { + const list_cell = t.screen.pages.getCell(.{ .screen = .{ .x = 0, .y = 0 } }).?; + const cell = list_cell.cell; + try testing.expectEqual(@as(u21, 0x2614), cell.content.codepoint); + try testing.expect(cell.hasGrapheme()); + try testing.expectEqual(Cell.Wide.narrow, cell.wide); + const cps = list_cell.node.data.lookupGrapheme(cell).?; + try testing.expectEqual(@as(usize, 1), cps.len); + } +} + test "Terminal: VS16 to make wide character with mode 2027" { var t = try init(testing.allocator, .{ .rows = 5, .cols = 5 }); defer t.deinit(testing.allocator); From ae95bb39abeb8619a5fd98c2998466d0dd90e39e Mon Sep 17 00:00:00 2001 From: mitchellh <1299+mitchellh@users.noreply.github.com> Date: Sun, 7 Sep 2025 00:15:14 +0000 Subject: [PATCH 02/12] deps: Update iTerm2 color schemes --- build.zig.zon | 4 ++-- build.zig.zon.json | 6 +++--- build.zig.zon.nix | 6 +++--- build.zig.zon.txt | 2 +- flatpak/zig-packages.json | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/build.zig.zon b/build.zig.zon index 05ca3134e..1c631d2cb 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -112,8 +112,8 @@ // Other .apple_sdk = .{ .path = "./pkg/apple-sdk" }, .iterm2_themes = .{ - .url = "https://github.com/mbadolato/iTerm2-Color-Schemes/archive/6cdbc8501d48601302e32d6b53e9e7934bf354b4.tar.gz", - .hash = "N-V-__8AAAtjXwSdhZq_xYbCXo0SZMqoNoQuHFkC07sijQME", + .url = "https://github.com/mbadolato/iTerm2-Color-Schemes/archive/b314fc540434cc037c2811fc048d32854b5b78c3.tar.gz", + .hash = "N-V-__8AAGupuwFrRxb2dkqFqmEChLEa4J3e95GReqvomV1b", .lazy = true, }, }, diff --git a/build.zig.zon.json b/build.zig.zon.json index a28569dc4..b2aeb7cdf 100644 --- a/build.zig.zon.json +++ b/build.zig.zon.json @@ -49,10 +49,10 @@ "url": "https://deps.files.ghostty.org/imgui-1220bc6b9daceaf7c8c60f3c3998058045ba0c5c5f48ae255ff97776d9cd8bfc6402.tar.gz", "hash": "sha256-oF/QHgTPEat4Hig4fGIdLkIPHmBEyOJ6JeYD6pnveGA=" }, - "N-V-__8AAAtjXwSdhZq_xYbCXo0SZMqoNoQuHFkC07sijQME": { + "N-V-__8AAGupuwFrRxb2dkqFqmEChLEa4J3e95GReqvomV1b": { "name": "iterm2_themes", - "url": "https://github.com/mbadolato/iTerm2-Color-Schemes/archive/6cdbc8501d48601302e32d6b53e9e7934bf354b4.tar.gz", - "hash": "sha256-NlUXcBOmaA8W+7RXuXcn9TIhm964dXO2Op4QCQxhDyc=" + "url": "https://github.com/mbadolato/iTerm2-Color-Schemes/archive/b314fc540434cc037c2811fc048d32854b5b78c3.tar.gz", + "hash": "sha256-3vPlDDjv6BCLyro1YytzPtF0FfBH20skYuA9laDWhac=" }, "N-V-__8AAIC5lwAVPJJzxnCAahSvZTIlG-HhtOvnM1uh-66x": { "name": "jetbrains_mono", diff --git a/build.zig.zon.nix b/build.zig.zon.nix index 866da31ea..22ca13248 100644 --- a/build.zig.zon.nix +++ b/build.zig.zon.nix @@ -163,11 +163,11 @@ in }; } { - name = "N-V-__8AAAtjXwSdhZq_xYbCXo0SZMqoNoQuHFkC07sijQME"; + name = "N-V-__8AAGupuwFrRxb2dkqFqmEChLEa4J3e95GReqvomV1b"; path = fetchZigArtifact { name = "iterm2_themes"; - url = "https://github.com/mbadolato/iTerm2-Color-Schemes/archive/6cdbc8501d48601302e32d6b53e9e7934bf354b4.tar.gz"; - hash = "sha256-NlUXcBOmaA8W+7RXuXcn9TIhm964dXO2Op4QCQxhDyc="; + url = "https://github.com/mbadolato/iTerm2-Color-Schemes/archive/b314fc540434cc037c2811fc048d32854b5b78c3.tar.gz"; + hash = "sha256-3vPlDDjv6BCLyro1YytzPtF0FfBH20skYuA9laDWhac="; }; } { diff --git a/build.zig.zon.txt b/build.zig.zon.txt index c2d45a16e..69059038a 100644 --- a/build.zig.zon.txt +++ b/build.zig.zon.txt @@ -28,7 +28,7 @@ https://deps.files.ghostty.org/zig_js-12205a66d423259567764fa0fc60c82be35365c21a https://deps.files.ghostty.org/ziglyph-b89d43d1e3fb01b6074bc1f7fc980324b04d26a5.tar.gz https://deps.files.ghostty.org/zlib-1220fed0c74e1019b3ee29edae2051788b080cd96e90d56836eea857b0b966742efb.tar.gz https://github.com/jcollie/ghostty-gobject/releases/download/0.15.1-2025-09-04-48-1/ghostty-gobject-0.15.1-2025-09-04-48-1.tar.zst -https://github.com/mbadolato/iTerm2-Color-Schemes/archive/6cdbc8501d48601302e32d6b53e9e7934bf354b4.tar.gz +https://github.com/mbadolato/iTerm2-Color-Schemes/archive/b314fc540434cc037c2811fc048d32854b5b78c3.tar.gz https://github.com/mitchellh/libxev/archive/7f803181b158a10fec8619f793e3b4df515566cb.tar.gz https://github.com/mitchellh/zig-objc/archive/c9e917a4e15a983b672ca779c7985d738a2d517c.tar.gz https://github.com/natecraddock/zf/archive/7aacbe6d155d64d15937ca95ca6c014905eb531f.tar.gz diff --git a/flatpak/zig-packages.json b/flatpak/zig-packages.json index 0663b41df..2bdee65b1 100644 --- a/flatpak/zig-packages.json +++ b/flatpak/zig-packages.json @@ -61,9 +61,9 @@ }, { "type": "archive", - "url": "https://github.com/mbadolato/iTerm2-Color-Schemes/archive/6cdbc8501d48601302e32d6b53e9e7934bf354b4.tar.gz", - "dest": "vendor/p/N-V-__8AAAtjXwSdhZq_xYbCXo0SZMqoNoQuHFkC07sijQME", - "sha256": "3655177013a6680f16fbb457b97727f532219bdeb87573b63a9e10090c610f27" + "url": "https://github.com/mbadolato/iTerm2-Color-Schemes/archive/b314fc540434cc037c2811fc048d32854b5b78c3.tar.gz", + "dest": "vendor/p/N-V-__8AAGupuwFrRxb2dkqFqmEChLEa4J3e95GReqvomV1b", + "sha256": "def3e50c38efe8108bcaba35632b733ed17415f047db4b2462e03d95a0d685a7" }, { "type": "archive", From 38544b7a8b34faecb7cc97c4bb1040874a890652 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 6 Sep 2025 14:11:44 -0700 Subject: [PATCH 03/12] ci: do not run release tip workflow if corresponding commit released Fixes #8549 This also brings the release tip workflow more in line with the release tag workflow by using a setup job to create outputs that are reused by the other jobs. https://ampcode.com/threads/T-e2d431ad-8be8-46d2-aaa3-9fae71f9ff31 --- .github/scripts/ghostty-tip | 19 +++++ .github/workflows/release-tip.yml | 125 +++++++++++++++++++++--------- 2 files changed, 108 insertions(+), 36 deletions(-) create mode 100755 .github/scripts/ghostty-tip diff --git a/.github/scripts/ghostty-tip b/.github/scripts/ghostty-tip new file mode 100755 index 000000000..8b577bcac --- /dev/null +++ b/.github/scripts/ghostty-tip @@ -0,0 +1,19 @@ +#!/usr/bin/env nu + +# Check if a given commit SHA has a corresponding tip release. +# +# This does not validate that the commit SHA is valid for the +# Ghostty repository, only that a tip release exists for it. +def main [ + commit: string, # The full length commit SHA +] { + let url = $"https://tip.files.ghostty.org/($commit)/ghostty-macos-universal.zip" + + try { + http head $url + exit 0 + } catch { + print -e $"The SHA ($commit) does not have a corresponding tip release." + exit 1 + } +} diff --git a/.github/workflows/release-tip.yml b/.github/workflows/release-tip.yml index 009708f56..fe939492e 100644 --- a/.github/workflows/release-tip.yml +++ b/.github/workflows/release-tip.yml @@ -15,9 +15,57 @@ concurrency: cancel-in-progress: false jobs: + setup: + if: | + github.event_name == 'workflow_dispatch' || + ( + github.event.workflow_run.conclusion == 'success' && + github.repository_owner == 'ghostty-org' && + github.ref_name == 'main' + ) + runs-on: namespace-profile-ghostty-sm + outputs: + should_skip: ${{ steps.check.outputs.should_skip }} + build: ${{ steps.extract_build_info.outputs.build }} + commit: ${{ steps.extract_build_info.outputs.commit }} + commit_long: ${{ steps.extract_build_info.outputs.commit_long }} + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + # Important so that build number generation works + fetch-depth: 0 + - uses: cachix/install-nix-action@56a7bb7b56d9a92d4fd1bc05758de7eea4a370a8 # v31.6.0 + with: + nix_path: nixpkgs=channel:nixos-unstable + - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 + with: + name: ghostty + authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" + - name: Extract build info + id: extract_build_info + run: | + GHOSTTY_BUILD=$(git rev-list --count HEAD) + GHOSTTY_COMMIT=$(git rev-parse --short HEAD) + GHOSTTY_COMMIT_LONG=$(git rev-parse HEAD) + echo "build=$GHOSTTY_BUILD" >> $GITHUB_OUTPUT + echo "commit=$GHOSTTY_COMMIT" >> $GITHUB_OUTPUT + echo "commit_long=$GHOSTTY_COMMIT_LONG" >> $GITHUB_OUTPUT + - name: Check if tip already exists + id: check + run: | + GHOSTTY_COMMIT_LONG=$(git rev-parse HEAD) + if nix develop -c nu .github/scripts/ghostty-tip $GHOSTTY_COMMIT_LONG; then + echo "Tip release already exists for commit $GHOSTTY_COMMIT_LONG" + echo "should_skip=true" >> $GITHUB_OUTPUT + else + echo "No tip release found for commit $GHOSTTY_COMMIT_LONG" + echo "should_skip=false" >> $GITHUB_OUTPUT + fi + tag: runs-on: namespace-profile-ghostty-sm - needs: [build-macos] + needs: [setup, build-macos] + if: needs.setup.outputs.should_skip != 'true' steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Tip Tag @@ -29,7 +77,10 @@ jobs: sentry-dsym-debug-slow: runs-on: namespace-profile-ghostty-sm - needs: [build-macos-debug-slow] + needs: [setup, build-macos-debug-slow] + if: needs.setup.outputs.should_skip != 'true' + env: + GHOSTTY_COMMIT_LONG: ${{ needs.setup.outputs.commit_long }} steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -39,7 +90,6 @@ jobs: - name: Download dSYM run: | - GHOSTTY_COMMIT_LONG=$(git rev-parse HEAD) curl -L https://tip.files.ghostty.dev/${GHOSTTY_COMMIT_LONG}/ghostty-macos-universal-debug-slow-dsym.zip > dsym.zip - name: Upload dSYM to Sentry @@ -50,7 +100,10 @@ jobs: sentry-dsym-debug-fast: runs-on: namespace-profile-ghostty-sm - needs: [build-macos-debug-fast] + needs: [setup, build-macos-debug-fast] + if: needs.setup.outputs.should_skip != 'true' + env: + GHOSTTY_COMMIT_LONG: ${{ needs.setup.outputs.commit_long }} steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -60,7 +113,6 @@ jobs: - name: Download dSYM run: | - GHOSTTY_COMMIT_LONG=$(git rev-parse HEAD) curl -L https://tip.files.ghostty.dev/${GHOSTTY_COMMIT_LONG}/ghostty-macos-universal-debug-fast-dsym.zip > dsym.zip - name: Upload dSYM to Sentry @@ -71,7 +123,10 @@ jobs: sentry-dsym: runs-on: namespace-profile-ghostty-sm - needs: [build-macos] + needs: [setup, build-macos] + if: needs.setup.outputs.should_skip != 'true' + env: + GHOSTTY_COMMIT_LONG: ${{ needs.setup.outputs.commit_long }} steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -81,7 +136,6 @@ jobs: - name: Download dSYM run: | - GHOSTTY_COMMIT_LONG=$(git rev-parse HEAD) curl -L https://tip.files.ghostty.dev/${GHOSTTY_COMMIT_LONG}/ghostty-macos-universal-dsym.zip > dsym.zip - name: Upload dSYM to Sentry @@ -91,15 +145,17 @@ jobs: sentry-cli dif upload --project ghostty --wait dsym.zip source-tarball: + needs: [setup] if: | - ${{ + needs.setup.outputs.should_skip != 'true' && + ( github.event_name == 'workflow_dispatch' || ( github.event.workflow_run.conclusion == 'success' && github.repository_owner == 'ghostty-org' && github.ref_name == 'main' ) - }} + ) runs-on: namespace-profile-ghostty-md env: ZIG_LOCAL_CACHE_DIR: /zig/local-cache @@ -144,18 +200,24 @@ jobs: token: ${{ secrets.GH_RELEASE_TOKEN }} build-macos: + needs: [setup] if: | - ${{ + needs.setup.outputs.should_skip != 'true' && + ( github.event_name == 'workflow_dispatch' || ( github.event.workflow_run.conclusion == 'success' && github.repository_owner == 'ghostty-org' && github.ref_name == 'main' ) - }} + ) runs-on: namespace-profile-ghostty-macos-tahoe timeout-minutes: 90 + env: + GHOSTTY_BUILD: ${{ needs.setup.outputs.build }} + GHOSTTY_COMMIT: ${{ needs.setup.outputs.commit }} + GHOSTTY_COMMIT_LONG: ${{ needs.setup.outputs.commit_long }} steps: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -189,13 +251,6 @@ jobs: unzip sparkle.zip echo "$(pwd)/bin" >> $GITHUB_PATH - # Load Build Number - - name: Build Number - run: | - echo "GHOSTTY_BUILD=$(git rev-list --count head)" >> $GITHUB_ENV - echo "GHOSTTY_COMMIT=$(git rev-parse --short HEAD)" >> $GITHUB_ENV - echo "GHOSTTY_COMMIT_LONG=$(git rev-parse HEAD)" >> $GITHUB_ENV - # GhosttyKit is the framework that is built from Zig for our native # Mac app to access. Build this in release mode. - name: Build GhosttyKit @@ -364,18 +419,24 @@ jobs: destination-dir: ./ build-macos-debug-slow: + needs: [setup] if: | - ${{ + needs.setup.outputs.should_skip != 'true' && + ( github.event_name == 'workflow_dispatch' || ( github.event.workflow_run.conclusion == 'success' && github.repository_owner == 'ghostty-org' && github.ref_name == 'main' ) - }} + ) runs-on: namespace-profile-ghostty-macos-tahoe timeout-minutes: 90 + env: + GHOSTTY_BUILD: ${{ needs.setup.outputs.build }} + GHOSTTY_COMMIT: ${{ needs.setup.outputs.commit }} + GHOSTTY_COMMIT_LONG: ${{ needs.setup.outputs.commit_long }} steps: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -409,13 +470,6 @@ jobs: unzip sparkle.zip echo "$(pwd)/bin" >> $GITHUB_PATH - # Load Build Number - - name: Build Number - run: | - echo "GHOSTTY_BUILD=$(git rev-list --count head)" >> $GITHUB_ENV - echo "GHOSTTY_COMMIT=$(git rev-parse --short HEAD)" >> $GITHUB_ENV - echo "GHOSTTY_COMMIT_LONG=$(git rev-parse HEAD)" >> $GITHUB_ENV - # GhosttyKit is the framework that is built from Zig for our native # Mac app to access. Build this in release mode. - name: Build GhosttyKit @@ -544,18 +598,24 @@ jobs: destination-dir: ./ build-macos-debug-fast: + needs: [setup] if: | - ${{ + needs.setup.outputs.should_skip != 'true' && + ( github.event_name == 'workflow_dispatch' || ( github.event.workflow_run.conclusion == 'success' && github.repository_owner == 'ghostty-org' && github.ref_name == 'main' ) - }} + ) runs-on: namespace-profile-ghostty-macos-tahoe timeout-minutes: 90 + env: + GHOSTTY_BUILD: ${{ needs.setup.outputs.build }} + GHOSTTY_COMMIT: ${{ needs.setup.outputs.commit }} + GHOSTTY_COMMIT_LONG: ${{ needs.setup.outputs.commit_long }} steps: - name: Checkout code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -589,13 +649,6 @@ jobs: unzip sparkle.zip echo "$(pwd)/bin" >> $GITHUB_PATH - # Load Build Number - - name: Build Number - run: | - echo "GHOSTTY_BUILD=$(git rev-list --count head)" >> $GITHUB_ENV - echo "GHOSTTY_COMMIT=$(git rev-parse --short HEAD)" >> $GITHUB_ENV - echo "GHOSTTY_COMMIT_LONG=$(git rev-parse HEAD)" >> $GITHUB_ENV - # GhosttyKit is the framework that is built from Zig for our native # Mac app to access. Build this in release mode. - name: Build GhosttyKit From 24b9e33a8c5514006106c9a242390efbe5e41e19 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 6 Sep 2025 20:43:56 -0700 Subject: [PATCH 04/12] ci: only release tip releases when triggered from the main branch --- .github/workflows/release-tip.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/release-tip.yml b/.github/workflows/release-tip.yml index fe939492e..d632d0cc5 100644 --- a/.github/workflows/release-tip.yml +++ b/.github/workflows/release-tip.yml @@ -372,6 +372,10 @@ jobs: # Create our appcast for Sparkle - name: Generate Appcast + if: | + github.event.workflow_run.conclusion == 'success' && + github.repository_owner == 'ghostty-org' && + github.ref_name == 'main' env: SPARKLE_KEY: ${{ secrets.PROD_MACOS_SPARKLE_KEY }} run: | @@ -403,12 +407,20 @@ jobs: # Now upload our appcast. This ensures that the appcast never # gets out of sync with the binaries. - name: Prep R2 Storage for Appcast + if: | + github.event.workflow_run.conclusion == 'success' && + github.repository_owner == 'ghostty-org' && + github.ref_name == 'main' run: | rm -r blob mkdir blob cp appcast_new.xml blob/appcast.xml - name: Upload Appcast to R2 + if: | + github.event.workflow_run.conclusion == 'success' && + github.repository_owner == 'ghostty-org' && + github.ref_name == 'main' uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c # v1.4 with: r2-account-id: ${{ secrets.CF_R2_TIP_ACCOUNT_ID }} From fc9c3dab6752f060547e8998d1943619a2161674 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 6 Sep 2025 20:48:43 -0700 Subject: [PATCH 05/12] ci: echo release URLs for tip releases --- .github/workflows/release-tip.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.github/workflows/release-tip.yml b/.github/workflows/release-tip.yml index d632d0cc5..f53e426e7 100644 --- a/.github/workflows/release-tip.yml +++ b/.github/workflows/release-tip.yml @@ -430,6 +430,13 @@ jobs: source-dir: blob destination-dir: ./ + - name: Echo Release URLs + run: | + echo "Release URLs:" + echo " App Bundle: https://tip.files.ghostty.org/${GHOSTTY_COMMIT_LONG}/ghostty-macos-universal.zip" + echo " Debug Symbols: https://tip.files.ghostty.org/${GHOSTTY_COMMIT_LONG}/ghostty-macos-universal-dsym.zip" + echo " DMG: https://tip.files.ghostty.org/${GHOSTTY_COMMIT_LONG}/Ghostty.dmg" + build-macos-debug-slow: needs: [setup] if: | @@ -609,6 +616,12 @@ jobs: source-dir: blob destination-dir: ./ + - name: Echo Release URLs + run: | + echo "Release URLs:" + echo " App Bundle: https://tip.files.ghostty.org/${GHOSTTY_COMMIT_LONG}/ghostty-macos-universal-debug-slow.zip" + echo " Debug Symbols: https://tip.files.ghostty.org/${GHOSTTY_COMMIT_LONG}/ghostty-macos-universal-debug-slow-dsym.zip" + build-macos-debug-fast: needs: [setup] if: | @@ -787,3 +800,9 @@ jobs: r2-bucket: ghostty-tip source-dir: blob destination-dir: ./ + + - name: Echo Release URLs + run: | + echo "Release URLs:" + echo " App Bundle: https://tip.files.ghostty.org/${GHOSTTY_COMMIT_LONG}/ghostty-macos-universal-debug-fast.zip" + echo " Debug Symbols: https://tip.files.ghostty.org/${GHOSTTY_COMMIT_LONG}/ghostty-macos-universal-debug-fast-dsym.zip" From f198e5f163275e2afe7deaee36cfcf1ee238536b Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 6 Sep 2025 20:49:51 -0700 Subject: [PATCH 06/12] ci: remove the release PR workflow You can now use a dispatch of release tip; it'll only trigger a appcast update when triggered on the main branch. --- .github/workflows/release-pr.yml | 357 ------------------------------- 1 file changed, 357 deletions(-) delete mode 100644 .github/workflows/release-pr.yml diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml deleted file mode 100644 index 8c42a2a55..000000000 --- a/.github/workflows/release-pr.yml +++ /dev/null @@ -1,357 +0,0 @@ -on: - workflow_dispatch: {} - -name: Release PR - -jobs: - sentry-dsym-debug: - runs-on: namespace-profile-ghostty-sm - needs: [build-macos-debug] - steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Install sentry-cli - run: | - curl -sL https://sentry.io/get-cli/ | bash - - - name: Download dSYM - run: | - GHOSTTY_COMMIT_LONG=$(git rev-parse HEAD) - curl -L https://pr.files.ghostty.dev/${GHOSTTY_COMMIT_LONG}/ghostty-macos-universal-debug-dsym.zip > dsym.zip - - - name: Upload dSYM to Sentry - env: - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - run: | - sentry-cli dif upload --project ghostty --wait dsym.zip - - sentry-dsym: - runs-on: namespace-profile-ghostty-sm - needs: [build-macos] - steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Install sentry-cli - run: | - curl -sL https://sentry.io/get-cli/ | bash - - - name: Download dSYM - run: | - GHOSTTY_COMMIT_LONG=$(git rev-parse HEAD) - curl -L https://pr.files.ghostty.dev/${GHOSTTY_COMMIT_LONG}/ghostty-macos-universal-dsym.zip > dsym.zip - - - name: Upload dSYM to Sentry - env: - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - run: | - sentry-cli dif upload --project ghostty --wait dsym.zip - - build-macos: - runs-on: namespace-profile-ghostty-macos-tahoe - timeout-minutes: 90 - steps: - - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - with: - # Important so that build number generation works - fetch-depth: 0 - - # Install Nix and use that to run our tests so our environment matches exactly. - - uses: DeterminateSystems/nix-installer-action@main - with: - determinate: true - - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 - with: - name: ghostty - authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" - - # Setup Sparkle - - name: Setup Sparkle - env: - SPARKLE_VERSION: 2.7.1 - run: | - mkdir -p .action/sparkle - cd .action/sparkle - curl -L https://github.com/sparkle-project/Sparkle/releases/download/${SPARKLE_VERSION}/Sparkle-for-Swift-Package-Manager.zip > sparkle.zip - unzip sparkle.zip - echo "$(pwd)/bin" >> $GITHUB_PATH - - # Load Build Number - - name: Build Number - run: | - echo "GHOSTTY_BUILD=$(git rev-list --count head)" >> $GITHUB_ENV - echo "GHOSTTY_COMMIT=$(git rev-parse --short HEAD)" >> $GITHUB_ENV - echo "GHOSTTY_COMMIT_LONG=$(git rev-parse HEAD)" >> $GITHUB_ENV - - # GhosttyKit is the framework that is built from Zig for our native - # Mac app to access. Build this in release mode. - - name: Build GhosttyKit - run: nix develop -c zig build -Doptimize=ReleaseSafe -Demit-macos-app=false - - # 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 - sudo xcode-select -s /Applications/Xcode_26.0.app - xcodebuild -version - xcodebuild -target Ghostty -configuration Release - - # We inject the "build number" as simply the number of commits since HEAD. - # This will be a monotonically always increasing build number that we use. - - name: Update Info.plist - env: - SPARKLE_KEY_PUB: ${{ secrets.PROD_MACOS_SPARKLE_KEY_PUB }} - run: | - # Version Info - /usr/libexec/PlistBuddy -c "Set :GhosttyCommit $GHOSTTY_COMMIT" "macos/build/Release/Ghostty.app/Contents/Info.plist" - /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $GHOSTTY_BUILD" "macos/build/Release/Ghostty.app/Contents/Info.plist" - /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $GHOSTTY_COMMIT" "macos/build/Release/Ghostty.app/Contents/Info.plist" - - # Updater - /usr/libexec/PlistBuddy -c "Set :SUPublicEDKey $SPARKLE_KEY_PUB" "macos/build/Release/Ghostty.app/Contents/Info.plist" - /usr/libexec/PlistBuddy -c "Delete :SUEnableAutomaticChecks" "macos/build/Release/Ghostty.app/Contents/Info.plist" - - - name: Codesign app bundle - env: - MACOS_CERTIFICATE: ${{ secrets.PROD_MACOS_CERTIFICATE }} - MACOS_CERTIFICATE_PWD: ${{ secrets.PROD_MACOS_CERTIFICATE_PWD }} - MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }} - MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }} - run: | - # Turn our base64-encoded certificate back to a regular .p12 file - echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12 - - # We need to create a new keychain, otherwise using the certificate will prompt - # with a UI dialog asking for the certificate password, which we can't - # use in a headless CI environment - security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain - security default-keychain -s build.keychain - security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain - security import certificate.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign - security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CI_KEYCHAIN_PWD" build.keychain - - # Codesign Sparkle. Some notes here: - # - The XPC services aren't used since we don't sandbox Ghostty, - # but since they're part of the build, they still need to be - # codesigned. - # - The binaries in the "Versions" folders need to NOT be symlinks. - /usr/bin/codesign --verbose -f -s "$MACOS_CERTIFICATE_NAME" -o runtime "macos/build/Release/Ghostty.app/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Downloader.xpc" - /usr/bin/codesign --verbose -f -s "$MACOS_CERTIFICATE_NAME" -o runtime "macos/build/Release/Ghostty.app/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Installer.xpc" - /usr/bin/codesign --verbose -f -s "$MACOS_CERTIFICATE_NAME" -o runtime "macos/build/Release/Ghostty.app/Contents/Frameworks/Sparkle.framework/Versions/B/Autoupdate" - /usr/bin/codesign --verbose -f -s "$MACOS_CERTIFICATE_NAME" -o runtime "macos/build/Release/Ghostty.app/Contents/Frameworks/Sparkle.framework/Versions/B/Updater.app" - /usr/bin/codesign --verbose -f -s "$MACOS_CERTIFICATE_NAME" -o runtime "macos/build/Release/Ghostty.app/Contents/Frameworks/Sparkle.framework" - - # Codesign the app bundle - /usr/bin/codesign --verbose -f -s "$MACOS_CERTIFICATE_NAME" -o runtime --entitlements "macos/Ghostty.entitlements" macos/build/Release/Ghostty.app - - - name: "Notarize app bundle" - env: - APPLE_NOTARIZATION_ISSUER: ${{ secrets.APPLE_NOTARIZATION_ISSUER }} - APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }} - APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }} - run: | - # Store the notarization credentials so that we can prevent a UI password dialog - # from blocking the CI - echo "Create keychain profile" - echo "$APPLE_NOTARIZATION_KEY" > notarization_key.p8 - xcrun notarytool store-credentials "notarytool-profile" --key notarization_key.p8 --key-id "$APPLE_NOTARIZATION_KEY_ID" --issuer "$APPLE_NOTARIZATION_ISSUER" - rm notarization_key.p8 - - # We can't notarize an app bundle directly, but we need to compress it as an archive. - # Therefore, we create a zip file containing our app bundle, so that we can send it to the - # notarization service - echo "Creating temp notarization archive" - ditto -c -k --keepParent "macos/build/Release/Ghostty.app" "notarization.zip" - - # Here we send the notarization request to the Apple's Notarization service, waiting for the result. - # This typically takes a few seconds inside a CI environment, but it might take more depending on the App - # characteristics. Visit the Notarization docs for more information and strategies on how to optimize it if - # you're curious - echo "Notarize app" - xcrun notarytool submit "notarization.zip" --keychain-profile "notarytool-profile" --wait - - # Finally, we need to "attach the staple" to our executable, which will allow our app to be - # validated by macOS even when an internet connection is not available. - echo "Attach staple" - xcrun stapler staple "macos/build/Release/Ghostty.app" - - # Zip up the app - - name: Zip App - run: | - cd macos/build/Release - zip -9 -r --symlinks ../../../ghostty-macos-universal.zip Ghostty.app - zip -9 -r --symlinks ../../../ghostty-macos-universal-dsym.zip Ghostty.app.dSYM/ - - # Update Blob Storage - - name: Prep R2 Storage - run: | - mkdir blob - mkdir -p blob/${GHOSTTY_COMMIT_LONG} - cp ghostty-macos-universal.zip blob/${GHOSTTY_COMMIT_LONG}/ghostty-macos-universal.zip - cp ghostty-macos-universal-dsym.zip blob/${GHOSTTY_COMMIT_LONG}/ghostty-macos-universal-dsym.zip - - name: Upload to R2 - uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c # v1.4 - with: - r2-account-id: ${{ secrets.CF_R2_PR_ACCOUNT_ID }} - r2-access-key-id: ${{ secrets.CF_R2_PR_AWS_KEY }} - r2-secret-access-key: ${{ secrets.CF_R2_PR_SECRET_KEY }} - r2-bucket: ghostty-pr - source-dir: blob - destination-dir: ./ - - build-macos-debug: - runs-on: namespace-profile-ghostty-macos-tahoe - timeout-minutes: 90 - steps: - - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - with: - # Important so that build number generation works - fetch-depth: 0 - - # Install Nix and use that to run our tests so our environment matches exactly. - - uses: DeterminateSystems/nix-installer-action@main - with: - determinate: true - - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 - with: - name: ghostty - authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" - - # Setup Sparkle - - name: Setup Sparkle - env: - SPARKLE_VERSION: 2.7.1 - run: | - mkdir -p .action/sparkle - cd .action/sparkle - curl -L https://github.com/sparkle-project/Sparkle/releases/download/${SPARKLE_VERSION}/Sparkle-for-Swift-Package-Manager.zip > sparkle.zip - unzip sparkle.zip - echo "$(pwd)/bin" >> $GITHUB_PATH - - # Load Build Number - - name: Build Number - run: | - echo "GHOSTTY_BUILD=$(git rev-list --count head)" >> $GITHUB_ENV - echo "GHOSTTY_COMMIT=$(git rev-parse --short HEAD)" >> $GITHUB_ENV - echo "GHOSTTY_COMMIT_LONG=$(git rev-parse HEAD)" >> $GITHUB_ENV - - # GhosttyKit is the framework that is built from Zig for our native - # Mac app to access. Build this in release mode. - - name: Build GhosttyKit - run: nix develop -c zig build -Doptimize=Debug -Demit-macos-app=false - - # 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 - sudo xcode-select -s /Applications/Xcode_26.0.app - xcodebuild -version - xcodebuild -target Ghostty -configuration Release - - # We inject the "build number" as simply the number of commits since HEAD. - # This will be a monotonically always increasing build number that we use. - - name: Update Info.plist - env: - SPARKLE_KEY_PUB: ${{ secrets.PROD_MACOS_SPARKLE_KEY_PUB }} - run: | - # Version Info - /usr/libexec/PlistBuddy -c "Set :GhosttyCommit $GHOSTTY_COMMIT" "macos/build/Release/Ghostty.app/Contents/Info.plist" - /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $GHOSTTY_BUILD" "macos/build/Release/Ghostty.app/Contents/Info.plist" - /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $GHOSTTY_COMMIT" "macos/build/Release/Ghostty.app/Contents/Info.plist" - - # Updater - /usr/libexec/PlistBuddy -c "Set :SUPublicEDKey $SPARKLE_KEY_PUB" "macos/build/Release/Ghostty.app/Contents/Info.plist" - /usr/libexec/PlistBuddy -c "Delete :SUEnableAutomaticChecks" "macos/build/Release/Ghostty.app/Contents/Info.plist" - - - name: Codesign app bundle - env: - MACOS_CERTIFICATE: ${{ secrets.PROD_MACOS_CERTIFICATE }} - MACOS_CERTIFICATE_PWD: ${{ secrets.PROD_MACOS_CERTIFICATE_PWD }} - MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }} - MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }} - run: | - # Turn our base64-encoded certificate back to a regular .p12 file - echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12 - - # We need to create a new keychain, otherwise using the certificate will prompt - # with a UI dialog asking for the certificate password, which we can't - # use in a headless CI environment - security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain - security default-keychain -s build.keychain - security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain - security import certificate.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign - security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CI_KEYCHAIN_PWD" build.keychain - - # Codesign Sparkle. Some notes here: - # - The XPC services aren't used since we don't sandbox Ghostty, - # but since they're part of the build, they still need to be - # codesigned. - # - The binaries in the "Versions" folders need to NOT be symlinks. - /usr/bin/codesign --verbose -f -s "$MACOS_CERTIFICATE_NAME" -o runtime "macos/build/Release/Ghostty.app/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Downloader.xpc" - /usr/bin/codesign --verbose -f -s "$MACOS_CERTIFICATE_NAME" -o runtime "macos/build/Release/Ghostty.app/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Installer.xpc" - /usr/bin/codesign --verbose -f -s "$MACOS_CERTIFICATE_NAME" -o runtime "macos/build/Release/Ghostty.app/Contents/Frameworks/Sparkle.framework/Versions/B/Autoupdate" - /usr/bin/codesign --verbose -f -s "$MACOS_CERTIFICATE_NAME" -o runtime "macos/build/Release/Ghostty.app/Contents/Frameworks/Sparkle.framework/Versions/B/Updater.app" - /usr/bin/codesign --verbose -f -s "$MACOS_CERTIFICATE_NAME" -o runtime "macos/build/Release/Ghostty.app/Contents/Frameworks/Sparkle.framework" - - # Codesign the app bundle - /usr/bin/codesign --verbose -f -s "$MACOS_CERTIFICATE_NAME" -o runtime --entitlements "macos/Ghostty.entitlements" macos/build/Release/Ghostty.app - - - name: "Notarize app bundle" - env: - APPLE_NOTARIZATION_ISSUER: ${{ secrets.APPLE_NOTARIZATION_ISSUER }} - APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }} - APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }} - run: | - # Store the notarization credentials so that we can prevent a UI password dialog - # from blocking the CI - echo "Create keychain profile" - echo "$APPLE_NOTARIZATION_KEY" > notarization_key.p8 - xcrun notarytool store-credentials "notarytool-profile" --key notarization_key.p8 --key-id "$APPLE_NOTARIZATION_KEY_ID" --issuer "$APPLE_NOTARIZATION_ISSUER" - rm notarization_key.p8 - - # We can't notarize an app bundle directly, but we need to compress it as an archive. - # Therefore, we create a zip file containing our app bundle, so that we can send it to the - # notarization service - echo "Creating temp notarization archive" - ditto -c -k --keepParent "macos/build/Release/Ghostty.app" "notarization.zip" - - # Here we send the notarization request to the Apple's Notarization service, waiting for the result. - # This typically takes a few seconds inside a CI environment, but it might take more depending on the App - # characteristics. Visit the Notarization docs for more information and strategies on how to optimize it if - # you're curious - echo "Notarize app" - xcrun notarytool submit "notarization.zip" --keychain-profile "notarytool-profile" --wait - - # Finally, we need to "attach the staple" to our executable, which will allow our app to be - # validated by macOS even when an internet connection is not available. - echo "Attach staple" - xcrun stapler staple "macos/build/Release/Ghostty.app" - - # Zip up the app - - name: Zip App - run: | - cd macos/build/Release - zip -9 -r --symlinks ../../../ghostty-macos-universal-debug.zip Ghostty.app - zip -9 -r --symlinks ../../../ghostty-macos-universal-debug-dsym.zip Ghostty.app.dSYM/ - - # Update Blob Storage - - name: Prep R2 Storage - run: | - mkdir blob - mkdir -p blob/${GHOSTTY_COMMIT_LONG} - cp ghostty-macos-universal-debug.zip blob/${GHOSTTY_COMMIT_LONG}/ghostty-macos-universal-debug.zip - cp ghostty-macos-universal-debug-dsym.zip blob/${GHOSTTY_COMMIT_LONG}/ghostty-macos-universal-debug-dsym.zip - - name: Upload to R2 - uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c # v1.4 - with: - r2-account-id: ${{ secrets.CF_R2_PR_ACCOUNT_ID }} - r2-access-key-id: ${{ secrets.CF_R2_PR_AWS_KEY }} - r2-secret-access-key: ${{ secrets.CF_R2_PR_SECRET_KEY }} - r2-bucket: ghostty-pr - source-dir: blob - destination-dir: ./ From cff32c527f4a3eee6996ac1d64c8d0f429197336 Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Tue, 26 Aug 2025 14:35:51 -0500 Subject: [PATCH 07/12] ci: move snap build to separate workflow --- .github/workflows/snap.yml | 53 ++++++++++++++++++++++++++++++++++++++ .github/workflows/test.yml | 52 ++++++++++--------------------------- 2 files changed, 66 insertions(+), 39 deletions(-) create mode 100644 .github/workflows/snap.yml diff --git a/.github/workflows/snap.yml b/.github/workflows/snap.yml new file mode 100644 index 000000000..007f70650 --- /dev/null +++ b/.github/workflows/snap.yml @@ -0,0 +1,53 @@ +on: + workflow_dispatch: + inputs: + source-tarball-id: + description: source tarball built during build-dist + required: true + type: string + +name: Snap + +jobs: + build: + strategy: + fail-fast: false + matrix: + os: + [namespace-profile-ghostty-snap, namespace-profile-ghostty-snap-arm64] + runs-on: ${{ matrix.os }} + timeout-minutes: 45 + env: + ZIG_LOCAL_CACHE_DIR: /zig/local-cache + ZIG_GLOBAL_CACHE_DIR: /zig/global-cache + steps: + - name: Download Source Tarball Artifacts + uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + with: + artifact-ids: ${{ inputs.source-tarball-id }} + + - name: Extract tarball + run: | + mkdir dist + tar --verbose --extract --strip-components 1 --directory dist --file ghostty-source.tar.gz + + - name: Setup Cache + uses: namespacelabs/nscloud-cache-action@305bfa7ea980a858d511af4899414a84847c7991 # v1.2.16 + with: + path: | + /nix + /zig + + - run: sudo apt install -y udev + + - run: sudo systemctl start systemd-udevd + + # Workaround until this is fixed: https://github.com/canonical/lxd-pkg-snap/pull/789 + - run: | + _LXD_SNAP_DEVCGROUP_CONFIG="/var/lib/snapd/cgroup/snap.lxd.device" + sudo mkdir -p /var/lib/snapd/cgroup + echo 'self-managed=true' | sudo tee "${_LXD_SNAP_DEVCGROUP_CONFIG}" + + - uses: snapcore/action-build@3bdaa03e1ba6bf59a65f84a751d943d549a54e79 # v1.3.0 + with: + path: dist diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a2b2a84aa..a40858d54 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,7 +17,6 @@ jobs: - build-linux - build-linux-libghostty - build-nix - - build-snap - build-macos - build-macos-matrix - build-windows @@ -234,6 +233,8 @@ jobs: build-dist: runs-on: namespace-profile-ghostty-md needs: test + outputs: + artifact-id: ${{ steps.upload-artifact.outputs.artifact-id }} env: ZIG_LOCAL_CACHE_DIR: /zig/local-cache ZIG_GLOBAL_CACHE_DIR: /zig/global-cache @@ -264,12 +265,23 @@ jobs: cp zig-out/dist/*.tar.gz ghostty-source.tar.gz - name: Upload artifact + id: upload-artifact uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: source-tarball path: |- ghostty-source.tar.gz + trigger-snap: + runs-on: namespace-profile-ghostty-xsm + needs: build-dist + steps: + - name: Trigger Snap workflow + run: | + gh workflow run snap.yml --ref ${{ github.sha }} --field source-tarball-id=${{ needs.build-dist.outputs.artifact-id }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + build-macos: runs-on: namespace-profile-ghostty-macos-tahoe needs: test @@ -355,44 +367,6 @@ jobs: nix develop -c zig build --system ${{ steps.deps.outputs.deps }} -Demit-macos-app=false -Drenderer=metal -Dfont-backend=coretext_harfbuzz nix develop -c zig build --system ${{ steps.deps.outputs.deps }} -Demit-macos-app=false -Drenderer=metal -Dfont-backend=coretext_noshape - build-snap: - strategy: - fail-fast: false - matrix: - os: - [namespace-profile-ghostty-snap, namespace-profile-ghostty-snap-arm64] - runs-on: ${{ matrix.os }} - timeout-minutes: 45 - needs: [test, build-dist] - env: - ZIG_LOCAL_CACHE_DIR: /zig/local-cache - ZIG_GLOBAL_CACHE_DIR: /zig/global-cache - steps: - - name: Download Source Tarball Artifacts - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 - with: - name: source-tarball - - name: Extract tarball - run: | - mkdir dist - tar --verbose --extract --strip-components 1 --directory dist --file ghostty-source.tar.gz - - name: Setup Cache - uses: namespacelabs/nscloud-cache-action@a289cf5d2fcd6874376aa92f0ef7f99dc923592a # v1.2.17 - with: - path: | - /nix - /zig - - run: sudo apt install -y udev - - run: sudo systemctl start systemd-udevd - # Workaround until this is fixed: https://github.com/canonical/lxd-pkg-snap/pull/789 - - run: | - _LXD_SNAP_DEVCGROUP_CONFIG="/var/lib/snapd/cgroup/snap.lxd.device" - sudo mkdir -p /var/lib/snapd/cgroup - echo 'self-managed=true' | sudo tee "${_LXD_SNAP_DEVCGROUP_CONFIG}" - - uses: snapcore/action-build@3bdaa03e1ba6bf59a65f84a751d943d549a54e79 # v1.3.0 - with: - path: dist - build-windows: runs-on: windows-2022 # this will not stop other jobs from running From 42a54d8d7ffc3c8666dff71c9cae773e2cdd93f5 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 7 Sep 2025 08:00:50 -0700 Subject: [PATCH 08/12] ci: try to checkout in snap.yml --- .github/workflows/snap.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/snap.yml b/.github/workflows/snap.yml index 007f70650..26b49cad2 100644 --- a/.github/workflows/snap.yml +++ b/.github/workflows/snap.yml @@ -21,6 +21,9 @@ jobs: ZIG_LOCAL_CACHE_DIR: /zig/local-cache ZIG_GLOBAL_CACHE_DIR: /zig/global-cache steps: + - name: Checkout code + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - name: Download Source Tarball Artifacts uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 with: From 55798edc9b0a66329f8c83d11c85b80a8fba2ef2 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 7 Sep 2025 08:22:28 -0700 Subject: [PATCH 09/12] ci: checkout in trigger-snap --- .github/workflows/snap.yml | 3 --- .github/workflows/test.yml | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/snap.yml b/.github/workflows/snap.yml index 26b49cad2..007f70650 100644 --- a/.github/workflows/snap.yml +++ b/.github/workflows/snap.yml @@ -21,9 +21,6 @@ jobs: ZIG_LOCAL_CACHE_DIR: /zig/local-cache ZIG_GLOBAL_CACHE_DIR: /zig/global-cache steps: - - name: Checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - name: Download Source Tarball Artifacts uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a40858d54..d2aee0085 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -276,6 +276,9 @@ jobs: runs-on: namespace-profile-ghostty-xsm needs: build-dist steps: + - name: Checkout code + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - name: Trigger Snap workflow run: | gh workflow run snap.yml --ref ${{ github.sha }} --field source-tarball-id=${{ needs.build-dist.outputs.artifact-id }} From 6d3bab725c88545b4f614d3ae99599c7d8966c62 Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Sun, 7 Sep 2025 10:32:46 -0500 Subject: [PATCH 10/12] nix: remove unnecessary input override --- flake.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/flake.nix b/flake.nix index dd97744b6..23b07f734 100644 --- a/flake.nix +++ b/flake.nix @@ -30,7 +30,6 @@ # we are using for "normal" builds. # # nixpkgs.follows = "nixpkgs"; - flake-utils.follows = "flake-utils"; }; }; }; From e1627a80e952afce5144d1f826e2ef35cd224cc3 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 7 Sep 2025 08:34:15 -0700 Subject: [PATCH 11/12] ci: I think --ref can only be a branch/tag name... --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d2aee0085..055bcf372 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -281,7 +281,7 @@ jobs: - name: Trigger Snap workflow run: | - gh workflow run snap.yml --ref ${{ github.sha }} --field source-tarball-id=${{ needs.build-dist.outputs.artifact-id }} + gh workflow run snap.yml --ref ${{ github.ref_name || 'main' }} --field source-tarball-id=${{ needs.build-dist.outputs.artifact-id }} env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 7582035a466feeebdfd5d5a2263a7295be359ae8 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 7 Sep 2025 13:32:54 -0700 Subject: [PATCH 12/12] ci: working on snaps --- .github/workflows/snap.yml | 10 ++++++++-- .github/workflows/test.yml | 6 +++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/snap.yml b/.github/workflows/snap.yml index 007f70650..dbb13ae95 100644 --- a/.github/workflows/snap.yml +++ b/.github/workflows/snap.yml @@ -1,7 +1,11 @@ on: workflow_dispatch: inputs: - source-tarball-id: + source-run-id: + description: run id of the workflow that generated the artifact + required: true + type: string + source-artifact-id: description: source tarball built during build-dist required: true type: string @@ -24,7 +28,9 @@ jobs: - name: Download Source Tarball Artifacts uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 with: - artifact-ids: ${{ inputs.source-tarball-id }} + run-id: ${{ inputs.source-run-id }} + artifact-ids: ${{ inputs.source-artifact-id }} + github-token: ${{ github.token }} - name: Extract tarball run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 055bcf372..dfd81b522 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -281,7 +281,11 @@ jobs: - name: Trigger Snap workflow run: | - gh workflow run snap.yml --ref ${{ github.ref_name || 'main' }} --field source-tarball-id=${{ needs.build-dist.outputs.artifact-id }} + gh workflow run \ + snap.yml \ + --ref ${{ github.ref_name || 'main' }} \ + --field source-run-id=${{ github.run_id }} \ + --field source-artifact-id=${{ needs.build-dist.outputs.artifact-id }} env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}