]> source.dussan.org Git - gitea.git/commitdiff
Run Migrate in Install rather than just SyncTables (#17475)
authorzeripath <art27@cantab.net>
Fri, 29 Oct 2021 08:23:10 +0000 (09:23 +0100)
committerGitHub <noreply@github.com>
Fri, 29 Oct 2021 08:23:10 +0000 (09:23 +0100)
* Run Migrate in Install rather than just SyncTables

The underlying problem in #17328 appears to be that users are re-running the install
page during upgrades. The function that tests and creates the db did not intend for
this and thus instead the migration scripts being run - a simple sync tables occurs.

This then causes a weird partially migrated DB which causes, in this release cycle,
the duplicate column in task table error. It is likely the cause of some weird
partial migration errors in other cycles too.

This PR simply ensures that the migration scripts are also run at this point too.

Fix #17328

Signed-off-by: Andrew Thornton <art27@cantab.net>
models/db/engine.go
routers/install/install.go

index 78b4ac22dde8524733ca1964d885e391e9869495..bd55aa7a039c62247475e8ccb1b32f2b85f1d16c 100755 (executable)
@@ -128,16 +128,35 @@ func syncTables() error {
        return x.StoreEngine("InnoDB").Sync2(tables...)
 }
 
-// NewTestEngine sets a new test xorm.Engine
-func NewTestEngine() (err error) {
+// NewInstallTestEngine creates a new xorm.Engine for testing during install
+//
+// This function will cause the basic database schema to be created
+func NewInstallTestEngine(ctx context.Context, migrateFunc func(*xorm.Engine) error) (err error) {
        x, err = GetNewEngine()
        if err != nil {
-               return fmt.Errorf("Connect to database: %v", err)
+               return fmt.Errorf("failed to connect to database: %w", err)
        }
 
        x.SetMapper(names.GonicMapper{})
        x.SetLogger(NewXORMLogger(!setting.IsProd))
        x.ShowSQL(!setting.IsProd)
+
+       x.SetDefaultContext(ctx)
+
+       if err = x.Ping(); err != nil {
+               return err
+       }
+
+       // We have to run migrateFunc here in case the user is re-running installation on a previously created DB.
+       // If we do not then table schemas will be changed and there will be conflicts when the migrations run properly.
+       //
+       // Installation should only be being re-run if users want to recover an old database.
+       // However, we should think carefully about should we support re-install on an installed instance,
+       // as there may be other problems due to secret reinitialization.
+       if err = migrateFunc(x); err != nil {
+               return fmt.Errorf("migrate: %v", err)
+       }
+
        return syncTables()
 }
 
index 8143ad8089a8d7c17ee3c47ac4c958b66d4b3690..1c042f9b4e2dccbcaa9f72e52031c6d1f7e9a623 100644 (file)
@@ -16,6 +16,7 @@ import (
 
        "code.gitea.io/gitea/models"
        "code.gitea.io/gitea/models/db"
+       "code.gitea.io/gitea/models/migrations"
        "code.gitea.io/gitea/modules/base"
        "code.gitea.io/gitea/modules/context"
        "code.gitea.io/gitea/modules/generate"
@@ -208,7 +209,7 @@ func SubmitInstall(ctx *context.Context) {
        }
 
        // Set test engine.
-       if err = db.NewTestEngine(); err != nil {
+       if err = db.NewInstallTestEngine(ctx, migrations.Migrate); err != nil {
                if strings.Contains(err.Error(), `Unknown database type: sqlite3`) {
                        ctx.Data["Err_DbType"] = true
                        ctx.RenderWithErr(ctx.Tr("install.sqlite3_not_available", "https://docs.gitea.io/en-us/install-from-binary/"), tplInstall, &form)