Skip to content

Commit 6ee6dc2

Browse files
forgejo-backport-actionoliverpool
authored andcommitted
[v14.0/forgejo] fix: prevent panic on gitlab import (releases/issues) (#11484)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11282 It is unfortunately all mixed up, because refreshing the data, means breaking the tests. And changing the code means needing fresh data. - tests: ignore some more headers and sort the rest when dumping http responses - code: fixed #10234 by requesting the latest issues first. - tests: created a new repo to replace the disappeared repo, needed for the skip-numbers test - refreshed the testdata. - follow-up fixes to get the tests green. - including a cherry-pick of go-gitea/gitea#36295 and #11272 Co-authored-by: oliverpool <git@olivier.pfad.fr> Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11484 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Reviewed-by: Robert Wolff <mahlzahn@posteo.de> Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org> Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
1 parent 230ccf5 commit 6ee6dc2

65 files changed

Lines changed: 859 additions & 1228 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

models/unittest/mock_http.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"bufio"
88
"fmt"
99
"io"
10+
"maps"
1011
"net/http"
1112
"net/http/httptest"
1213
"net/url"
@@ -29,7 +30,7 @@ import (
2930
// test data files
3031
func NewMockWebServer(t *testing.T, liveServerBaseURL, testDataDir string, liveMode bool) *httptest.Server {
3132
mockServerBaseURL := ""
32-
ignoredHeaders := []string{"cf-ray", "server", "date", "report-to", "nel", "x-request-id"}
33+
ignoredHeaders := []string{"cf-ray", "server", "date", "report-to", "nel", "x-request-id", "set-cookie", "x-gitlab-meta"}
3334

3435
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
3536
path := NormalizedFullPath(r.URL)
@@ -46,6 +47,7 @@ func NewMockWebServer(t *testing.T, liveServerBaseURL, testDataDir string, liveM
4647
fixturePath = fmt.Sprintf("%s/%s", testDataDir, strings.TrimLeft(r.URL.Path, "/"))
4748
}
4849
if liveMode {
50+
require.NoError(t, os.MkdirAll(testDataDir, 0o755))
4951
liveURL := fmt.Sprintf("%s%s", liveServerBaseURL, path)
5052

5153
request, err := http.NewRequest(r.Method, liveURL, nil)
@@ -68,8 +70,8 @@ func NewMockWebServer(t *testing.T, liveServerBaseURL, testDataDir string, liveM
6870
defer fixture.Close()
6971
fixtureWriter := bufio.NewWriter(fixture)
7072

71-
for headerName, headerValues := range response.Header {
72-
for _, headerValue := range headerValues {
73+
for _, headerName := range slices.Sorted(maps.Keys(response.Header)) {
74+
for _, headerValue := range response.Header[headerName] {
7375
if !slices.Contains(ignoredHeaders, strings.ToLower(headerName)) {
7476
_, err := fmt.Fprintf(fixtureWriter, "%s: %s\n", headerName, headerValue)
7577
require.NoError(t, err, "writing the header of the HTTP response to the fixture file failed")

modules/migration/release.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ import (
1010

1111
// ReleaseAsset represents a release asset
1212
type ReleaseAsset struct {
13-
ID int64
14-
Name string
15-
ContentType *string `yaml:"content_type"`
13+
ID int64
14+
Name string
15+
1616
Size *int
1717
DownloadCount *int `yaml:"download_count"`
1818
Created time.Time

release-notes/11282.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fix: prevent panic when importing issues from GitLab
2+
fix: prevent panic when importing releases with more than 4 release assets from GitLab
3+
fix: correct re-mapping of merge-request numbers mentioned in GitLab comments

services/migrations/github.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,6 @@ func (g *GithubDownloaderV3) convertGithubRelease(rel *github.RepositoryRelease)
352352
r.Assets = append(r.Assets, &base.ReleaseAsset{
353353
ID: asset.GetID(),
354354
Name: asset.GetName(),
355-
ContentType: asset.ContentType,
356355
Size: asset.Size,
357356
DownloadCount: asset.DownloadCount,
358357
Created: asset.CreatedAt.Time,

services/migrations/github_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,6 @@ func TestGitHubDownloadRepo(t *testing.T) {
236236
}, labels)
237237

238238
id := int64(280443629)
239-
ct := "application/pdf"
240239
size := 550175
241240
dc := 0
242241

@@ -256,7 +255,6 @@ func TestGitHubDownloadRepo(t *testing.T) {
256255
{
257256
ID: id,
258257
Name: "wireguard.pdf",
259-
ContentType: &ct,
260258
Size: &size,
261259
DownloadCount: &dc,
262260
Created: time.Date(2025, time.August, 7, 23, 39, 27, 0, time.UTC),

services/migrations/gitlab.go

Lines changed: 21 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,13 @@ type gitlabIIDResolver struct {
6565
}
6666

6767
func (r *gitlabIIDResolver) recordIssueIID(issueIID int) {
68+
if int64(issueIID) <= r.maxIssueIID {
69+
return
70+
}
6871
if r.frozen {
69-
panic("cannot record issue IID after pull request IID generation has started")
72+
panic("cannot record bigger issue IID after pull request IID generation has started")
7073
}
71-
r.maxIssueIID = max(r.maxIssueIID, int64(issueIID))
74+
r.maxIssueIID = int64(issueIID)
7275
}
7376

7477
func (r *gitlabIIDResolver) generatePullRequestNumber(mrIID int) int64 {
@@ -332,12 +335,11 @@ func (g *GitlabDownloader) convertGitlabRelease(rel *gitlab.Release) *base.Relea
332335

333336
httpClient := NewMigrationHTTPClient()
334337

335-
for k, asset := range rel.Assets.Links {
338+
for _, asset := range rel.Assets.Links {
336339
assetID := asset.ID // Don't optimize this, for closure we need a local variable
337340
r.Assets = append(r.Assets, &base.ReleaseAsset{
338341
ID: int64(asset.ID),
339342
Name: asset.Name,
340-
ContentType: &rel.Assets.Sources[k].Format,
341343
Size: &zero,
342344
DownloadCount: &zero,
343345
DownloadFunc: func() (io.ReadCloser, error) {
@@ -403,15 +405,18 @@ type gitlabIssueContext struct {
403405
// Note: issue label description and colors are not supported by the go-gitlab library at this time
404406
func (g *GitlabDownloader) GetIssues(page, perPage int) ([]*base.Issue, bool, error) {
405407
state := "all"
406-
sort := "asc"
408+
// we want most recent issues first, to get the biggest issue IID immediately
409+
sort := "desc"
410+
orderBy := "created_at"
407411

408412
if perPage > g.maxPerPage {
409413
perPage = g.maxPerPage
410414
}
411415

412416
opt := &gitlab.ListProjectIssuesOptions{
413-
State: &state,
414-
Sort: &sort,
417+
State: &state,
418+
Sort: &sort,
419+
OrderBy: &orderBy,
415420
ListOptions: gitlab.ListOptions{
416421
PerPage: perPage,
417422
Page: page,
@@ -795,39 +800,14 @@ func (g *GitlabDownloader) awardsToReactions(awards []*gitlab.AwardEmoji) []*bas
795800
return result
796801
}
797802

798-
// Build on the assumption, that PR IDs will resolve after Issue IDs
799-
func (g *GitlabDownloader) convertMRReference(body string) string {
800-
maxLength := len(body)
801-
for i := 0; i < maxLength; i++ {
802-
if body[i] == '!' {
803-
var collected string
804-
for k := i + 1; k < maxLength; k++ { // for each rune after ! check if next rune is integer
805-
if body[k]-'0' <= 9 {
806-
collected += string(body[k])
807-
if k == maxLength-1 { // The last rune in the string was an integer
808-
body = g.updateAndInsert(body, collected, i+1, k)
809-
}
810-
} else if len(collected) > 0 { // Integers have been collected, update value
811-
body = g.updateAndInsert(body, collected, i+1, k)
812-
maxLength = len(body)
813-
i = k
814-
break // We're done, continue after our replacement
815-
}
816-
}
817-
}
818-
}
819-
return body
820-
}
803+
var mrFinder = regexp.MustCompile(`![0-9]+`)
821804

822-
func (g *GitlabDownloader) updateAndInsert(description, oldReference string, endFirst, startSecond int) string {
823-
oldVal, _ := strconv.Atoi(oldReference)
824-
newVal := oldVal + int(g.iidResolver.maxIssueIID)
825-
firstPart := description[0:endFirst]
826-
firstPart += strconv.Itoa(newVal)
827-
var secondPart string
828-
if startSecond < len(description)-1 {
829-
secondPart = description[startSecond:]
830-
}
831-
description = firstPart + secondPart
832-
return description
805+
// In gitlab, issues and merge-request have split numbering
806+
// Adjust the merge-request numbers (preserve the issue numbers)
807+
func (g *GitlabDownloader) convertMRReference(body string) string {
808+
return mrFinder.ReplaceAllStringFunc(body, func(s string) string {
809+
oldVal, _ := strconv.Atoi(s[1:]) // skip the leading exclamation mark
810+
newVal := g.iidResolver.generatePullRequestNumber(oldVal)
811+
return "!" + strconv.FormatInt(newVal, 10)
812+
})
833813
}

0 commit comments

Comments
 (0)