-
-
Notifications
You must be signed in to change notification settings - Fork 398
Add ways to let users verify if new CLI released #1416
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
Changes from 7 commits
8e5f74c
ca10595
fd1bc79
ca4c678
2991e9f
78a8ba4
7f6a897
cf4d75a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
// This file is part of arduino-cli. | ||
// | ||
// Copyright 2020 ARDUINO SA (http://www.arduino.cc/) | ||
// | ||
// This software is released under the GNU General Public License version 3, | ||
// which covers the main part of arduino-cli. | ||
// The terms of this license can be found at: | ||
// https://www.gnu.org/licenses/gpl-3.0.en.html | ||
// | ||
// You can be released from the requirements of the above licenses by purchasing | ||
// a commercial license. Buying such a license is mandatory if you want to | ||
// modify or otherwise use the software for commercial activities involving the | ||
// Arduino software without disclosing the source code of your own applications. | ||
// To purchase a commercial license, send an email to [email protected]. | ||
|
||
package updater | ||
|
||
import ( | ||
"os" | ||
"strings" | ||
"time" | ||
|
||
"github.com/arduino/arduino-cli/cli/feedback" | ||
"github.com/arduino/arduino-cli/cli/globals" | ||
"github.com/arduino/arduino-cli/configuration" | ||
"github.com/arduino/arduino-cli/httpclient" | ||
"github.com/arduino/arduino-cli/i18n" | ||
"github.com/arduino/arduino-cli/inventory" | ||
"github.com/fatih/color" | ||
semver "go.bug.st/relaxed-semver" | ||
) | ||
|
||
var tr = i18n.Tr | ||
|
||
// CheckForUpdate returns the latest available version if greater than | ||
// the one running and it makes sense to check for an update, nil in all other cases | ||
func CheckForUpdate(currentVersion *semver.Version) *semver.Version { | ||
if !shouldCheckForUpdate(currentVersion) { | ||
return nil | ||
} | ||
|
||
return checkForUpdate(currentVersion) | ||
} | ||
|
||
// ForceCheckForUpdate always returns the latest available version if greater than | ||
// the one running, nil in all other cases | ||
func ForceCheckForUpdate(currentVersion *semver.Version) *semver.Version { | ||
return checkForUpdate(currentVersion) | ||
} | ||
|
||
func checkForUpdate(currentVersion *semver.Version) *semver.Version { | ||
silvanocerza marked this conversation as resolved.
Show resolved
Hide resolved
|
||
defer func() { | ||
// Always save the last time we checked for updates at the end | ||
inventory.Store.Set("updater.last_check_time", time.Now()) | ||
inventory.WriteStore() | ||
}() | ||
|
||
latestVersion, err := semver.Parse(getLatestRelease()) | ||
if err != nil { | ||
return nil | ||
} | ||
|
||
if currentVersion.GreaterThanOrEqual(latestVersion) { | ||
// Current version is already good enough | ||
return nil | ||
} | ||
|
||
return latestVersion | ||
} | ||
|
||
// NotifyNewVersionIsAvailable prints information about the new latestVersion | ||
func NotifyNewVersionIsAvailable(latestVersion string) { | ||
feedback.Errorf("\n\n%s %s → %s\n%s", | ||
color.YellowString(tr("A new release of Arduino CLI is available:")), | ||
color.CyanString(globals.VersionInfo.VersionString), | ||
color.CyanString(latestVersion), | ||
color.YellowString("https://arduino.github.io/arduino-cli/latest/installation/#latest-packages")) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this URL going to stay? Will it move at some point from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ideally we'll change it in the future when the Arduino CLI will be added to https://www.arduino.cc/en/software. |
||
} | ||
|
||
// shouldCheckForUpdate return true if it actually makes sense to check for new updates, | ||
// false in all other cases. | ||
func shouldCheckForUpdate(currentVersion *semver.Version) bool { | ||
if strings.Contains(currentVersion.String(), "git-snapshot") || strings.Contains(currentVersion.String(), "nightly") { | ||
// This is a dev build, no need to check for updates | ||
return false | ||
} | ||
|
||
if !configuration.Settings.GetBool("updater.enable_notification") { | ||
// Don't check if the user disabled the notification | ||
return false | ||
} | ||
|
||
if inventory.Store.IsSet("updater.last_check_time") && time.Since(inventory.Store.GetTime("updater.last_check_time")).Hours() < 24 { | ||
// Checked less than 24 hours ago, let's wait | ||
return false | ||
} | ||
|
||
// Don't check when running on CI or on non interactive consoles | ||
return !isCI() && configuration.IsInteractive && configuration.HasConsole | ||
} | ||
|
||
// based on https://github.com/watson/ci-info/blob/HEAD/index.js | ||
func isCI() bool { | ||
return os.Getenv("CI") != "" || // GitHub Actions, Travis CI, CircleCI, Cirrus CI, GitLab CI, AppVeyor, CodeShip, dsari | ||
os.Getenv("BUILD_NUMBER") != "" || // Jenkins, TeamCity | ||
os.Getenv("RUN_ID") != "" // TaskCluster, dsari | ||
} | ||
|
||
// getLatestRelease queries the official Arduino download server for the latest release, | ||
// if there are no errors or issues a version string is returned, in all other case an empty string. | ||
func getLatestRelease() string { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can make this function return a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think that would help that much, this Don't seem much of an improvement to me really. 🤔 |
||
client, err := httpclient.New() | ||
if err != nil { | ||
return "" | ||
} | ||
|
||
// We just use this URL to check if there's a new release available and | ||
// never show it to the user, so it's fine to use the Linux one for all OSs. | ||
URL := "https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_Linux_64bit.tar.gz" | ||
res, err := client.Head(URL) | ||
if err != nil { | ||
// Yes, we ignore it | ||
return "" | ||
} | ||
|
||
// Get redirected URL | ||
location := res.Request.URL.String() | ||
|
||
// The location header points to the the latest release of the CLI, it's supposed to be formatted like this: | ||
// https://downloads.arduino.cc/arduino-cli/arduino-cli_0.18.3_Linux_64bit.tar.gz | ||
// so we split it to get the version, if there are not enough splits something must have gone wrong. | ||
split := strings.Split(location, "_") | ||
if len(split) < 2 { | ||
return "" | ||
} | ||
|
||
return split[1] | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -17,11 +17,15 @@ package version | |||||||||||||
|
||||||||||||||
import ( | ||||||||||||||
"os" | ||||||||||||||
"strings" | ||||||||||||||
|
||||||||||||||
"github.com/arduino/arduino-cli/cli/errorcodes" | ||||||||||||||
"github.com/arduino/arduino-cli/cli/feedback" | ||||||||||||||
"github.com/arduino/arduino-cli/cli/globals" | ||||||||||||||
"github.com/arduino/arduino-cli/cli/updater" | ||||||||||||||
"github.com/arduino/arduino-cli/i18n" | ||||||||||||||
"github.com/spf13/cobra" | ||||||||||||||
semver "go.bug.st/relaxed-semver" | ||||||||||||||
) | ||||||||||||||
|
||||||||||||||
var tr = i18n.Tr | ||||||||||||||
|
@@ -39,5 +43,29 @@ func NewCommand() *cobra.Command { | |||||||||||||
} | ||||||||||||||
|
||||||||||||||
func run(cmd *cobra.Command, args []string) { | ||||||||||||||
feedback.Print(globals.VersionInfo) | ||||||||||||||
if strings.Contains(globals.VersionInfo.VersionString, "git-snapshot") || strings.Contains(globals.VersionInfo.VersionString, "nightly") { | ||||||||||||||
// We're using a development version, no need to check if there's a | ||||||||||||||
// new release available | ||||||||||||||
feedback.Print(globals.VersionInfo) | ||||||||||||||
return | ||||||||||||||
} | ||||||||||||||
Comment on lines
+46
to
+51
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know if this is sensible here... I'd leave the
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't, it would fail because |
||||||||||||||
|
||||||||||||||
currentVersion, err := semver.Parse(globals.VersionInfo.VersionString) | ||||||||||||||
if err != nil { | ||||||||||||||
feedback.Errorf("Error parsing current version: %s", err) | ||||||||||||||
os.Exit(errorcodes.ErrGeneric) | ||||||||||||||
} | ||||||||||||||
latestVersion := updater.ForceCheckForUpdate(currentVersion) | ||||||||||||||
|
||||||||||||||
versionInfo := globals.VersionInfo | ||||||||||||||
if feedback.GetFormat() == feedback.JSON && latestVersion != nil { | ||||||||||||||
// Set this only we managed to get the latest version | ||||||||||||||
versionInfo.LatestVersion = latestVersion.String() | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
feedback.Print(versionInfo) | ||||||||||||||
|
||||||||||||||
if feedback.GetFormat() == feedback.Text && latestVersion != nil { | ||||||||||||||
updater.NotifyNewVersionIsAvailable(latestVersion.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.
Is VersionString supposed to be always semver compliant? if yes you can use
semver.MustParse
to avoid checking the errorThere 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.
It's not always semver compliant, it can also be
git-snapshot
ornightly-<timestamp>
so I can't usesemver.MustParse
.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.
Shouldn't those versions be changed to
0.0.0-git
or0.0.0-nightly-<timestamp>
?These non-semver versions plugged in feels "wrong" to me...
Also we already had:
in
version.go
IMHO we should follow the same pattern and force semver compliance.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 get what you mean but probably would be better if done in a separate PR.