diff --git a/.gitignore b/.gitignore index 974c238..a68401f 100644 --- a/.gitignore +++ b/.gitignore @@ -80,4 +80,7 @@ dist/ build/ # Mac... files -**/.DS_Store \ No newline at end of file +**/.DS_Store + +# Releases +releases/ \ No newline at end of file diff --git a/CommandNotch/CommandNotch.xcodeproj/project.pbxproj b/CommandNotch/CommandNotch.xcodeproj/project.pbxproj index 4f3e447..9af2fa9 100644 --- a/CommandNotch/CommandNotch.xcodeproj/project.pbxproj +++ b/CommandNotch/CommandNotch.xcodeproj/project.pbxproj @@ -511,20 +511,14 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = CommandNotch/Resources/CommandNotch.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = G698BP272N; INFOPLIST_FILE = CommandNotch/Resources/Info.plist; - INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 0.0.3; PRODUCT_BUNDLE_IDENTIFIER = com.commandnotch.app; PRODUCT_NAME = CommandNotch; - PROVISIONING_PROFILE_SPECIFIER = ""; SDKROOT = macosx; }; name = Debug; @@ -616,20 +610,14 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = CommandNotch/Resources/CommandNotch.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = G698BP272N; INFOPLIST_FILE = CommandNotch/Resources/Info.plist; - INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 0.0.3; PRODUCT_BUNDLE_IDENTIFIER = com.commandnotch.app; PRODUCT_NAME = CommandNotch; - PROVISIONING_PROFILE_SPECIFIER = ""; SDKROOT = macosx; }; name = Release; diff --git a/CommandNotch/CommandNotch.xcodeproj/project.xcworkspace/xcuserdata/harvmaster.xcuserdatad/UserInterfaceState.xcuserstate b/CommandNotch/CommandNotch.xcodeproj/project.xcworkspace/xcuserdata/harvmaster.xcuserdatad/UserInterfaceState.xcuserstate index 53017dc..9f6b18f 100644 Binary files a/CommandNotch/CommandNotch.xcodeproj/project.xcworkspace/xcuserdata/harvmaster.xcuserdatad/UserInterfaceState.xcuserstate and b/CommandNotch/CommandNotch.xcodeproj/project.xcworkspace/xcuserdata/harvmaster.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/README.md b/README.md index 9adb230..2b6d275 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ Click the preview above to watch the demo recording. - macOS 14 or later - Xcode 16 or later - Homebrew `xcodegen` +- Homebrew `create-dmg` for release `.dmg` packaging ### Build @@ -81,6 +82,33 @@ DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer \ xcodebuild build -project CommandNotch.xcodeproj -scheme CommandNotch -destination 'platform=macOS' ``` +### Build a release `.dmg` + +Use `create-dmg` to build the styled Finder installer window with the usual drag-to-`Applications` layout. + +Install the packaging dependency once: + +```bash +brew install create-dmg +``` + +Then build from the `app/` directory: + +```bash +./scripts/build-release-dmg.sh +``` + +That produces: + +- `releases/CommandNotch YYYY-MM-DD HH-MM-SS/CommandNotch.app` +- `releases/CommandNotch YYYY-MM-DD HH-MM-SS/CommandNotch.dmg` + +Notes: + +- The script regenerates the Xcode project, archives the Release build, then packages the archived app into a styled `.dmg`. +- The archive is written to `/tmp` and is only used as the source for the exported `.app`. +- If you want a distributable build signed with a specific identity, make sure your Xcode signing settings are configured before running the archive step. + ## Project Layout ```text diff --git a/scripts/build-release-dmg.sh b/scripts/build-release-dmg.sh new file mode 100755 index 0000000..f238ee1 --- /dev/null +++ b/scripts/build-release-dmg.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +APP_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +PROJECT_DIR="$APP_ROOT/CommandNotch" + +if ! command -v xcodegen >/dev/null 2>&1; then + echo "error: xcodegen is required. Install it with: brew install xcodegen" >&2 + exit 1 +fi + +if ! command -v create-dmg >/dev/null 2>&1; then + echo "error: create-dmg is required. Install it with: brew install create-dmg" >&2 + exit 1 +fi + +timestamp="$(date '+%Y-%m-%d %H-%M-%S')" +release_dir="$APP_ROOT/releases/CommandNotch $timestamp" +archive_path="/tmp/CommandNotch-$timestamp.xcarchive" +staging_dir="$(mktemp -d)" +app_path="$release_dir/CommandNotch.app" +dmg_path="$release_dir/CommandNotch.dmg" + +cleanup() { + rm -rf "$staging_dir" +} + +trap cleanup EXIT + +mkdir -p "$release_dir" + +cd "$PROJECT_DIR" +xcodegen generate --spec project.yml + +DEVELOPER_DIR="${DEVELOPER_DIR:-/Applications/Xcode.app/Contents/Developer}" \ + xcodebuild archive \ + -project CommandNotch.xcodeproj \ + -scheme CommandNotch \ + -configuration Release \ + -destination 'generic/platform=macOS' \ + -archivePath "$archive_path" + +ditto "$archive_path/Products/Applications/CommandNotch.app" "$app_path" +ditto "$app_path" "$staging_dir/CommandNotch.app" +ln -s /Applications "$staging_dir/Applications" + +create-dmg \ + --volname "CommandNotch" \ + --window-pos 200 120 \ + --window-size 720 420 \ + --icon-size 128 \ + --icon "CommandNotch.app" 180 210 \ + --icon "Applications" 540 210 \ + --hide-extension "CommandNotch.app" \ + --app-drop-link 540 210 \ + "$dmg_path" \ + "$staging_dir" + +echo "Created:" +echo " $app_path" +echo " $dmg_path"