Add simple update checker to Gitea (#17212)

* Add simple update checker to Gitea

* update struct and remove comments

* fix lint

* Update custom/conf/app.example.ini

* Update docs/content/doc/advanced/config-cheat-sheet.en-us.md

Co-authored-by: delvh <dev.lh@web.de>

* Update custom/conf/app.example.ini

Co-authored-by: delvh <dev.lh@web.de>

* Update docs/content/doc/advanced/config-cheat-sheet.en-us.md

Co-authored-by: delvh <dev.lh@web.de>

* Update docs/content/doc/advanced/config-cheat-sheet.en-us.md

Co-authored-by: Steven <61625851+justusbunsi@users.noreply.github.com>

* Update docs/content/doc/advanced/config-cheat-sheet.en-us.md

* Update modules/cron/tasks_extended.go

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

* Update custom/conf/app.example.ini

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

* take PR feedback into account and display banner on admin dashboard for alerts

* Add more detailed message

* placate lint

* update per feedback

Co-authored-by: delvh <dev.lh@web.de>
Co-authored-by: Steven <61625851+justusbunsi@users.noreply.github.com>
Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
techknowlogick 2021-10-16 02:14:34 -04:00 committed by GitHub
parent e18ea9e349
commit 8edda8b446
Signed by: GitHub
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 195 additions and 3 deletions

@ -1925,6 +1925,19 @@ PATH =
;SCHEDULE = @every 168h
;OLDER_THAN = 8760h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Check for new Gitea versions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;[cron.update_checker]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;ENABLED = false
;RUN_AT_START = false
;ENABLE_SUCCESS_NOTICE = false
;SCHEDULE = @every 168h
;HTTP_ENDPOINT = https://dl.gitea.io/gitea/version.json
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Git Operation timeout in seconds

@ -23,8 +23,8 @@ or any corresponding location. When installing from a distribution, this will
typically be found at `/etc/gitea/conf/app.ini`.
The defaults provided here are best-effort (not built automatically). They are
accurately recorded in [app.example.ini](https://github.com/go-gitea/gitea/blob/master/custom/conf/app.example.ini)
(s/master/\<tag|release\>). Any string in the format `%(X)s` is a feature powered
accurately recorded in [app.example.ini](https://github.com/go-gitea/gitea/blob/main/custom/conf/app.example.ini)
(s/main/\<tag|release\>). Any string in the format `%(X)s` is a feature powered
by [ini](https://github.com/go-ini/ini/#recursive-values), for reading values recursively.
Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
@ -824,9 +824,16 @@ NB: You must have `DISABLE_ROUTER_LOG` set to `false` for this option to take ef
- `ENABLED`: **false**: Enable service.
- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
- `NO_SUCCESS_NOTICE`: **false**: Set to true to switch off success notices.
- `SCHEDULE`: **@every 128h**: Cron syntax for scheduling a work, e.g. `@every 128h`.
- `SCHEDULE`: **@every 168h**: Cron syntax to set how often to check.
- `OLDER_THAN`: **@every 8760h**: any action older than this expression will be deleted from database, suggest using `8760h` (1 year) because that's the max length of heatmap.
#### Cron - Check for new Gitea versions ('cron.update_checker')
- `ENABLED`: **false**: Enable service.
- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
- `ENABLE_SUCCESS_NOTICE`: **true**: Set to false to switch off success notices.
- `SCHEDULE`: **@every 168h**: Cron syntax for scheduling a work, e.g. `@every 168h`.
- `HTTP_ENDPOINT`: **https://dl.gitea.io/gitea/version.json**: the endpoint that Gitea will check for newer versions
## Git (`git`)
- `PATH`: **""**: The path of git executable. If empty, Gitea searches through the PATH environment.

@ -350,6 +350,8 @@ var migrations = []Migration{
NewMigration("Add renamed_branch table", addRenamedBranchTable),
// v198 -> v199
NewMigration("Add issue content history table", addTableIssueContentHistory),
// v199 -> v200
NewMigration("Add remote version table", addRemoteVersionTable),
}
// GetCurrentDBVersion returns the current db version

23
models/migrations/v199.go Normal file

@ -0,0 +1,23 @@
// 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)
}
return nil
}

121
models/update_checker.go Normal file

@ -0,0 +1,121 @@
// 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 {
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
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)
if err != nil {
return err
}
return UpdateRemoteVersion(ver.Latest.Version)
}
// UpdateRemoteVersion updates the latest available version of Gitea
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 = 1
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 (or currently installed verson if fail to fetch from DB)
func GetRemoteVersion() string {
e := db.GetEngine(db.DefaultContext)
v := &RemoteVersion{ID: 1}
_, err := e.Get(&v)
if err != nil {
// return current version if fail to fetch from DB
return setting.AppVer
}
return v.Version
}
// GetNeedUpdate returns true whether a newer version of Gitea is available
func GetNeedUpdate() bool {
curVer, err := version.NewVersion(setting.AppVer)
if err != nil {
// return false to fail silently
return false
}
remoteVer, err := version.NewVersion(GetRemoteVersion())
if err != nil {
// return false to fail silently
return false
}
return curVer.LessThan(remoteVer)
}

@ -131,6 +131,24 @@ func registerDeleteOldActions() {
})
}
func registerUpdateGiteaChecker() {
type UpdateCheckerConfig struct {
BaseConfig
HTTPEndpoint string
}
RegisterTaskFatal("update_checker", &UpdateCheckerConfig{
BaseConfig: BaseConfig{
Enabled: true,
RunAtStart: false,
Schedule: "@every 168h",
},
HTTPEndpoint: "https://dl.gitea.io/gitea/version.json",
}, func(ctx context.Context, _ *models.User, config Config) error {
updateCheckerConfig := config.(*UpdateCheckerConfig)
return models.GiteaUpdateChecker(updateCheckerConfig.HTTPEndpoint)
})
}
func initExtendedTasks() {
registerDeleteInactiveUsers()
registerDeleteRepositoryArchives()
@ -142,4 +160,5 @@ func initExtendedTasks() {
registerDeleteMissingRepositories()
registerRemoveRandomAvatars()
registerDeleteOldActions()
registerUpdateGiteaChecker()
}

@ -125,6 +125,8 @@ func Dashboard(ctx *context.Context) {
ctx.Data["PageIsAdmin"] = true
ctx.Data["PageIsAdminDashboard"] = true
ctx.Data["Stats"] = models.GetStatistic()
ctx.Data["NeedUpdate"] = models.GetNeedUpdate()
ctx.Data["RemoteVersion"] = models.GetRemoteVersion()
// FIXME: update periodically
updateSystemStatus()
ctx.Data["SysStatus"] = sysStatus

@ -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>
</div>
{{end}}
<h4 class="ui top attached header">
{{.i18n.Tr "admin.dashboard.statistic"}}
</h4>