]> source.dussan.org Git - gitea.git/commitdiff
Store task errors following migrations and display them (#13246) (#13287)
authortechknowlogick <techknowlogick@gitea.io>
Sat, 24 Oct 2020 05:02:36 +0000 (01:02 -0400)
committerGitHub <noreply@github.com>
Sat, 24 Oct 2020 05:02:36 +0000 (13:02 +0800)
* Store task errors following migrations and display them

When migrate tasks fail store the error in the task table
and ensure that they show on the status page.

Fix #13242

Signed-off-by: Andrew Thornton <art27@cantab.net>
* Update web_src/js/index.js

* Hide the failed first

Signed-off-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
Co-authored-by: zeripath <art27@cantab.net>
models/task.go
modules/task/migrate.go
public/img/failed.png [new file with mode: 0644]
routers/repo/repo.go
routers/routes/routes.go
routers/user/task.go [new file with mode: 0644]
templates/repo/migrate/migrating.tmpl
web_src/js/index.js

index 43cb2d4d9a633c64a16dc22394885c776f4f8873..b86314b44938af47951fc12e5501b53da56e7c07 100644 (file)
@@ -147,6 +147,27 @@ func GetMigratingTask(repoID int64) (*Task, error) {
        return &task, nil
 }
 
+// GetMigratingTaskByID returns the migrating task by repo's id
+func GetMigratingTaskByID(id, doerID int64) (*Task, *migration.MigrateOptions, error) {
+       var task = Task{
+               ID:     id,
+               DoerID: doerID,
+               Type:   structs.TaskTypeMigrateRepo,
+       }
+       has, err := x.Get(&task)
+       if err != nil {
+               return nil, nil, err
+       } else if !has {
+               return nil, nil, ErrTaskDoesNotExist{id, 0, task.Type}
+       }
+
+       var opts migration.MigrateOptions
+       if err := json.Unmarshal([]byte(task.PayloadContent), &opts); err != nil {
+               return nil, nil, err
+       }
+       return &task, &opts, nil
+}
+
 // FindTaskOptions find all tasks
 type FindTaskOptions struct {
        Status int
index d25decaa001156e70e7731e4ac1ba776874f4eaa..99f0435b280d0f4f9d59ec45f815460a4f582d05 100644 (file)
@@ -20,7 +20,7 @@ import (
        "code.gitea.io/gitea/modules/util"
 )
 
-func handleCreateError(owner *models.User, err error, name string) error {
+func handleCreateError(owner *models.User, err error) error {
        switch {
        case models.IsErrReachLimitOfRepo(err):
                return fmt.Errorf("You have already reached your limit of %d repositories", owner.MaxCreationLimit())
@@ -38,8 +38,8 @@ func handleCreateError(owner *models.User, err error, name string) error {
 func runMigrateTask(t *models.Task) (err error) {
        defer func() {
                if e := recover(); e != nil {
-                       err = fmt.Errorf("PANIC whilst trying to do migrate task: %v\nStacktrace: %v", err, log.Stack(2))
-                       log.Critical("PANIC during runMigrateTask[%d] by DoerID[%d] to RepoID[%d] for OwnerID[%d]: %v", t.ID, t.DoerID, t.RepoID, t.OwnerID, err)
+                       err = fmt.Errorf("PANIC whilst trying to do migrate task: %v", e)
+                       log.Critical("PANIC during runMigrateTask[%d] by DoerID[%d] to RepoID[%d] for OwnerID[%d]: %v\nStacktrace: %v", t.ID, t.DoerID, t.RepoID, t.OwnerID, e, log.Stack(2))
                }
 
                if err == nil {
@@ -55,7 +55,8 @@ func runMigrateTask(t *models.Task) (err error) {
                t.EndTime = timeutil.TimeStampNow()
                t.Status = structs.TaskStatusFailed
                t.Errors = err.Error()
-               if err := t.UpdateCols("status", "errors", "end_time"); err != nil {
+               t.RepoID = 0
+               if err := t.UpdateCols("status", "errors", "repo_id", "end_time"); err != nil {
                        log.Error("Task UpdateCols failed: %v", err)
                }
 
@@ -66,8 +67,8 @@ func runMigrateTask(t *models.Task) (err error) {
                }
        }()
 
-       if err := t.LoadRepo(); err != nil {
-               return err
+       if err = t.LoadRepo(); err != nil {
+               return
        }
 
        // if repository is ready, then just finsih the task
@@ -75,33 +76,35 @@ func runMigrateTask(t *models.Task) (err error) {
                return nil
        }
 
-       if err := t.LoadDoer(); err != nil {
-               return err
+       if err = t.LoadDoer(); err != nil {
+               return
        }
-       if err := t.LoadOwner(); err != nil {
-               return err
+       if err = t.LoadOwner(); err != nil {
+               return
        }
        t.StartTime = timeutil.TimeStampNow()
        t.Status = structs.TaskStatusRunning
-       if err := t.UpdateCols("start_time", "status"); err != nil {
-               return err
+       if err = t.UpdateCols("start_time", "status"); err != nil {
+               return
        }
 
        var opts *migration.MigrateOptions
        opts, err = t.MigrateConfig()
        if err != nil {
-               return err
+               return
        }
 
        opts.MigrateToRepoID = t.RepoID
-       repo, err := migrations.MigrateRepository(graceful.GetManager().HammerContext(), t.Doer, t.Owner.Name, *opts)
+       var repo *models.Repository
+       repo, err = migrations.MigrateRepository(graceful.GetManager().HammerContext(), t.Doer, t.Owner.Name, *opts)
        if err == nil {
                log.Trace("Repository migrated [%d]: %s/%s", repo.ID, t.Owner.Name, repo.Name)
-               return nil
+               return
        }
 
        if models.IsErrRepoAlreadyExist(err) {
-               return errors.New("The repository name is already used")
+               err = errors.New("The repository name is already used")
+               return
        }
 
        // remoteAddr may contain credentials, so we sanitize it
@@ -113,5 +116,7 @@ func runMigrateTask(t *models.Task) (err error) {
                return fmt.Errorf("Migration failed: %v", err.Error())
        }
 
-       return handleCreateError(t.Owner, err, "MigratePost")
+       // do not be tempted to coalesce this line with the return
+       err = handleCreateError(t.Owner, err)
+       return
 }
diff --git a/public/img/failed.png b/public/img/failed.png
new file mode 100644 (file)
index 0000000..b37545f
Binary files /dev/null and b/public/img/failed.png differ
index 742c952f6e7f667e4e8ea894d4497adb9eed5c16..422075032883b76573a6c086e07ca1017968a1e0 100644 (file)
@@ -402,19 +402,3 @@ func Download(ctx *context.Context) {
 
        ctx.ServeFile(archivePath, ctx.Repo.Repository.Name+"-"+refName+ext)
 }
-
-// Status returns repository's status
-func Status(ctx *context.Context) {
-       task, err := models.GetMigratingTask(ctx.Repo.Repository.ID)
-       if err != nil {
-               ctx.JSON(500, map[string]interface{}{
-                       "err": err,
-               })
-               return
-       }
-
-       ctx.JSON(200, map[string]interface{}{
-               "status": ctx.Repo.Repository.Status,
-               "err":    task.Errors,
-       })
-}
index 135c6b56a8ba8f57b2f63e28264f88b1016754aa..586474a661f859f6de4a18e5108b9c589531ae12 100644 (file)
@@ -479,6 +479,7 @@ func RegisterRoutes(m *macaron.Macaron) {
                m.Get("/forgot_password", user.ForgotPasswd)
                m.Post("/forgot_password", user.ForgotPasswdPost)
                m.Post("/logout", user.SignOut)
+               m.Get("/task/:task", user.TaskStatus)
        })
        // ***** END: User *****
 
@@ -986,8 +987,6 @@ func RegisterRoutes(m *macaron.Macaron) {
 
                m.Get("/archive/*", repo.MustBeNotEmpty, reqRepoCodeReader, repo.Download)
 
-               m.Get("/status", reqRepoCodeReader, repo.Status)
-
                m.Group("/branches", func() {
                        m.Get("", repo.Branches)
                }, repo.MustBeNotEmpty, context.RepoRef(), reqRepoCodeReader)
diff --git a/routers/user/task.go b/routers/user/task.go
new file mode 100644 (file)
index 0000000..a88257e
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2020 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 user
+
+import (
+       "code.gitea.io/gitea/models"
+       "code.gitea.io/gitea/modules/context"
+)
+
+// TaskStatus returns task's status
+func TaskStatus(ctx *context.Context) {
+       task, opts, err := models.GetMigratingTaskByID(ctx.ParamsInt64("task"), ctx.User.ID)
+       if err != nil {
+               ctx.JSON(500, map[string]interface{}{
+                       "err": err,
+               })
+               return
+       }
+
+       ctx.JSON(200, map[string]interface{}{
+               "status":    task.Status,
+               "err":       task.Errors,
+               "repo-id":   task.RepoID,
+               "repo-name": opts.RepoName,
+               "start":     task.StartTime,
+               "end":       task.EndTime,
+       })
+}
index 0057325e914da5085a8c80796e81b12a420cea9c..fdda33a2c7e4a4635e05ef5ef787d417c19b1195 100644 (file)
@@ -7,11 +7,16 @@
                                {{template "base/alert" .}}
                                <div class="home">
                                        <div class="ui stackable middle very relaxed page grid">
-                                               <div id="repo_migrating" class="sixteen wide center aligned centered column" repo="{{.Repo.Repository.FullName}}">
+                                               <div id="repo_migrating" class="sixteen wide center aligned centered column" task="{{.MigrateTask.ID}}">
                                                        <div>
                                                                <img src="{{StaticUrlPrefix}}/img/loading.png"/>
                                                        </div>
                                                </div>
+                                               <div id="repo_migrating_failed_image" class="sixteen wide center aligned centered column" style="display: none;">
+                                                       <div>
+                                                               <img src="{{StaticUrlPrefix}}/img/failed.png"/>
+                                                       </div>
+                                               </div>
                                        </div>
                                        <div class="ui stackable middle very relaxed page grid">
                                                <div class="sixteen wide center aligned centered column">
@@ -20,6 +25,7 @@
                                                        </div>
                                                        <div id="repo_migrating_failed">
                                                                <p>{{.i18n.Tr "repo.migrate.migrating_failed" .CloneAddr | Safe}}</p>
+                                                               <p id="repo_migrating_failed_error"></p>
                                                        </div>
                                                </div>
                                        </div>
index 9fafe62d3ed9f1e596d734ec51e434ed6e3030f3..94238ca3d9b080d899ffb3161070b07959777791 100644 (file)
@@ -191,25 +191,32 @@ function updateIssuesMeta(url, action, issueIds, elementId) {
 function initRepoStatusChecker() {
   const migrating = $('#repo_migrating');
   $('#repo_migrating_failed').hide();
+  $('#repo_migrating_failed_image').hide();
   if (migrating) {
-    const repo_name = migrating.attr('repo');
-    if (typeof repo_name === 'undefined') {
+    const task = migrating.attr('task');
+    if (typeof task === 'undefined') {
       return;
     }
     $.ajax({
       type: 'GET',
-      url: `${AppSubUrl}/${repo_name}/status`,
+      url: `${AppSubUrl}/user/task/${task}`,
       data: {
         _csrf: csrf,
       },
       complete(xhr) {
         if (xhr.status === 200) {
           if (xhr.responseJSON) {
-            if (xhr.responseJSON.status === 0) {
+            if (xhr.responseJSON.status === 4) {
               window.location.reload();
               return;
+            } else if (xhr.responseJSON.status === 3) {
+              $('#repo_migrating_progress').hide();
+              $('#repo_migrating').hide();
+              $('#repo_migrating_failed').show();
+              $('#repo_migrating_failed_image').show();
+              $('#repo_migrating_failed_error').text(xhr.responseJSON.err);
+              return;
             }
-
             setTimeout(() => {
               initRepoStatusChecker();
             }, 2000);
@@ -217,7 +224,9 @@ function initRepoStatusChecker() {
           }
         }
         $('#repo_migrating_progress').hide();
+        $('#repo_migrating').hide();
         $('#repo_migrating_failed').show();
+        $('#repo_migrating_failed_image').show();
       }
     });
   }