-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Add simple update checker to Gitea #17212
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 17 commits
e7467b5
b73aa6c
b6ef89b
5d13cb5
c1aa2fb
57dc076
6df9747
28c36c7
2fcd728
c1b875e
e67c006
b891967
fd13167
dd118f4
4e80fb0
0cfd1d8
13c631b
fc77ce3
0b2de8a
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,27 @@ | ||
// Copyright 2021 The Gitea Authors. All rights reserved. | ||
// Use of this source code is governed by a MIT-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package migrations | ||
|
||
import ( | ||
"fmt" | ||
|
||
"xorm.io/xorm" | ||
) | ||
|
||
func addRemoteVersionTable(x *xorm.Engine) error { | ||
type RemoteVersion struct { | ||
ID int64 `xorm:"pk autoincr"` | ||
Version string `xorm:"VARCHAR(50)"` | ||
} | ||
|
||
if err := x.Sync2(new(RemoteVersion)); err != nil { | ||
return fmt.Errorf("Sync2: %v", err) | ||
} | ||
|
||
remoteVersion := new(RemoteVersion) | ||
remoteVersion.Version = "0" | ||
_, err := x.Insert(remoteVersion) | ||
return err | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
// Copyright 2021 The Gitea Authors. All rights reserved. | ||
// Use of this source code is governed by a MIT-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package models | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io/ioutil" | ||
"net/http" | ||
|
||
"code.gitea.io/gitea/models/db" | ||
"code.gitea.io/gitea/modules/proxy" | ||
"code.gitea.io/gitea/modules/setting" | ||
|
||
"github.com/hashicorp/go-version" | ||
) | ||
|
||
// RemoteVersion stores the remote version from the JSON endpoint | ||
type RemoteVersion struct { | ||
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 also think store the version into database is unnecessary. Just send http request every check is better. 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 are storing in the database because we don't want to DDOS ourselves when everyone goes to admin dashboard. Even if we get beefy servers, the user dashboard will always be slower because an HTTP check would need to happen. By storing it in the DB we will eventually be able to add a check to send out an email to admins when a new update happens. 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. On option is storing the remote version into Gitea local cache in memory. Another option is using database (this PR). Both are fine to me. |
||
ID int64 `xorm:"pk autoincr"` | ||
Version string `xorm:"VARCHAR(50)"` | ||
} | ||
|
||
func init() { | ||
db.RegisterModel(new(RemoteVersion)) | ||
} | ||
|
||
// GiteaUpdateChecker returns error when new version of Gitea is available | ||
techknowlogick marked this conversation as resolved.
Show resolved
Hide resolved
|
||
func GiteaUpdateChecker(httpEndpoint string) error { | ||
httpClient := &http.Client{ | ||
Transport: &http.Transport{ | ||
Proxy: proxy.Proxy(), | ||
}, | ||
} | ||
|
||
req, err := http.NewRequest("GET", httpEndpoint, nil) | ||
if err != nil { | ||
return err | ||
} | ||
resp, err := httpClient.Do(req) | ||
if err != nil { | ||
return err | ||
} | ||
defer resp.Body.Close() | ||
body, err := ioutil.ReadAll(resp.Body) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
type v struct { | ||
Latest struct { | ||
Version string `json:"version"` | ||
} `json:"latest"` | ||
} | ||
ver := v{} | ||
err = json.Unmarshal(body, &ver) | ||
techknowlogick marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
return UpdateRemoteVersion(ver.Latest.Version) | ||
|
||
} | ||
|
||
// UpdateRemoteVersion marks someone be another's follower. | ||
techknowlogick marked this conversation as resolved.
Show resolved
Hide resolved
|
||
func UpdateRemoteVersion(version string) (err error) { | ||
sess := db.NewSession(db.DefaultContext) | ||
defer sess.Close() | ||
if err = sess.Begin(); err != nil { | ||
return err | ||
} | ||
|
||
currentVersion := &RemoteVersion{ID: 1} | ||
has, err := sess.Get(currentVersion) | ||
if err != nil { | ||
return fmt.Errorf("get: %v", err) | ||
} else if !has { | ||
currentVersion.ID = 0 | ||
techknowlogick marked this conversation as resolved.
Show resolved
Hide resolved
|
||
currentVersion.Version = version | ||
|
||
if _, err = sess.InsertOne(currentVersion); err != nil { | ||
return fmt.Errorf("insert: %v", err) | ||
} | ||
return nil | ||
} | ||
|
||
if _, err = sess.Update(&RemoteVersion{ID: 1, Version: version}); err != nil { | ||
return err | ||
} | ||
|
||
return sess.Commit() | ||
} | ||
|
||
// GetRemoteVersion returns the current remote version | ||
func GetRemoteVersion() string { | ||
techknowlogick marked this conversation as resolved.
Show resolved
Hide resolved
|
||
e := db.GetEngine(db.DefaultContext) | ||
v := &RemoteVersion{ID: 1} | ||
_, err := e.Get(&v) | ||
if err != nil { | ||
// return 0 if fail to get fetch from DB, so it fails silently | ||
techknowlogick marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return "0" | ||
techknowlogick marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
return v.Version | ||
} | ||
|
||
// GetNeedUpdate returns true if there is an update needed of Gitea | ||
func GetNeedUpdate() bool { | ||
techknowlogick marked this conversation as resolved.
Show resolved
Hide resolved
|
||
e := db.GetEngine(db.DefaultContext) | ||
v := &RemoteVersion{ID: 1} | ||
_, err := e.Get(&v) | ||
if err != nil { | ||
// return false if fail to get fetch from DB, so it fails silently | ||
return false | ||
} | ||
|
||
giteaVersion, err := version.NewVersion(setting.AppVer) | ||
if err != nil { | ||
// return false to fail silently | ||
return false | ||
} | ||
updateVersion, err := version.NewVersion(v.Version) | ||
if err != nil { | ||
// return false to fail silently | ||
return false | ||
} | ||
if giteaVersion.LessThan(updateVersion) { | ||
return true | ||
} | ||
|
||
return false | ||
techknowlogick marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,11 @@ | |
{{template "admin/navbar" .}} | ||
<div class="ui container"> | ||
{{template "base/alert" .}} | ||
{{if .NeedUpdate}} | ||
<div class="ui negative message flash-error"> | ||
<p>"Gitea {{.RemoteVersion | Str2html}} is now available, you are running {{.AppVer | Str2html}}. Check the <a href="https://blog.gitea.io">blog</a> for more details.</p> | ||
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. i18n? |
||
</div> | ||
{{end}} | ||
<h4 class="ui top attached header"> | ||
{{.i18n.Tr "admin.dashboard.statistic"}} | ||
</h4> | ||
|
Uh oh!
There was an error while loading. Please reload this page.