2017-08-09 16:12:24 +02:00
package iris
import (
2017-08-10 14:21:42 +02:00
"encoding/json"
2017-10-26 01:48:16 +02:00
"fmt"
2017-08-09 16:12:24 +02:00
"io/ioutil"
2017-08-10 14:21:42 +02:00
"net/url"
2017-08-09 16:12:24 +02:00
"os"
"os/exec"
"sync"
"time"
"github.com/kataras/golog"
2017-08-10 14:21:42 +02:00
"github.com/kataras/iris/core/netutil"
2017-10-26 01:48:16 +02:00
"github.com/kataras/survey"
"github.com/skratchdot/open-golang/open"
2017-08-09 16:12:24 +02:00
)
var checkVersionOnce = sync . Once { }
// CheckVersion checks for any available updates.
func CheckVersion ( ) {
checkVersionOnce . Do ( func ( ) {
checkVersion ( )
} )
}
2017-08-10 14:21:42 +02:00
type versionInfo struct {
Version string ` json:"version" `
ChangelogURL string ` json:"changelog_url" `
UpdateAvailable bool ` json:"update_available" `
2017-10-26 01:48:16 +02:00
FirstTime bool ` json:"first_time" `
2017-08-10 14:21:42 +02:00
}
2017-08-09 16:12:24 +02:00
2017-08-10 14:21:42 +02:00
func checkVersion ( ) {
2017-10-26 04:10:40 +02:00
client := netutil . Client ( 25 * time . Second )
2017-08-26 19:12:57 +02:00
r , err := client . PostForm ( "https://iris-go.com/version" , url . Values { "current_version" : { Version } } )
2017-08-09 16:12:24 +02:00
if err != nil {
golog . Debugf ( "%v" , err )
return
}
defer r . Body . Close ( )
if r . StatusCode >= 400 {
return
}
b , err := ioutil . ReadAll ( r . Body )
if len ( b ) == 0 || err != nil {
golog . Debugf ( "%v" , err )
return
}
2017-08-10 14:21:42 +02:00
v := new ( versionInfo )
if err := json . Unmarshal ( b , v ) ; err != nil {
golog . Debugf ( "error while unmarshal the response body: %v" , err )
2017-08-09 16:12:24 +02:00
return
}
2017-10-26 01:48:16 +02:00
var qs [ ] * survey . Question
// on help? when asking for installing the new update
// and when answering "No".
ignoreUpdatesMsg := "Would you like to ignore future updates? Disable the version checker via:\napp.Run(..., iris.WithoutVersionChecker)"
if v . UpdateAvailable {
// if update available ask for update action.
shouldUpdateNowMsg :=
fmt . Sprintf ( "A new version is available online[%s > %s].\nRelease notes: %s.\nUpdate now?" ,
v . Version , Version ,
v . ChangelogURL )
qs = append ( qs , & survey . Question {
Name : "shouldUpdateNow" ,
Prompt : & survey . Confirm {
Message : shouldUpdateNowMsg ,
Help : ignoreUpdatesMsg ,
} ,
Validate : survey . Required ,
} )
2017-08-09 16:12:24 +02:00
}
2017-10-26 01:48:16 +02:00
// firs time and update available is not relative because if no update often server will decide when to ask this,
// so separate the actions and if statements here.
if v . FirstTime {
// if first time that this server was updated then ask if enjoying the framework.
qs = append ( qs , & survey . Question {
Name : "enjoyingIris" ,
Prompt : & survey . Confirm {
Message : "Enjoying Iris Framework?" ,
Help : "yes or no" ,
} ,
Validate : survey . Required ,
} )
}
2017-08-10 14:21:42 +02:00
2017-10-26 01:48:16 +02:00
// Ask if should update(if available) and enjoying iris(if first time) in the same survey.
ans := struct {
ShouldUpdateNow bool ` survey:"shouldUpdateNow" `
EnjoyingIris bool ` survey:"enjoyingIris" `
} { }
survey . Ask ( qs , & ans )
if ans . EnjoyingIris {
// if the answer to the previous survey about enjoying the framework
// was positive then do the survey (currently only one question and its action).
qs2 := [ ] * survey . Question {
{
Name : "starNow" ,
Prompt : & survey . Confirm {
Message : "Would you mind giving us a star on GitHub? It really helps us out! Thanks for your support:)" ,
Help : "Its free so let's do that, type 'y'" ,
} ,
Validate : survey . Required ,
} ,
/* any future questions should be here, at this second survey. */
}
ans2 := struct {
StarNow bool ` survey:"starNow" `
} { }
survey . Ask ( qs2 , & ans2 )
if ans2 . StarNow {
starRepo := "https://github.com/kataras/iris/stargazers"
if err := open . Run ( starRepo ) ; err != nil {
golog . Warnf ( "tried to open the browser for you but failed, please give us a star at: %s\n" , starRepo )
2017-08-09 16:12:24 +02:00
}
}
}
2017-10-26 01:48:16 +02:00
// run the updater last, so the user can star the repo and at the same time
// the app will update her/his local iris.
if ans . ShouldUpdateNow { // it's true only when update was available and user typed "yes".
2017-08-19 21:54:13 +02:00
repo := "github.com/kataras/iris/..."
cmd := exec . Command ( "go" , "get" , "-u" , "-v" , repo )
2017-08-09 16:12:24 +02:00
cmd . Stdout = os . Stdout
cmd . Stderr = os . Stdout
if err := cmd . Run ( ) ; err != nil {
2017-08-19 21:54:13 +02:00
golog . Warnf ( "unexpected message while trying to go get,\nif you edited the original source code then you've to remove the whole $GOPATH/src/github.com/kataras folder and execute `go get -u github.com/kataras/iris/...` manually\n%v" , err )
2017-08-09 16:12:24 +02:00
return
}
2017-10-26 01:48:16 +02:00
golog . Infof ( "Update process finished.\nManual rebuild and restart is required to apply the changes...\n" )
2017-10-26 04:10:40 +02:00
} else if v . UpdateAvailable { // if update was available but choosen not to update.
2017-10-26 01:48:16 +02:00
golog . Infof ( ignoreUpdatesMsg )
2017-08-09 16:12:24 +02:00
}
}