fixed #26156 * Added a retry button in the frontend (only displayed when the status is abnormal) * After clicking Retry, the backend adds the task back to the task queue ![7UJDNM671RI})EA8~~XPL39](https://github.com/go-gitea/gitea/assets/3371163/e088fd63-5dcc-4bc6-8849-7db3086511b7) ![T83F1WL9)VGHR@MB956$VT9](https://github.com/go-gitea/gitea/assets/3371163/744425bb-dde1-4315-be2e-5c99ac3a44d4) --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>tags/v1.21.0-rc0
ok = OK | ok = OK | ||||
cancel = Cancel | cancel = Cancel | ||||
retry = Retry | |||||
rerun = Re-run | rerun = Re-run | ||||
rerun_all = Re-run all jobs | rerun_all = Re-run all jobs | ||||
save = Save | save = Save |
ctx.Data["service"] = serviceType | ctx.Data["service"] = serviceType | ||||
} | } | ||||
func MigrateRetryPost(ctx *context.Context) { | |||||
if err := task.RetryMigrateTask(ctx.Repo.Repository.ID); err != nil { | |||||
log.Error("Retry task failed: %v", err) | |||||
ctx.ServerError("task.RetryMigrateTask", err) | |||||
return | |||||
} | |||||
ctx.JSONOK() | |||||
} | |||||
func MigrateCancelPost(ctx *context.Context) { | func MigrateCancelPost(ctx *context.Context) { | ||||
migratingTask, err := admin_model.GetMigratingTask(ctx.Repo.Repository.ID) | migratingTask, err := admin_model.GetMigratingTask(ctx.Repo.Repository.ID) | ||||
if err != nil { | if err != nil { |
addSettingsSecretsRoutes() | addSettingsSecretsRoutes() | ||||
addSettingVariablesRoutes() | addSettingVariablesRoutes() | ||||
}, actions.MustEnableActions) | }, actions.MustEnableActions) | ||||
m.Post("/migrate/cancel", repo.MigrateCancelPost) // this handler must be under "settings", otherwise this incomplete repo can't be accessed | |||||
// the follow handler must be under "settings", otherwise this incomplete repo can't be accessed | |||||
m.Group("/migrate", func() { | |||||
m.Post("/retry", repo.MigrateRetryPost) | |||||
m.Post("/cancel", repo.MigrateCancelPost) | |||||
}) | |||||
}, ctxDataSet("PageIsRepoSettings", true, "LFSStartServer", setting.LFS.StartServer)) | }, ctxDataSet("PageIsRepoSettings", true, "LFSStartServer", setting.LFS.StartServer)) | ||||
}, reqSignIn, context.RepoAssignment, context.UnitTypes(), reqRepoAdmin, context.RepoRef()) | }, reqSignIn, context.RepoAssignment, context.UnitTypes(), reqRepoAdmin, context.RepoRef()) | ||||
return task, nil | return task, nil | ||||
} | } | ||||
// RetryMigrateTask retry a migrate task | |||||
func RetryMigrateTask(repoID int64) error { | |||||
migratingTask, err := admin_model.GetMigratingTask(repoID) | |||||
if err != nil { | |||||
log.Error("GetMigratingTask: %v", err) | |||||
return err | |||||
} | |||||
if migratingTask.Status == structs.TaskStatusQueued || migratingTask.Status == structs.TaskStatusRunning { | |||||
return nil | |||||
} | |||||
// TODO Need to removing the storage/database garbage brought by the failed task | |||||
// Reset task status and messages | |||||
migratingTask.Status = structs.TaskStatusQueued | |||||
migratingTask.Message = "" | |||||
if err = migratingTask.UpdateCols("status", "message"); err != nil { | |||||
log.Error("task.UpdateCols failed: %v", err) | |||||
return err | |||||
} | |||||
return taskQueue.Push(migratingTask) | |||||
} |
<div class="divider"></div> | <div class="divider"></div> | ||||
<div class="item"> | <div class="item"> | ||||
{{if .Failed}} | {{if .Failed}} | ||||
<button class="ui basic red show-modal button" data-modal="#delete-repo-modal">{{.locale.Tr "repo.settings.delete"}}</button> | |||||
<button class="ui basic red show-modal button" data-modal="#delete-repo-modal">{{.locale.Tr "repo.settings.delete"}}</button> | |||||
{{else}} | {{else}} | ||||
<button class="ui basic red show-modal button" data-modal="#cancel-repo-modal">{{.locale.Tr "cancel"}}</button> | |||||
<button class="ui basic red show-modal button" data-modal="#cancel-repo-modal">{{.locale.Tr "cancel"}}</button> | |||||
{{end}} | {{end}} | ||||
<button id="repo_migrating_retry" data-migrating-task-retry-url="{{.Link}}/settings/migrate/retry" class="ui basic button gt-hidden">{{.locale.Tr "retry"}}</button> | |||||
</div> | </div> | ||||
{{end}} | {{end}} | ||||
</div> | </div> |
import $ from 'jquery'; | import $ from 'jquery'; | ||||
import {hideElem, showElem} from '../utils/dom.js'; | import {hideElem, showElem} from '../utils/dom.js'; | ||||
const {appSubUrl} = window.config; | |||||
const {appSubUrl, csrfToken} = window.config; | |||||
export function initRepoMigrationStatusChecker() { | export function initRepoMigrationStatusChecker() { | ||||
const $repoMigrating = $('#repo_migrating'); | const $repoMigrating = $('#repo_migrating'); | ||||
if (!$repoMigrating.length) return; | if (!$repoMigrating.length) return; | ||||
$('#repo_migrating_retry').on('click', doMigrationRetry); | |||||
const task = $repoMigrating.attr('data-migrating-task-id'); | const task = $repoMigrating.attr('data-migrating-task-id'); | ||||
// returns true if the refresh still need to be called after a while | // returns true if the refresh still need to be called after a while | ||||
if (data.status === 3) { | if (data.status === 3) { | ||||
hideElem('#repo_migrating_progress'); | hideElem('#repo_migrating_progress'); | ||||
hideElem('#repo_migrating'); | hideElem('#repo_migrating'); | ||||
showElem('#repo_migrating_retry'); | |||||
showElem('#repo_migrating_failed'); | showElem('#repo_migrating_failed'); | ||||
showElem('#repo_migrating_failed_image'); | showElem('#repo_migrating_failed_image'); | ||||
$('#repo_migrating_failed_error').text(data.message); | $('#repo_migrating_failed_error').text(data.message); | ||||
syncTaskStatus(); // no await | syncTaskStatus(); // no await | ||||
} | } | ||||
async function doMigrationRetry(e) { | |||||
await fetch($(e.target).attr('data-migrating-task-retry-url'), { | |||||
method: 'post', | |||||
headers: { | |||||
'X-Csrf-Token': csrfToken, | |||||
'Content-Type': 'application/json', | |||||
}, | |||||
}); | |||||
window.location.reload(); | |||||
} |