|
| 1 | +#!/usr/bin/env bash |
| 2 | +set -euo pipefail |
| 3 | + |
| 4 | +# ── Configuration ──────────────────────────────────────────────────── |
| 5 | +APP_NAME="Devtail" |
| 6 | +BUNDLE_ID="com.leerosen.devtail" |
| 7 | +EXECUTABLE="devtail" |
| 8 | +VERSION="${VERSION:-1.0.0}" |
| 9 | +SIGNING_IDENTITY="${SIGNING_IDENTITY:-Developer ID Application: Lee Rosen (RQ4599WP39)}" |
| 10 | + |
| 11 | +# ── Paths ──────────────────────────────────────────────────────────── |
| 12 | +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" |
| 13 | +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" |
| 14 | +BUILD_DIR="$PROJECT_DIR/.build/release" |
| 15 | +STAGING_DIR="$PROJECT_DIR/.build/package" |
| 16 | +APP_BUNDLE="$STAGING_DIR/$APP_NAME.app" |
| 17 | +DMG_DIR="$STAGING_DIR/dmg" |
| 18 | +DMG_OUTPUT="$STAGING_DIR/$APP_NAME-$VERSION.dmg" |
| 19 | + |
| 20 | +# ── Clean previous packaging artifacts ─────────────────────────────── |
| 21 | +rm -rf "$STAGING_DIR" |
| 22 | +mkdir -p "$STAGING_DIR" |
| 23 | + |
| 24 | +# ── Step 1: Build release binary ───────────────────────────────────── |
| 25 | +echo "▸ Building release binary…" |
| 26 | +swift build -c release --package-path "$PROJECT_DIR" |
| 27 | + |
| 28 | +if [ ! -f "$BUILD_DIR/$EXECUTABLE" ]; then |
| 29 | + echo "✗ Build failed — binary not found at $BUILD_DIR/$EXECUTABLE" >&2 |
| 30 | + exit 1 |
| 31 | +fi |
| 32 | + |
| 33 | +# ── Step 2: Assemble .app bundle ───────────────────────────────────── |
| 34 | +echo "▸ Assembling $APP_NAME.app bundle…" |
| 35 | +mkdir -p "$APP_BUNDLE/Contents/MacOS" |
| 36 | +mkdir -p "$APP_BUNDLE/Contents/Resources" |
| 37 | + |
| 38 | +cp "$BUILD_DIR/$EXECUTABLE" "$APP_BUNDLE/Contents/MacOS/$EXECUTABLE" |
| 39 | + |
| 40 | +cat > "$APP_BUNDLE/Contents/Info.plist" << PLIST |
| 41 | +<?xml version="1.0" encoding="UTF-8"?> |
| 42 | +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" |
| 43 | + "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| 44 | +<plist version="1.0"> |
| 45 | +<dict> |
| 46 | + <key>CFBundleName</key> |
| 47 | + <string>$APP_NAME</string> |
| 48 | + <key>CFBundleDisplayName</key> |
| 49 | + <string>$APP_NAME</string> |
| 50 | + <key>CFBundleIdentifier</key> |
| 51 | + <string>$BUNDLE_ID</string> |
| 52 | + <key>CFBundleVersion</key> |
| 53 | + <string>$VERSION</string> |
| 54 | + <key>CFBundleShortVersionString</key> |
| 55 | + <string>$VERSION</string> |
| 56 | + <key>CFBundleExecutable</key> |
| 57 | + <string>$EXECUTABLE</string> |
| 58 | + <key>CFBundlePackageType</key> |
| 59 | + <string>APPL</string> |
| 60 | + <key>LSMinimumSystemVersion</key> |
| 61 | + <string>14.0</string> |
| 62 | + <key>LSUIElement</key> |
| 63 | + <true/> |
| 64 | + <key>NSHighResolutionCapable</key> |
| 65 | + <true/> |
| 66 | +</dict> |
| 67 | +</plist> |
| 68 | +PLIST |
| 69 | + |
| 70 | +# ── Step 3: Code sign ─────────────────────────────────────────────── |
| 71 | +echo "▸ Signing with \"$SIGNING_IDENTITY\"…" |
| 72 | +codesign --force --options runtime --timestamp \ |
| 73 | + --sign "$SIGNING_IDENTITY" \ |
| 74 | + "$APP_BUNDLE" |
| 75 | + |
| 76 | +echo "▸ Verifying signature…" |
| 77 | +codesign --verify --verbose=2 "$APP_BUNDLE" |
| 78 | + |
| 79 | +# ── Step 4: Create DMG ────────────────────────────────────────────── |
| 80 | +echo "▸ Creating DMG…" |
| 81 | +mkdir -p "$DMG_DIR" |
| 82 | +cp -R "$APP_BUNDLE" "$DMG_DIR/" |
| 83 | +ln -s /Applications "$DMG_DIR/Applications" |
| 84 | + |
| 85 | +hdiutil create \ |
| 86 | + -volname "$APP_NAME" \ |
| 87 | + -srcfolder "$DMG_DIR" \ |
| 88 | + -ov -format UDZO \ |
| 89 | + "$DMG_OUTPUT" |
| 90 | + |
| 91 | +# Sign the DMG itself |
| 92 | +codesign --force --timestamp \ |
| 93 | + --sign "$SIGNING_IDENTITY" \ |
| 94 | + "$DMG_OUTPUT" |
| 95 | + |
| 96 | +# ── Done ───────────────────────────────────────────────────────────── |
| 97 | +echo "" |
| 98 | +echo "✔ $DMG_OUTPUT" |
| 99 | +echo "" |
| 100 | +echo "To notarize (required for Gatekeeper on other machines):" |
| 101 | +echo " xcrun notarytool submit \"$DMG_OUTPUT\" \\" |
| 102 | +echo " --apple-id YOUR_APPLE_ID \\" |
| 103 | +echo " --team-id RQ4599WP39 \\" |
| 104 | +echo " --password YOUR_APP_SPECIFIC_PASSWORD \\" |
| 105 | +echo " --wait" |
| 106 | +echo " xcrun stapler staple \"$DMG_OUTPUT\"" |
0 commit comments