Skip to content

Commit a2c7d74

Browse files
committed
feat: enhance notarization process with validation and retry logic for macOS DMG files
1 parent aaf45de commit a2c7d74

File tree

1 file changed

+159
-39
lines changed

1 file changed

+159
-39
lines changed

.github/workflows/release.yml

Lines changed: 159 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -127,39 +127,158 @@ jobs:
127127
DMG_PATH=$(find src-tauri/target/universal-apple-darwin/release/bundle/dmg -name "*.dmg" | head -n 1)
128128
129129
if [ -z "$DMG_PATH" ]; then
130-
echo "❌ Error: DMG file not found"
130+
echo "❌ Error: DMG file not found in expected location"
131+
echo "Expected path: src-tauri/target/universal-apple-darwin/release/bundle/dmg/"
132+
echo "Available files:"
133+
find src-tauri/target/universal-apple-darwin/release/bundle -type f || true
131134
exit 1
132135
fi
133136
134137
echo "📦 Found DMG: $DMG_PATH"
138+
139+
# Verify DMG is valid before notarization
140+
echo "🔍 Validating DMG integrity..."
141+
if ! hdiutil verify "$DMG_PATH"; then
142+
echo "❌ Error: DMG file is corrupted or invalid"
143+
exit 1
144+
fi
145+
echo "✅ DMG integrity verified"
146+
147+
# Verify code signing before notarization
148+
echo "🔍 Verifying code signature..."
149+
if ! codesign -dv --verbose=4 "$DMG_PATH" 2>&1; then
150+
echo "❌ Error: DMG is not properly code signed"
151+
exit 1
152+
fi
153+
echo "✅ Code signature verified"
154+
135155
echo "🔐 Submitting for notarization..."
136156
137-
# Submit for notarization
138-
xcrun notarytool submit "$DMG_PATH" \
139-
--apple-id "$APPLE_ID" \
140-
--team-id "$APPLE_TEAM_ID" \
141-
--password "$APPLE_PASSWORD" \
142-
--wait \
143-
--timeout 30m
157+
# Submit for notarization with retry logic
158+
SUBMISSION_OUTPUT=$(mktemp)
159+
MAX_RETRIES=3
160+
RETRY_COUNT=0
161+
SUCCESS=false
162+
163+
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
164+
if [ $RETRY_COUNT -gt 0 ]; then
165+
echo "⏳ Retry attempt $RETRY_COUNT of $((MAX_RETRIES - 1))..."
166+
sleep 30
167+
fi
168+
169+
if xcrun notarytool submit "$DMG_PATH" \
170+
--apple-id "$APPLE_ID" \
171+
--team-id "$APPLE_TEAM_ID" \
172+
--password "$APPLE_PASSWORD" \
173+
--wait \
174+
--timeout 30m 2>&1 | tee "$SUBMISSION_OUTPUT"; then
175+
SUCCESS=true
176+
break
177+
fi
178+
179+
RETRY_COUNT=$((RETRY_COUNT + 1))
180+
echo "⚠️ Notarization attempt $RETRY_COUNT failed"
181+
done
182+
183+
if [ "$SUCCESS" = false ]; then
184+
echo "❌ Notarization failed after $MAX_RETRIES attempts"
185+
echo "Final submission output:"
186+
cat "$SUBMISSION_OUTPUT"
187+
188+
# Try to extract submission ID for logs
189+
SUBMISSION_ID=$(grep -oE '[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}' "$SUBMISSION_OUTPUT" | head -n 1 || true)
190+
if [ -n "$SUBMISSION_ID" ]; then
191+
echo "📋 Fetching notarization logs for submission: $SUBMISSION_ID"
192+
xcrun notarytool log "$SUBMISSION_ID" \
193+
--apple-id "$APPLE_ID" \
194+
--team-id "$APPLE_TEAM_ID" \
195+
--password "$APPLE_PASSWORD" || true
196+
fi
197+
198+
rm -f "$SUBMISSION_OUTPUT"
199+
exit 1
200+
fi
144201
202+
rm -f "$SUBMISSION_OUTPUT"
145203
echo "✅ Notarization complete!"
146204
147205
# Staple the notarization ticket
148206
echo "📎 Stapling notarization ticket..."
149-
xcrun stapler staple "$DMG_PATH"
150-
207+
if ! xcrun stapler staple "$DMG_PATH"; then
208+
echo "❌ Error: Failed to staple notarization ticket"
209+
echo "This may indicate the notarization didn't complete successfully"
210+
exit 1
211+
fi
151212
echo "✅ Stapling complete!"
152213
153-
# Verify notarization
154-
echo "🔍 Verifying notarization..."
155-
spctl -a -vvv -t install "$DMG_PATH"
214+
# Verify notarization with Gatekeeper
215+
echo "🔍 Verifying notarization with Gatekeeper..."
216+
if ! spctl -a -vvv -t install "$DMG_PATH" 2>&1; then
217+
echo "❌ Error: Gatekeeper verification failed"
218+
echo "The app may not open on user systems"
219+
exit 1
220+
fi
221+
echo "✅ Gatekeeper verification passed!"
222+
223+
# Final validation
224+
echo "🔍 Final validation checks..."
225+
echo "Staple status:"
226+
xcrun stapler validate "$DMG_PATH" || {
227+
echo "⚠️ Warning: Staple validation failed"
228+
echo "The app is notarized but stapling may need to be checked"
229+
}
230+
231+
echo "✅ All notarization checks passed!"
156232
157233
- name: Generate checksums
158234
run: |
159235
cd src-tauri/target/universal-apple-darwin/release/bundle/dmg
236+
237+
# Verify DMG exists before generating checksums
238+
if [ ! -f *.dmg ]; then
239+
echo "❌ Error: No DMG file found for checksum generation"
240+
exit 1
241+
fi
242+
160243
shasum -a 256 *.dmg > checksums-macos.txt
244+
245+
# Verify checksum file was created and is not empty
246+
if [ ! -s checksums-macos.txt ]; then
247+
echo "❌ Error: Checksum file is empty or was not created"
248+
exit 1
249+
fi
250+
251+
echo "✅ Checksums generated:"
161252
cat checksums-macos.txt
162253
254+
- name: Validate artifacts before upload
255+
run: |
256+
DMG_PATH=$(find src-tauri/target/universal-apple-darwin/release/bundle/dmg -name "*.dmg" | head -n 1)
257+
258+
echo "🔍 Final artifact validation..."
259+
260+
# Verify file exists and has content
261+
if [ ! -f "$DMG_PATH" ]; then
262+
echo "❌ Error: DMG file not found"
263+
exit 1
264+
fi
265+
266+
FILE_SIZE=$(stat -f%z "$DMG_PATH" 2>/dev/null || stat -c%s "$DMG_PATH" 2>/dev/null)
267+
if [ "$FILE_SIZE" -lt 1048576 ]; then
268+
echo "❌ Error: DMG file is suspiciously small ($FILE_SIZE bytes)"
269+
exit 1
270+
fi
271+
272+
echo "✅ DMG size: $(echo "$FILE_SIZE" | awk '{printf "%.2f MB", $1/1024/1024}')"
273+
274+
# Verify notarization is still valid
275+
echo "🔍 Re-verifying notarization before upload..."
276+
if ! xcrun stapler validate "$DMG_PATH" >/dev/null 2>&1; then
277+
echo "⚠️ Warning: Staple validation check failed"
278+
fi
279+
280+
echo "✅ All artifact validations passed!"
281+
163282
- name: Upload macOS artifacts
164283
uses: actions/upload-artifact@v4
165284
with:
@@ -208,17 +327,16 @@ jobs:
208327

