Squirrel.Mac
Squirrel.Mac copied to clipboard
Updater state transition is incorrect
According to one of the specs, it "should transition through idle, checking, downloading and awaiting relaunch, when there is an update". However, the fact is:
- if the update is not already downloaded, the transition is idle -> checking -> downloading -> idle
- if the update is already downloaded, the transition is idle -> checking -> downloading -> awaiting relaunch
@psequel Can you explain how to reproduce this? It'd be pretty surprising and looking at the code I'm not sure why that'd happen.
Never mind. The release build actually works as expected. Interesting, only the debug build has the issue I described above. I'm not sure if the SQRLCodeSignatureError matters. I don't see this error in the release build.
Here is the logs from the debug build:
2016-10-21 22:31:31.215 ExampleApp[11446:13794499] SQRLUpdaterStateCheckingForUpdate 2016-10-21 22:31:31.749 ExampleApp[11446:13794873] SQRLUpdaterStateDownloadingUpdate 2016-10-21 22:31:33.391 ExampleApp[11446:13794873] Download completed to: file:///~/Library/Caches/com.example.ShipIt/update.zfts9mU/download 2016-10-21 22:31:33.519 ExampleApp[11446:13794874] SQRLUpdaterStateIdle 2016-10-21 22:31:33.520 ExampleApp[11446:13794499] Error checking for updates: Error Domain=SQRLCodeSignatureErrorDomain Code=-1 "Code signature at URL file:///~/Library/Caches/com.example.ShipIt/update.zfts9mU/ExampleApp.app/ did not pass validation" UserInfo={NSLocalizedFailureReason=code failed to satisfy specified code requirement(s), NSLocalizedDescription=Code signature at URL file:///~/Library/Caches/com.example.ShipIt/update.zfts9mU/ExampleApp.app/ did not pass validation, NSUnderlyingError=0x610000241e90 {Error Domain=NSOSStatusErrorDomain Code=-67050 "(null)" UserInfo={SecCSArchitecture=x86_64}}} 2016-10-21 22:32:01.213 ExampleApp[11446:13794499] SQRLUpdaterStateCheckingForUpdate 2016-10-21 22:32:01.361 ExampleApp[11446:13794903] SQRLUpdaterStateDownloadingUpdate 2016-10-21 22:32:04.500 ExampleApp[11446:13795270] SQRLUpdaterStateAwaitingRelaunch
And here is the code (in Swift 3) to reproduce it:
import Cocoa
import Squirrel
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
let dummy = UpdateEngine()
}
class UpdateEngine: NSObject {
private let updater: SQRLUpdater = {
let url = URL(string: "https://my.update.server?version=1.0.0")!
return SQRLUpdater(update: URLRequest(url: url))!
}()
override init() {
super.init()
updater.startAutomaticChecks(withInterval: 30)
updater.addObserver(self, forKeyPath: "state", options: .new, context: nil)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "state" && object is SQRLUpdater {
switch (object as! SQRLUpdater).state {
case SQRLUpdaterStateIdle:
NSLog("SQRLUpdaterStateIdle")
case SQRLUpdaterStateCheckingForUpdate:
NSLog("SQRLUpdaterStateCheckingForUpdate")
case SQRLUpdaterStateDownloadingUpdate:
NSLog("SQRLUpdaterStateDownloadingUpdate")
case SQRLUpdaterStateAwaitingRelaunch:
NSLog("SQRLUpdaterStateAwaitingRelaunch")
default:
NSLog("unknown state")
}
}
}
}
Yes, the code signatures of both builds must match for Squirrel to perform the update.
But if you take a look at my logs, the second time when checking for updates, it doesn't download the updated bundle (because it's already downloaded) , and it doesn't show the signature error and it moves to SQRLUpdaterStateAwaitingRelaunch state. My question, why the first time when checking for update, the signature doesn't match but the second time is fine even if it doesn't download the update at all? Note that this happens only for the debug build (started by Xcode).
But if you take a look at my logs, the second time [...]
Oh, I didn't notice that! I'm not sure how to explain that without digging into it more.