Skip to content

Commit 2e0fe90

Browse files
Fix macOS release packaging to use proper .app bundle structure (#51)
macOS builds were shipping as flat folders of DLLs/binaries that weren't runnable. Now creates a proper .app bundle (Contents/MacOS, Contents/Resources, Info.plist) so the app is double-clickable on macOS. Also adds missing CFBundleExecutable to Info.plist and auto-syncs the plist version from the csproj at build time so it can't drift. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 58273ac commit 2e0fe90

2 files changed

Lines changed: 42 additions & 4 deletions

File tree

.github/workflows/release.yml

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,49 @@ jobs:
7373
run: |
7474
New-Item -ItemType Directory -Force -Path releases
7575
76-
$rids = @('win-x64', 'linux-x64', 'osx-x64', 'osx-arm64')
77-
foreach ($rid in $rids) {
76+
# Package Windows and Linux as flat zips
77+
foreach ($rid in @('win-x64', 'linux-x64')) {
7878
if (Test-Path 'README.md') { Copy-Item 'README.md' "publish/$rid/" }
7979
if (Test-Path 'LICENSE') { Copy-Item 'LICENSE' "publish/$rid/" }
8080
Compress-Archive -Path "publish/$rid/*" -DestinationPath "releases/PerformanceStudio-$rid.zip" -Force
8181
}
8282
83+
# Package macOS as proper .app bundles
84+
foreach ($rid in @('osx-x64', 'osx-arm64')) {
85+
$appName = "PerformanceStudio.app"
86+
$bundleDir = "publish/$rid-bundle/$appName"
87+
88+
# Create .app bundle structure
89+
New-Item -ItemType Directory -Force -Path "$bundleDir/Contents/MacOS"
90+
New-Item -ItemType Directory -Force -Path "$bundleDir/Contents/Resources"
91+
92+
# Copy all published files into Contents/MacOS
93+
Copy-Item -Path "publish/$rid/*" -Destination "$bundleDir/Contents/MacOS/" -Recurse
94+
95+
# Move Info.plist to Contents/ (it was copied to MacOS/ with the publish output)
96+
if (Test-Path "$bundleDir/Contents/MacOS/Info.plist") {
97+
Move-Item -Path "$bundleDir/Contents/MacOS/Info.plist" -Destination "$bundleDir/Contents/Info.plist" -Force
98+
}
99+
100+
# Update version in Info.plist to match csproj
101+
$plist = Get-Content "$bundleDir/Contents/Info.plist" -Raw
102+
$plist = $plist -replace '(<key>CFBundleVersion</key>\s*<string>)[^<]*(</string>)', "`${1}$env:VERSION`${2}"
103+
$plist = $plist -replace '(<key>CFBundleShortVersionString</key>\s*<string>)[^<]*(</string>)', "`${1}$env:VERSION`${2}"
104+
Set-Content -Path "$bundleDir/Contents/Info.plist" -Value $plist -NoNewline
105+
106+
# Move icon to Contents/Resources
107+
if (Test-Path "$bundleDir/Contents/MacOS/EDD.icns") {
108+
Move-Item -Path "$bundleDir/Contents/MacOS/EDD.icns" -Destination "$bundleDir/Contents/Resources/EDD.icns" -Force
109+
}
110+
111+
# Add README and LICENSE alongside the .app bundle
112+
$wrapperDir = "publish/$rid-bundle"
113+
if (Test-Path 'README.md') { Copy-Item 'README.md' "$wrapperDir/" }
114+
if (Test-Path 'LICENSE') { Copy-Item 'LICENSE' "$wrapperDir/" }
115+
116+
Compress-Archive -Path "$wrapperDir/*" -DestinationPath "releases/PerformanceStudio-$rid.zip" -Force
117+
}
118+
83119
# Checksums
84120
$checksums = Get-ChildItem releases/*.zip | ForEach-Object {
85121
$hash = (Get-FileHash $_.FullName -Algorithm SHA256).Hash.ToLower()

src/PlanViewer.App/Info.plist

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
<string>Performance Studio</string>
99
<key>CFBundleIdentifier</key>
1010
<string>com.darlingdata.sqlperformancestudio</string>
11+
<key>CFBundleExecutable</key>
12+
<string>PlanViewer.App</string>
1113
<key>CFBundleVersion</key>
12-
<string>0.7.0</string>
14+
<string>0.9.0</string>
1315
<key>CFBundleShortVersionString</key>
14-
<string>0.7.0</string>
16+
<string>0.9.0</string>
1517
<key>CFBundlePackageType</key>
1618
<string>APPL</string>
1719
<key>NSHumanReadableCopyright</key>

0 commit comments

Comments
 (0)