]> source.dussan.org Git - gitea.git/commitdiff
Refactor update checker to use AppState (#17387)
authorwxiaoguang <wxiaoguang@gmail.com>
Thu, 21 Oct 2021 16:10:49 +0000 (00:10 +0800)
committerGitHub <noreply@github.com>
Thu, 21 Oct 2021 16:10:49 +0000 (17:10 +0100)
We have the `AppState` module now, it can store app related data easily. We do not need to create separate tables for each feature.

So the update checker can use `AppState` instead of a one-row dedicate table.

And the code of update checker is moved from `models` to `modules`.

models/migrations/migrations.go
models/migrations/v199.go
models/migrations/v201.go [new file with mode: 0644]
models/update_checker.go [deleted file]
modules/cron/tasks_extended.go
modules/updatechecker/update_checker.go [new file with mode: 0644]
routers/web/admin/admin.go

index b1c91beef6bddb87381d10511bbc96705141e96d..2686dfb3cff962ff9c71661a21830c65de2787d8 100644 (file)
@@ -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
index 64b21172c103eb99e6350641363aeae3f30143e3..4351ba4fa80bd0f114901df0c6f67c2bd4e094ed 100644 (file)
@@ -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
 }
diff --git a/models/migrations/v201.go b/models/migrations/v201.go
new file mode 100644 (file)
index 0000000..637c306
--- /dev/null
@@ -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
+}
diff --git a/models/update_checker.go b/models/update_checker.go
deleted file mode 100644 (file)
index 5b4fce6..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-// 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)
-}
index 6645e71d2cb26e5e85bba67fb13a61ec062f7176..9a37c40fafe7751fcbc80970ae497567aa7cce0f 100644 (file)
@@ -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() {
@@ -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)
        })
 }
 
diff --git a/modules/updatechecker/update_checker.go b/modules/updatechecker/update_checker.go
new file mode 100644 (file)
index 0000000..0124218
--- /dev/null
@@ -0,0 +1,98 @@
+// 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 updatechecker
+
+import (
+       "encoding/json"
+       "io/ioutil"
+       "net/http"
+
+       "code.gitea.io/gitea/modules/appstate"
+       "code.gitea.io/gitea/modules/proxy"
+       "code.gitea.io/gitea/modules/setting"
+
+       "github.com/hashicorp/go-version"
+)
+
+// CheckerState stores the remote version from the JSON endpoint
+type CheckerState struct {
+       LatestVersion string
+}
+
+// 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
+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 respType struct {
+               Latest struct {
+                       Version string `json:"version"`
+               } `json:"latest"`
+       }
+       respData := respType{}
+       err = json.Unmarshal(body, &respData)
+       if err != nil {
+               return err
+       }
+
+       return UpdateRemoteVersion(respData.Latest.Version)
+
+}
+
+// UpdateRemoteVersion updates the latest available version of Gitea
+func UpdateRemoteVersion(version string) (err error) {
+       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 {
+       item := new(CheckerState)
+       if err := appstate.AppState.Get(item); err != nil {
+               return ""
+       }
+       return item.LatestVersion
+}
+
+// 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
+       }
+       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
+       }
+       return curVer.LessThan(remoteVer)
+}
index ca5b157523c5082678480a4bf0541b0df078d61c..223114dae1cc2dad4179600c59e54d13f0822a6f 100644 (file)
@@ -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"
@@ -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