Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 53 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,39 @@ To install via Winget, run:
winget install Twitch.TwitchCLI
```

To update, run:
### Manual Download

To download, go to the [Releases tab of GitHub](https://github.com/twitchdev/twitch-cli/releases). The examples in the documentation assume you have put this into your PATH and renamed to `twitch` (or symlinked as such).

**Note**: If using MacOS and downloading manually, you may need to adjust the permissions of the file to allow for execution.

To do so, please run: `chmod 755 <filename>` where the filename is the name of the downloaded binary.

## Updating

To update the Twitch CLI, run the command relevant to your installation method.

**NOTE:** Once a day the program will make an HTTP call to Github to check if the application is of the latest version. For information on disabling this, see *Disabling release version checks and notices* below.

### Homebrew

To update using Homebrew, run:

```sh
brew upgrade twitchdev/twitch/twitch-cli
```

### Scoop

To update using Scoop, run:

```sh
scoop update twitch-cli
```

### WinGet

To update using WinGet, run:

```sh
winget update Twitch.TwitchCLI
Expand All @@ -56,7 +88,26 @@ To download, go to the [Releases tab of GitHub](https://github.com/twitchdev/twi

**Note**: If using MacOS and downloading manually, you may need to adjust the permissions of the file to allow for execution.

To do so, please run: `chmod 755 <filename>` where the filename is the name of the downloaded binary.
To do so, please run: `chmod 755 <filename>` where the filename is the name of the downloaded binary.

## Disabling release version checks and notices

When the Twitch CLI exits successfully, the application will automatically check the Twitch CLI's Github releases at the following URL:

```
https://api.github.com/repos/twitchdev/twitch-cli/releases/latest
```

If the version of the Twitch CLI you are running is older than the latest released version, a notice will be printed to the console.

To prevent this from happening, make one of the following changes:

- Set the environment variable `CI` to `true`
- Set the environment variable `TWITCH_DISABLE_UPDATE_CHECKS` to `true`
- Add `DISABLE_UPDATE_CHECKS=true` to your **.twitch-cli.env** configuration file
- SET `LAST_UPDATE_CHECK` to `3000-01-01` in your **.twitch-cli.env** configuration file, which will prevent it from running until the year 3000

If you're running the Twitch CLI in a CI/CD environment, most environments will have already set the `CI` environment variable to `true`.

## Usage

Expand Down
4 changes: 4 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@ var rootCmd = &cobra.Command{
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
// Execute normally; Exit without checking for updates if there's an error.
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}

// Check Github's Releases API to see if we're running the latest version.
util.CheckForUpdatesAndPrintNotice()
}

func init() {
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ require (
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hokaccha/go-prettyjson v0.0.0-20201222001619-a42f9ac2ec8e // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
Expand Down
3 changes: 2 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerX
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
Expand Down Expand Up @@ -149,7 +151,6 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
Expand Down
132 changes: 132 additions & 0 deletions internal/util/version_checker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package util

import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"regexp"
"strings"
"time"

"github.com/fatih/color"
"github.com/spf13/viper"

vrs "github.com/hashicorp/go-version"
)

type updateCheckerReleasesResponse struct {
// Only thing we really care about here is the tag name
TagName string `json:"tag_name"`
}

// Check Github's Releases API to see if we're running the latest version.
// If there's any errors, quietly allow it to fail.
func CheckForUpdatesAndPrintNotice() {
// Don't bother running this if current application is built from source
if strings.EqualFold(GetVersion(), "source") {
return
}

// Don't run if program is running in CI/CD (CI env variable will be set), or if TWITCH_DISABLE_UPDATE_CHECKS is set to true.
if viper.GetBool("disable_update_checks") || strings.EqualFold(os.Getenv("CI"), "true") {
return
}

// Don't run if this already ran successfully today
today, _ := time.Parse(time.DateOnly, time.Now().Format(time.DateOnly))
lastRunDate, _ := time.Parse(time.DateOnly, viper.GetString("last_update_check"))
if !today.After(lastRunDate) {
return
}

runningLatestVersion, latestVersionTag, err := areWeRunningLatestVersion()
if err != nil {
return // Drop errors without notifying
}

if !runningLatestVersion {
// Messages to be displayed
messages := []string{
" A new Twitch CLI release is available: " + latestVersionTag + " ",
"",
" See upgrade instructions at: ",
" https://github.com/twitchdev/twitch-cli/blob/main/README.md#updating ",
"",
" Check out the release notes at: ",
" https://github.com/twitchdev/twitch-cli/releases/latest ",
}

// Find longest message
longestMessageLength := 0
for _, str := range messages {
if len(str) > longestMessageLength {
longestMessageLength = len(str)
}
}

// Print messages
shaded := color.New(color.BgWhite, color.FgBlack).SprintfFunc()

fmt.Println()
for _, str := range messages {
fmt.Printf(" %v\n", shaded(str+strings.Repeat(" ", longestMessageLength-len(str))))
}
fmt.Println()

// Update config so this isn't repeated until tomorrow
viper.Set("last_update_check", GetTimestamp().Format(time.DateOnly))
configPath, err := GetConfigPath()
if err != nil {
return
}
_ = viper.WriteConfigAs(configPath)
}
}

// Makes the call to Github's Releases API to check for the latest release version, and compares it to the current version.
func areWeRunningLatestVersion() (bool, string, error) {
REGEX_TAG_NAME_VERSION := regexp.MustCompile("^(?:v)(.+)") // Removes the v from the start of the tag, if it exists

client := &http.Client{
Timeout: time.Second * 2,
}

req, err := http.NewRequest("GET", "https://api.github.com/repos/twitchdev/twitch-cli/releases/latest", nil)
if err != nil {
return false, "", err
}
req.Header.Set("User-Agent", "twitch-cli/"+GetVersion())

response, err := client.Do(req)
if err != nil {
return false, "", err
}
defer response.Body.Close()

body, err := io.ReadAll(response.Body)
if err != nil {
return false, "", err
}

var obj updateCheckerReleasesResponse
err = json.Unmarshal(body, &obj)
if err != nil {
return false, "", err
}

latestReleaseVersion, err := vrs.NewVersion(REGEX_TAG_NAME_VERSION.FindAllStringSubmatch(obj.TagName, -1)[0][1])
if err != nil {
return false, "", err
}

currentVersion, err := vrs.NewVersion(GetVersion())
if err != nil {
return false, "", err
}

return currentVersion.GreaterThanOrEqual(latestReleaseVersion), obj.TagName, nil
}