Skip to content

Refactor update checker to use AppState #17387

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

Merged
merged 2 commits into from
Oct 21, 2021
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
4 changes: 3 additions & 1 deletion models/migrations/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,9 +351,11 @@ var migrations = []Migration{
// v198 -> v199
NewMigration("Add issue content history table", addTableIssueContentHistory),
// v199 -> v200
NewMigration("Add remote version table", addRemoteVersionTable),
NewMigration("No-op (remote version is using AppState now)", addRemoteVersionTableNoop),
// v200 -> v201
NewMigration("Add table app_state", addTableAppState),
// v201 -> v202
NewMigration("Drop table remote_version (if exists)", dropTableRemoteVersion),
}

// GetCurrentDBVersion returns the current db version
Expand Down
13 changes: 2 additions & 11 deletions models/migrations/v199.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,10 @@
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)
}
func addRemoteVersionTableNoop(x *xorm.Engine) error {
// we used to use a table `remote_version` to store information for updater, now we use `AppState`, so this migration task is a no-op now.
return nil
}
15 changes: 15 additions & 0 deletions models/migrations/v201.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// 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 (
"xorm.io/xorm"
)

func dropTableRemoteVersion(x *xorm.Engine) error {
// drop the orphaned table introduced in `v199`, now the update checker also uses AppState, do not need this table
_ = x.DropTables("remote_version")
return nil
}
3 changes: 2 additions & 1 deletion modules/cron/tasks_extended.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"code.gitea.io/gitea/models"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/updatechecker"
)

func registerDeleteInactiveUsers() {
Expand Down Expand Up @@ -145,7 +146,7 @@ func registerUpdateGiteaChecker() {
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)
return updatechecker.GiteaUpdateChecker(updateCheckerConfig.HTTPEndpoint)
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,28 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package models
package updatechecker

import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"

"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/appstate"
"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)"`
// CheckerState stores the remote version from the JSON endpoint
type CheckerState struct {
LatestVersion string
}

func init() {
db.RegisterModel(new(RemoteVersion))
// Name returns the name of the state item for update checker
func (r *CheckerState) Name() string {
return "update-checker"
}

// GiteaUpdateChecker returns error when new version of Gitea is available
Expand All @@ -49,60 +48,33 @@ func GiteaUpdateChecker(httpEndpoint string) error {
return err
}

type v struct {
type respType struct {
Latest struct {
Version string `json:"version"`
} `json:"latest"`
}
ver := v{}
err = json.Unmarshal(body, &ver)
respData := respType{}
err = json.Unmarshal(body, &respData)
if err != nil {
return err
}

return UpdateRemoteVersion(ver.Latest.Version)
return UpdateRemoteVersion(respData.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()
return appstate.AppState.Set(&CheckerState{LatestVersion: version})
}

// 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
item := new(CheckerState)
if err := appstate.AppState.Get(item); err != nil {
return ""
}
return v.Version
return item.LatestVersion
}

// GetNeedUpdate returns true whether a newer version of Gitea is available
Expand All @@ -112,7 +84,12 @@ func GetNeedUpdate() bool {
// return false to fail silently
return false
}
remoteVer, err := version.NewVersion(GetRemoteVersion())
remoteVerStr := GetRemoteVersion()
if remoteVerStr == "" {
// no remote version is known
return false
}
remoteVer, err := version.NewVersion(remoteVerStr)
if err != nil {
// return false to fail silently
return false
Expand Down
5 changes: 3 additions & 2 deletions routers/web/admin/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"code.gitea.io/gitea/modules/queue"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/updatechecker"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/mailer"
Expand Down Expand Up @@ -125,8 +126,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()
ctx.Data["NeedUpdate"] = updatechecker.GetNeedUpdate()
ctx.Data["RemoteVersion"] = updatechecker.GetRemoteVersion()
// FIXME: update periodically
updateSystemStatus()
ctx.Data["SysStatus"] = sysStatus
Expand Down