Run the version check in parallel (#3441)

I noticed that we block startup on performing the version check.
Although we cache the latest version from the server for 24 hours,
this check also runs the `brew --prefix pulumi` command which
(at least for me) takes between 0.5-1s on average. Thus, running it
in parallel, which requires no shared state, saves us that amount
of time in the end to end execution time. Notably, this shortens the
amount of time from command start to the first "previewing..." message.

This does change the user experience: rather than reporting the
new version up front, we report it at the end after running the
requested command (both on success and failure). This is what I'd
have assumed we'd want anyway, and what many other tools do, but
it's entirely reasonable if folks object to the change in UX.
This commit is contained in:
Joe Duffy 2019-11-06 13:44:27 -05:00 committed by GitHub
parent 1ad7e80624
commit 9b1df6f9e6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 5 deletions

View file

@ -6,6 +6,8 @@ CHANGELOG
- Gracefully handle errors when resources use duplicate aliases.
- Use the update token for renew_lease calls and update the API version to 5.
[#3348](https://github.com/pulumi/pulumi/pull/3348)
- Improve startup time performance by 0.5-1s by checking for a newer CLI release in parallel.
[#3441](https://github.com/pulumi/pulumi/pull/3441)
## 1.4.1 (2019-11-01)

View file

@ -60,6 +60,8 @@ func NewPulumiCmd() *cobra.Command {
var verbose int
var color string
updateCheckResult := make(chan *diag.Diag)
cmd := &cobra.Command{
Use: "pulumi",
Short: "Pulumi command line",
@ -115,13 +117,24 @@ func NewPulumiCmd() *cobra.Command {
if cmdutil.IsTruthy(os.Getenv("PULUMI_SKIP_UPDATE_CHECK")) {
logging.Infof("skipping update check")
close(updateCheckResult)
} else {
checkForUpdate()
// Run the version check in parallel so that it doesn't block executing the command.
// If there is a new version to report, we will do so after the command has finished.
go func() {
updateCheckResult <- checkForUpdate()
close(updateCheckResult)
}()
}
return nil
}),
PersistentPostRun: func(cmd *cobra.Command, args []string) {
// Before exiting, if there is a new version of the CLI available, print it out.
if checkVersionMsg := <-updateCheckResult; checkVersionMsg != nil {
cmdutil.Diag().Warningf(checkVersionMsg)
}
logging.Flush()
cmdutil.CloseTracing()
@ -130,7 +143,6 @@ func NewPulumiCmd() *cobra.Command {
logging.Warningf("could not close profiling: %v", err)
}
}
},
}
@ -200,7 +212,7 @@ func NewPulumiCmd() *cobra.Command {
// checkForUpdate checks to see if the CLI needs to be updated, and if so emits a warning, as well as information
// as to how it can be upgraded.
func checkForUpdate() {
func checkForUpdate() *diag.Diag {
curVer, err := semver.ParseTolerant(version.Version)
if err != nil {
logging.V(3).Infof("error parsing current version: %s", err)
@ -208,7 +220,7 @@ func checkForUpdate() {
// We don't care about warning for you to update if you have installed a developer version
if isDevVersion(curVer) {
return
return nil
}
latestVer, oldestAllowedVer, err := getCLIVersionInfo()
@ -217,8 +229,10 @@ func checkForUpdate() {
}
if oldestAllowedVer.GT(curVer) {
cmdutil.Diag().Warningf(diag.RawMessage("", getUpgradeMessage(latestVer, curVer)))
return diag.RawMessage("", getUpgradeMessage(latestVer, curVer))
}
return nil
}
// getCLIVersionInfo returns information about the latest version of the CLI and the oldest version that should be