From c6865eb4a910992cadce1690cbbacfb15d63290a Mon Sep 17 00:00:00 2001 From: Honza Dvorsky Date: Sun, 12 Apr 2015 20:45:00 +0100 Subject: [PATCH 1/3] piping logging through one place now --- BuildaCIServer/XcodeServerEndpoints.swift | 2 +- BuildaGitServer/GitHubEndpoints.swift | 2 +- BuildaGitServerTests/GitHubServerTests.swift | 4 +-- BuildaUtils/Logging.swift | 28 +++++++++++++++++++ BuildaUtils/UIUtils.swift | 2 +- BuildaUtils/XcodeProjectParser.swift | 2 +- Buildasaur/BuildTemplateViewController.swift | 2 +- Buildasaur/HDGitHubXCBotSyncer.swift | 20 ++++++------- Buildasaur/LocalSource.swift | 8 +++--- .../ManualBotManagementViewController.swift | 2 +- Buildasaur/Persistence.swift | 5 ++-- Buildasaur/StatusProjectViewController.swift | 2 +- Buildasaur/StatusSyncerViewController.swift | 11 +------- Buildasaur/StorageManager.swift | 16 +++++------ Buildasaur/StorageUtils.swift | 10 ++++--- Buildasaur/Syncer.swift | 10 +++---- Buildasaur/XcodeServerSyncerUtils.swift | 6 ++-- 17 files changed, 77 insertions(+), 55 deletions(-) create mode 100644 BuildaUtils/Logging.swift diff --git a/BuildaCIServer/XcodeServerEndpoints.swift b/BuildaCIServer/XcodeServerEndpoints.swift index 6bd1368..3675f34 100644 --- a/BuildaCIServer/XcodeServerEndpoints.swift +++ b/BuildaCIServer/XcodeServerEndpoints.swift @@ -122,7 +122,7 @@ public class XcodeServerEndPoints { let data = NSJSONSerialization.dataWithJSONObject(body, options: .allZeros, error: &error) if let error = error { //parsing error - println("Parsing error \(error.description)") + Log.error("Parsing error \(error.description)") return nil } diff --git a/BuildaGitServer/GitHubEndpoints.swift b/BuildaGitServer/GitHubEndpoints.swift index 9447b9f..0b79231 100644 --- a/BuildaGitServer/GitHubEndpoints.swift +++ b/BuildaGitServer/GitHubEndpoints.swift @@ -165,7 +165,7 @@ public class GitHubEndpoints { let data = NSJSONSerialization.dataWithJSONObject(body, options: .allZeros, error: &error) if let error = error { //parsing error - println("Parsing error \(error.description)") + Log.error("Parsing error \(error.description)") return nil } diff --git a/BuildaGitServerTests/GitHubServerTests.swift b/BuildaGitServerTests/GitHubServerTests.swift index ff5b58b..2dca681 100644 --- a/BuildaGitServerTests/GitHubServerTests.swift +++ b/BuildaGitServerTests/GitHubServerTests.swift @@ -58,7 +58,7 @@ class GitHubSourceTests: XCTestCase { XCTAssertNotNil(body, "Body must be non-nil") let prs: [PullRequest] = GitHubArray(body as! NSArray) XCTAssertGreaterThan(prs.count, 0, "We need > 0 items to test parsing") - println("Parsed PRs: \(prs)") + Log.verbose("Parsed PRs: \(prs)") } } @@ -73,7 +73,7 @@ class GitHubSourceTests: XCTestCase { XCTAssertNotNil(body, "Body must be non-nil") let branches: [Branch] = GitHubArray(body as! NSArray) XCTAssertGreaterThan(branches.count, 0, "We need > 0 items to test parsing") - println("Parsed branches: \(branches)") + Log.verbose("Parsed branches: \(branches)") } } diff --git a/BuildaUtils/Logging.swift b/BuildaUtils/Logging.swift new file mode 100644 index 0000000..00214e2 --- /dev/null +++ b/BuildaUtils/Logging.swift @@ -0,0 +1,28 @@ +// +// Logging.swift +// Buildasaur +// +// Created by Honza Dvorsky on 12/04/2015. +// Copyright (c) 2015 Honza Dvorsky. All rights reserved. +// + +import Foundation + +public class Log { + + public class func verbose(message: String) { + println("[VERBOSE]: " + message) + } + + public class func info(message: String) { + println("[INFO]: " + message) + } + + public class func error(message: String) { + println("[ERROR]: " + message) + } + + public class func untouched(message: String) { + println(message) + } +} diff --git a/BuildaUtils/UIUtils.swift b/BuildaUtils/UIUtils.swift index ac17214..a3129ee 100644 --- a/BuildaUtils/UIUtils.swift +++ b/BuildaUtils/UIUtils.swift @@ -78,7 +78,7 @@ public class UIUtils { // alert.beginSheetModalForWindow(window, completionHandler: completion) } else { //no window to present in, at least print - println("Alert: \(alert.messageText)") + Log.info("Alert: \(alert.messageText)") } } } diff --git a/BuildaUtils/XcodeProjectParser.swift b/BuildaUtils/XcodeProjectParser.swift index 11c7911..1874dd6 100644 --- a/BuildaUtils/XcodeProjectParser.swift +++ b/BuildaUtils/XcodeProjectParser.swift @@ -193,7 +193,7 @@ public class XcodeProjectParser { return absolutePaths } } - println("Couldn't load contents of workspace \(url)") + Log.error("Couldn't load contents of workspace \(url)") return nil } diff --git a/Buildasaur/BuildTemplateViewController.swift b/Buildasaur/BuildTemplateViewController.swift index 942af91..00c7b6e 100644 --- a/Buildasaur/BuildTemplateViewController.swift +++ b/Buildasaur/BuildTemplateViewController.swift @@ -226,7 +226,7 @@ class BuildTemplateViewController: SetupViewController, NSComboBoxDelegate, NSTa self.schemesComboBox.delegate = self self.fetchDevices { () -> () in - println("Finished fetching devices") + Log.verbose("Finished fetching devices") } } diff --git a/Buildasaur/HDGitHubXCBotSyncer.swift b/Buildasaur/HDGitHubXCBotSyncer.swift index c46ef0d..adf1798 100644 --- a/Buildasaur/HDGitHubXCBotSyncer.swift +++ b/Buildasaur/HDGitHubXCBotSyncer.swift @@ -120,7 +120,7 @@ public class HDGitHubXCBotSyncer : Syncer { let prsDescription = prs.map({ "\n\tPR \($0.number): \($0.title) [\($0.head.ref) -> \($0.base.ref))]" }) + ["\n"] let botsDescription = bots.map({ "\n\t\($0.name)" }) + ["\n"] - println("Resolving prs:\n\(prsDescription) \nand bots:\n\(botsDescription)") + Log.verbose("Resolving prs:\n\(prsDescription) \nand bots:\n\(botsDescription)") if let repoName = self.repoName() { @@ -207,7 +207,7 @@ public class HDGitHubXCBotSyncer : Syncer { pairs.mapVoidAsync({ (pair, itemCompletion) -> () in self.tryToSyncPRWithBot(pair.pr, bot: pair.bot, completion: { () -> () in - println("Synced up PR #\(pair.pr.number) with bot \(pair.bot.name)") + Log.verbose("Synced up PR #\(pair.pr.number) with bot \(pair.bot.name)") itemCompletion() }) }, completion: completion) @@ -246,7 +246,7 @@ public class HDGitHubXCBotSyncer : Syncer { } } else { - println("No repo name, cannot find the GitHub repo!") + Log.error("No repo name, cannot find the GitHub repo!") completion(isEnabled: false) } } @@ -281,7 +281,7 @@ public class HDGitHubXCBotSyncer : Syncer { } else { //not enabled, make sure the PR reflects that and the instructions are clear - println("Bot \(bot.name) is not yet enabled, ignoring...") + Log.verbose("Bot \(bot.name) is not yet enabled, ignoring...") let status = Status(state: .Pending, description: "Waiting for \"lttm\" to start testing", targetUrl: nil, context: nil) let notYetEnabled = GitHubStatusAndComment(status: status, comment: nil) @@ -372,7 +372,7 @@ public class HDGitHubXCBotSyncer : Syncer { if integration.currentStep == .Completed { if let result = integration.result { if result == .CheckoutError { - println("Integration #\(integration.number) finished with a checkout error - please check that your SSH keys setup in Buildasaur are correct! If you need to fix them, please do so and then you need to recreate the bot - e.g. by closing the Pull Request, waiting for a sync (bot will disappear) and then reopening the Pull Request - should do the job!") + Log.error("Integration #\(integration.number) finished with a checkout error - please check that your SSH keys setup in Buildasaur are correct! If you need to fix them, please do so and then you need to recreate the bot - e.g. by closing the Pull Request, waiting for a sync (bot will disappear) and then reopening the Pull Request - should do the job!") return true } } @@ -426,7 +426,7 @@ public class HDGitHubXCBotSyncer : Syncer { self.xcodeServer.postIntegration(bot.id, completion: { (integration, error) -> () in if let integration = integration where error == nil { - println("Bot \(bot.name) successfully enqueued Integration #\(integration.number)") + Log.info("Bot \(bot.name) successfully enqueued Integration #\(integration.number)") } else { self.notifyError(error, context: "Bot \(bot.name) failed to enqueue an integration") } @@ -503,7 +503,7 @@ public class HDGitHubXCBotSyncer : Syncer { let oldStatus = status?.description ?? "[no status]" let newStatus = statusWithComment let comment = newStatus.comment ?? "[no comment]" - println("Updating status of commit \(headCommit) in PR #\(pr.number) from \(oldStatus) to \(newStatus), will add comment \(comment)") + Log.info("Updating status of commit \(headCommit) in PR #\(pr.number) from \(oldStatus) to \(newStatus), will add comment \(comment)") //we need to update status self.postStatusWithComment(statusWithComment, commit: headCommit, repo: repoName, pr: pr, completion: { () -> () in @@ -593,7 +593,7 @@ public class HDGitHubXCBotSyncer : Syncer { } else { //this shouldn't happen. - println("LOGIC ERROR! This shouldn't happen, there are no completed integrations!") + Log.error("LOGIC ERROR! This shouldn't happen, there are no completed integrations!") let status = self.createStatusFromState(.Error, description: "* UNKNOWN STATE, Builda ERROR *") statusWithComment = (status: status, "Builda error, unknown state!") } @@ -693,7 +693,7 @@ public class HDGitHubXCBotSyncer : Syncer { if error != nil { self.notifyError(error, context: "Failed to cancel integration \(integration.number)") } else { - println("Successfully cancelled integration \(integration.number)") + Log.info("Successfully cancelled integration \(integration.number)") } itemCompletion() }) @@ -710,7 +710,7 @@ public class HDGitHubXCBotSyncer : Syncer { if error != nil { self.notifyError(error, context: "Failed to delete bot with name \(bot.name)") } else { - println("Successfully deleted bot \(bot.name)") + Log.info("Successfully deleted bot \(bot.name)") } itemCompletion() }) diff --git a/Buildasaur/LocalSource.swift b/Buildasaur/LocalSource.swift index 8de30b5..d707541 100644 --- a/Buildasaur/LocalSource.swift +++ b/Buildasaur/LocalSource.swift @@ -119,7 +119,7 @@ public class LocalSource : JSONSerializable { //SVN } - println("HTTPS or SVN not yet supported, please create an issue on GitHub if you want it added (czechboy0/Buildasaur)") + Log.error("HTTPS or SVN not yet supported, please create an issue on GitHub if you want it added (czechboy0/Buildasaur)") return nil default: return nil @@ -169,7 +169,7 @@ public class LocalSource : JSONSerializable { } let (success, error) = self.refreshMetadata() if !success { - println("Error parsing: \(error)") + Log.error("Error parsing: \(error)") return nil } @@ -242,10 +242,10 @@ public class LocalSource : JSONSerializable { if let key = NSString(contentsOfURL: url, encoding: NSASCIIStringEncoding, error: &error) { return key as String } - println("Couldn't load key at url \(url) with error \(error)") + Log.error("Couldn't load key at url \(url) with error \(error)") return nil } - println("Couldn't load key at nil url") + Log.error("Couldn't load key at nil url") return nil } diff --git a/Buildasaur/ManualBotManagementViewController.swift b/Buildasaur/ManualBotManagementViewController.swift index de88664..0bdebdf 100644 --- a/Buildasaur/ManualBotManagementViewController.swift +++ b/Buildasaur/ManualBotManagementViewController.swift @@ -124,7 +124,7 @@ class ManualBotManagementViewController: NSViewController { }) } else { - println("Failed to satisfy some bot dependencies, ignoring...") + Log.error("Failed to satisfy some bot dependencies, ignoring...") } } diff --git a/Buildasaur/Persistence.swift b/Buildasaur/Persistence.swift index ae999ae..080fa72 100644 --- a/Buildasaur/Persistence.swift +++ b/Buildasaur/Persistence.swift @@ -7,6 +7,7 @@ // import Foundation +import BuildaUtils class Persistence { @@ -66,7 +67,7 @@ class Persistence { return buildaAppSupport } else { - println("Failed to create Builda's Application Support folder, error \(error)") + Log.error("Failed to create Builda's Application Support folder, error \(error)") } } @@ -81,7 +82,7 @@ class Persistence { if let contents = fm.contentsOfDirectoryAtURL(folderUrl, includingPropertiesForKeys: nil, options: NSDirectoryEnumerationOptions.SkipsHiddenFiles | NSDirectoryEnumerationOptions.SkipsSubdirectoryDescendants, error: &error) as? [NSURL] { contents.map { visit(url: $0) } } else { - println("Couldn't read folder \(folderUrl), error \(error)") + Log.error("Couldn't read folder \(folderUrl), error \(error)") } } diff --git a/Buildasaur/StatusProjectViewController.swift b/Buildasaur/StatusProjectViewController.swift index f0764c2..ba0e650 100644 --- a/Buildasaur/StatusProjectViewController.swift +++ b/Buildasaur/StatusProjectViewController.swift @@ -119,7 +119,7 @@ class StatusProjectViewController: StatusViewController, NSComboBoxDelegate, Set let status: AvailabilityCheckState if let error = error { - println("Error: \(error)") + Log.error("Checking github availability error: \(error)") status = AvailabilityCheckState.Failed(error) } else { status = .Succeeded diff --git a/Buildasaur/StatusSyncerViewController.swift b/Buildasaur/StatusSyncerViewController.swift index 51a81ac..3ebe50b 100644 --- a/Buildasaur/StatusSyncerViewController.swift +++ b/Buildasaur/StatusSyncerViewController.swift @@ -126,17 +126,8 @@ class StatusSyncerViewController: StatusViewController, SyncerDelegate { super.viewDidAppear() if let syncer = self.syncer() { - println("We have a syncer \(syncer)") - - //test -// syncer.xcodeServer.getDevices({ (devices, error) -> () in -// -// println() -// }) + Log.info("We have a syncer \(syncer)") } - - - } override func reloadStatus() { diff --git a/Buildasaur/StorageManager.swift b/Buildasaur/StorageManager.swift index 6b95273..fe9fdc2 100644 --- a/Buildasaur/StorageManager.swift +++ b/Buildasaur/StorageManager.swift @@ -55,7 +55,7 @@ class StorageManager { func addSyncer(syncInterval: NSTimeInterval, project: LocalSource, serverConfig: XcodeServerConfig) -> HDGitHubXCBotSyncer? { if syncInterval <= 0 { - println("Sync interval must be > 0 seconds.") + Log.error("Sync interval must be > 0 seconds.") return nil } @@ -151,7 +151,7 @@ class StorageManager { let allConfigs = json.map { XcodeServerConfig(json: $0) } let parsedConfigs = allConfigs.filter { $0 != nil }.map { $0! } if allConfigs.count != parsedConfigs.count { - println("Some configs failed to parse, will be ignored.") + Log.error("Some configs failed to parse, will be ignored.") //maybe show a popup } parsedConfigs.map { self.servers.append($0) } @@ -160,7 +160,7 @@ class StorageManager { //file not found if error?.code != 260 { - println("Failed to read ServerConfigs, error \(error). Will be ignored. Please don't play with the persistence :(") + Log.error("Failed to read ServerConfigs, error \(error). Will be ignored. Please don't play with the persistence :(") } } @@ -175,7 +175,7 @@ class StorageManager { let allProjects = json.map { LocalSource(json: $0) } let parsedProjects = allProjects.filter { $0 != nil }.map { $0! } if allProjects.count != parsedProjects.count { - println("Some projects failed to parse, will be ignored.") + Log.error("Some projects failed to parse, will be ignored.") //maybe show a popup } parsedProjects.map { self.projects.append($0) } @@ -183,7 +183,7 @@ class StorageManager { } //file not found if error?.code != 260 { - println("Failed to read Projects, error \(error). Will be ignored. Please don't play with the persistence :(") + Log.error("Failed to read Projects, error \(error). Will be ignored. Please don't play with the persistence :(") } } @@ -198,7 +198,7 @@ class StorageManager { let allSyncers = json.map { HDGitHubXCBotSyncer(json: $0, storageManager: self) } let parsedSyncers = allSyncers.filter { $0 != nil }.map { $0! } if allSyncers.count != parsedSyncers.count { - println("Some syncers failed to parse, will be ignored.") + Log.error("Some syncers failed to parse, will be ignored.") //maybe show a popup } parsedSyncers.map { self.syncers.append($0) } @@ -206,7 +206,7 @@ class StorageManager { } //file not found if error?.code != 260 { - println("Failed to read Syncers, error \(error). Will be ignored. Please don't play with the persistence :(") + Log.error("Failed to read Syncers, error \(error). Will be ignored. Please don't play with the persistence :(") } } @@ -225,7 +225,7 @@ class StorageManager { return } } - println("Couldn't parse Build Template at url \(url), error \(error)") + Log.error("Couldn't parse Build Template at url \(url), error \(error)") }) } diff --git a/Buildasaur/StorageUtils.swift b/Buildasaur/StorageUtils.swift index a437c25..d6bbd73 100644 --- a/Buildasaur/StorageUtils.swift +++ b/Buildasaur/StorageUtils.swift @@ -8,6 +8,7 @@ import Foundation import Cocoa +import BuildaUtils class StorageUtils { @@ -25,11 +26,12 @@ class StorageUtils { switch clicked { case NSFileHandlingPanelOKButton: let url = openPanel.URL - println("Project: \(url)") + let urlOrEmpty = url ?? NSURL() + Log.info("Project: \(urlOrEmpty)") return url default: //do nothing - println("Dismissed open dialog") + Log.verbose("Dismissed open dialog") } return nil } @@ -49,11 +51,11 @@ class StorageUtils { switch clicked { case NSFileHandlingPanelOKButton: let url = openPanel.URL - println("Key: \(url)") + Log.info("Key: \(url)") return url default: //do nothing - println("Dismissed open dialog") + Log.verbose("Dismissed open dialog") } return nil } diff --git a/Buildasaur/Syncer.swift b/Buildasaur/Syncer.swift index 3d9dd29..4b661d6 100644 --- a/Buildasaur/Syncer.swift +++ b/Buildasaur/Syncer.swift @@ -87,18 +87,18 @@ public protocol SyncerDelegate: class { if self.isSyncing { //already is syncing, wait till it's finished - println("Trying to sync again even though the previous sync hasn't finished. You might want to consider making the sync interval longer. Just sayin'") + Log.info("Trying to sync again even though the previous sync hasn't finished. You might want to consider making the sync interval longer. Just sayin'") return } - println("\n------------------------------------\n") + Log.untouched("\n------------------------------------\n") self.isSyncing = true self.currentSyncError = nil self.reports.removeAll(keepCapacity: true) let start = NSDate() - println("Sync starting at \(start)") + Log.info("Sync starting at \(start)") self.sync { () -> () in @@ -112,7 +112,7 @@ public protocol SyncerDelegate: class { self.lastSyncError = nil self.lastSuccessfulSyncFinishedDate = NSDate() } - println("Sync finished \(finishState) at \(end), took \(end.timeIntervalSinceDate(start)) seconds.") + Log.info("Sync finished \(finishState) at \(end), took \(end.timeIntervalSinceDate(start)) seconds.") self.isSyncing = false } } @@ -127,7 +127,7 @@ public protocol SyncerDelegate: class { if let context = context { message += "Context: \(context)" } - println(message) + Log.error(message) self.currentSyncError = error self.delegate?.syncerEncounteredError(self, error: Errors.errorWithInfo(message)) } diff --git a/Buildasaur/XcodeServerSyncerUtils.swift b/Buildasaur/XcodeServerSyncerUtils.swift index 78e1fe1..91f3755 100644 --- a/Buildasaur/XcodeServerSyncerUtils.swift +++ b/Buildasaur/XcodeServerSyncerUtils.swift @@ -43,12 +43,12 @@ class XcodeServerSyncerUtils { //print success/failure etc if let error = error { outError = error - println("Failed to create bot with name \(botName) and json \(newBot.dictionarify()), error \(error)") + Log.error("Failed to create bot with name \(botName) and json \(newBot.dictionarify()), error \(error)") } else if let bot = bot { - println("Successfully created bot \(bot.name)") + Log.info("Successfully created bot \(bot.name)") } else { outError = Errors.errorWithInfo("Failed to return bot after creation even after error was nil!") - println(outError) + Log.error(outError?.description ?? "") } NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in completion(bot: bot, error: outError) From 21f42ad2fc46ffeae31beda1c6672916e020cc51 Mon Sep 17 00:00:00 2001 From: Honza Dvorsky Date: Sun, 12 Apr 2015 21:25:08 +0100 Subject: [PATCH 2/3] rolled my own logging in the end --- BuildaUtils/Logging.swift | 68 +++++++++++++++++-- {Buildasaur => BuildaUtils}/Persistence.swift | 14 ++-- Buildasaur.xcodeproj/project.pbxproj | 12 ++-- Buildasaur/AppDelegate.swift | 31 +++++++-- 4 files changed, 104 insertions(+), 21 deletions(-) rename {Buildasaur => BuildaUtils}/Persistence.swift (85%) diff --git a/BuildaUtils/Logging.swift b/BuildaUtils/Logging.swift index 00214e2..07c38a0 100644 --- a/BuildaUtils/Logging.swift +++ b/BuildaUtils/Logging.swift @@ -8,21 +8,81 @@ import Foundation +public protocol Logger { + + func description() -> String + func log(message: String) +} + +public class FileLogger: Logger { + + let filePath: NSURL + let stream: NSOutputStream + + public init(filePath: NSURL) { + self.filePath = filePath + self.stream = NSOutputStream(URL: filePath, append: true)! + self.stream.open() + } + + deinit { + self.stream.close() + } + + public func description() -> String { + return "File logger into file at path \(self.filePath)" + } + + public func log(message: String) { + let data: NSData = "\(message)\n".dataUsingEncoding(NSUTF8StringEncoding)! + self.stream.write(UnsafePointer(data.bytes), maxLength: data.length) + } +} + +public class ConsoleLogger: Logger { + + public init() { + // + } + + public func description() -> String { + return "Console logger" + } + + public func log(message: String) { + println(message) + } +} + public class Log { + static private var _loggers = [Logger]() + public class func addLoggers(loggers: [Logger]) { + for i in loggers { + _loggers.append(i) + println("Added logger: \(i)") + } + } + + private class func log(message: String) { + for i in _loggers { + i.log(message) + } + } + public class func verbose(message: String) { - println("[VERBOSE]: " + message) + Log.log("[VERBOSE]: " + message) } public class func info(message: String) { - println("[INFO]: " + message) + Log.log("[INFO]: " + message) } public class func error(message: String) { - println("[ERROR]: " + message) + Log.log("[ERROR]: " + message) } public class func untouched(message: String) { - println(message) + Log.log(message) } } diff --git a/Buildasaur/Persistence.swift b/BuildaUtils/Persistence.swift similarity index 85% rename from Buildasaur/Persistence.swift rename to BuildaUtils/Persistence.swift index 080fa72..3624292 100644 --- a/Buildasaur/Persistence.swift +++ b/BuildaUtils/Persistence.swift @@ -9,9 +9,9 @@ import Foundation import BuildaUtils -class Persistence { +public class Persistence { - class func loadJSONFromUrl(url: NSURL) -> (AnyObject?, NSError?) { + public class func loadJSONFromUrl(url: NSURL) -> (AnyObject?, NSError?) { var error: NSError? if let data = NSData(contentsOfURL: url, options: NSDataReadingOptions.allZeros, error: &error) { @@ -23,7 +23,7 @@ class Persistence { return (nil, error) } - class func saveJSONToUrl(json: AnyObject, url: NSURL) -> (Bool, NSError?) { + public class func saveJSONToUrl(json: AnyObject, url: NSURL) -> (Bool, NSError?) { var error: NSError? if let data = NSJSONSerialization.dataWithJSONObject(json, options: NSJSONWritingOptions.PrettyPrinted, error: &error) { @@ -35,7 +35,7 @@ class Persistence { return (false, error) } - class func getFileInAppSupportWithName(name: String, isDirectory: Bool) -> NSURL { + public class func getFileInAppSupportWithName(name: String, isDirectory: Bool) -> NSURL { let root = self.buildaApplicationSupportFolderURL() let url = root.URLByAppendingPathComponent(name, isDirectory: isDirectory) @@ -45,7 +45,7 @@ class Persistence { return url } - class func createFolderIfNotExists(url: NSURL) { + public class func createFolderIfNotExists(url: NSURL) { let fm = NSFileManager.defaultManager() @@ -54,7 +54,7 @@ class Persistence { assert(success, "Failed to create a folder in Builda's Application Support folder \(url), error \(error)") } - class func buildaApplicationSupportFolderURL() -> NSURL { + public class func buildaApplicationSupportFolderURL() -> NSURL { let fm = NSFileManager.defaultManager() if let appSupport = fm.URLsForDirectory(NSSearchPathDirectory.ApplicationSupportDirectory, inDomains:NSSearchPathDomainMask.UserDomainMask).first as? NSURL { @@ -75,7 +75,7 @@ class Persistence { return NSURL() } - class func iterateThroughFilesInFolder(folderUrl: NSURL, visit: (url: NSURL) -> ()) { + public class func iterateThroughFilesInFolder(folderUrl: NSURL, visit: (url: NSURL) -> ()) { let fm = NSFileManager.defaultManager() var error: NSError? diff --git a/Buildasaur.xcodeproj/project.pbxproj b/Buildasaur.xcodeproj/project.pbxproj index 0db41c1..97eab76 100644 --- a/Buildasaur.xcodeproj/project.pbxproj +++ b/Buildasaur.xcodeproj/project.pbxproj @@ -35,12 +35,13 @@ 3A7B91391A3E44100060A21A /* XcodeServerEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7B91381A3E44100060A21A /* XcodeServerEntity.swift */; }; 3A7B913B1A3E450D0060A21A /* Bot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7B913A1A3E450D0060A21A /* Bot.swift */; }; 3A7B913D1A3E455A0060A21A /* BotConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7B913C1A3E455A0060A21A /* BotConfiguration.swift */; }; + 3A808A1B1ADB03640073145D /* Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A808A1A1ADB03640073145D /* Logging.swift */; }; + 3A808A1D1ADB063F0073145D /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A808A1C1ADB063F0073145D /* Persistence.swift */; }; 3A90C4C01A90220F0048C040 /* HDGitHubXCBotSyncer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A90C4BF1A90220F0048C040 /* HDGitHubXCBotSyncer.swift */; }; 3AA04CB31A62DAC600350811 /* SourceControlBlueprint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA04CB21A62DAC600350811 /* SourceControlBlueprint.swift */; }; 3AA04CB51A62E1D600350811 /* Integration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA04CB41A62E1D600350811 /* Integration.swift */; }; 3AAA1B661AAB6E9800FA1598 /* SeparatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AAA1B651AAB6E9800FA1598 /* SeparatorView.swift */; }; 3AAA1B681AAB722600FA1598 /* StatusProjectViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AAA1B671AAB722600FA1598 /* StatusProjectViewController.swift */; }; - 3AAA1B6C1AAB9D2A00FA1598 /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AAA1B6B1AAB9D2A00FA1598 /* Persistence.swift */; }; 3AAA1B721AABBBB200FA1598 /* NetworkUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AAA1B711AABBBB200FA1598 /* NetworkUtils.swift */; }; 3AAA1B741AABBD3A00FA1598 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AAA1B731AABBD3A00FA1598 /* Errors.swift */; }; 3AAA1B761AAC504700FA1598 /* StatusServerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AAA1B751AAC504700FA1598 /* StatusServerViewController.swift */; }; @@ -187,13 +188,14 @@ 3A7B91381A3E44100060A21A /* XcodeServerEntity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XcodeServerEntity.swift; sourceTree = ""; }; 3A7B913A1A3E450D0060A21A /* Bot.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Bot.swift; sourceTree = ""; }; 3A7B913C1A3E455A0060A21A /* BotConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BotConfiguration.swift; sourceTree = ""; }; + 3A808A1A1ADB03640073145D /* Logging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logging.swift; sourceTree = ""; }; + 3A808A1C1ADB063F0073145D /* Persistence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Persistence.swift; sourceTree = ""; }; 3A90C4BF1A90220F0048C040 /* HDGitHubXCBotSyncer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HDGitHubXCBotSyncer.swift; sourceTree = ""; }; 3A9DEC7A1A3BDA6C008C8270 /* PullRequestBranch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PullRequestBranch.swift; path = BuildaGitServer/PullRequestBranch.swift; sourceTree = SOURCE_ROOT; }; 3AA04CB21A62DAC600350811 /* SourceControlBlueprint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SourceControlBlueprint.swift; sourceTree = ""; }; 3AA04CB41A62E1D600350811 /* Integration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Integration.swift; sourceTree = ""; }; 3AAA1B651AAB6E9800FA1598 /* SeparatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SeparatorView.swift; sourceTree = ""; }; 3AAA1B671AAB722600FA1598 /* StatusProjectViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusProjectViewController.swift; sourceTree = ""; }; - 3AAA1B6B1AAB9D2A00FA1598 /* Persistence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Persistence.swift; sourceTree = ""; }; 3AAA1B711AABBBB200FA1598 /* NetworkUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkUtils.swift; sourceTree = ""; }; 3AAA1B731AABBD3A00FA1598 /* Errors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = ""; }; 3AAA1B751AAC504700FA1598 /* StatusServerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusServerViewController.swift; sourceTree = ""; }; @@ -273,7 +275,6 @@ 3A2F9D841A8FE64900B0DB68 /* LocalSource.swift */, 3A5591551A913C0A00FB19F2 /* XcodeLocalSource.swift */, 3A4770A11A745F470016E170 /* StorageUtils.swift */, - 3AAA1B6B1AAB9D2A00FA1598 /* Persistence.swift */, 3AAA1B711AABBBB200FA1598 /* NetworkUtils.swift */, ); name = Model; @@ -411,6 +412,8 @@ 3AAF6E751A3CE4CC00C657FB /* BuildaUtils */ = { isa = PBXGroup; children = ( + 3A808A1C1ADB063F0073145D /* Persistence.swift */, + 3A808A1A1ADB03640073145D /* Logging.swift */, 3AF1B1211AAC621800917EF3 /* UIUtils.swift */, 3A4770A31A745FFA0016E170 /* XcodeProjectParser.swift */, 3A6355DC1A3BC19800545BF9 /* HTTPUtils.swift */, @@ -728,7 +731,6 @@ 3A5B04AC1AB4AC0F00F60536 /* SetupViewController.swift in Sources */, 3A5B04AA1AB4ABEB00F60536 /* TriggerViewController.swift in Sources */, 3AF1B1241AAC7CA500917EF3 /* StatusSyncerViewController.swift in Sources */, - 3AAA1B6C1AAB9D2A00FA1598 /* Persistence.swift in Sources */, 3A5B04B21AB5C42A00F60536 /* XcodeServerSyncerUtils.swift in Sources */, 3A5B04B01AB5144700F60536 /* ManualBotManagementViewController.swift in Sources */, 3A5687761A3B93BD0066DB2B /* AppDelegate.swift in Sources */, @@ -751,8 +753,10 @@ buildActionMask = 2147483647; files = ( 3AAF6F091A3CE75600C657FB /* HTTPUtils.swift in Sources */, + 3A808A1D1ADB063F0073145D /* Persistence.swift in Sources */, 3AAA1B741AABBD3A00FA1598 /* Errors.swift in Sources */, 3A7B91361A3E41980060A21A /* Server.swift in Sources */, + 3A808A1B1ADB03640073145D /* Logging.swift in Sources */, 3AF1B1221AAC621800917EF3 /* UIUtils.swift in Sources */, 3A4770A41A745FFA0016E170 /* XcodeProjectParser.swift in Sources */, 3AAF6F0A1A3CE75600C657FB /* JSON.swift in Sources */, diff --git a/Buildasaur/AppDelegate.swift b/Buildasaur/AppDelegate.swift index f6526ea..07ab4d8 100644 --- a/Buildasaur/AppDelegate.swift +++ b/Buildasaur/AppDelegate.swift @@ -9,23 +9,42 @@ import Cocoa /* -TODO: Keychain: GitHub token - Please report any crashes on GitHub, I may optionally ask you to email them to me. Thanks! You can find them at ~/Library/Logs/DiagnosticReports/Buildasaur-* - +Also, you can find the log at ~/Library/Application Support/Buildasaur/Builda.log */ -import BuildaCIServer +import BuildaUtils @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { - var server: XcodeServer? - func applicationDidFinishLaunching(aNotification: NSNotification) { // Insert code here to initialize your application + self.setupLogging() + } + + func setupLogging() { + + let path = Persistence.buildaApplicationSupportFolderURL().URLByAppendingPathComponent("Builda.log", isDirectory: false) + let fileLogger = FileLogger(filePath: path) + let consoleLogger = ConsoleLogger() + let loggers: [Logger] = [ + consoleLogger, + fileLogger + ] + Log.addLoggers(loggers) + let version = NSBundle.mainBundle().infoDictionary!["CFBundleShortVersionString"] as! String + let ascii = + " ____ _ _ _\n" + + "| _ \\ (_) | | |\n" + + "| |_) |_ _ _| | __| | __ _ ___ __ _ _ _ _ __\n" + + "| _ <| | | | | |/ _` |/ _` / __|/ _` | | | | '__|\n" + + "| |_) | |_| | | | (_| | (_| \\__ \\ (_| | |_| | |\n" + + "|____/ \\__,_|_|_|\\__,_|\\__,_|___/\\__,_|\\__,_|_|\n" + + Log.untouched("*\n*\n*\n\(ascii)\nBuildasaur \(version) launched at \(NSDate()).\n*\n*\n*\n") } func applicationWillTerminate(aNotification: NSNotification) { From d33633af2682aaddfb0ff588e6a67f57f50cf763 Mon Sep 17 00:00:00 2001 From: Honza Dvorsky Date: Sun, 12 Apr 2015 21:30:01 +0100 Subject: [PATCH 3/3] updated readme --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index fe08615..85ad521 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,10 @@ Manual Bot Management --------------------- In addition to automatic bot management with syncers, you can create bots from an existing Build Template and a branch by clicking *Manual Bot Management* when your syncer is setup. This is useful for creating one-off bots based on e.g. release branches with a different Build Template than you use for PRs. +Troubleshooting +--------------- +In case Builda crashes (God forbid), you can find crash logs at `~/Library/Logs/DiagnosticReports/Buildasaur-*`. Please let me know if that happens and I'll take a look. Also, Builda logs (pretty verbosely) to `~/Library/Application Support/Buildasaur/Builda.log`, so this is another place to watch in case of any problems. + Contributing ------------ Please create an issue with a description of a problem or a pull request with a fix. I'll see what I can do ;-)