Skip to content
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

Store task errors following migrations and display them #13246

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
21 changes: 21 additions & 0 deletions models/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
39 changes: 22 additions & 17 deletions modules/task/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand All @@ -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 {
Expand All @@ -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)
}

Expand All @@ -66,42 +67,44 @@ 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
if t.Repo.Status == models.RepositoryReady {
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
Expand All @@ -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
}
Binary file added public/img/failed.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 0 additions & 16 deletions routers/repo/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
})
}
3 changes: 1 addition & 2 deletions routers/routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,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 *****

Expand Down Expand Up @@ -997,8 +998,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)
Expand Down
30 changes: 30 additions & 0 deletions routers/user/task.go
Original file line number Diff line number Diff line change
@@ -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,
})
}
8 changes: 7 additions & 1 deletion templates/repo/migrate/migrating.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -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">
<div>
<img src="{{StaticUrlPrefix}}/img/failed.png"/>
zeripath marked this conversation as resolved.
Show resolved Hide resolved
</div>
</div>
</div>
<div class="ui stackable middle very relaxed page grid">
<div class="sixteen wide center aligned centered column">
Expand All @@ -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>
Expand Down
19 changes: 14 additions & 5 deletions web_src/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,33 +192,42 @@ 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').html(xhr.responseJSON.err);
zeripath marked this conversation as resolved.
Show resolved Hide resolved
return;
}

setTimeout(() => {
initRepoStatusChecker();
}, 2000);
return;
}
}
$('#repo_migrating_progress').hide();
$('#repo_migrating').hide();
$('#repo_migrating_failed').show();
$('#repo_migrating_failed_image').show();
}
});
}
Expand Down