Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
2074718
docs: design observable automatic retry progress
AlexanderSmyslowski Jul 31, 2026
e7c4a27
docs: plan automatic retry progress implementation
AlexanderSmyslowski Jul 31, 2026
140ceb9
chore: ignore local worktrees
AlexanderSmyslowski Aug 1, 2026
ddbfe24
feat: mount NAS backups silently in v2.4.3
AlexanderSmyslowski Aug 1, 2026
4de4d21
feat: persist private backup progress telemetry
AlexanderSmyslowski Aug 1, 2026
9fb9023
fix: harden backup progress telemetry
AlexanderSmyslowski Aug 1, 2026
07b67a1
feat: show automatic retry progress in the overview
AlexanderSmyslowski Aug 1, 2026
c822024
fix: update the alert when an automatic retry starts
AlexanderSmyslowski Aug 1, 2026
32993c2
test: keep native harnesses out of the Dock
AlexanderSmyslowski Aug 1, 2026
7949450
fix: persist monotonic notification lifecycle state
AlexanderSmyslowski Aug 1, 2026
caceba2
fix: migrate partial notification lifecycle state
AlexanderSmyslowski Aug 1, 2026
b7988d3
chore: prepare v2.4.4 retry progress release
AlexanderSmyslowski Aug 1, 2026
5fc0505
docs: clarify v2.4.3 release publication
AlexanderSmyslowski Aug 1, 2026
89c0709
fix: preserve guest SMB remounts
AlexanderSmyslowski Aug 1, 2026
8dd766a
fix: preserve newer backup failure alerts
AlexanderSmyslowski Aug 1, 2026
d43a59b
fix: keep backup progress truthful
AlexanderSmyslowski Aug 1, 2026
e17e100
docs: harden release and install transaction
AlexanderSmyslowski Aug 1, 2026
26069bc
fix: close release install safety gaps
AlexanderSmyslowski Aug 1, 2026
84b7c4e
docs: complete v2.4.4 release notes
AlexanderSmyslowski Aug 1, 2026
d92128f
fix: materialize publication tracking ref
AlexanderSmyslowski Aug 1, 2026
050e060
fix: avoid publication fetch refspec coupling
AlexanderSmyslowski Aug 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*.tmp
build/
dist/
.worktrees/
*.app/
.config/
rclone.conf
Expand Down
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@

## Unreleased

## v2.4.4 - 2026-08-01

- Automatic retries now replace the stale waiting alert with a truthful running state.
- The overview and menu bar show private, per-phase progress without opening a foreground window.
- Progress is explicitly current-phase progress; scheduled and retry runs remain passive in full-screen Spaces.
- Restore accountless/guest SMB remounting without Keychain lookup or UI while leaving authenticated SMB behavior unchanged.
- Limit delayed success cleanup to issue origins older than or equal to that success, so it can never erase a newer persistent same-profile failure alert.
- Keep unknown-total progress indeterminate, remove stale or invented percentages, and show completion only after durable terminal status publication.

## v2.4.3 - 2026-07-30

- Mount a configured SMB backup target through a bounded native NetFS helper before scheduled work starts, using the Finder-saved password only in memory and explicitly prohibiting Finder, AppleScript, Keychain, or mount authentication UI during automatic runs.
- Preserve the authenticated SMB account when setup learns a mounted share, discard any password from legacy mount metadata, and provide an explicit one-time Keychain authorization mode for unattended access.
- Replace the preliminary “retry in 30 minutes” alert after a failed automatic retry has been accepted by macOS, while retaining the final alert until a newer automatic success or a human dismissal and healing an interrupted cleanup after controller restart.
- Make NAS mount tests inject every UI-capable executable and verify the native helper path, preventing test hostnames from reaching Finder.

## v2.4.2 - 2026-07-29

- Remove the protected time-sensitive notification entitlement from ad-hoc, unsigned-package, and Developer ID build paths until a provisioning profile can authorize it; this fixes the macOS `OS_REASON_EXEC` launch rejection introduced in v2.4.1.
Expand Down
80 changes: 61 additions & 19 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
APP_DIR := /Applications/GDrive Backup Tiger.app
PROGRESS_SUPPORT_SOURCE := macos/GDriveBackupTiger/BackupProgressSupport.m
APP_SOURCES := \
macos/GDriveBackupTiger/main.m \
macos/GDriveBackupTiger/ConfigSupport.m \
macos/GDriveBackupTiger/ProfileSupport.m \
macos/GDriveBackupTiger/BackupStatusSupport.m \
$(PROGRESS_SUPPORT_SOURCE) \
macos/GDriveBackupTiger/NotificationSupport.m \
macos/GDriveBackupTiger/SetupHealthSupport.m \
macos/GDriveBackupTiger/RestoreSupport.m \
macos/GDriveBackupTiger/RestoreBrowserView.m \
macos/GDriveBackupTiger/DiagnosticsSupport.m \
macos/GDriveBackupTiger/DiagnosticsView.m \
macos/GDriveBackupTiger/UpdateSupport.m \
macos/GDriveBackupTiger/NetworkMountSupport.m \
macos/GDriveBackupTiger/Localization.m
OBJC_FLAGS := -fobjc-arc -Wall -Wextra -Werror
MACOS_DEPLOYMENT_TARGET ?= 13.0
APP_ARCH_FLAGS ?= -arch arm64 -arch x86_64
APP_OBJC_FLAGS := $(OBJC_FLAGS) -mmacosx-version-min=$(MACOS_DEPLOYMENT_TARGET) $(APP_ARCH_FLAGS)
USER_NOTIFICATIONS_FRAMEWORK := -framework UserNotifications -framework Security
USER_NOTIFICATIONS_FRAMEWORK := -framework UserNotifications -framework Security \
-framework NetFS
NETWORK_MOUNT_SOURCE := macos/GDriveBackupTiger/NetworkMountSupport.m

.PHONY: build install dry-run pkg test clean

