krz/octosentry
macOS menu bar app to monitor GitHub security alerts
clone: git clone https://gitbay.org/krz/octosentry.git
main: scripts/build-dmg.sh · raw
1#!/bin/bash
2#
3# build-dmg.sh
4#
5# Builds a notarized, Developer-ID-signed DMG for direct distribution
6# (spec §9: DMG/Homebrew channel). Requires local one-time setup this
7# script does NOT do for you:
8#
9# 1. A "Developer ID Application" certificate in your keychain, tied to
10# an active Apple Developer Program membership. Xcode > Settings >
11# Accounts > Manage Certificates > + > Developer ID Application.
12# 2. Notarization credentials stored once via:
13# xcrun notarytool store-credentials "octosentry-notary" \
14# --apple-id "you@example.com" \
15# --team-id "YOUR_TEAM_ID" \
16# --password "an-app-specific-password"
17# (App-specific password from appleid.apple.com, not your main
18# Apple ID password.)
19#
20# Usage: scripts/build-dmg.sh [version]
21# Output: build/octosentry-<version>.dmg
22
23set -euo pipefail
24
25VERSION="${1:-dev}"
26PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
27BUILD_DIR="$PROJECT_DIR/build"
28ARCHIVE_PATH="$BUILD_DIR/octosentry.xcarchive"
29EXPORT_PATH="$BUILD_DIR/export"
30EXPORT_OPTIONS_PLIST="$BUILD_DIR/export-options.plist"
31DMG_PATH="$BUILD_DIR/octosentry-$VERSION.dmg"
32NOTARY_PROFILE="octosentry-notary"
33
34rm -rf "$BUILD_DIR"
35mkdir -p "$BUILD_DIR"
36
37echo "==> Archiving (Release configuration)"
38xcodebuild archive \
39 -project "$PROJECT_DIR/octosentry.xcodeproj" \
40 -scheme octosentry \
41 -configuration Release \
42 -archivePath "$ARCHIVE_PATH"
43
44cat > "$EXPORT_OPTIONS_PLIST" <<PLIST
45<?xml version="1.0" encoding="UTF-8"?>
46<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
47<plist version="1.0">
48<dict>
49 <key>method</key>
50 <string>developer-id</string>
51</dict>
52</plist>
53PLIST
54
55echo "==> Exporting (Developer ID)"
56xcodebuild -exportArchive \
57 -archivePath "$ARCHIVE_PATH" \
58 -exportPath "$EXPORT_PATH" \
59 -exportOptionsPlist "$EXPORT_OPTIONS_PLIST"
60
61APP_PATH="$EXPORT_PATH/octosentry.app"
62
63# The app is notarized and stapled before it goes into the DMG, then the DMG
64# is notarized and stapled in turn. Stapling only the DMG leaves the app
65# itself without a ticket: once a user drags it to /Applications the disk
66# image is gone, and a machine that is offline has nothing local to check the
67# notarization against. Two submissions, but each artifact carries its own
68# ticket.
69echo "==> Notarizing app"
70APP_ZIP="$BUILD_DIR/octosentry.zip"
71ditto -c -k --keepParent "$APP_PATH" "$APP_ZIP"
72xcrun notarytool submit "$APP_ZIP" --keychain-profile "$NOTARY_PROFILE" --wait
73
74echo "==> Stapling ticket to app"
75xcrun stapler staple "$APP_PATH"
76
77echo "==> Building DMG"
78DMG_STAGING="$BUILD_DIR/staging"
79mkdir -p "$DMG_STAGING"
80cp -R "$APP_PATH" "$DMG_STAGING/"
81ln -s /Applications "$DMG_STAGING/Applications"
82
83hdiutil create -volname "octosentry" -srcfolder "$DMG_STAGING" -ov -format UDZO "$DMG_PATH"
84
85echo "==> Notarizing DMG"
86xcrun notarytool submit "$DMG_PATH" --keychain-profile "$NOTARY_PROFILE" --wait
87
88echo "==> Stapling ticket to DMG"
89xcrun stapler staple "$DMG_PATH"
90
91echo "==> Done: $DMG_PATH"