From 44992d24d39e7cfe677f829491e859744238a351 Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Mon, 15 May 2023 15:41:05 +0200 Subject: [PATCH 01/31] Make macos-WakaTime run on macOS 10.15 or newer --- WakaTime Helper/AppDelegate.swift | 31 ++++++++++ WakaTime Helper/WakaTime Helper-Info.plist | 8 +++ WakaTime Helper/main.swift | 6 ++ WakaTime/AppDelegate.swift | 64 +++++++++++++++++++++ WakaTime/Settings.swift | 58 ------------------- WakaTime/SettingsWindowController.swift | 67 ++++++++++++++++++++++ WakaTime/WakaTime.swift | 66 ++++++++------------- WakaTime/main.swift | 6 ++ project.yml | 29 +++++++++- 9 files changed, 233 insertions(+), 102 deletions(-) create mode 100644 WakaTime Helper/AppDelegate.swift create mode 100644 WakaTime Helper/WakaTime Helper-Info.plist create mode 100644 WakaTime Helper/main.swift create mode 100644 WakaTime/AppDelegate.swift delete mode 100644 WakaTime/Settings.swift create mode 100644 WakaTime/SettingsWindowController.swift create mode 100644 WakaTime/main.swift diff --git a/WakaTime Helper/AppDelegate.swift b/WakaTime Helper/AppDelegate.swift new file mode 100644 index 0000000..50d5b1c --- /dev/null +++ b/WakaTime Helper/AppDelegate.swift @@ -0,0 +1,31 @@ +import Cocoa + +class AppDelegate: NSObject, NSApplicationDelegate { + struct Constants { + static let mainAppBundleID = "macos-wakatime.WakaTime" + } + + func applicationDidFinishLaunching(_ aNotification: Notification) { + let runningApps = NSWorkspace.shared.runningApplications + let isRunning = runningApps.contains { + $0.bundleIdentifier == Constants.mainAppBundleID + } + + if !isRunning { + var path = Bundle.main.bundlePath as NSString + for _ in 1...4 { + path = path.deletingLastPathComponent as NSString + } + let fileURL = URL(fileURLWithPath: path as String) + print("Opening", fileURL.absoluteString) + NSWorkspace.shared.openApplication( + at: fileURL, + configuration: NSWorkspace.OpenConfiguration() + ) { _, error in + if let error { + print(error.localizedDescription) + } + } + } + } +} diff --git a/WakaTime Helper/WakaTime Helper-Info.plist b/WakaTime Helper/WakaTime Helper-Info.plist new file mode 100644 index 0000000..a69c6e9 --- /dev/null +++ b/WakaTime Helper/WakaTime Helper-Info.plist @@ -0,0 +1,8 @@ + + + + + LSBackgroundOnly + + + diff --git a/WakaTime Helper/main.swift b/WakaTime Helper/main.swift new file mode 100644 index 0000000..ae50fab --- /dev/null +++ b/WakaTime Helper/main.swift @@ -0,0 +1,6 @@ +import Cocoa + +let delegate = AppDelegate() +let application = NSApplication.shared +application.delegate = delegate +application.run() diff --git a/WakaTime/AppDelegate.swift b/WakaTime/AppDelegate.swift new file mode 100644 index 0000000..8967dcd --- /dev/null +++ b/WakaTime/AppDelegate.swift @@ -0,0 +1,64 @@ +import Cocoa + +class AppDelegate: NSObject, NSApplicationDelegate { + var window: NSWindow! + var statusBarItem: NSStatusItem! + var settingsWindowController = SettingsWindowController() + var wakaTime: WakaTime? + + func applicationDidFinishLaunching(_ aNotification: Notification) { + wakaTime = WakaTime() + + // Handle deep links + let eventManager = NSAppleEventManager.shared() + eventManager.setEventHandler( + self, + andSelector: #selector(handleGetURL(_:withReplyEvent:)), + forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL) + ) + + let statusBar = NSStatusBar.system + statusBarItem = statusBar.statusItem(withLength: NSStatusItem.variableLength) + statusBarItem.button?.image = NSImage(named: NSImage.Name("WakaTime")) + + let menu = NSMenu() + + menu.addItem(withTitle: "Dashboard", action: #selector(AppDelegate.dashboardClicked(_:)), keyEquivalent: "") + menu.addItem(withTitle: "Settings", action: #selector(AppDelegate.settingsClicked(_:)), keyEquivalent: "") + menu.addItem(NSMenuItem.separator()) + menu.addItem(withTitle: "Quit", action: #selector(AppDelegate.quitClicked(_:)), keyEquivalent: "") + + statusBarItem.menu = menu + } + + @objc func handleGetURL(_ event: NSAppleEventDescriptor, withReplyEvent replyEvent: NSAppleEventDescriptor) { + // Handle deep links + guard let urlString = event.paramDescriptor(forKeyword: keyDirectObject)?.stringValue, + let url = URL(string: urlString), + url.scheme == "wakatime" + else { return } + + if url.host == "settings" { + showSettings() + } + } + + @objc func dashboardClicked(_ sender: AnyObject) { + if let url = URL(string: "https://wakatime.com/") { + NSWorkspace.shared.open(url) + } + } + + @objc func settingsClicked(_ sender: AnyObject) { + showSettings() + } + + @objc func quitClicked(_ sender: AnyObject) { + NSApplication.shared.terminate(self) + } + + private func showSettings() { + NSApp.activate(ignoringOtherApps: true) + settingsWindowController.showWindow(self) + } +} diff --git a/WakaTime/Settings.swift b/WakaTime/Settings.swift deleted file mode 100644 index 3a89269..0000000 --- a/WakaTime/Settings.swift +++ /dev/null @@ -1,58 +0,0 @@ -import Foundation -import SwiftUI - -struct SettingsView: View { - @Environment(\.dismiss) private var dismiss - @Binding var apiKey: String - @SwiftUI.State private var isToggleOn = PropertiesManager.shouldLaunchOnLogin - - var body: some View { - GeometryReader { geometry in - HStack { - VStack(alignment: .leading) { - Toggle("Launch on login", isOn: $isToggleOn) - .onChange(of: isToggleOn) { newValue in - if newValue { - SettingsManager.registerAsLoginItem() - } else { - SettingsManager.unregisterAsLoginItem() - } - } - Spacer() - Divider() - Spacer() - Text("WakaTime API Key:") - TextField("apikey", text: $apiKey).frame(width: 200) - HStack { - Button("Save") { - ConfigFile.setSetting(section: "settings", key: "api_key", val: $apiKey.wrappedValue) - dismiss() - } - .keyboardShortcut(.defaultAction) - Button("Cancel") { - dismiss() - } - .keyboardShortcut(.cancelAction) - } - Spacer() - Text("Version: \(Bundle.main.version) (\(Bundle.main.build))") - .padding(.top) - } - .padding() - .frame(maxWidth: geometry.size.width) - } - } - .task { - if let window = NSApplication.shared.windows.first(where: { $0.identifier?.rawValue == "settings" }) { - window.styleMask.insert(.closable) - window.styleMask.remove(.miniaturizable) - window.styleMask.remove(.resizable) - window.setFrame(NSRect(x: window.frame.origin.x, y: window.frame.origin.y, width: 400, height: 180), display: true) - } - } - } -} - -class SettingsModel: ObservableObject { - @Published var apiKey = "" -} diff --git a/WakaTime/SettingsWindowController.swift b/WakaTime/SettingsWindowController.swift new file mode 100644 index 0000000..52b4840 --- /dev/null +++ b/WakaTime/SettingsWindowController.swift @@ -0,0 +1,67 @@ +import Foundation +import AppKit + +class SettingsWindowController: NSWindowController, NSTextFieldDelegate { + var apiKey: String = "" + var textField: NSTextField? + + convenience init() { + self.init(window: nil) + + let window = NSWindow( + contentRect: NSRect(x: 0, y: 0, width: 400, height: 150), + styleMask: [.titled, .closable], + backing: .buffered, + defer: false + ) + window.center() + window.title = "Settings" + self.window = window + + let contentView = NSView() + window.contentView = contentView + + let apiKeyLabel = NSTextField(labelWithString: "WakaTime API Key:") + apiKeyLabel.frame = NSRect(x: 20, y: 110, width: 200, height: 20) + contentView.addSubview(apiKeyLabel) + + textField = NSTextField(frame: NSRect(x: 20, y: 80, width: 360, height: 20)) + if let textField { + textField.stringValue = ConfigFile.getSetting(section: "settings", key: "api_key") ?? "" + textField.delegate = self + contentView.addSubview(textField) + } + + let saveButton = NSButton(title: "Save", target: self, action: #selector(saveButtonClicked)) + saveButton.frame = NSRect(x: 10, y: 40, width: 80, height: 40) + saveButton.keyEquivalent = "\r" + window.defaultButtonCell = saveButton.cell as? NSButtonCell + contentView.addSubview(saveButton) + + let cancelButton = NSButton(title: "Cancel", target: self, action: #selector(cancelButtonClicked)) + cancelButton.frame = NSRect(x: 80, y: 40, width: 80, height: 40) + cancelButton.keyEquivalent = "\u{1b}" + contentView.addSubview(cancelButton) + + let versionString = "Version: \(Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "")" + + "(\(Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String ?? ""))" + let versionLabel = NSTextField(labelWithString: versionString) + versionLabel.frame = NSRect(x: 20, y: 20, width: 360, height: 20) + contentView.addSubview(versionLabel) + } + + @objc func saveButtonClicked() { + if let text = textField?.stringValue { + ConfigFile.setSetting(section: "settings", key: "api_key", val: text) + } + self.window?.close() + } + + @objc func cancelButtonClicked() { + self.window?.close() + } + + func controlTextDidChange(_ obj: Notification) { + apiKey = textField?.stringValue ?? "" + } +} diff --git a/WakaTime/WakaTime.swift b/WakaTime/WakaTime.swift index 7e28774..9785e18 100644 --- a/WakaTime/WakaTime.swift +++ b/WakaTime/WakaTime.swift @@ -1,15 +1,10 @@ import ServiceManagement import SwiftUI -@main // swiftlint:disable force_unwrapping // swiftlint:disable force_try -struct WakaTime: App { - @Environment(\.openWindow) private var openWindow - - @StateObject private var settings = SettingsModel() +class WakaTime { var state = State() - let watcher = Watcher() enum Constants { @@ -17,9 +12,7 @@ struct WakaTime: App { } init() { -#if !DEBUG registerAsLoginItem() -#endif Task { if !(await Self.isCLILatest()) { Self.downloadCLI() @@ -30,27 +23,6 @@ struct WakaTime: App { checkForApiKey() } - var body: some Scene { - MenuBarExtra("WakaTime", image: "WakaTime") { - Button("Dashboard") { self.dashboard() } - Button("Settings") { - promptForApiKey() - } - Button("Monitored Apps") { - openWindow(id: "monitored_apps_container_view") - NSApp.activate(ignoringOtherApps: true) - } - Divider() - Button("Quit") { self.quit() } - } - WindowGroup("WakaTime Settings", id: "settings") { - SettingsView(apiKey: $settings.apiKey) - }.handlesExternalEvents(matching: ["settings"]) - WindowGroup("Monitored Apps", id: "monitored_apps_container_view") { - MonitoredAppsContainerView() - }.handlesExternalEvents(matching: ["monitored_apps_container_view"]) - } - private func checkForApiKey() { let apiKey = ConfigFile.getSetting(section: "settings", key: "api_key") if apiKey.isEmpty { @@ -58,12 +30,6 @@ struct WakaTime: App { } } - private func promptForApiKey() { - openWindow(id: "settings") - NSApp.activate(ignoringOtherApps: true) - settings.apiKey = ConfigFile.getSetting(section: "settings", key: "api_key") ?? "" - } - private func openSettingsDeeplink() { if let url = URL(string: Constants.settingsDeepLink) { NSWorkspace.shared.open(url) @@ -71,12 +37,11 @@ struct WakaTime: App { } private func registerAsLoginItem() { - guard - SMAppService.mainApp.status == .notFound, - PropertiesManager.shouldLaunchOnLogin - else { return } - - SettingsManager.registerAsLoginItem() + if SMLoginItemSetEnabled("macos-wakatime.WakaTimeHelper" as CFString, true) { + print("Login item added successfully.") + } else { + print("Failed to add login item.") + } } private func requestA11yPermission() { @@ -141,13 +106,20 @@ struct WakaTime: App { } let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile() let output = String(decoding: outputData, as: UTF8.self) - let version = output.firstMatch(of: /([0 - 9] + \.[0 - 9] + \.[0 - 9]+)/) + let version: String? + if let regex = try? NSRegularExpression(pattern: "([0-9]+\\.[0-9]+\\.[0-9]+)"), + let match = regex.firstMatch(in: output, range: NSRange(output.startIndex..., in: output)), + let range = Range(match.range, in: output) { + version = String(output[range]) + } else { + version = nil + } let remoteVersion = try? await getLatestVersion() guard let remoteVersion else { // Could not retrieve remote version return true } - if let version, "v" + version.0 == remoteVersion { + if let version, "v" + version == remoteVersion { // Local version up to date return true } else { @@ -298,6 +270,14 @@ extension Optional where Wrapped: Collection { self?.isEmpty ?? true } } + +extension URL { + func formatted() -> String { + let components = URLComponents(url: self, resolvingAgainstBaseURL: true) + let path = components?.path ?? "" + return path.replacingOccurrences(of: " ", with: "\\ ") + } +} // swiftlint:enable force_unwrapping // swiftlint:enable force_try diff --git a/WakaTime/main.swift b/WakaTime/main.swift new file mode 100644 index 0000000..ae50fab --- /dev/null +++ b/WakaTime/main.swift @@ -0,0 +1,6 @@ +import Cocoa + +let delegate = AppDelegate() +let application = NSApplication.shared +application.delegate = delegate +application.run() diff --git a/project.yml b/project.yml index 6df2a48..7d72fcb 100644 --- a/project.yml +++ b/project.yml @@ -8,7 +8,7 @@ targets: WakaTime: type: application platform: macOS - deploymentTarget: 13.0 + deploymentTarget: 10.15 sources: [WakaTime] settings: CURRENT_PROJECT_VERSION: 2 @@ -22,3 +22,30 @@ targets: postCompileScripts: - script: ./Scripts/Lint/swiftlint lint --quiet name: Swiftlint + dependencies: + - target: WakaTime Helper + postBuildScripts: + - script: | + LOGIN_ITEMS_DIR="$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.app/Contents/Library/LoginItems" + rm -rf "$LOGIN_ITEMS_DIR" + mkdir -p "$LOGIN_ITEMS_DIR" + mv "$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.app/Contents/Resources/WakaTime Helper.app" "$LOGIN_ITEMS_DIR/" + name: Move "WakaTime Helper.app" to LoginItems + WakaTime Helper: + type: application + platform: macOS + deploymentTarget: 10.15 + sources: [WakaTime Helper] + settings: + CURRENT_PROJECT_VERSION: 1 + MARKETING_VERSION: 0.0.1 + INFOPLIST_FILE: WakaTime Helper/WakaTime Helper-Info.plist + GENERATE_INFOPLIST_FILE: YES + CODE_SIGN_STYLE: Automatic + DEVELOPMENT_TEAM: ${SV_DEVELOPMENT_TEAM} + ENABLE_HARDENED_RUNTIME: YES + DEAD_CODE_STRIPPING: YES + SKIP_INSTALL: YES + postCompileScripts: + - script: ./Scripts/Lint/swiftlint lint --quiet + name: Swiftlint From 0c2d9b19572d78894eca3dfc91857107b4556555 Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 16 May 2023 15:20:48 +0200 Subject: [PATCH 02/31] Integrate new changes --- WakaTime/AppDelegate.swift | 11 ++ WakaTime/Helpers/AppInfo.swift | 2 +- WakaTime/Helpers/SettingsManager.swift | 19 ++- WakaTime/MonitoredAppsWindowController.swift | 20 +++ WakaTime/SettingsWindowController.swift | 51 +------- WakaTime/Views/MonitoredAppsView.swift | 23 +--- WakaTime/Views/SettingsView.swift | 127 +++++++++++++++++++ WakaTime/WakaTime.swift | 14 +- 8 files changed, 177 insertions(+), 90 deletions(-) create mode 100644 WakaTime/MonitoredAppsWindowController.swift create mode 100644 WakaTime/Views/SettingsView.swift diff --git a/WakaTime/AppDelegate.swift b/WakaTime/AppDelegate.swift index 8967dcd..cc00b70 100644 --- a/WakaTime/AppDelegate.swift +++ b/WakaTime/AppDelegate.swift @@ -4,6 +4,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { var window: NSWindow! var statusBarItem: NSStatusItem! var settingsWindowController = SettingsWindowController() + var monitoredAppsWindowController = MonitoredAppsWindowController() var wakaTime: WakaTime? func applicationDidFinishLaunching(_ aNotification: Notification) { @@ -25,6 +26,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { menu.addItem(withTitle: "Dashboard", action: #selector(AppDelegate.dashboardClicked(_:)), keyEquivalent: "") menu.addItem(withTitle: "Settings", action: #selector(AppDelegate.settingsClicked(_:)), keyEquivalent: "") + menu.addItem(withTitle: "Monitored Apps", action: #selector(AppDelegate.monitoredAppsClicked(_:)), keyEquivalent: "") menu.addItem(NSMenuItem.separator()) menu.addItem(withTitle: "Quit", action: #selector(AppDelegate.quitClicked(_:)), keyEquivalent: "") @@ -53,6 +55,10 @@ class AppDelegate: NSObject, NSApplicationDelegate { showSettings() } + @objc func monitoredAppsClicked(_ sender: AnyObject) { + showMonitoredApps() + } + @objc func quitClicked(_ sender: AnyObject) { NSApplication.shared.terminate(self) } @@ -61,4 +67,9 @@ class AppDelegate: NSObject, NSApplicationDelegate { NSApp.activate(ignoringOtherApps: true) settingsWindowController.showWindow(self) } + + private func showMonitoredApps() { + NSApp.activate(ignoringOtherApps: true) + monitoredAppsWindowController.showWindow(self) + } } diff --git a/WakaTime/Helpers/AppInfo.swift b/WakaTime/Helpers/AppInfo.swift index 05696a1..d6b72e8 100644 --- a/WakaTime/Helpers/AppInfo.swift +++ b/WakaTime/Helpers/AppInfo.swift @@ -25,6 +25,6 @@ class AppInfo { static func getIcon(bundleId: String) -> NSImage? { guard let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: bundleId) else { return nil } - return getIcon(file: url.path()) + return getIcon(file: url.absoluteURL.path) } } diff --git a/WakaTime/Helpers/SettingsManager.swift b/WakaTime/Helpers/SettingsManager.swift index e435afd..54ecbce 100644 --- a/WakaTime/Helpers/SettingsManager.swift +++ b/WakaTime/Helpers/SettingsManager.swift @@ -5,23 +5,20 @@ class SettingsManager { static func registerAsLoginItem() { PropertiesManager.shouldLaunchOnLogin = true - do { - try SMAppService.mainApp.register() - print("Registered for login") - } catch let error { - print(error) + if SMLoginItemSetEnabled("macos-wakatime.WakaTimeHelper" as CFString, true) { + print("Login item enabled successfully.") + } else { + print("Failed to enable login item.") } } static func unregisterAsLoginItem() { PropertiesManager.shouldLaunchOnLogin = false - do { - try SMAppService.mainApp.unregister() - print("Unregistered for login") - } catch let error { - print(error) + if SMLoginItemSetEnabled("macos-wakatime.WakaTimeHelper" as CFString, false) { + print("Login item disabled successfully.") + } else { + print("Failed to disable login item.") } } - } diff --git a/WakaTime/MonitoredAppsWindowController.swift b/WakaTime/MonitoredAppsWindowController.swift new file mode 100644 index 0000000..3bd0b00 --- /dev/null +++ b/WakaTime/MonitoredAppsWindowController.swift @@ -0,0 +1,20 @@ +import AppKit + +class MonitoredAppsWindowController: NSWindowController { + let monitoredAppsView = MonitoredAppsView() + + convenience init() { + self.init(window: nil) + + let window = NSWindow( + contentRect: NSRect(x: 0, y: 0, width: 400, height: 150), + styleMask: [.titled, .closable, .resizable], + backing: .buffered, + defer: false + ) + window.center() + window.title = "Monitored Apps" + window.contentView = monitoredAppsView + self.window = window + } +} diff --git a/WakaTime/SettingsWindowController.swift b/WakaTime/SettingsWindowController.swift index 52b4840..27320eb 100644 --- a/WakaTime/SettingsWindowController.swift +++ b/WakaTime/SettingsWindowController.swift @@ -1,9 +1,7 @@ -import Foundation import AppKit class SettingsWindowController: NSWindowController, NSTextFieldDelegate { - var apiKey: String = "" - var textField: NSTextField? + let settingsView = SettingsView() convenience init() { self.init(window: nil) @@ -16,52 +14,7 @@ class SettingsWindowController: NSWindowController, NSTextFieldDelegate { ) window.center() window.title = "Settings" + window.contentView = settingsView self.window = window - - let contentView = NSView() - window.contentView = contentView - - let apiKeyLabel = NSTextField(labelWithString: "WakaTime API Key:") - apiKeyLabel.frame = NSRect(x: 20, y: 110, width: 200, height: 20) - contentView.addSubview(apiKeyLabel) - - textField = NSTextField(frame: NSRect(x: 20, y: 80, width: 360, height: 20)) - if let textField { - textField.stringValue = ConfigFile.getSetting(section: "settings", key: "api_key") ?? "" - textField.delegate = self - contentView.addSubview(textField) - } - - let saveButton = NSButton(title: "Save", target: self, action: #selector(saveButtonClicked)) - saveButton.frame = NSRect(x: 10, y: 40, width: 80, height: 40) - saveButton.keyEquivalent = "\r" - window.defaultButtonCell = saveButton.cell as? NSButtonCell - contentView.addSubview(saveButton) - - let cancelButton = NSButton(title: "Cancel", target: self, action: #selector(cancelButtonClicked)) - cancelButton.frame = NSRect(x: 80, y: 40, width: 80, height: 40) - cancelButton.keyEquivalent = "\u{1b}" - contentView.addSubview(cancelButton) - - let versionString = "Version: \(Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "")" - + "(\(Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String ?? ""))" - let versionLabel = NSTextField(labelWithString: versionString) - versionLabel.frame = NSRect(x: 20, y: 20, width: 360, height: 20) - contentView.addSubview(versionLabel) - } - - @objc func saveButtonClicked() { - if let text = textField?.stringValue { - ConfigFile.setSetting(section: "settings", key: "api_key", val: text) - } - self.window?.close() - } - - @objc func cancelButtonClicked() { - self.window?.close() - } - - func controlTextDidChange(_ obj: Notification) { - apiKey = textField?.stringValue ?? "" } } diff --git a/WakaTime/Views/MonitoredAppsView.swift b/WakaTime/Views/MonitoredAppsView.swift index 9234c82..90fbc53 100644 --- a/WakaTime/Views/MonitoredAppsView.swift +++ b/WakaTime/Views/MonitoredAppsView.swift @@ -1,9 +1,9 @@ -import Foundation import AppKit -import SwiftUI class MonitoredAppsView: NSView { - func viewDidLoad() { + init() { + super.init(frame: .zero) + let stackView = NSStackView(frame: .zero) stackView.orientation = .vertical stackView.distribution = .equalSpacing @@ -20,6 +20,10 @@ class MonitoredAppsView: NSView { buildView(stackView: stackView) } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + func buildView(stackView: NSStackView) { for (index, bundleId) in MonitoringManager.appIDsToWatch.enumerated() { guard @@ -76,16 +80,3 @@ class MonitoredAppsView: NSView { MonitoringManager.set(monitoringState: sender.state == .on ? .on : .off, for: bundleId) } } - -struct MonitoredAppsViewRepresentable: NSViewRepresentable { - func makeNSView(context: Context) -> NSView { - let view = MonitoredAppsView() - // Configure your NSView here - view.viewDidLoad() - return view - } - - func updateNSView(_ nsView: NSView, context: Context) { - // Update your NSView here - } -} diff --git a/WakaTime/Views/SettingsView.swift b/WakaTime/Views/SettingsView.swift new file mode 100644 index 0000000..55f21eb --- /dev/null +++ b/WakaTime/Views/SettingsView.swift @@ -0,0 +1,127 @@ +import AppKit + +class SettingsView: NSView, NSTextFieldDelegate { + // MARK: State + + var apiKey: String = "" + + // MARK: Controls + + lazy var launchAtLoginCheckbox: NSButton = { + let checkbox = NSButton(checkboxWithTitle: "Launch at login", target: self, action: #selector(launchAtLoginCheckboxClicked)) + checkbox.state = PropertiesManager.shouldLaunchOnLogin ? .on : .off + checkbox.translatesAutoresizingMaskIntoConstraints = false + return checkbox + }() + + lazy var apiKeyLabel: NSTextField = { + let apiKeyLabel = NSTextField(labelWithString: "WakaTime API Key:") + apiKeyLabel.translatesAutoresizingMaskIntoConstraints = false + return apiKeyLabel + }() + + lazy var textField: NSTextField = { + let textField = NSTextField(frame: .zero) + textField.stringValue = ConfigFile.getSetting(section: "settings", key: "api_key") ?? "" + textField.delegate = self + textField.translatesAutoresizingMaskIntoConstraints = false + return textField + }() + + lazy var saveButton: NSButton = { + let saveButton = NSButton(title: "Save", target: self, action: #selector(saveButtonClicked)) + saveButton.translatesAutoresizingMaskIntoConstraints = false + saveButton.keyEquivalent = "\r" + return saveButton + }() + + lazy var cancelButton: NSButton = { + let cancelButton = NSButton(title: "Cancel", target: self, action: #selector(cancelButtonClicked)) + cancelButton.translatesAutoresizingMaskIntoConstraints = false + cancelButton.keyEquivalent = "\u{1b}" + return cancelButton + }() + + lazy var stackView: NSStackView = { + let stackView = NSStackView(views: [saveButton, cancelButton]) + stackView.translatesAutoresizingMaskIntoConstraints = false + stackView.orientation = .horizontal + stackView.spacing = 10 + return stackView + }() + + lazy var versionLabel: NSTextField = { + let versionString = "Version: \(Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "")" + + "(\(Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String ?? ""))" + let versionLabel = NSTextField(labelWithString: versionString) + versionLabel.translatesAutoresizingMaskIntoConstraints = false + return versionLabel + }() + + init() { + super.init(frame: .zero) + + addSubview(launchAtLoginCheckbox) + addSubview(apiKeyLabel) + addSubview(textField) + addSubview(stackView) + addSubview(versionLabel) + + setupConstraints() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidMoveToWindow() { + window?.defaultButtonCell = saveButton.cell as? NSButtonCell + } + + @objc func launchAtLoginCheckboxClicked() { + PropertiesManager.shouldLaunchOnLogin = launchAtLoginCheckbox.state == .on + if launchAtLoginCheckbox.state == .on { + SettingsManager.registerAsLoginItem() + } else { + SettingsManager.unregisterAsLoginItem() + } + } + + @objc func saveButtonClicked() { + ConfigFile.setSetting(section: "settings", key: "api_key", val: textField.stringValue) + self.window?.close() + } + + @objc func cancelButtonClicked() { + self.window?.close() + } + + func controlTextDidChange(_ obj: Notification) { + apiKey = textField.stringValue + } + + private func setupConstraints() { + let constraints = [ + launchAtLoginCheckbox.topAnchor.constraint(equalTo: topAnchor, constant: 20), + launchAtLoginCheckbox.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20), + + apiKeyLabel.topAnchor.constraint(equalTo: launchAtLoginCheckbox.bottomAnchor, constant: 20), + apiKeyLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20), + + textField.topAnchor.constraint(equalTo: apiKeyLabel.bottomAnchor, constant: 10), + textField.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20), + textField.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20), + + stackView.topAnchor.constraint(equalTo: textField.bottomAnchor, constant: 4), + stackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20), + stackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20), + stackView.heightAnchor.constraint(equalToConstant: 40), + + versionLabel.topAnchor.constraint(equalTo: stackView.bottomAnchor, constant: 10), + versionLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20), + versionLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20), + versionLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -20) + ] + NSLayoutConstraint.activate(constraints) + } +} diff --git a/WakaTime/WakaTime.swift b/WakaTime/WakaTime.swift index 9785e18..1a30c8e 100644 --- a/WakaTime/WakaTime.swift +++ b/WakaTime/WakaTime.swift @@ -37,11 +37,7 @@ class WakaTime { } private func registerAsLoginItem() { - if SMLoginItemSetEnabled("macos-wakatime.WakaTimeHelper" as CFString, true) { - print("Login item added successfully.") - } else { - print("Failed to add login item.") - } + SettingsManager.registerAsLoginItem() } private func requestA11yPermission() { @@ -285,11 +281,3 @@ class State: ObservableObject { @Published var lastFile = "" @Published var lastTime = 0 } - -struct MonitoredAppsContainerView: View { - var body: some View { - VStack { - MonitoredAppsViewRepresentable() - } - } -} From 5a2d652be6c059377e674799e71617994032570b Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Wed, 7 Jun 2023 11:30:47 +0200 Subject: [PATCH 03/31] Enable use of shortcuts in API key text fields without menu --- WakaTime/Controls/WKTextField.swift | 35 +++++++++++++++++++++++++++++ WakaTime/Views/SettingsView.swift | 4 ++-- 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 WakaTime/Controls/WKTextField.swift diff --git a/WakaTime/Controls/WKTextField.swift b/WakaTime/Controls/WKTextField.swift new file mode 100644 index 0000000..ca74dd4 --- /dev/null +++ b/WakaTime/Controls/WKTextField.swift @@ -0,0 +1,35 @@ +// +// WKTextField.swift +// WakaTime +// +// Created by Tobias Lensing on 07.06.23. +// + +import AppKit + +class WKTextField: NSTextField { + override func performKeyEquivalent(with event: NSEvent) -> Bool { + if event.type == NSEvent.EventType.keyDown { + let modifierFlags = event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue + if modifierFlags == NSEvent.ModifierFlags.command.rawValue { + switch event.charactersIgnoringModifiers?.first { + case "x": + if NSApp.sendAction(#selector(NSText.cut(_:)), to: nil, from: self) { return true } + case "c": + if NSApp.sendAction(#selector(NSText.copy(_:)), to: nil, from: self) { return true } + case "v": + if NSApp.sendAction(#selector(NSText.paste(_:)), to: nil, from: self) { return true } + case "a": + if NSApp.sendAction(#selector(NSText.selectAll(_:)), to: nil, from: self) { return true } + case "z": + if NSApp.sendAction(Selector(("undo:")), to: nil, from: self) { return true } + default: + break + } + } else if modifierFlags == NSEvent.ModifierFlags.command.rawValue | NSEvent.ModifierFlags.shift.rawValue { + if NSApp.sendAction(Selector(("redo:")), to: nil, from: self) { return true } + } + } + return super.performKeyEquivalent(with: event) + } +} diff --git a/WakaTime/Views/SettingsView.swift b/WakaTime/Views/SettingsView.swift index 55f21eb..2444bc6 100644 --- a/WakaTime/Views/SettingsView.swift +++ b/WakaTime/Views/SettingsView.swift @@ -20,8 +20,8 @@ class SettingsView: NSView, NSTextFieldDelegate { return apiKeyLabel }() - lazy var textField: NSTextField = { - let textField = NSTextField(frame: .zero) + lazy var textField: WKTextField = { + let textField = WKTextField(frame: .zero) textField.stringValue = ConfigFile.getSetting(section: "settings", key: "api_key") ?? "" textField.delegate = self textField.translatesAutoresizingMaskIntoConstraints = false From 18f5dea73792f3f38f39bca70f3238e11b57872d Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Wed, 7 Jun 2023 11:32:47 +0200 Subject: [PATCH 04/31] Move window controllers to WindowControllers directory --- .../{ => WindowControllers}/MonitoredAppsWindowController.swift | 0 WakaTime/{ => WindowControllers}/SettingsWindowController.swift | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename WakaTime/{ => WindowControllers}/MonitoredAppsWindowController.swift (100%) rename WakaTime/{ => WindowControllers}/SettingsWindowController.swift (100%) diff --git a/WakaTime/MonitoredAppsWindowController.swift b/WakaTime/WindowControllers/MonitoredAppsWindowController.swift similarity index 100% rename from WakaTime/MonitoredAppsWindowController.swift rename to WakaTime/WindowControllers/MonitoredAppsWindowController.swift diff --git a/WakaTime/SettingsWindowController.swift b/WakaTime/WindowControllers/SettingsWindowController.swift similarity index 100% rename from WakaTime/SettingsWindowController.swift rename to WakaTime/WindowControllers/SettingsWindowController.swift From 57b7544bd549b842e5935542971a4faea5f2db0b Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Wed, 7 Jun 2023 11:35:38 +0200 Subject: [PATCH 05/31] Refactor SwiftUI state (no longer needed with AppKit) --- WakaTime/WakaTime.swift | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/WakaTime/WakaTime.swift b/WakaTime/WakaTime.swift index 1a30c8e..ca49c61 100644 --- a/WakaTime/WakaTime.swift +++ b/WakaTime/WakaTime.swift @@ -4,8 +4,9 @@ import SwiftUI // swiftlint:disable force_unwrapping // swiftlint:disable force_try class WakaTime { - var state = State() let watcher = Watcher() + var lastFile = "" + var lastTime = 0 enum Constants { static let settingsDeepLink: String = "wakatime://settings" @@ -216,8 +217,8 @@ class WakaTime { private func shouldSendHeartbeat(file: URL, time: Int, isWrite: Bool) -> Bool { guard !isWrite, - file.formatted() == state.lastFile, - state.lastTime + 120 > time + file.formatted() == lastFile, + lastTime + 120 > time else { return true } return false @@ -227,8 +228,8 @@ class WakaTime { let time = Int(NSDate().timeIntervalSince1970) guard shouldSendHeartbeat(file: file, time: time, isWrite: isWrite) else { return } - state.lastFile = file.formatted() - state.lastTime = time + lastFile = file.formatted() + lastTime = time guard let id = app.bundleIdentifier, @@ -276,8 +277,3 @@ extension URL { } // swiftlint:enable force_unwrapping // swiftlint:enable force_try - -class State: ObservableObject { - @Published var lastFile = "" - @Published var lastTime = 0 -} From cef3b242110fa89f0b65b7f38cff05cc3108d483 Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Wed, 7 Jun 2023 12:06:36 +0200 Subject: [PATCH 06/31] Use SMAppService on macOS 13 or newer and SMLoginItemSetEnabled() on macOS versions prior to 13 --- WakaTime/Helpers/SettingsManager.swift | 46 ++++++++++++++++++++++---- WakaTime/WakaTime.swift | 4 +++ 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/WakaTime/Helpers/SettingsManager.swift b/WakaTime/Helpers/SettingsManager.swift index 54ecbce..b66c2e4 100644 --- a/WakaTime/Helpers/SettingsManager.swift +++ b/WakaTime/Helpers/SettingsManager.swift @@ -2,23 +2,57 @@ import Foundation import ServiceManagement class SettingsManager { +#if !SIMULATE_OLD_MACOS + static let simulateOldMacOS = false +#else + static let simulateOldMacOS = true +#endif + + static func loginItemRegistered() -> Bool { + if #available(macOS 13.0, *) { + return SMAppService.mainApp.status != .notFound + } else { + return false + } + } + static func registerAsLoginItem() { PropertiesManager.shouldLaunchOnLogin = true - if SMLoginItemSetEnabled("macos-wakatime.WakaTimeHelper" as CFString, true) { - print("Login item enabled successfully.") + // Use SMAppService on macOS 13 or newer to add WakaTime to the "Open at Login" list and SMLoginItemSetEnabled + // for older versions of macOS to add WakaTime to the "Allow in Background" list + if #available(macOS 13.0, *), !simulateOldMacOS { + do { + try SMAppService.mainApp.register() + print("Registered for login") + } catch let error { + print(error) + } } else { - print("Failed to enable login item.") + if SMLoginItemSetEnabled("macos-wakatime.WakaTimeHelper" as CFString, true) { + print("Login item enabled successfully.") + } else { + print("Failed to enable login item.") + } } } static func unregisterAsLoginItem() { PropertiesManager.shouldLaunchOnLogin = false - if SMLoginItemSetEnabled("macos-wakatime.WakaTimeHelper" as CFString, false) { - print("Login item disabled successfully.") + if #available(macOS 13.0, *), !simulateOldMacOS { + do { + try SMAppService.mainApp.unregister() + print("Unregistered for login") + } catch let error { + print(error) + } } else { - print("Failed to disable login item.") + if SMLoginItemSetEnabled("macos-wakatime.WakaTimeHelper" as CFString, false) { + print("Login item disabled successfully.") + } else { + print("Failed to disable login item.") + } } } } diff --git a/WakaTime/WakaTime.swift b/WakaTime/WakaTime.swift index ca49c61..35eec25 100644 --- a/WakaTime/WakaTime.swift +++ b/WakaTime/WakaTime.swift @@ -38,6 +38,10 @@ class WakaTime { } private func registerAsLoginItem() { + guard + !SettingsManager.loginItemRegistered(), + PropertiesManager.shouldLaunchOnLogin + else { return } SettingsManager.registerAsLoginItem() } From 5fa73ea44ef387f919dfd7d9a637834abc9df642 Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 08:56:50 +0200 Subject: [PATCH 07/31] Add on_push.yml for testing --- .github/workflows/on_push.yml | 148 +--------------------------------- 1 file changed, 1 insertion(+), 147 deletions(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index 6bb3f0d..9f025dc 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -3,77 +3,10 @@ name: Release on: pull_request: types: [opened, reopened, ready_for_review, synchronize] - push: - branches: [main, release] - tags-ignore: "**" jobs: - test: - name: Tests and Build - runs-on: macos-latest - steps: - - - name: Checkout - uses: actions/checkout@v3 - - - name: Install xcodegen via Homebrew for linting and building xcode project - run: brew install xcodegen - - - name: Generate project - run: xcodegen - - - name: Build app to run linters - run: xcodebuild - - version: - name: Version - concurrency: tagging - if: ${{ github.ref == 'refs/heads/release' || github.ref == 'refs/heads/main' }} - runs-on: ubuntu-latest - needs: [test] - outputs: - semver: ${{ steps.format.outputs.semver }} - semver_tag: ${{ steps.semver-tag.outputs.semver_tag }} - ancestor_tag: ${{ steps.semver-tag.outputs.ancestor_tag }} - is_prerelease: ${{ steps.semver-tag.outputs.is_prerelease }} - steps: - - - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Calculate semver tag - id: semver-tag - uses: wakatime/semver-action@master - with: - prerelease_id: alpha - develop_branch_name: main - main_branch_name: release - - - name: Format - id: format - run: | - echo "${{ steps.semver-tag.outputs.semver_tag }}" - ver=`echo "${{ steps.semver-tag.outputs.semver_tag }}" | sed 's/^v//'` - echo "$ver" - echo "semver=$ver" >> $GITHUB_OUTPUT - - - name: Create tag - uses: actions/github-script@v6 - with: - github-token: ${{ github.token }} - script: | - github.rest.git.createRef({ - owner: context.repo.owner, - repo: context.repo.repo, - ref: "refs/tags/${{ steps.semver-tag.outputs.semver_tag }}", - sha: context.sha - }) - sign: name: Sign Apple app - needs: [version] runs-on: macos-latest steps: - @@ -85,7 +18,7 @@ jobs: with: valueFile: 'project.yml' propertyPath: 'targets.WakaTime.settings.MARKETING_VERSION' - value: ${{ needs.version.outputs.semver }} + value: '1.2.3' commitChange: false - name: Install xcodegen via Homebrew for linting and building xcode project @@ -131,82 +64,3 @@ jobs: with: name: app path: ./WakaTime.zip - - - name: Remove tag if failure - if: ${{ failure() }} - uses: actions/github-script@v6 - with: - github-token: ${{ github.token }} - script: | - github.rest.git.deleteRef({ - owner: context.repo.owner, - repo: context.repo.repo, - ref: "tags/${{ needs.version.outputs.semver_tag }}" - }) - - release: - name: Release - runs-on: ubuntu-latest - needs: [version, sign] - steps: - - - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - # Run only for main branch - if: ${{ github.ref == 'refs/heads/main' }} - name: Changelog for main - uses: gandarez/changelog-action@v1.2.0 - id: changelog-main - with: - current_tag: ${{ github.sha }} - previous_tag: ${{ needs.version.outputs.ancestor_tag }} - exclude: | - ^Merge pull request .* - - - # Run only for release branch - if: ${{ github.ref == 'refs/heads/release' }} - name: Get related pull request - uses: 8BitJonny/gh-get-current-pr@2.2.0 - id: changelog-release - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - - - name: Prepare changelog - id: changelog - run: | - echo "${{ steps.changelog-main.outputs.changelog || steps.changelog-release.outputs.pr_body }}" > changelog.txt - ./bin/prepare_changelog.sh $(echo ${GITHUB_REF#refs/heads/}) "$(cat changelog.txt)" - - - name: Download artifacts - uses: actions/download-artifact@v3 - with: - name: app - path: ./ - - - name: "Create release" - uses: softprops/action-gh-release@master - with: - name: ${{ needs.version.outputs.semver_tag }} - tag_name: ${{ needs.version.outputs.semver_tag }} - body: "## Changelog\n${{ steps.changelog.outputs.changelog }}" - prerelease: ${{ needs.version.outputs.is_prerelease }} - target_commitish: ${{ github.sha }} - draft: false - files: ./WakaTime.zip - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Remove tag if failure - if: ${{ failure() }} - uses: actions/github-script@v6 - with: - github-token: ${{ github.token }} - script: | - github.rest.git.deleteRef({ - owner: context.repo.owner, - repo: context.repo.repo, - ref: "tags/${{ needs.version.outputs.semver_tag }}" - }) From 8de3789d35d3304c154ef6c82fd2f35dc67ae7c2 Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 09:32:42 +0200 Subject: [PATCH 08/31] Notarize WakaTime Helper before notarizing main bundle --- .github/workflows/on_push.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index 9f025dc..1b4d9fb 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -50,7 +50,13 @@ jobs: NOTARIZATION_PWD: ${{ secrets.AC_PASSWORD }} run: xcrun notarytool store-credentials "notarytool-profile" --apple-id "$NOTARIZATION_APPLE_ID" --team-id "$NOTARIZATION_TEAM_ID" --password "$NOTARIZATION_PWD" - - name: Notarize + name: Notarize WakaTime Helper.app + run: | + ditto -c -k --keepParent "build/Release/WakaTime.app/Contents/Library/LoginItems/WakaTime Helper.app" helper.zip + xcrun notarytool submit helper.zip --keychain-profile "notarytool-profile" --wait + xcrun stapler staple "build/Release/WakaTime.app/Contents/Library/LoginItems/WakaTime Helper.app" + - + name: Notarize WakaTime.app run: | ditto -c -k --keepParent build/Release/WakaTime.app main.zip xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait From dcadfaa72680f6285c14779fc21f338252d8e5b4 Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 10:13:30 +0200 Subject: [PATCH 09/31] Add code signing step for WakaTime Helper.app --- .github/workflows/on_push.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index 1b4d9fb..c7f7f4f 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -38,7 +38,12 @@ jobs: # The password used to import the PKCS12 file. p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }} - - name: Codesign + name: Codesign WakaTime Helper.app + run: | + /usr/bin/codesign --force -s "WakaTime" --options runtime "build/Release/WakaTime.app/Contents/Library/LoginItems/WakaTime Helper.app" -v + /usr/bin/codesign --verify --deep --strict --verbose=2 "build/Release/WakaTime.app/Contents/Library/LoginItems/WakaTime Helper.app" + - + name: Codesign WakaTime.app run: | /usr/bin/codesign --force -s "WakaTime" --options runtime build/Release/WakaTime.app -v /usr/bin/codesign --verify --deep --strict --verbose=2 build/Release/WakaTime.app From f794bb2ef786ab3f8278ce2cf60bed74a3256b0f Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 10:24:49 +0200 Subject: [PATCH 10/31] Separate the staple and notarization step for debugging purposes --- .github/workflows/on_push.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index c7f7f4f..a0b1dd0 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -65,6 +65,9 @@ jobs: run: | ditto -c -k --keepParent build/Release/WakaTime.app main.zip xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait + - + name: Staple WakaTime.app + run: | xcrun stapler staple build/Release/WakaTime.app - name: Zip From 3bd7d8a6d1d732fd768ef968ee324d6d35a43819 Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 10:36:32 +0200 Subject: [PATCH 11/31] Add log output --- .github/workflows/on_push.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index a0b1dd0..1655261 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -64,7 +64,8 @@ jobs: name: Notarize WakaTime.app run: | ditto -c -k --keepParent build/Release/WakaTime.app main.zip - xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait + UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') + xcrun notarytool log $UUID --keychain-profile "notarytool-profile" - name: Staple WakaTime.app run: | From 333c070022095092faf7e8c3bc8d25d30909845f Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 10:53:09 +0200 Subject: [PATCH 12/31] Fix log wip --- .github/workflows/on_push.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index 1655261..36dde18 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -65,7 +65,8 @@ jobs: run: | ditto -c -k --keepParent build/Release/WakaTime.app main.zip UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') - xcrun notarytool log $UUID --keychain-profile "notarytool-profile" + xcrun notarytool log $UUID main_notarize.log --keychain-profile "notarytool-profile" + cat main_notarize.log - name: Staple WakaTime.app run: | From 943ea853cdade5d28f80a1b5813dc2a2808daacc Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 10:59:42 +0200 Subject: [PATCH 13/31] Fix log wip --- .github/workflows/on_push.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index 36dde18..c1755a4 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -65,8 +65,7 @@ jobs: run: | ditto -c -k --keepParent build/Release/WakaTime.app main.zip UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') - xcrun notarytool log $UUID main_notarize.log --keychain-profile "notarytool-profile" - cat main_notarize.log + xcrun notarytool log --keychain-profile "notarytool-profile" $UUID - name: Staple WakaTime.app run: | From 67c99a8ede2803130383d3b33e6740b3e1ec4939 Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 13:47:57 +0200 Subject: [PATCH 14/31] Notarize libswift_Concurrency.dylib --- .github/workflows/on_push.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index c1755a4..897cd2a 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -60,6 +60,12 @@ jobs: ditto -c -k --keepParent "build/Release/WakaTime.app/Contents/Library/LoginItems/WakaTime Helper.app" helper.zip xcrun notarytool submit helper.zip --keychain-profile "notarytool-profile" --wait xcrun stapler staple "build/Release/WakaTime.app/Contents/Library/LoginItems/WakaTime Helper.app" + - + name: Notarize libswift_Concurrency.dylib + run: | + ditto -c -k --keepParent "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" concurrency.zip + xcrun notarytool submit concurrency.zip --keychain-profile "notarytool-profile" --wait + xcrun stapler staple "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" - name: Notarize WakaTime.app run: | From f90db2e64ba13e7336c65cd711069e8708c1e3b3 Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 13:55:35 +0200 Subject: [PATCH 15/31] Codesign libswift_Concurrency.dylib --- .github/workflows/on_push.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index 897cd2a..62b946d 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -42,6 +42,11 @@ jobs: run: | /usr/bin/codesign --force -s "WakaTime" --options runtime "build/Release/WakaTime.app/Contents/Library/LoginItems/WakaTime Helper.app" -v /usr/bin/codesign --verify --deep --strict --verbose=2 "build/Release/WakaTime.app/Contents/Library/LoginItems/WakaTime Helper.app" + - + name: Codesign libswift_Concurrency.dylib + run: | + /usr/bin/codesign --force -s "WakaTime" --options runtime "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" -v + /usr/bin/codesign --verify --deep --strict --verbose=2 "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" - name: Codesign WakaTime.app run: | From 59218beebc60d75c28baf9d8c2c0274a3e3fb2fe Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 14:08:54 +0200 Subject: [PATCH 16/31] Remove libswift_Concurrency.dylib codesigning --- .github/workflows/on_push.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index 62b946d..7e2b410 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -42,11 +42,11 @@ jobs: run: | /usr/bin/codesign --force -s "WakaTime" --options runtime "build/Release/WakaTime.app/Contents/Library/LoginItems/WakaTime Helper.app" -v /usr/bin/codesign --verify --deep --strict --verbose=2 "build/Release/WakaTime.app/Contents/Library/LoginItems/WakaTime Helper.app" - - - name: Codesign libswift_Concurrency.dylib - run: | - /usr/bin/codesign --force -s "WakaTime" --options runtime "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" -v - /usr/bin/codesign --verify --deep --strict --verbose=2 "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" + #- + # name: Codesign libswift_Concurrency.dylib + # run: | + # /usr/bin/codesign --force -s "WakaTime" --options runtime "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" -v + # /usr/bin/codesign --verify --deep --strict --verbose=2 "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" - name: Codesign WakaTime.app run: | @@ -65,12 +65,12 @@ jobs: ditto -c -k --keepParent "build/Release/WakaTime.app/Contents/Library/LoginItems/WakaTime Helper.app" helper.zip xcrun notarytool submit helper.zip --keychain-profile "notarytool-profile" --wait xcrun stapler staple "build/Release/WakaTime.app/Contents/Library/LoginItems/WakaTime Helper.app" - - - name: Notarize libswift_Concurrency.dylib - run: | - ditto -c -k --keepParent "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" concurrency.zip - xcrun notarytool submit concurrency.zip --keychain-profile "notarytool-profile" --wait - xcrun stapler staple "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" + #- + # name: Notarize libswift_Concurrency.dylib + # run: | + # ditto -c -k --keepParent "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" concurrency.zip + # xcrun notarytool submit concurrency.zip --keychain-profile "notarytool-profile" --wait + # xcrun stapler staple "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" - name: Notarize WakaTime.app run: | From 87566bc51c7bbbdb725b981a74d57a6851427d42 Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 14:19:52 +0200 Subject: [PATCH 17/31] Try to fix unexpected argument --- .github/workflows/on_push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index 7e2b410..f530c64 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -76,7 +76,7 @@ jobs: run: | ditto -c -k --keepParent build/Release/WakaTime.app main.zip UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') - xcrun notarytool log --keychain-profile "notarytool-profile" $UUID + xcrun notarytool log --keychain-profile "notarytool-profile" "$UUID" - name: Staple WakaTime.app run: | From d9c093496cd76ddba0173e55440563429b2042fb Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 14:28:20 +0200 Subject: [PATCH 18/31] wip --- .github/workflows/on_push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index f530c64..52f24b4 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -76,7 +76,7 @@ jobs: run: | ditto -c -k --keepParent build/Release/WakaTime.app main.zip UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') - xcrun notarytool log --keychain-profile "notarytool-profile" "$UUID" + xcrun notarytool log $UUID --keychain-profile "notarytool-profile" - name: Staple WakaTime.app run: | From c84b5b3deccbe120adb9efeb319bad9fcfb54afa Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 14:33:36 +0200 Subject: [PATCH 19/31] wip --- .github/workflows/on_push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index 52f24b4..3b6c9d1 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -76,7 +76,7 @@ jobs: run: | ditto -c -k --keepParent build/Release/WakaTime.app main.zip UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') - xcrun notarytool log $UUID --keychain-profile "notarytool-profile" + xcrun notarytool log "$UUID" --keychain-profile "notarytool-profile" - name: Staple WakaTime.app run: | From d2da464a4cab142276bedfa14587595de0e91dbf Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 14:42:50 +0200 Subject: [PATCH 20/31] wip --- .github/workflows/on_push.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index 3b6c9d1..e2fdb0e 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -76,7 +76,8 @@ jobs: run: | ditto -c -k --keepParent build/Release/WakaTime.app main.zip UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') - xcrun notarytool log "$UUID" --keychain-profile "notarytool-profile" + echo $UUID + xcrun notarytool log $UUID --keychain-profile "notarytool-profile" - name: Staple WakaTime.app run: | From 8ba818072192cd94d06aa11ad83ecf4637bee1f1 Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 14:54:41 +0200 Subject: [PATCH 21/31] Fix grep --- .github/workflows/on_push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index e2fdb0e..ffb2054 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -75,7 +75,7 @@ jobs: name: Notarize WakaTime.app run: | ditto -c -k --keepParent build/Release/WakaTime.app main.zip - UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') + UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -m 1 -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') echo $UUID xcrun notarytool log $UUID --keychain-profile "notarytool-profile" - From 344a503e49d0e8a49b15d368809d1ae98390c21b Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 16:15:02 +0200 Subject: [PATCH 22/31] Add history output --- .github/workflows/on_push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index ffb2054..1874ce4 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -76,7 +76,7 @@ jobs: run: | ditto -c -k --keepParent build/Release/WakaTime.app main.zip UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -m 1 -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') - echo $UUID + xcrun notarytool history --keychain-profile "notarytool-profile" xcrun notarytool log $UUID --keychain-profile "notarytool-profile" - name: Staple WakaTime.app From 9f2b4fa665007823f968bd1663abf1f75a45ff06 Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 16:21:35 +0200 Subject: [PATCH 23/31] Add sleep --- .github/workflows/on_push.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index 1874ce4..7bd8579 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -77,7 +77,8 @@ jobs: ditto -c -k --keepParent build/Release/WakaTime.app main.zip UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -m 1 -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') xcrun notarytool history --keychain-profile "notarytool-profile" - xcrun notarytool log $UUID --keychain-profile "notarytool-profile" + #xcrun notarytool log $UUID --keychain-profile "notarytool-profile" + sleep 300 - name: Staple WakaTime.app run: | From 85a9af2a94fc70dda49f38db667a6ca9165a4231 Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 16:32:03 +0200 Subject: [PATCH 24/31] Remove sleep --- .github/workflows/on_push.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index 7bd8579..555713d 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -76,9 +76,8 @@ jobs: run: | ditto -c -k --keepParent build/Release/WakaTime.app main.zip UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -m 1 -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') - xcrun notarytool history --keychain-profile "notarytool-profile" - #xcrun notarytool log $UUID --keychain-profile "notarytool-profile" - sleep 300 + #xcrun notarytool history --keychain-profile "notarytool-profile" + xcrun notarytool log $UUID --keychain-profile "notarytool-profile" - name: Staple WakaTime.app run: | From 88f2ef31b5371b4258f4d30d1fab9cd7b547181c Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 16:41:16 +0200 Subject: [PATCH 25/31] Just run notarytool log with hard-coded id for testing --- .github/workflows/on_push.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index 555713d..3596ec7 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -75,9 +75,10 @@ jobs: name: Notarize WakaTime.app run: | ditto -c -k --keepParent build/Release/WakaTime.app main.zip - UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -m 1 -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') + #UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -m 1 -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') #xcrun notarytool history --keychain-profile "notarytool-profile" - xcrun notarytool log $UUID --keychain-profile "notarytool-profile" + #xcrun notarytool log $UUID --keychain-profile "notarytool-profile" + xcrun notarytool log 8757991b-d7e8-4dda-9fb5-350c50173646 --keychain-profile "notarytool-profile" - name: Staple WakaTime.app run: | From 3a2ef5b02a5a7ab1419564e6938c50e1e45bfdc7 Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 16:54:18 +0200 Subject: [PATCH 26/31] Codesign libswift_Concurrency.dylib --- .github/workflows/on_push.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index 3596ec7..4af683f 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -42,11 +42,11 @@ jobs: run: | /usr/bin/codesign --force -s "WakaTime" --options runtime "build/Release/WakaTime.app/Contents/Library/LoginItems/WakaTime Helper.app" -v /usr/bin/codesign --verify --deep --strict --verbose=2 "build/Release/WakaTime.app/Contents/Library/LoginItems/WakaTime Helper.app" - #- - # name: Codesign libswift_Concurrency.dylib - # run: | - # /usr/bin/codesign --force -s "WakaTime" --options runtime "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" -v - # /usr/bin/codesign --verify --deep --strict --verbose=2 "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" + - + name: Codesign libswift_Concurrency.dylib + run: | + /usr/bin/codesign --force -s "WakaTime" --options runtime "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" -v + /usr/bin/codesign --verify --deep --strict --verbose=2 "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" - name: Codesign WakaTime.app run: | @@ -75,10 +75,10 @@ jobs: name: Notarize WakaTime.app run: | ditto -c -k --keepParent build/Release/WakaTime.app main.zip - #UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -m 1 -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') + UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -m 1 -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') #xcrun notarytool history --keychain-profile "notarytool-profile" #xcrun notarytool log $UUID --keychain-profile "notarytool-profile" - xcrun notarytool log 8757991b-d7e8-4dda-9fb5-350c50173646 --keychain-profile "notarytool-profile" + #xcrun notarytool log 8757991b-d7e8-4dda-9fb5-350c50173646 --keychain-profile "notarytool-profile" - name: Staple WakaTime.app run: | From c4d8da01b509b4d11fd4d16791c9ecb30dc6c398 Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 16:58:54 +0200 Subject: [PATCH 27/31] Echo UUID --- .github/workflows/on_push.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index 4af683f..cb28ec5 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -76,6 +76,7 @@ jobs: run: | ditto -c -k --keepParent build/Release/WakaTime.app main.zip UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -m 1 -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') + echo $UUID #xcrun notarytool history --keychain-profile "notarytool-profile" #xcrun notarytool log $UUID --keychain-profile "notarytool-profile" #xcrun notarytool log 8757991b-d7e8-4dda-9fb5-350c50173646 --keychain-profile "notarytool-profile" From e98ffcded76692434855955caa47eabcc4cafcf7 Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 17:03:04 +0200 Subject: [PATCH 28/31] Log output --- .github/workflows/on_push.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index cb28ec5..edce5f2 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -75,11 +75,11 @@ jobs: name: Notarize WakaTime.app run: | ditto -c -k --keepParent build/Release/WakaTime.app main.zip - UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -m 1 -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') - echo $UUID + #UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -m 1 -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') + #echo $UUID #xcrun notarytool history --keychain-profile "notarytool-profile" #xcrun notarytool log $UUID --keychain-profile "notarytool-profile" - #xcrun notarytool log 8757991b-d7e8-4dda-9fb5-350c50173646 --keychain-profile "notarytool-profile" + xcrun notarytool log 1b0112d7-1b83-414b-82a0-0e376d1d81bd --keychain-profile "notarytool-profile" - name: Staple WakaTime.app run: | From 554a8af5a037c09d0ff62fa2b90366867efcc948 Mon Sep 17 00:00:00 2001 From: Tobias Lensing Date: Tue, 13 Jun 2023 17:09:26 +0200 Subject: [PATCH 29/31] Re-add sleep --- .github/workflows/on_push.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index edce5f2..741c1d1 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -75,11 +75,12 @@ jobs: name: Notarize WakaTime.app run: | ditto -c -k --keepParent build/Release/WakaTime.app main.zip - #UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -m 1 -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') + UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -m 1 -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') #echo $UUID #xcrun notarytool history --keychain-profile "notarytool-profile" #xcrun notarytool log $UUID --keychain-profile "notarytool-profile" - xcrun notarytool log 1b0112d7-1b83-414b-82a0-0e376d1d81bd --keychain-profile "notarytool-profile" + #xcrun notarytool log 1b0112d7-1b83-414b-82a0-0e376d1d81bd --keychain-profile "notarytool-profile" + sleep 300 - name: Staple WakaTime.app run: | From 9facfa520832133ca614b9b775d7884a7b1fd040 Mon Sep 17 00:00:00 2001 From: Alan Hamlett Date: Tue, 13 Jun 2023 18:29:24 +0200 Subject: [PATCH 30/31] add back release workflow --- .github/workflows/on_push.yml | 184 +++++++++++++++++++++++++++++----- 1 file changed, 161 insertions(+), 23 deletions(-) diff --git a/.github/workflows/on_push.yml b/.github/workflows/on_push.yml index 741c1d1..a64a2f5 100644 --- a/.github/workflows/on_push.yml +++ b/.github/workflows/on_push.yml @@ -3,10 +3,77 @@ name: Release on: pull_request: types: [opened, reopened, ready_for_review, synchronize] + push: + branches: [main, release] + tags-ignore: "**" jobs: + test: + name: Tests and Build + runs-on: macos-latest + steps: + - + name: Checkout + uses: actions/checkout@v3 + - + name: Install xcodegen via Homebrew for linting and building xcode project + run: brew install xcodegen + - + name: Generate project + run: xcodegen + - + name: Build app to run linters + run: xcodebuild + + version: + name: Version + concurrency: tagging + if: ${{ github.ref == 'refs/heads/release' || github.ref == 'refs/heads/main' }} + runs-on: ubuntu-latest + needs: [test] + outputs: + semver: ${{ steps.format.outputs.semver }} + semver_tag: ${{ steps.semver-tag.outputs.semver_tag }} + ancestor_tag: ${{ steps.semver-tag.outputs.ancestor_tag }} + is_prerelease: ${{ steps.semver-tag.outputs.is_prerelease }} + steps: + - + name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - + name: Calculate semver tag + id: semver-tag + uses: wakatime/semver-action@master + with: + prerelease_id: alpha + develop_branch_name: main + main_branch_name: release + - + name: Format + id: format + run: | + echo "${{ steps.semver-tag.outputs.semver_tag }}" + ver=`echo "${{ steps.semver-tag.outputs.semver_tag }}" | sed 's/^v//'` + echo "$ver" + echo "semver=$ver" >> $GITHUB_OUTPUT + - + name: Create tag + uses: actions/github-script@v6 + with: + github-token: ${{ github.token }} + script: | + github.rest.git.createRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: "refs/tags/${{ steps.semver-tag.outputs.semver_tag }}", + sha: context.sha + }) + sign: name: Sign Apple app + needs: [version] runs-on: macos-latest steps: - @@ -18,7 +85,7 @@ jobs: with: valueFile: 'project.yml' propertyPath: 'targets.WakaTime.settings.MARKETING_VERSION' - value: '1.2.3' + value: ${{ needs.version.outputs.semver }} commitChange: false - name: Install xcodegen via Homebrew for linting and building xcode project @@ -38,17 +105,17 @@ jobs: # The password used to import the PKCS12 file. p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }} - - name: Codesign WakaTime Helper.app + name: Codesign Helper run: | /usr/bin/codesign --force -s "WakaTime" --options runtime "build/Release/WakaTime.app/Contents/Library/LoginItems/WakaTime Helper.app" -v /usr/bin/codesign --verify --deep --strict --verbose=2 "build/Release/WakaTime.app/Contents/Library/LoginItems/WakaTime Helper.app" - name: Codesign libswift_Concurrency.dylib run: | - /usr/bin/codesign --force -s "WakaTime" --options runtime "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" -v - /usr/bin/codesign --verify --deep --strict --verbose=2 "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" + /usr/bin/codesign --force -s "WakaTime" --options runtime build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib -v + /usr/bin/codesign --verify --deep --strict --verbose=2 build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib - - name: Codesign WakaTime.app + name: Codesign App run: | /usr/bin/codesign --force -s "WakaTime" --options runtime build/Release/WakaTime.app -v /usr/bin/codesign --verify --deep --strict --verbose=2 build/Release/WakaTime.app @@ -60,30 +127,22 @@ jobs: NOTARIZATION_PWD: ${{ secrets.AC_PASSWORD }} run: xcrun notarytool store-credentials "notarytool-profile" --apple-id "$NOTARIZATION_APPLE_ID" --team-id "$NOTARIZATION_TEAM_ID" --password "$NOTARIZATION_PWD" - - name: Notarize WakaTime Helper.app + name: Notarize Helper run: | ditto -c -k --keepParent "build/Release/WakaTime.app/Contents/Library/LoginItems/WakaTime Helper.app" helper.zip xcrun notarytool submit helper.zip --keychain-profile "notarytool-profile" --wait xcrun stapler staple "build/Release/WakaTime.app/Contents/Library/LoginItems/WakaTime Helper.app" - #- - # name: Notarize libswift_Concurrency.dylib - # run: | - # ditto -c -k --keepParent "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" concurrency.zip - # xcrun notarytool submit concurrency.zip --keychain-profile "notarytool-profile" --wait - # xcrun stapler staple "build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib" - - - name: Notarize WakaTime.app + - + name: Notarize libswift_Concurrency.dylib run: | - ditto -c -k --keepParent build/Release/WakaTime.app main.zip - UUID=$(xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait | grep -m 1 -o '[0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}') - #echo $UUID - #xcrun notarytool history --keychain-profile "notarytool-profile" - #xcrun notarytool log $UUID --keychain-profile "notarytool-profile" - #xcrun notarytool log 1b0112d7-1b83-414b-82a0-0e376d1d81bd --keychain-profile "notarytool-profile" - sleep 300 - - - name: Staple WakaTime.app + ditto -c -k --keepParent build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib concurrency.zip + xcrun notarytool submit concurrency.zip --keychain-profile "notarytool-profile" --wait + xcrun stapler staple build/Release/WakaTime.app/Contents/Frameworks/libswift_Concurrency.dylib + - + name: Notarize App run: | + ditto -c -k --keepParent build/Release/WakaTime.app main.zip + xcrun notarytool submit main.zip --keychain-profile "notarytool-profile" --wait xcrun stapler staple build/Release/WakaTime.app - name: Zip @@ -94,3 +153,82 @@ jobs: with: name: app path: ./WakaTime.zip + - + name: Remove tag if failure + if: ${{ failure() }} + uses: actions/github-script@v6 + with: + github-token: ${{ github.token }} + script: | + github.rest.git.deleteRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: "tags/${{ needs.version.outputs.semver_tag }}" + }) + + release: + name: Release + runs-on: ubuntu-latest + needs: [version, sign] + steps: + - + name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - + # Run only for main branch + if: ${{ github.ref == 'refs/heads/main' }} + name: Changelog for main + uses: gandarez/changelog-action@v1.2.0 + id: changelog-main + with: + current_tag: ${{ github.sha }} + previous_tag: ${{ needs.version.outputs.ancestor_tag }} + exclude: | + ^Merge pull request .* + - + # Run only for release branch + if: ${{ github.ref == 'refs/heads/release' }} + name: Get related pull request + uses: 8BitJonny/gh-get-current-pr@2.2.0 + id: changelog-release + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + - + name: Prepare changelog + id: changelog + run: | + echo "${{ steps.changelog-main.outputs.changelog || steps.changelog-release.outputs.pr_body }}" > changelog.txt + ./bin/prepare_changelog.sh $(echo ${GITHUB_REF#refs/heads/}) "$(cat changelog.txt)" + - + name: Download artifacts + uses: actions/download-artifact@v3 + with: + name: app + path: ./ + - + name: "Create release" + uses: softprops/action-gh-release@master + with: + name: ${{ needs.version.outputs.semver_tag }} + tag_name: ${{ needs.version.outputs.semver_tag }} + body: "## Changelog\n${{ steps.changelog.outputs.changelog }}" + prerelease: ${{ needs.version.outputs.is_prerelease }} + target_commitish: ${{ github.sha }} + draft: false + files: ./WakaTime.zip + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - + name: Remove tag if failure + if: ${{ failure() }} + uses: actions/github-script@v6 + with: + github-token: ${{ github.token }} + script: | + github.rest.git.deleteRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: "tags/${{ needs.version.outputs.semver_tag }}" + }) From bd554a8cd4a286935957fcfe71a90a63c51054a5 Mon Sep 17 00:00:00 2001 From: Alan Hamlett Date: Tue, 13 Jun 2023 18:43:03 +0200 Subject: [PATCH 31/31] only register as login item in Release builds --- WakaTime/WakaTime.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/WakaTime/WakaTime.swift b/WakaTime/WakaTime.swift index 35eec25..b6ae552 100644 --- a/WakaTime/WakaTime.swift +++ b/WakaTime/WakaTime.swift @@ -38,6 +38,7 @@ class WakaTime { } private func registerAsLoginItem() { + guard shouldRegisterAsLoginItem() else { return } guard !SettingsManager.loginItemRegistered(), PropertiesManager.shouldLaunchOnLogin @@ -45,6 +46,14 @@ class WakaTime { SettingsManager.registerAsLoginItem() } + private func shouldRegisterAsLoginItem() -> Bool { +#if DEBUG + return false +#else + return true +#endif + } + private func requestA11yPermission() { let prompt = kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String let options: NSDictionary = [prompt: true]