mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2026-05-28 11:14:54 -04:00
feat: show progress of issues and PRs migrations (#12738)
These are by the far the longest time spent on during a migration. Indicate the progress of how many issues and PRs were migrated so far. Don't overwhelm the messenger, so they are only updated once a batch is migrated. Which is "slow" enough to see it's not stuck and still doing work. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12738 Reviewed-by: Ellen Εμίλια Άννα Zscheile <fogti@noreply.codeberg.org> Reviewed-by: 0ko <0ko@noreply.codeberg.org>
This commit is contained in:
parent
68858a9de2
commit
d25f7ae70d
6 changed files with 136 additions and 2 deletions
|
|
@ -1,3 +1,4 @@
|
|||
// Copyright 2026 The Forgejo Authors. All rights reserved.
|
||||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// Copyright 2018 Jonas Franz. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
|
|
|||
|
|
@ -119,7 +119,15 @@
|
|||
"migrate.in_progress.labels": "Migrating labels",
|
||||
"migrate.in_progress.releases": "Migrating releases",
|
||||
"migrate.in_progress.issues": "Migrating issues",
|
||||
"migrate.in_progress.issues.progress": {
|
||||
"one": "Migrated %[1]d issue",
|
||||
"other": "Migrated %[1]d issues"
|
||||
},
|
||||
"migrate.in_progress.pulls": "Migrating pull requests",
|
||||
"migrate.in_progress.pulls.progress": {
|
||||
"one": "Migrated %[1]d pull request",
|
||||
"other": "Migrated %[1]d pull requests"
|
||||
},
|
||||
"migrate.cancel.title": "Cancel migration",
|
||||
"migrate.cancel.confirmation": "Do you want to cancel this migration?",
|
||||
"repo.issue_indexer.title": "Issue Indexer",
|
||||
|
|
|
|||
|
|
@ -39,6 +39,14 @@ func TaskStatus(ctx *context.Context) {
|
|||
Args: []any{task.Message},
|
||||
}
|
||||
}
|
||||
|
||||
// Convert float64 to integers. Currently no usage of floats.
|
||||
for i := range translatableMessage.Args {
|
||||
if arg, ok := translatableMessage.Args[i].(float64); ok {
|
||||
translatableMessage.Args[i] = int64(arg)
|
||||
}
|
||||
}
|
||||
|
||||
message = ctx.Locale.TrString(translatableMessage.Format, translatableMessage.Args...)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ func HandleMessengerInFunc(handler llu.Handler, fset *token.FileSet, n2 *ast.Fun
|
|||
if ret, ok := call.Fun.(*ast.Ident); !(ok && messenger.Contains(ret.Name)) {
|
||||
return true
|
||||
}
|
||||
if len(call.Args) != 1 {
|
||||
handler.OnWarning(fset, call.Lparen, "unexpected invocation of base.Messenger (expected exactly 1 argument)")
|
||||
if len(call.Args) == 0 {
|
||||
handler.OnWarning(fset, call.Lparen, "unexpected invocation of base.Messenger (expected at least one argument)")
|
||||
return true
|
||||
}
|
||||
handler.HandleGoTrArgument(fset, call.Args[0], "")
|
||||
|
|
|
|||
|
|
@ -344,6 +344,7 @@ func migrateRepository(_ context.Context, doer *user_model.User, downloader base
|
|||
log.Trace("migrating issues and comments")
|
||||
messenger("migrate.in_progress.issues")
|
||||
issueBatchSize := uploader.MaxBatchInsertSize("issue")
|
||||
var processedIssuesLen int
|
||||
|
||||
for i := 1; ; i++ {
|
||||
issues, isEnd, err := downloader.GetIssues(i, issueBatchSize)
|
||||
|
|
@ -389,6 +390,8 @@ func migrateRepository(_ context.Context, doer *user_model.User, downloader base
|
|||
}
|
||||
}
|
||||
|
||||
processedIssuesLen += len(issues)
|
||||
messenger("migrate.in_progress.issues.progress", processedIssuesLen)
|
||||
if isEnd {
|
||||
break
|
||||
}
|
||||
|
|
@ -399,6 +402,8 @@ func migrateRepository(_ context.Context, doer *user_model.User, downloader base
|
|||
log.Trace("migrating pull requests and comments")
|
||||
messenger("migrate.in_progress.pulls")
|
||||
prBatchSize := uploader.MaxBatchInsertSize("pullrequest")
|
||||
var processedPrsLen int
|
||||
|
||||
for i := 1; ; i++ {
|
||||
prs, isEnd, err := downloader.GetPullRequests(i, prBatchSize)
|
||||
if err != nil {
|
||||
|
|
@ -471,6 +476,8 @@ func migrateRepository(_ context.Context, doer *user_model.User, downloader base
|
|||
}
|
||||
}
|
||||
|
||||
processedPrsLen += len(prs)
|
||||
messenger("migrate.in_progress.pulls.progress", processedPrsLen)
|
||||
if isEnd {
|
||||
break
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
// Copyright 2026 The Forgejo Authors. All rights reserved.
|
||||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
|
|
@ -10,8 +11,10 @@ import (
|
|||
|
||||
"forgejo.org/models/unittest"
|
||||
user_model "forgejo.org/models/user"
|
||||
"forgejo.org/modules/migration"
|
||||
"forgejo.org/modules/setting"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
|
@ -128,3 +131,110 @@ func TestURLAllowedSSH(t *testing.T) {
|
|||
require.NoError(t, IsPushMirrorURLAllowed(sshURL, user))
|
||||
})
|
||||
}
|
||||
|
||||
var _ migration.Uploader = nullUploader{}
|
||||
|
||||
type nullUploader struct{}
|
||||
|
||||
func (nullUploader) MaxBatchInsertSize(string) int {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (nullUploader) CreateRepo(*migration.Repository, migration.MigrateOptions) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nullUploader) CreateTopics(...string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nullUploader) CreateMilestones(...*migration.Milestone) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nullUploader) CreateReleases(...*migration.Release) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nullUploader) SyncTags() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nullUploader) CreateLabels(...*migration.Label) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nullUploader) CreateIssues(...*migration.Issue) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nullUploader) CreateComments(...*migration.Comment) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nullUploader) CreatePullRequests(...*migration.PullRequest) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nullUploader) CreateReviews(...*migration.Review) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nullUploader) Rollback() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nullUploader) Finish() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nullUploader) Close() {}
|
||||
|
||||
type testingDownloader struct {
|
||||
migration.NullDownloader
|
||||
}
|
||||
|
||||
func (testingDownloader) GetRepoInfo() (*migration.Repository, error) {
|
||||
return &migration.Repository{
|
||||
CloneURL: "https://codeberg.org/forgejo-contrib/delightful-forgejo.git",
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (testingDownloader) GetIssues(page, _ int) ([]*migration.Issue, bool, error) {
|
||||
return make([]*migration.Issue, 1), page == 2, nil
|
||||
}
|
||||
|
||||
func (testingDownloader) GetPullRequests(page, _ int) ([]*migration.PullRequest, bool, error) {
|
||||
return make([]*migration.PullRequest, 1), page == 3, nil
|
||||
}
|
||||
|
||||
func TestMigrateRepository(t *testing.T) {
|
||||
messages := []struct {
|
||||
key string
|
||||
args []any
|
||||
}{
|
||||
{key: "migrate.in_progress.git"},
|
||||
{key: "migrate.in_progress.topics"},
|
||||
{key: "migrate.in_progress.issues"},
|
||||
{key: "migrate.in_progress.issues.progress", args: []any{1}},
|
||||
{key: "migrate.in_progress.issues.progress", args: []any{2}},
|
||||
{key: "migrate.in_progress.pulls"},
|
||||
{key: "migrate.in_progress.pulls.progress", args: []any{1}},
|
||||
{key: "migrate.in_progress.pulls.progress", args: []any{2}},
|
||||
{key: "migrate.in_progress.pulls.progress", args: []any{3}},
|
||||
}
|
||||
messenger := func(key string, args ...any) {
|
||||
if assert.NotEmpty(t, messages, key) {
|
||||
assert.Equal(t, messages[0].key, key)
|
||||
assert.Equal(t, messages[0].args, args)
|
||||
messages = messages[1:]
|
||||
}
|
||||
}
|
||||
|
||||
require.NoError(t, migrateRepository(nil, nil, testingDownloader{}, nullUploader{}, migration.MigrateOptions{
|
||||
PullRequests: true,
|
||||
Issues: true,
|
||||
}, messenger))
|
||||
|
||||
assert.Empty(t, messages)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue