Skip to content

Commit 7c2df55

Browse files
revmischaclaude
andcommitted
Add code signing and notarization for macOS releases
Signs the app bundle and .pkg installer with Developer ID certificates, then notarizes both with Apple's notary service for Gatekeeper approval. Uses App Store Connect API key for notarization credentials. Replaces CPack with direct pkgbuild/productbuild for better signing control. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 0231108 commit 7c2df55

File tree

5 files changed

+131
-7
lines changed

5 files changed

+131
-7
lines changed

.github/workflows/release-macos.yaml

Lines changed: 110 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,121 @@ jobs:
117117
'-DDEFAULT_TEXTURES_PATH=${application.dir}/../share/projectMSDL/textures/' \
118118
-DENABLE_INSTALL_BDEPS=ON
119119
cmake --build cmake-build-frontend-sdl2 --parallel
120+
cmake --install cmake-build-frontend-sdl2 --prefix "${{ github.workspace }}/install"
121+
122+
- name: Import Code Signing Certificates
123+
env:
124+
MACOS_CERTIFICATE_APPLICATION: ${{ secrets.MACOS_CERTIFICATE_APPLICATION }}
125+
MACOS_CERTIFICATE_INSTALLER: ${{ secrets.MACOS_CERTIFICATE_INSTALLER }}
126+
MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
127+
run: |
128+
echo "$MACOS_CERTIFICATE_APPLICATION" | base64 --decode > app_cert.p12 && chmod 600 app_cert.p12
129+
echo "$MACOS_CERTIFICATE_INSTALLER" | base64 --decode > installer_cert.p12 && chmod 600 installer_cert.p12
130+
131+
KEYCHAIN_PASSWORD=$(openssl rand -base64 32)
132+
security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
133+
security default-keychain -s build.keychain
134+
security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
135+
136+
security import app_cert.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
137+
security import installer_cert.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PASSWORD" -T /usr/bin/productsign
138+
139+
security set-key-partition-list -S apple-tool:,apple:,codesign:,productbuild: -s -k "$KEYCHAIN_PASSWORD" build.keychain
140+
141+
rm app_cert.p12 installer_cert.p12
142+
143+
- name: Sign Application Bundle
144+
run: |
145+
APP_PATH="${{ github.workspace }}/install/projectM.app"
146+
IDENTITY="Developer ID Application: Mischa Spiegelmock (5926VBQM6Y)"
147+
148+
# Sign all dylibs first (if PlugIns directory exists)
149+
if [ -d "$APP_PATH/Contents/PlugIns" ]; then
150+
find "$APP_PATH/Contents/PlugIns" -name "*.dylib" -exec \
151+
codesign --force --options runtime --sign "$IDENTITY" {} \;
152+
fi
153+
154+
# Sign the main executable
155+
codesign --force --options runtime --sign "$IDENTITY" \
156+
"$APP_PATH/Contents/MacOS/projectM"
157+
158+
# Sign the entire bundle
159+
codesign --force --options runtime --sign "$IDENTITY" "$APP_PATH"
160+
161+
# Verify
162+
codesign --verify --deep --strict "$APP_PATH"
163+
164+
- name: Notarize Application
165+
env:
166+
API_KEY_BASE64: ${{ secrets.MACOS_NOTARY_API_KEY }}
167+
API_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }}
168+
API_ISSUER_ID: ${{ secrets.MACOS_NOTARY_ISSUER_ID }}
169+
run: |
170+
mkdir -p ~/.private_keys
171+
echo "$API_KEY_BASE64" | base64 --decode > ~/.private_keys/AuthKey_${API_KEY_ID}.p8
172+
chmod 600 ~/.private_keys/AuthKey_${API_KEY_ID}.p8
173+
174+
ditto -c -k --keepParent \
175+
"${{ github.workspace }}/install/projectM.app" \
176+
"projectM-notarize.zip"
177+
178+
xcrun notarytool submit "projectM-notarize.zip" \
179+
--key ~/.private_keys/AuthKey_${API_KEY_ID}.p8 \
180+
--key-id "$API_KEY_ID" \
181+
--issuer "$API_ISSUER_ID" \
182+
--wait
183+
184+
xcrun stapler staple "${{ github.workspace }}/install/projectM.app"
120185
121186
- name: Package projectMSDL
122187
run: |
123-
cd cmake-build-frontend-sdl2
124-
cpack -G productbuild
188+
# Get version from CMake
189+
VERSION=$(grep "project(projectMSDL" frontend-sdl2/CMakeLists.txt | sed -E 's/.*VERSION ([0-9.]+).*/\1/')
190+
191+
# Build component package from signed app
192+
pkgbuild \
193+
--root "${{ github.workspace }}/install" \
194+
--identifier "org.projectm-visualizer.projectmsdl" \
195+
--version "$VERSION" \
196+
--install-location "/Applications" \
197+
--component-plist "frontend-sdl2/src/resources/projectMSDL-component.plist" \
198+
"projectMSDL-component.pkg"
199+
200+
# Build unsigned product archive
201+
productbuild \
202+
--distribution "frontend-sdl2/src/resources/distribution.xml" \
203+
--package-path "." \
204+
--resources "frontend-sdl2/src/resources" \
205+
"projectM-${VERSION}-macOS-universal-unsigned.pkg"
206+
207+
# Sign the package with productsign
208+
productsign \
209+
--sign "Developer ID Installer: Mischa Spiegelmock (5926VBQM6Y)" \
210+
"projectM-${VERSION}-macOS-universal-unsigned.pkg" \
211+
"projectM-${VERSION}-macOS-universal.pkg"
212+
213+
rm "projectM-${VERSION}-macOS-universal-unsigned.pkg"
214+
215+
- name: Notarize Package
216+
env:
217+
API_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }}
218+
API_ISSUER_ID: ${{ secrets.MACOS_NOTARY_ISSUER_ID }}
219+
run: |
220+
PKG_FILE=$(ls projectM-*.pkg | head -1)
221+
222+
xcrun notarytool submit "$PKG_FILE" \
223+
--key ~/.private_keys/AuthKey_${API_KEY_ID}.p8 \
224+
--key-id "$API_KEY_ID" \
225+
--issuer "$API_ISSUER_ID" \
226+
--wait
227+
228+
xcrun stapler staple "$PKG_FILE"
229+
230+
# Clean up API key
231+
rm -f ~/.private_keys/AuthKey_${API_KEY_ID}.p8
125232
126233
- name: Upload Artifact
127234
uses: actions/upload-artifact@v4
128235
with:
129236
name: projectMSDL-macOS-Universal
130-
path: cmake-build-frontend-sdl2/*.pkg
237+
path: projectM-*.pkg

packaging-macos.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/src/resources/gpl-3
1010
set(CPACK_STRIP_FILES TRUE)
1111

1212
### Productbuild configuration
13-
set(CPACK_PKGBUILD_IDENTITY_NAME "${CODESIGN_IDENTITY_INSTALLER}")
14-
set(CPACK_PRODUCTBUILD_IDENTITY_NAME "${CODESIGN_IDENTITY_INSTALLER}")
13+
set(CPACK_PKGBUILD_IDENTITY_NAME "$ENV{CODESIGN_IDENTITY_INSTALLER}")
14+
set(CPACK_PRODUCTBUILD_IDENTITY_NAME "$ENV{CODESIGN_IDENTITY_INSTALLER}")
1515
set(CPACK_PRODUCTBUILD_IDENTIFIER "org.projectm-visualizer.projectmsdl")
1616

1717
string(REPLACE ";" "," INSTALL_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}")

src/resources/distribution.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<installer-gui-script minSpecVersion="2">
3+
<title>projectM</title>
4+
<organization>org.projectm-visualizer</organization>
5+
<welcome file="macos-welcome.txt"/>
6+
<readme file="macos-readme.txt"/>
7+
<license file="gpl-3.0.rtf"/>
8+
<options customize="never" require-scripts="false" hostArchitectures="x86_64,arm64"/>
9+
<domains enable_anywhere="false" enable_currentUserHome="false" enable_localSystem="true"/>
10+
<choices-outline>
11+
<line choice="default"/>
12+
</choices-outline>
13+
<choice id="default" title="projectM">
14+
<pkg-ref id="org.projectm-visualizer.projectmsdl"/>
15+
</choice>
16+
<pkg-ref id="org.projectm-visualizer.projectmsdl" version="0" onConclusion="none">projectMSDL-component.pkg</pkg-ref>
17+
</installer-gui-script>

src/resources/projectMSDL-component.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<key>BundleOverwriteAction</key>
1313
<string>upgrade</string>
1414
<key>RootRelativeBundlePath</key>
15-
<string>Applications/projectM.app</string>
15+
<string>projectM.app</string>
1616
</dict>
1717
</array>
1818
</plist>

vendor/imgui

Submodule imgui updated 157 files

0 commit comments

Comments
 (0)