-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remote Version Validation #1533
Conversation
I think this would have a negative impact for GitHub API's rate limiting, especially on CI environments. |
CI environments are already unable to use the GitHub API since it's aggressively rate-limited. Using the API features is basically dependent on authenticated use of the API. So I think this is okay. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this will be a big improvement. Users frequently have problems when running older versions.
|
||
/// Attemps to create an instance of NSScaner and then use the convenience | ||
/// function specified in the protocol | ||
static public func fromString(string: String) -> Result<Self,CarthageError> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be a
here after the,
.
|
||
extension Scannable { | ||
|
||
/// Attemps to create an instance of NSScaner and then use the convenience |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple typos here: attempts, NSScanner
/// function specified in the protocol | ||
static public func fromString(string: String) -> Result<Self,CarthageError> | ||
{ | ||
return Self.fromScanner(NSScanner(string:string)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be a
here after the:
.
} | ||
} | ||
|
||
func fetchLatestCarthageVersion() -> CarthageVersion{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it'd be better to split this into two code units:
- one to get the latest version from the server
- one to get the local version (which could be used for
carthage version
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
.timeoutWithError(CarthageError.GitHubAPITimeout, afterInterval: 0.1, onScheduler: QueueScheduler.mainQueueScheduler) | ||
.first() | ||
|
||
return CarthageVersion(localVersion: SemanticVersion.fromString(versionString).value!, remoteVersion: latestVersion!.value!) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't use !
s with latestVersion
because it shouldn't be a hard error if this API request fails.
let carthageVersion = fetchLatestCarthageVersion() | ||
|
||
if carthageVersion.shouldUpgrade() == true { | ||
print("Please update to the latest Carthage version: \(carthageVersion.remoteVersion). You currently are on \(carthageVersion.localVersion)") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use carthage.println
here to format and color this text. (See Formatting.swift
.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are lots of style violations. I could swear the repo had SwiftLint (I can work on adding it), but in the mean time can you fix them by hand?
/// Attempts to create an instance of NSScanner and then use the convenience | ||
/// function specified in the protocol | ||
static public func fromString(string: String) -> Result<Self, CarthageError> | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should go on the previous line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
import Result | ||
import Tentacle | ||
|
||
public struct CarthageVersion{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space before {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
public struct CarthageVersion{ | ||
|
||
public let localVersion:SemanticVersion | ||
public let remoteVersion:SemanticVersion |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spaces after :
. Didn't SwiftLint
catch these?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
BTW, I activated SwiftLint and got ˜15000 issues :D in the project. I think that it isn't being used.
public let remoteVersion:SemanticVersion | ||
|
||
public init (localVersion: SemanticVersion, remoteVersion:SemanticVersion){ | ||
self.localVersion = localVersion |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No space before (
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
.attemptMap { (release) -> Result<SemanticVersion, CarthageError> in | ||
return SemanticVersion.fromString(release.tag) | ||
} | ||
.timeoutWithError(CarthageError.GitHubAPITimeout, afterInterval: 0.1, onScheduler: QueueScheduler.mainQueueScheduler) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just 0.1s?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated the value to 3 seconds. Thanks for catching this.
return SemanticVersion.fromString(release.tag) | ||
} | ||
.timeoutWithError(CarthageError.GitHubAPITimeout, afterInterval: 0.1, onScheduler: QueueScheduler.mainQueueScheduler) | ||
.first() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm why make this blocking?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because we want to validate first Carthage version before doing any task. In case their version is behind, we let know right away about that.
|
||
let formatting = ColorOptions.Formatting(true) | ||
|
||
carthage.println(formatting.bullets + "Please update to the latest Carthage version: \(carthageVersion.remoteVersion). You currently are on \(carthageVersion.localVersion)") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏼
self.remoteVersion = remoteVersion | ||
} | ||
|
||
func shouldUpgrade() ->Bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
func shouldUpgrade() ->Bool { | ||
|
||
if localVersion < remoteVersion { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is redundant, can just return localVersion < remoteVersion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Woah - totally agree. Thanks for catching this.
public let localVersion:SemanticVersion | ||
public let remoteVersion:SemanticVersion | ||
|
||
public init (localVersion: SemanticVersion, remoteVersion:SemanticVersion){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
return releases.first! | ||
} | ||
.mapError(CarthageError.GitHubAPIRequestFailed) | ||
.attemptMap { (release) -> Result<SemanticVersion, CarthageError> in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be
.map { $0.tag }
.attemptMap(SemanticVersion.fromString)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that the more verbose version is easier to understand. @mdiep what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd go with @NachoSoto's suggestion. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried this suggestion and seems that there is an issue with the inferrer based on the $0.tag
value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great! Almost there!
.attemptMap { (release) -> Result<SemanticVersion, CarthageError> in | ||
return SemanticVersion.fromString(release.tag) | ||
} | ||
.timeoutWithError(CarthageError.GitHubAPITimeout, afterInterval: 3, onScheduler: QueueScheduler.mainQueueScheduler) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This timeout should be much lower. I wouldn't want to keep users waiting for 3 seconds on every carthage
invocation. Maybe 0.5
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
func shouldUpgrade() -> Bool { | ||
return localVersion < remoteVersion | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this struct gets us anything. Lets get rid of it and just use localVersion
and remoteVersion
directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
@@ -20,6 +20,15 @@ guard ensureGitVersion().first()?.value == true else { | |||
exit(EXIT_FAILURE) | |||
} | |||
|
|||
let carthageVersion = fetchLatestCarthageVersion() | |||
|
|||
if carthageVersion.shouldUpgrade() == true { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the changes I've suggested, this would become:
if let remoteVersion = remoteVersion() where localVersion() < remoteVersion {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
.timeoutWithError(CarthageError.GitHubAPITimeout, afterInterval: 3, onScheduler: QueueScheduler.mainQueueScheduler) | ||
.first() | ||
|
||
return latestRemoteVersion!.value! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This definitely shouldn't use !
. This feature is optional, so if GitHub goes down, carthage
shouldn't become unusable. The function return a SemanticVersion?
and this should be return latestRemoveVersion?.value
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done!
🚢 |
Verifies if the local version of Carthage is up to date.
It should solve #1181 and #1130
Credits also to @mdiep for his help!