diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1dd81f..a79331a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,8 +65,8 @@ jobs: # Create app bundle mkdir -p "$APP_PATH/Contents/MacOS" mkdir -p "$APP_PATH/Contents/Resources" - cp .build/apple/Products/Release/bootstrapmate "$APP_PATH/Contents/MacOS/installapplications" - chmod 755 "$APP_PATH/Contents/MacOS/installapplications" + cp .build/apple/Products/Release/bootstrapmate "$APP_PATH/Contents/MacOS/managedbootstrapinstall" + chmod 755 "$APP_PATH/Contents/MacOS/managedbootstrapinstall" sed "s/{{VERSION}}/$VERSION/g" "$PACKAGING_DIR/resources/Info.plist.template" > "$APP_PATH/Contents/Info.plist" # Copy LaunchDaemon and scripts diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3501f1d..6f2bc5c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -89,10 +89,10 @@ jobs: "$PKG_ROOT/usr/local/bootstrapmate" "$ACTOOL_OUT" # Binaries (NO codesign -- the Munki pipeline signs downstream). - cp "$SWIFT_REL/bootstrapmate" "$APP_MACOS/installapplications" + cp "$SWIFT_REL/bootstrapmate" "$APP_MACOS/managedbootstrapinstall" cp "$SWIFT_REL/BootstrapMateApp" "$APP_MACOS/BootstrapMateGUI" cp "$SWIFT_REL/BootstrapMateHelper" "$APP_MACOS/BootstrapMateHelper" - chmod 755 "$APP_MACOS/installapplications" "$APP_MACOS/BootstrapMateGUI" "$APP_MACOS/BootstrapMateHelper" + chmod 755 "$APP_MACOS/managedbootstrapinstall" "$APP_MACOS/BootstrapMateGUI" "$APP_MACOS/BootstrapMateHelper" # Info.plist (version placeholders). sed -e "s/{{MARKETING_VERSION}}/$MARKETING_VERSION/g" \ @@ -134,7 +134,7 @@ jobs: echo "pkg=$PKG" >> "$GITHUB_OUTPUT" echo "--- built (unsigned) ---" ls -lh "$PKG" - pkgutil --payload-files "$PKG" | grep -E 'BootstrapMate(GUI|Helper)|installapplications' || true + pkgutil --payload-files "$PKG" | grep -E 'BootstrapMate(GUI|Helper)|managedbootstrapinstall' || true - name: Upload pkg artifact uses: actions/upload-artifact@v7 diff --git a/Makefile b/Makefile index 08e14c1..7205e53 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ BUILD_DIR = build PKG_ROOT = $(BUILD_DIR)/pkg-root PACKAGING_DIR = packaging SCRIPTS_DIR = $(BUILD_DIR)/scripts -BINARY_NAME = installapplications +BINARY_NAME = managedbootstrapinstall GUI_BINARY_NAME = BootstrapMateGUI HELPER_BINARY_NAME = BootstrapMateHelper BINARY_INSTALL_PATH = usr/local/bootstrapmate @@ -132,7 +132,7 @@ copy-binary: swift-build @codesign --force --sign "$(SIGNING_IDENTITY_APP)" \ --options runtime \ --timestamp \ - --identifier com.github.bootstrapmate.installapplications \ + --identifier com.github.bootstrapmate.managedbootstrapinstall \ $(SWIFT_BINARY) # Sign the GUI binary diff --git a/README.md b/README.md index 3d34312..4f9a42c 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Examples: Check installed version: ```bash -/usr/local/bootstrapmate/installapplications --version +/usr/local/bootstrapmate/managedbootstrapinstall --version ``` ## Building diff --git a/Sources/core/Managers/ConfigManager.swift b/Sources/core/Managers/ConfigManager.swift index 1939e2c..025b21f 100644 --- a/Sources/core/Managers/ConfigManager.swift +++ b/Sources/core/Managers/ConfigManager.swift @@ -92,8 +92,7 @@ public final class ConfigManager { // management preference domains to check (in order of priority) private let managementPreferenceDomains = [ - "com.github.bootstrapmate", // Primary BootstrapMate domain (management profile) - "io.macadmins.installapplications" // InstallApplications compatibility + "com.github.bootstrapmate" // Primary BootstrapMate domain (management profile) ] // Default installation path diff --git a/Sources/core/Utilities/BootstrapMateConstants.swift b/Sources/core/Utilities/BootstrapMateConstants.swift index b104937..a0902b3 100644 --- a/Sources/core/Utilities/BootstrapMateConstants.swift +++ b/Sources/core/Utilities/BootstrapMateConstants.swift @@ -2,7 +2,7 @@ import Foundation public enum BootstrapMateConstants { public static let daemonIdentifier = "com.github.bootstrapmate" - public static let executablePath = "/Applications/Utilities/BootstrapMate.app/Contents/MacOS/installapplications" + public static let executablePath = "/Applications/Utilities/BootstrapMate.app/Contents/MacOS/managedbootstrapinstall" public static let helperBundleID = "com.github.bootstrapmate.helper" public static let helperPlistName = "com.github.bootstrapmate.helper.plist" public static let defaultRetryCount = 3 diff --git a/Sources/core/Utilities/ManagementDetector.swift b/Sources/core/Utilities/ManagementDetector.swift index d270fc9..3cac878 100644 --- a/Sources/core/Utilities/ManagementDetector.swift +++ b/Sources/core/Utilities/ManagementDetector.swift @@ -14,8 +14,7 @@ public final class ManagementDetector: Sendable { /// Preference domains checked for management, in priority order. private let managedDomains = [ - "com.github.bootstrapmate", - "io.macadmins.installapplications" + "com.github.bootstrapmate" ] /// Known key aliases — maps canonical key to all variant names. diff --git a/Sources/core/Utilities/ManifestGenerator.swift b/Sources/core/Utilities/ManifestGenerator.swift index 51725f5..5dcf64f 100644 --- a/Sources/core/Utilities/ManifestGenerator.swift +++ b/Sources/core/Utilities/ManifestGenerator.swift @@ -37,11 +37,12 @@ public struct ManifestGenerator { ) } let hash = SHA256.hash(data: data).map { String(format: "%02x", $0) }.joined() + let filename = URL(fileURLWithPath: item.file).lastPathComponent let manifestItem = ManifestItem( name: item.name, - file: "/Library/bootstrapmate/\(URL(fileURLWithPath: item.file).lastPathComponent)", - url: "\(baseURL)/\(item.type)/\(URL(fileURLWithPath: item.file).lastPathComponent)", + file: "\(BootstrapMateConstants.cacheDirectory)/\(filename)", + url: "\(baseURL)/\(item.type)/\(filename)", hash: hash, type: item.type, retries: item.retries, diff --git a/packaging/LaunchDaemons/com.github.bootstrapmate.plist b/packaging/LaunchDaemons/com.github.bootstrapmate.plist index 5a980dd..07cfcee 100644 --- a/packaging/LaunchDaemons/com.github.bootstrapmate.plist +++ b/packaging/LaunchDaemons/com.github.bootstrapmate.plist @@ -6,7 +6,7 @@ com.github.bootstrapmate ProgramArguments - /Applications/Utilities/BootstrapMate.app/Contents/MacOS/installapplications + /Applications/Utilities/BootstrapMate.app/Contents/MacOS/managedbootstrapinstall RunAtLoad diff --git a/packaging/scripts/postinstall b/packaging/scripts/postinstall index a29dd1f..0aeb733 100755 --- a/packaging/scripts/postinstall +++ b/packaging/scripts/postinstall @@ -12,9 +12,9 @@ log() { log "=== BootstrapMate postinstall started ===" APP_PATH="/Applications/Utilities/BootstrapMate.app" -BINARY_PATH="${APP_PATH}/Contents/MacOS/installapplications" +BINARY_PATH="${APP_PATH}/Contents/MacOS/managedbootstrapinstall" SYMLINK_DIR="/usr/local/bootstrapmate" -SYMLINK_PATH="${SYMLINK_DIR}/installapplications" +SYMLINK_PATH="${SYMLINK_DIR}/managedbootstrapinstall" LAUNCHDAEMON_PATH="/Library/LaunchDaemons/com.github.bootstrapmate.plist" # Managed Bootstrap directory structure @@ -44,6 +44,9 @@ if [[ -x "${BINARY_PATH}" ]]; then mkdir -p "${SYMLINK_DIR}" ln -sf "${BINARY_PATH}" "${SYMLINK_PATH}" log "Symlink created: ${SYMLINK_PATH} -> ${BINARY_PATH}" + + # Hard cut: drop the legacy installapplications symlink from prior versions + rm -f "${SYMLINK_DIR}/installapplications" 2>/dev/null || true # Verify symlink works if [[ -x "${SYMLINK_PATH}" ]]; then @@ -60,8 +63,11 @@ if [[ -x "${BINARY_PATH}" ]]; then chown root:wheel "${LAUNCHDAEMON_PATH}" log "LaunchDaemon permissions set" - # Load the LaunchDaemon + # Boot out any previously loaded job first: launchctl load no-ops when the + # label is already loaded, which on an upgrade would leave launchd pointing + # at the old executable path (the binary was renamed). Boot out, then load. log "Loading LaunchDaemon..." + /bin/launchctl bootout system/com.github.bootstrapmate 2>/dev/null || true /bin/launchctl load -w "${LAUNCHDAEMON_PATH}" 2>&1 | tee -a /tmp/bootstrapmate-postinstall.log || log "launchctl load returned non-zero" log "LaunchDaemon load attempted" else