209328
- name: Generate checksums
210329
run: |
211-
cd src-tauri/target/release/bundle
212-
find . -type f \( -name "*.deb" -o -name "*.AppImage" \) -exec shasum -a 256 {} \; > checksums-linux.txt
213-
cat checksums-linux.txt
330+
cd src-tauri/target/release/bundle/deb
331+
shasum -a 256 *.deb > ../checksums-linux.txt
332+
cat ../checksums-linux.txt
214333
215334
- name: Upload Linux artifacts
216335
uses: actions/upload-artifact@v4
217336
with:
218337
name: linux-packages
219338
path: |
220339
src-tauri/target/release/bundle/deb/*.deb
221-
src-tauri/target/release/bundle/appimage/*.AppImage
222340
src-tauri/target/release/bundle/checksums-linux.txt
223341
224342
release-windows:
@@ -247,20 +365,19 @@ jobs:
247365
- name: Generate checksums
248366
shell: pwsh
249367
run: |
250-
cd src-tauri/target/release/bundle
251-
Get-ChildItem -Recurse -Include *.msi,*.exe | ForEach-Object {
368+
cd src-tauri/target/release/bundle/msi
369+
Get-ChildItem -Include *.msi | ForEach-Object {
252370
$hash = Get-FileHash $_.FullName -Algorithm SHA256
253371
"$($hash.Hash) $($_.Name)"
254-
} | Out-File -FilePath checksums-windows.txt
255-
Get-Content checksums-windows.txt
372+
} | Out-File -FilePath ..\checksums-windows.txt
373+
Get-Content ..\checksums-windows.txt
256374
257375
- name: Upload Windows artifacts
258376
uses: actions/upload-artifact@v4
259377
with:
260378
name: windows-installers
261379
path: |
262380
src-tauri/target/release/bundle/msi/*.msi
263-
src-tauri/target/release/bundle/nsis/*.exe
264381
src-tauri/target/release/bundle/checksums-windows.txt
265382
266383
create-release:
@@ -286,47 +403,50 @@ jobs:
286403
with:
287404
files: |
288405
artifacts/macos-dmg/*.dmg
289-
artifacts/macos-dmg/checksums-macos.txt
290-
artifacts/linux-packages/*.deb
291-
artifacts/linux-packages/*.AppImage
292-
artifacts/linux-packages/checksums-linux.txt
293-
artifacts/windows-installers/*.msi
294-
artifacts/windows-installers/*.exe
295-
artifacts/windows-installers/checksums-windows.txt
406+
artifacts/macos-dmg/*.txt
407+
artifacts/linux-packages/deb/*.deb
408+
artifacts/linux-packages/*.txt
409+
artifacts/windows-installers/msi/*.msi
410+
artifacts/windows-installers/*.txt
296411
draft: false
297412
prerelease: false
298413
generate_release_notes: true
299414
body: |
300415
## Installation
301416
302417
### macOS
303-
1. Download `Kide_*.dmg`
304-
2. Open the DMG and drag Kide to Applications
305-
3. Right-click Kide and select "Open" on first launch
306-
4. Verify: `codesign -dv --verbose=4 /Applications/Kide.app`
418+
1. Download the `.dmg` file
419+
2. Open the DMG and drag OpenObserve Kide to Applications
420+
3. Right-click and select "Open" on first launch (required for notarized apps)
421+
4. Verify signature: `codesign -dv --verbose=4 "/Applications/OpenObserve Kide.app"`
307422
308423
### Linux
309-
- **Debian/Ubuntu**: Download and install `.deb` file
310-
- **Other distros**: Download `.AppImage` file and make executable
424+
- **Debian/Ubuntu**: Download and install the `.deb` package
425+
```bash
426+
sudo dpkg -i openobserve-kide_*.deb
427+
```
311428
312429
### Windows
313-
- Download and run `.msi` installer
430+
- Download and run the `.msi` installer
314431
315432
## Verification
316433
317-
All releases include SHA-256 checksums. Verify your download:
434+
All releases include SHA-256 checksums for each platform. Verify your download:
318435
319436
```bash
320437
# macOS/Linux
321-
shasum -a 256 -c checksums-*.txt
438+
shasum -a 256 -c checksums-macos.txt
439+
shasum -a 256 -c checksums-linux.txt
322440
323441
# Windows (PowerShell)
324-
Get-FileHash Kide_*.msi -Algorithm SHA256
442+
Get-Content checksums-windows.txt
443+
Get-FileHash <downloaded-file> -Algorithm SHA256
325444
```
326445
327446
## Security
328447
329448
- macOS app is code-signed and notarized by Apple
449+
- All builds undergo security scanning (TruffleHog, npm audit, cargo audit)
330450
- All builds are reproducible from source
331451
- See [SECURITY.md](https://github.com/${{ github.repository }}/blob/main/SECURITY.md)
332452
env:

0 commit comments

Comments
 (0)