Expand Down Expand Up @@ -67,14 +72,16 @@ test:
bash tests/launch-agent-safety-test.sh
bash tests/release-metadata-test.sh
bash tests/release-workflow-test.sh
bash tests/release-install-runbook-test.sh
bash tests/package-entitlement-safety-test.sh
bash tests/app-build-artifacts-test.sh
bash tests/update-flow-safety-test.sh
@set -e; RUN_STATE_TEST_BIN="$$(/usr/bin/mktemp "$${TMPDIR:-/tmp}/gdrive-run-state-test.XXXXXX")"; \
clang $(OBJC_FLAGS) -framework Cocoa $(USER_NOTIFICATIONS_FRAMEWORK) -I macos/GDriveBackupTiger \
tests/run-state-ui-test.m macos/GDriveBackupTiger/ConfigSupport.m \
tests/run-state-ui-test.m macos/GDriveBackupTiger/ConfigSupport.m $(NETWORK_MOUNT_SOURCE) \
macos/GDriveBackupTiger/ProfileSupport.m \
macos/GDriveBackupTiger/BackupStatusSupport.m macos/GDriveBackupTiger/NotificationSupport.m \
macos/GDriveBackupTiger/BackupStatusSupport.m $(PROGRESS_SUPPORT_SOURCE) \
macos/GDriveBackupTiger/NotificationSupport.m \
macos/GDriveBackupTiger/SetupHealthSupport.m \
macos/GDriveBackupTiger/RestoreSupport.m macos/GDriveBackupTiger/RestoreBrowserView.m \
macos/GDriveBackupTiger/DiagnosticsSupport.m macos/GDriveBackupTiger/DiagnosticsView.m \
Expand All @@ -84,9 +91,10 @@ test:
./scripts/trash-path.sh "$$RUN_STATE_TEST_BIN"
@set -e; ACCESSIBILITY_TEST_BIN="$$(/usr/bin/mktemp "$${TMPDIR:-/tmp}/gdrive-accessibility-test.XXXXXX")"; \
clang $(OBJC_FLAGS) -framework Cocoa $(USER_NOTIFICATIONS_FRAMEWORK) -I macos/GDriveBackupTiger \
tests/tiger-accessibility-test.m macos/GDriveBackupTiger/ConfigSupport.m \
tests/tiger-accessibility-test.m macos/GDriveBackupTiger/ConfigSupport.m $(NETWORK_MOUNT_SOURCE) \
macos/GDriveBackupTiger/ProfileSupport.m \
macos/GDriveBackupTiger/BackupStatusSupport.m macos/GDriveBackupTiger/NotificationSupport.m \
macos/GDriveBackupTiger/BackupStatusSupport.m $(PROGRESS_SUPPORT_SOURCE) \
macos/GDriveBackupTiger/NotificationSupport.m \
macos/GDriveBackupTiger/SetupHealthSupport.m \
macos/GDriveBackupTiger/RestoreSupport.m macos/GDriveBackupTiger/RestoreBrowserView.m \
macos/GDriveBackupTiger/DiagnosticsSupport.m macos/GDriveBackupTiger/DiagnosticsView.m \
Expand All @@ -112,11 +120,25 @@ test:
-o "$$AUTOMATIC_RETRY_TEST_BIN"; \
"$$AUTOMATIC_RETRY_TEST_BIN"; \
./scripts/trash-path.sh "$$AUTOMATIC_RETRY_TEST_BIN"
@set -e; PROGRESS_SUPPORT_TEST_BIN="$$(/usr/bin/mktemp "$${TMPDIR:-/tmp}/gdrive-progress-support-test.XXXXXX")"; \
PROGRESS_SUPPORT_TEST_DIR="$$(/usr/bin/mktemp -d "$${TMPDIR:-/tmp}/gdrive-progress-support-fixtures.XXXXXX")"; \
COMPILE_STATUS=0; clang $(OBJC_FLAGS) -framework Foundation -I macos/GDriveBackupTiger \
tests/progress-support-test.m macos/GDriveBackupTiger/BackupProgressSupport.m \
-o "$$PROGRESS_SUPPORT_TEST_BIN" || COMPILE_STATUS=$$?; \
TEST_STATUS="$$COMPILE_STATUS"; \
if [ "$$COMPILE_STATUS" -eq 0 ]; then \
GDRIVE_PROGRESS_TEST_DIR="$$PROGRESS_SUPPORT_TEST_DIR" \
"$$PROGRESS_SUPPORT_TEST_BIN" || TEST_STATUS=$$?; \
fi; \
./scripts/trash-path.sh "$$PROGRESS_SUPPORT_TEST_BIN" \
"$$PROGRESS_SUPPORT_TEST_DIR"; \
exit "$$TEST_STATUS"
@set -e; NOTIFICATION_INTEGRATION_TEST_BIN="$$(/usr/bin/mktemp "$${TMPDIR:-/tmp}/gdrive-notification-integration-test.XXXXXX")"; \
clang $(OBJC_FLAGS) -framework Cocoa $(USER_NOTIFICATIONS_FRAMEWORK) -I macos/GDriveBackupTiger \
tests/notification-integration-test.m macos/GDriveBackupTiger/ConfigSupport.m \
tests/notification-integration-test.m macos/GDriveBackupTiger/ConfigSupport.m $(NETWORK_MOUNT_SOURCE) \
macos/GDriveBackupTiger/ProfileSupport.m \
macos/GDriveBackupTiger/BackupStatusSupport.m macos/GDriveBackupTiger/NotificationSupport.m \
macos/GDriveBackupTiger/BackupStatusSupport.m $(PROGRESS_SUPPORT_SOURCE) \
macos/GDriveBackupTiger/NotificationSupport.m \
macos/GDriveBackupTiger/SetupHealthSupport.m macos/GDriveBackupTiger/RestoreSupport.m \
macos/GDriveBackupTiger/RestoreBrowserView.m macos/GDriveBackupTiger/DiagnosticsSupport.m \
macos/GDriveBackupTiger/DiagnosticsView.m macos/GDriveBackupTiger/UpdateSupport.m \
Expand Down Expand Up @@ -175,9 +197,10 @@ test:
./scripts/trash-path.sh "$$DIAGNOSTICS_UI_TEST_BIN"
@set -e; DIAGNOSTICS_INTEGRATION_TEST_BIN="$$(/usr/bin/mktemp "$${TMPDIR:-/tmp}/gdrive-diagnostics-integration-test.XXXXXX")"; \
clang $(OBJC_FLAGS) -framework Cocoa $(USER_NOTIFICATIONS_FRAMEWORK) -I macos/GDriveBackupTiger \
tests/diagnostics-integration-test.m macos/GDriveBackupTiger/ConfigSupport.m \
tests/diagnostics-integration-test.m macos/GDriveBackupTiger/ConfigSupport.m $(NETWORK_MOUNT_SOURCE) \
macos/GDriveBackupTiger/ProfileSupport.m \
macos/GDriveBackupTiger/BackupStatusSupport.m macos/GDriveBackupTiger/NotificationSupport.m \
macos/GDriveBackupTiger/BackupStatusSupport.m $(PROGRESS_SUPPORT_SOURCE) \
macos/GDriveBackupTiger/NotificationSupport.m \
macos/GDriveBackupTiger/SetupHealthSupport.m \
macos/GDriveBackupTiger/RestoreSupport.m macos/GDriveBackupTiger/RestoreBrowserView.m \
macos/GDriveBackupTiger/DiagnosticsSupport.m macos/GDriveBackupTiger/DiagnosticsView.m \
Expand All @@ -187,9 +210,10 @@ test:
./scripts/trash-path.sh "$$DIAGNOSTICS_INTEGRATION_TEST_BIN"
@set -e; SETUP_HEALTH_UI_TEST_BIN="$$(/usr/bin/mktemp "$${TMPDIR:-/tmp}/gdrive-setup-health-ui-test.XXXXXX")"; \
clang $(OBJC_FLAGS) -framework Cocoa $(USER_NOTIFICATIONS_FRAMEWORK) -I macos/GDriveBackupTiger \
tests/setup-health-ui-test.m macos/GDriveBackupTiger/ConfigSupport.m \
tests/setup-health-ui-test.m macos/GDriveBackupTiger/ConfigSupport.m $(NETWORK_MOUNT_SOURCE) \
macos/GDriveBackupTiger/ProfileSupport.m \
macos/GDriveBackupTiger/BackupStatusSupport.m macos/GDriveBackupTiger/NotificationSupport.m \
macos/GDriveBackupTiger/BackupStatusSupport.m $(PROGRESS_SUPPORT_SOURCE) \
macos/GDriveBackupTiger/NotificationSupport.m \
macos/GDriveBackupTiger/SetupHealthSupport.m \
macos/GDriveBackupTiger/RestoreSupport.m macos/GDriveBackupTiger/RestoreBrowserView.m \
macos/GDriveBackupTiger/DiagnosticsSupport.m macos/GDriveBackupTiger/DiagnosticsView.m \
Expand All @@ -199,9 +223,10 @@ test:
./scripts/trash-path.sh "$$SETUP_HEALTH_UI_TEST_BIN"
@set -e; OVERVIEW_UI_TEST_BIN="$$(/usr/bin/mktemp "$${TMPDIR:-/tmp}/gdrive-overview-ui-test.XXXXXX")"; \
clang $(OBJC_FLAGS) -framework Cocoa $(USER_NOTIFICATIONS_FRAMEWORK) -I macos/GDriveBackupTiger \
tests/overview-ui-test.m macos/GDriveBackupTiger/ConfigSupport.m \
tests/overview-ui-test.m macos/GDriveBackupTiger/ConfigSupport.m $(NETWORK_MOUNT_SOURCE) \
macos/GDriveBackupTiger/ProfileSupport.m \
macos/GDriveBackupTiger/BackupStatusSupport.m macos/GDriveBackupTiger/NotificationSupport.m \
macos/GDriveBackupTiger/BackupStatusSupport.m $(PROGRESS_SUPPORT_SOURCE) \
macos/GDriveBackupTiger/NotificationSupport.m \
macos/GDriveBackupTiger/SetupHealthSupport.m \
macos/GDriveBackupTiger/RestoreSupport.m macos/GDriveBackupTiger/RestoreBrowserView.m \
macos/GDriveBackupTiger/DiagnosticsSupport.m macos/GDriveBackupTiger/DiagnosticsView.m \
Expand All @@ -212,9 +237,10 @@ test:
./scripts/trash-path.sh "$$OVERVIEW_UI_TEST_BIN"
@set -e; SETUP_SAFETY_TEST_BIN="$$(/usr/bin/mktemp "$${TMPDIR:-/tmp}/gdrive-setup-safety-test.XXXXXX")"; \
clang $(OBJC_FLAGS) -framework Cocoa $(USER_NOTIFICATIONS_FRAMEWORK) -I macos/GDriveBackupTiger \
tests/setup-safety-test.m macos/GDriveBackupTiger/ConfigSupport.m \
tests/setup-safety-test.m macos/GDriveBackupTiger/ConfigSupport.m $(NETWORK_MOUNT_SOURCE) \
macos/GDriveBackupTiger/ProfileSupport.m \
macos/GDriveBackupTiger/BackupStatusSupport.m macos/GDriveBackupTiger/NotificationSupport.m \
macos/GDriveBackupTiger/BackupStatusSupport.m $(PROGRESS_SUPPORT_SOURCE) \
macos/GDriveBackupTiger/NotificationSupport.m \
macos/GDriveBackupTiger/SetupHealthSupport.m \
macos/GDriveBackupTiger/RestoreSupport.m macos/GDriveBackupTiger/RestoreBrowserView.m \
macos/GDriveBackupTiger/DiagnosticsSupport.m macos/GDriveBackupTiger/DiagnosticsView.m \
Expand All @@ -225,9 +251,10 @@ test:
./scripts/trash-path.sh "$$SETUP_SAFETY_TEST_BIN"
@set -e; MOUNT_TRIGGER_TEST_BIN="$$(/usr/bin/mktemp "$${TMPDIR:-/tmp}/gdrive-mount-trigger-test.XXXXXX")"; \
clang $(OBJC_FLAGS) -framework Cocoa $(USER_NOTIFICATIONS_FRAMEWORK) -I macos/GDriveBackupTiger \
tests/mount-trigger-test.m macos/GDriveBackupTiger/ConfigSupport.m \
tests/mount-trigger-test.m macos/GDriveBackupTiger/ConfigSupport.m $(NETWORK_MOUNT_SOURCE) \
macos/GDriveBackupTiger/ProfileSupport.m \
macos/GDriveBackupTiger/BackupStatusSupport.m macos/GDriveBackupTiger/NotificationSupport.m \
macos/GDriveBackupTiger/BackupStatusSupport.m $(PROGRESS_SUPPORT_SOURCE) \
macos/GDriveBackupTiger/NotificationSupport.m \
macos/GDriveBackupTiger/SetupHealthSupport.m \
macos/GDriveBackupTiger/RestoreSupport.m macos/GDriveBackupTiger/RestoreBrowserView.m \
macos/GDriveBackupTiger/DiagnosticsSupport.m macos/GDriveBackupTiger/DiagnosticsView.m \
Expand All @@ -238,8 +265,9 @@ test:
./scripts/trash-path.sh "$$MOUNT_TRIGGER_TEST_BIN"
@set -e; PROFILE_UI_TEST_BIN="$$(/usr/bin/mktemp "$${TMPDIR:-/tmp}/gdrive-profile-ui-test.XXXXXX")"; \
clang $(OBJC_FLAGS) -framework Cocoa $(USER_NOTIFICATIONS_FRAMEWORK) -I macos/GDriveBackupTiger \
tests/profile-ui-test.m macos/GDriveBackupTiger/ConfigSupport.m \
tests/profile-ui-test.m macos/GDriveBackupTiger/ConfigSupport.m $(NETWORK_MOUNT_SOURCE) \
macos/GDriveBackupTiger/ProfileSupport.m macos/GDriveBackupTiger/BackupStatusSupport.m \
$(PROGRESS_SUPPORT_SOURCE) \
macos/GDriveBackupTiger/NotificationSupport.m \
macos/GDriveBackupTiger/SetupHealthSupport.m macos/GDriveBackupTiger/RestoreSupport.m \
macos/GDriveBackupTiger/RestoreBrowserView.m macos/GDriveBackupTiger/DiagnosticsSupport.m \
Expand All @@ -250,8 +278,9 @@ test:
./scripts/trash-path.sh "$$PROFILE_UI_TEST_BIN"
@set -e; UPDATE_UI_TEST_BIN="$$(/usr/bin/mktemp "$${TMPDIR:-/tmp}/gdrive-update-ui-test.XXXXXX")"; \
clang $(OBJC_FLAGS) -framework Cocoa $(USER_NOTIFICATIONS_FRAMEWORK) -I macos/GDriveBackupTiger \
tests/update-ui-test.m macos/GDriveBackupTiger/ConfigSupport.m \
tests/update-ui-test.m macos/GDriveBackupTiger/ConfigSupport.m $(NETWORK_MOUNT_SOURCE) \
macos/GDriveBackupTiger/ProfileSupport.m macos/GDriveBackupTiger/BackupStatusSupport.m \
$(PROGRESS_SUPPORT_SOURCE) \
macos/GDriveBackupTiger/NotificationSupport.m \
macos/GDriveBackupTiger/SetupHealthSupport.m macos/GDriveBackupTiger/RestoreSupport.m \
macos/GDriveBackupTiger/RestoreBrowserView.m macos/GDriveBackupTiger/DiagnosticsSupport.m \
Expand All @@ -267,6 +296,19 @@ test:
tests/config-support-test.m macos/GDriveBackupTiger/ConfigSupport.m -o "$$CONFIG_TEST_BIN"; \
"$$CONFIG_TEST_BIN"; \
./scripts/trash-path.sh "$$CONFIG_TEST_BIN"
@set -e; NAS_MOUNT_URL_TEST_BIN="$$(/usr/bin/mktemp "$${TMPDIR:-/tmp}/gdrive-nas-mount-url-test.XXXXXX")"; \
clang $(OBJC_FLAGS) -framework Foundation -I macos/GDriveBackupTiger \
tests/nas-mount-url-test.m macos/GDriveBackupTiger/ConfigSupport.m \
-o "$$NAS_MOUNT_URL_TEST_BIN"; \
"$$NAS_MOUNT_URL_TEST_BIN"; \
./scripts/trash-path.sh "$$NAS_MOUNT_URL_TEST_BIN"
@set -e; NETWORK_MOUNT_TEST_BIN="$$(/usr/bin/mktemp "$${TMPDIR:-/tmp}/gdrive-network-mount-test.XXXXXX")"; \
clang $(OBJC_FLAGS) -framework Foundation -framework Security -framework NetFS \
-I macos/GDriveBackupTiger tests/network-mount-support-test.m \
macos/GDriveBackupTiger/NetworkMountSupport.m \
-o "$$NETWORK_MOUNT_TEST_BIN"; \
"$$NETWORK_MOUNT_TEST_BIN"; \
./scripts/trash-path.sh "$$NETWORK_MOUNT_TEST_BIN"
bash -n bin/backup-google-drive.sh install.sh packaging/build-pkg.sh packaging/verify-pkg.sh packaging/scripts/postinstall scripts/*.sh tests/*.sh
plutil -lint launchd/com.commcats.gdrivebackup.plist macos/GDriveBackupTiger/Info.plist
shellcheck -x bin/backup-google-drive.sh install.sh packaging/build-pkg.sh packaging/verify-pkg.sh packaging/scripts/postinstall scripts/*.sh tests/*.sh
Expand Down
Loading
Loading