@@ -20,21 +20,28 @@ jobs:
2020 with :
2121 submodules : recursive
2222
23- - name : Install dependencies
24- run : brew install zig
25-
2623 - name : Extract version from tag
2724 id : version
2825 run : |
2926 VERSION="${GITHUB_REF_NAME#v}"
3027 echo "version=$VERSION" >> "$GITHUB_OUTPUT"
3128 echo "Building version $VERSION"
3229
33- - name : Build GhosttyKit
34- run : ./scripts/build-ghostty.sh
30+ - name : Check available secrets
31+ id : secrets
32+ run : |
33+ echo "has_signing=${{ secrets.CERTIFICATE_P12 != '' }}" >> "$GITHUB_OUTPUT"
34+ echo "has_notarize=${{ secrets.APPLE_ID != '' }}" >> "$GITHUB_OUTPUT"
35+ echo "has_sparkle=${{ secrets.SPARKLE_PRIVATE_KEY != '' }}" >> "$GITHUB_OUTPUT"
36+ echo "has_tap=${{ secrets.HOMEBREW_TAP_TOKEN != '' }}" >> "$GITHUB_OUTPUT"
3537
36- - name : Build universal release binary
37- run : swift build -c release --arch arm64 --arch x86_64
38+ - name : Download pre-built GhosttyKit
39+ env :
40+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
41+ run : ./scripts/download-ghosttykit.sh
42+
43+ - name : Build release binary
44+ run : swift build -c release
3845
3946 - name : Prepare app bundle
4047 run : |
@@ -51,22 +58,36 @@ jobs:
5158 /usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${{ github.run_number }}" \
5259 MaQuake/Resources/Info.plist
5360
54- # Copy binary (universal path)
55- cp .build/apple/Products/Release/${{ env.APP_NAME }} "$APP_BUNDLE/Contents/MacOS/${{ env.APP_NAME }}"
61+ # Copy binary
62+ cp .build/release/${{ env.APP_NAME }} "$APP_BUNDLE/Contents/MacOS/${{ env.APP_NAME }}" 2>/dev/null \
63+ || cp .build/arm64-apple-macosx/release/${{ env.APP_NAME }} "$APP_BUNDLE/Contents/MacOS/${{ env.APP_NAME }}"
5664
57- # Copy Info.plist and resources
65+ # Copy Info.plist and icon
5866 cp MaQuake/Resources/Info.plist "$APP_BUNDLE/Contents/Info.plist"
5967 cp MaQuake/Resources/maquake.icns "$APP_BUNDLE/Contents/Resources/" 2>/dev/null || true
6068
69+ # Copy SPM resource bundles that have valid Info.plist (codesign-compatible)
70+ for dir in .build/release .build/arm64-apple-macosx/release .build/apple/Products/Release; do
71+ for bundle in "$dir"/*.bundle; do
72+ [ -d "$bundle" ] || continue
73+ [ -f "$bundle/Info.plist" ] || [ -f "$bundle/Contents/Info.plist" ] || continue
74+ name="$(basename "$bundle")"
75+ cp -R "$bundle" "$APP_BUNDLE/Contents/Resources/$name"
76+ cp -R "$bundle" "$APP_BUNDLE/Contents/MacOS/$name"
77+ done
78+ done
79+
6180 # Embed Sparkle.framework
62- SPARKLE_SRC=".build/artifacts/sparkle/Sparkle/Sparkle.xcframework/macos-arm64_x86_64/Sparkle.framework"
81+ SPARKLE_SRC=$(find .build -path "*/macos-arm64*/Sparkle.framework" -type d | head -1)
82+ [ -z "$SPARKLE_SRC" ] && SPARKLE_SRC=".build/artifacts/sparkle/Sparkle/Sparkle.xcframework/macos-arm64_x86_64/Sparkle.framework"
6383 cp -R "$SPARKLE_SRC" "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework"
6484
6585 # Add rpath for embedded frameworks
6686 install_name_tool -add_rpath "@executable_path/../Frameworks" \
6787 "$APP_BUNDLE/Contents/MacOS/${{ env.APP_NAME }}" 2>/dev/null || true
6888
6989 - name : Import signing certificate
90+ if : steps.secrets.outputs.has_signing == 'true'
7091 env :
7192 CERTIFICATE_P12 : ${{ secrets.CERTIFICATE_P12 }}
7293 CERTIFICATE_PASSWORD : ${{ secrets.CERTIFICATE_PASSWORD }}
@@ -90,12 +111,19 @@ jobs:
90111 security list-keychains -d user -s "$KEYCHAIN_PATH" login.keychain
91112
92113 - name : Sign app bundle (inside-out)
114+ if : steps.secrets.outputs.has_signing == 'true'
93115 run : |
94116 APP_BUNDLE="build/${{ env.APP_NAME }}.app"
95117 IDENTITY="${{ secrets.SIGNING_IDENTITY }}"
96118 ENTITLEMENTS="MaQuake/Resources/MaQuake.entitlements"
97119
98- # Sign Sparkle XPC services and helpers first (inside-out)
120+ # Sign resource bundles in MacOS/ first
121+ for bundle in "$APP_BUNDLE"/Contents/MacOS/*.bundle; do
122+ [ -d "$bundle" ] || continue
123+ codesign --force --sign "$IDENTITY" "$bundle"
124+ done
125+
126+ # Sign Sparkle XPC services and helpers (inside-out)
99127 codesign --force --sign "$IDENTITY" --options runtime \
100128 "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Installer.xpc"
101129 codesign --force --sign "$IDENTITY" --options runtime \
@@ -115,16 +143,26 @@ jobs:
115143
116144 codesign --verify --deep --strict "$APP_BUNDLE"
117145
146+ - name : Ad-hoc sign (when no certificate)
147+ if : steps.secrets.outputs.has_signing != 'true'
148+ run : |
149+ codesign --force --deep --sign - "build/${{ env.APP_NAME }}.app"
150+
118151 - name : Create DMG
119152 run : |
120153 hdiutil create -volname "${{ env.APP_NAME }}" \
121154 -srcfolder "build/${{ env.APP_NAME }}.app" \
122155 -ov -format UDZO \
123156 "build/${{ env.APP_NAME }}.dmg"
157+
158+ - name : Sign DMG
159+ if : steps.secrets.outputs.has_signing == 'true'
160+ run : |
124161 codesign --force --sign "${{ secrets.SIGNING_IDENTITY }}" \
125162 "build/${{ env.APP_NAME }}.dmg"
126163
127164 - name : Notarize DMG
165+ if : steps.secrets.outputs.has_notarize == 'true'
128166 env :
129167 APPLE_ID : ${{ secrets.APPLE_ID }}
130168 APPLE_PASSWORD : ${{ secrets.APPLE_APP_PASSWORD }}
@@ -138,6 +176,7 @@ jobs:
138176 xcrun stapler staple "build/${{ env.APP_NAME }}.dmg"
139177
140178 - name : Sign update with Sparkle
179+ if : steps.secrets.outputs.has_sparkle == 'true'
141180 env :
142181 SPARKLE_KEY : ${{ secrets.SPARKLE_PRIVATE_KEY }}
143182 run : |
@@ -147,6 +186,7 @@ jobs:
147186 rm "$RUNNER_TEMP/sparkle_key"
148187
149188 - name : Generate appcast
189+ if : steps.secrets.outputs.has_sparkle == 'true'
150190 env :
151191 SPARKLE_KEY : ${{ secrets.SPARKLE_PRIVATE_KEY }}
152192 run : |
@@ -162,6 +202,8 @@ jobs:
162202 /tmp/appcast_dir
163203
164204 rm "$RUNNER_TEMP/sparkle_key"
205+ # Fix title to lowercase branding
206+ sed -i '' 's|<title>Macuake</title>|<title>macuake</title>|' /tmp/appcast_dir/appcast.xml
165207 cp /tmp/appcast_dir/appcast.xml build/appcast.xml
166208
167209 - name : Create GitHub Release
@@ -170,6 +212,48 @@ jobs:
170212 files : |
171213 build/${{ env.APP_NAME }}.dmg
172214 build/appcast.xml
215+ fail_on_unmatched_files : false
173216 generate_release_notes : true
174217 draft : false
175218 prerelease : ${{ contains(github.ref_name, 'beta') || contains(github.ref_name, 'rc') }}
219+
220+ - name : Update Homebrew cask
221+ if : steps.secrets.outputs.has_tap == 'true' && !contains(github.ref_name, 'beta') && !contains(github.ref_name, 'rc')
222+ env :
223+ GH_TOKEN : ${{ secrets.HOMEBREW_TAP_TOKEN }}
224+ run : |
225+ VERSION="${{ steps.version.outputs.version }}"
226+ SHA=$(shasum -a 256 "build/${{ env.APP_NAME }}.dmg" | awk '{print $1}')
227+
228+ git clone "https://x-access-token:${GH_TOKEN}@github.com/menemy/homebrew-macuake.git" /tmp/tap
229+ cd /tmp/tap
230+
231+ python3 -c "
232+ v, s = '$VERSION', '$SHA'
233+ print(f'''cask \"macuake\" do
234+ version \"{v}\"
235+ sha256 \"{s}\"
236+
237+ url \"https://github.com/menemy/macuake/releases/download/v#{{version}}/Macuake.dmg\"
238+ name \"Macuake\"
239+ desc \"Drop-down Quake-style terminal for macOS powered by Ghostty\"
240+ homepage \"https://macuake.com\"
241+
242+ depends_on macos: \">= :sonoma\"
243+
244+ app \"Macuake.app\"
245+
246+ zap trash: [
247+ \"~/Library/Preferences/com.macuake.terminal.plist\",
248+ \"~/Library/Application Support/macuake\",
249+ ]
250+ end''')
251+ " | sed 's/^ //' > Casks/macuake.rb
252+
253+ git config user.name "github-actions[bot]"
254+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
255+ git add Casks/macuake.rb
256+ if ! git diff --cached --quiet; then
257+ git commit -m "Update macuake to $VERSION"
258+ git push
259+ fi
0 commit comments