diff --git a/services/migrations/gitlab.go b/services/migrations/gitlab.go index 53d3ab7490..240fbd6f76 100644 --- a/services/migrations/gitlab.go +++ b/services/migrations/gitlab.go @@ -430,6 +430,14 @@ func (g *GitlabDownloader) GetIssues(page, perPage int) ([]*base.Issue, bool, er return nil, false, fmt.Errorf("error while listing issues: %w", err) } for _, issue := range issues { + // record the issue IID, to be used in GetPullRequests() + g.iidResolver.recordIssueIID(issue.IID) + + // Do not include confidential issues as long as Forgejo does not support them, see https://codeberg.org/forgejo/design/issues/2 + if issue.Confidential { + continue + } + labels := make([]*base.Label, 0, len(issue.Labels)) for _, l := range issue.Labels { labels = append(labels, &base.Label{ @@ -459,9 +467,6 @@ func (g *GitlabDownloader) GetIssues(page, perPage int) ([]*base.Issue, bool, er awardPage++ } - // record the issue IID, to be used in GetPullRequests() - g.iidResolver.recordIssueIID(issue.IID) - allIssues = append(allIssues, &base.Issue{ Title: issue.Title, Number: int64(issue.IID), @@ -517,6 +522,9 @@ func (g *GitlabDownloader) GetComments(commentable base.Commentable) ([]*base.Co } for _, comment := range comments { for _, note := range comment.Notes { + if note.Internal { + continue + } allComments = append(allComments, g.convertNoteToComment(commentable.GetLocalIndex(), note)) } } diff --git a/services/migrations/gitlab_test.go b/services/migrations/gitlab_test.go index 029a4ecce1..94968c2812 100644 --- a/services/migrations/gitlab_test.go +++ b/services/migrations/gitlab_test.go @@ -839,3 +839,73 @@ func TestCommentBodyParser(t *testing.T) { assert.Equal(t, "!21 and !11 are simillar but !211 and !110 are not!", parsedBody6) assert.Equal(t, "Simillar to #9, may be solved in !14", parsedBody7) } + +func TestGitlabConfidential(t *testing.T) { + // If a GitLab access token is provided, this test will make HTTP requests to the live gitlab.com instance. + // When doing so, the responses from gitlab.com will be saved as test data files. + // If no access token is available, those cached responses will be used instead. + gitlabPersonalAccessToken := os.Getenv("GITLAB_READ_TOKEN") + fixturePath := "./testdata/gitlab/confidential" + server := unittest.NewMockWebServer(t, "https://gitlab.com", fixturePath, gitlabPersonalAccessToken != "") + defer server.Close() + + downloader, err := NewGitlabDownloader(t.Context(), server.URL, "forgejo/test_repo-confidential", "", "", gitlabPersonalAccessToken) + if err != nil { + t.Fatalf("NewGitlabDownloader is nil: %v", err) + } + repo, err := downloader.GetRepoInfo() + require.NoError(t, err) + // Repo Owner is blank in Gitlab Group repos + assertRepositoryEqual(t, &base.Repository{ + Name: "test_repo-confidential", + Owner: "", + Description: "", + CloneURL: server.URL + "/forgejo/test_repo-confidential.git", + OriginalURL: server.URL + "/forgejo/test_repo-confidential", + DefaultBranch: "main", + }, repo) + + issues, isEnd, err := downloader.GetIssues(1, 10) + require.NoError(t, err) + assert.True(t, isEnd) + + // the only issue in this repository has number 1, confidential issue with number 2 is skipped + assert.Len(t, issues, 1) + assert.EqualValues(t, 1, issues[0].Number) + assert.Equal(t, "Normal issue", issues[0].Title) + + prs, _, err := downloader.GetPullRequests(1, 10) + require.NoError(t, err) + // the only merge request in this repository has number 1, + // but we offset it by the maximum issue number so it becomes + // pull request 2 in Forgejo + assert.Len(t, prs, 1) + assert.EqualValues(t, 3, prs[0].Number) + + // Issue with number 1 has two comments, but one of them is an internal note and is skipped + comments, _, err := downloader.GetComments(&base.Issue{ + Number: 1, + ForeignIndex: 1, + Context: gitlabIssueContext{IsMergeRequest: false}, + }) + require.NoError(t, err) + assertCommentsEqual(t, []*base.Comment{ + { + IssueIndex: 1, + PosterID: 3974632, + PosterName: "mahlzahn", + Created: time.Date(2026, 5, 26, 9, 32, 49, 748000000, time.UTC), + Content: "Normal comment", + Reactions: nil, + }, + }, comments) + + // Pull request with number 1 has only one comment, but it is an internal note and is skipped + comments, _, err = downloader.GetComments(&base.Issue{ + Number: 3, + ForeignIndex: 1, + Context: gitlabIssueContext{IsMergeRequest: true}, + }) + require.NoError(t, err) + assert.Empty(t, comments) +} diff --git a/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980 b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980 new file mode 100644 index 0000000000..8eb66ec1cc --- /dev/null +++ b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980 @@ -0,0 +1,20 @@ +Cache-Control: max-age=0, private, must-revalidate +Cf-Cache-Status: MISS +Content-Security-Policy: default-src 'none' +Content-Type: application/json +Etag: W/"97cea577ffb50ab0d0d5eae91cded085" +Gitlab-Lb: haproxy-main-35-lb-gprd +Gitlab-Sv: api-gke-us-east1-c +Ratelimit-Limit: 2000 +Ratelimit-Name: throttle_authenticated_api +Ratelimit-Observed: 3 +Ratelimit-Remaining: 1997 +Ratelimit-Reset: 1779789300 +Referrer-Policy: strict-origin-when-cross-origin +Strict-Transport-Security: max-age=31536000 +Vary: Origin, Accept-Encoding +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Runtime: 0.231219 + +{"id":82554980,"description":"","name":"test_repo-confidential","name_with_namespace":"Forgejo / test_repo-confidential","path":"test_repo-confidential","path_with_namespace":"forgejo/test_repo-confidential","created_at":"2026-05-26T08:54:51.953Z","default_branch":"main","tag_list":[],"topics":[],"ssh_url_to_repo":"git@gitlab.com:forgejo/test_repo-confidential.git","http_url_to_repo":"https://gitlab.com/forgejo/test_repo-confidential.git","web_url":"https://gitlab.com/forgejo/test_repo-confidential","readme_url":"https://gitlab.com/forgejo/test_repo-confidential/-/blob/main/README.md","forks_count":0,"avatar_url":null,"star_count":0,"last_activity_at":"2026-05-26T09:14:42.873Z","visibility":"public","namespace":{"id":64459497,"name":"Forgejo","path":"forgejo","kind":"group","full_path":"forgejo","parent_id":null,"avatar_url":"/uploads/-/system/group/avatar/64459497/73144-c883a242dec5299fbc06bbe3ee71d8c6.png","web_url":"https://gitlab.com/groups/forgejo"},"container_registry_image_prefix":"registry.gitlab.com/forgejo/test_repo-confidential","_links":{"self":"https://gitlab.com/api/v4/projects/82554980","issues":"https://gitlab.com/api/v4/projects/82554980/issues","merge_requests":"https://gitlab.com/api/v4/projects/82554980/merge_requests","repo_branches":"https://gitlab.com/api/v4/projects/82554980/repository/branches","labels":"https://gitlab.com/api/v4/projects/82554980/labels","events":"https://gitlab.com/api/v4/projects/82554980/events","members":"https://gitlab.com/api/v4/projects/82554980/members","cluster_agents":"https://gitlab.com/api/v4/projects/82554980/cluster_agents"},"marked_for_deletion_at":null,"marked_for_deletion_on":null,"packages_enabled":false,"empty_repo":false,"archived":true,"resolve_outdated_diff_discussions":false,"container_expiration_policy":{"cadence":"1d","enabled":false,"keep_n":10,"older_than":"90d","name_regex":".*","name_regex_keep":null,"next_run_at":"2026-05-27T08:54:51.971Z"},"repository_object_format":"sha1","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":false,"jobs_enabled":false,"snippets_enabled":false,"container_registry_enabled":false,"service_desk_enabled":true,"can_create_merge_request_in":false,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"disabled","wiki_access_level":"disabled","builds_access_level":"disabled","snippets_access_level":"disabled","pages_access_level":"disabled","analytics_access_level":"disabled","container_registry_access_level":"disabled","security_and_compliance_access_level":"disabled","releases_access_level":"enabled","environments_access_level":"disabled","feature_flags_access_level":"disabled","infrastructure_access_level":"disabled","monitor_access_level":"disabled","model_experiments_access_level":"disabled","model_registry_access_level":"disabled","package_registry_access_level":"disabled","emails_disabled":true,"emails_enabled":false,"show_diff_preview_in_email":false,"shared_runners_enabled":true,"lfs_enabled":false,"creator_id":3974632,"import_url":null,"import_type":null,"import_status":"none","import_error":null,"open_issues_count":1,"description_html":"","updated_at":"2026-05-26T09:54:06.589Z","ci_default_git_depth":20,"ci_delete_pipelines_in_seconds":null,"ci_forward_deployment_enabled":true,"ci_forward_deployment_rollback_allowed":true,"ci_job_token_scope_enabled":false,"ci_separated_caches":true,"ci_allow_fork_pipelines_to_run_in_parent_project":true,"ci_id_token_sub_claim_components":["project_path","ref_type","ref"],"build_git_strategy":"fetch","keep_latest_artifact":true,"restrict_user_defined_variables":false,"ci_pipeline_variables_minimum_override_role":"developer","runner_token_expiration_interval":null,"group_runners_enabled":true,"resource_group_default_process_mode":"unordered","auto_cancel_pending_pipelines":"enabled","build_timeout":3600,"auto_devops_enabled":false,"auto_devops_deploy_strategy":"continuous","ci_push_repository_for_job_token_allowed":false,"protect_merge_request_pipelines":true,"ci_display_pipeline_variables":false,"ci_config_path":"","public_jobs":true,"shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"allow_merge_on_skipped_pipeline":null,"request_access_enabled":false,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","squash_option":"default_off","enforce_auth_checks_on_uploads":true,"suggestion_commit_message":null,"merge_commit_template":null,"squash_commit_template":null,"mr_default_title_template":null,"issue_branch_template":null,"warn_about_potentially_unwanted_characters":false,"autoclose_referenced_issues":true,"max_artifacts_size":null,"external_authorization_classification_label":"","requirements_enabled":false,"requirements_access_level":"enabled","security_and_compliance_enabled":false,"compliance_frameworks":[],"web_based_commit_signing_enabled":false,"permissions":{"project_access":null,"group_access":{"access_level":50,"notification_level":3}}} \ No newline at end of file diff --git a/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fissues%2F1%2Faward_emoji%3Fpage=1&per_page=10 b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fissues%2F1%2Faward_emoji%3Fpage=1&per_page=10 new file mode 100644 index 0000000000..b0e2e1f3f6 --- /dev/null +++ b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fissues%2F1%2Faward_emoji%3Fpage=1&per_page=10 @@ -0,0 +1,28 @@ +Cache-Control: max-age=0, private, must-revalidate +Cf-Cache-Status: MISS +Content-Length: 2 +Content-Security-Policy: default-src 'none' +Content-Type: application/json +Etag: W/"4f53cda18c2baa0c0354bb5f9a3ecbe5" +Gitlab-Lb: haproxy-main-19-lb-gprd +Gitlab-Sv: api-gke-us-east1-b +Link: ; rel="first", ; rel="last" +Ratelimit-Limit: 2000 +Ratelimit-Name: throttle_authenticated_api +Ratelimit-Observed: 5 +Ratelimit-Remaining: 1995 +Ratelimit-Reset: 1779789300 +Referrer-Policy: strict-origin-when-cross-origin +Strict-Transport-Security: max-age=31536000 +Vary: Origin, Accept-Encoding +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Next-Page: +X-Page: 1 +X-Per-Page: 10 +X-Prev-Page: +X-Runtime: 0.073433 +X-Total: 0 +X-Total-Pages: 1 + +[] \ No newline at end of file diff --git a/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fissues%2F1%2Fdiscussions%3Fpage=1&per_page=100 b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fissues%2F1%2Fdiscussions%3Fpage=1&per_page=100 new file mode 100644 index 0000000000..4bc332f904 --- /dev/null +++ b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fissues%2F1%2Fdiscussions%3Fpage=1&per_page=100 @@ -0,0 +1,27 @@ +Cache-Control: max-age=0, private, must-revalidate +Cf-Cache-Status: MISS +Content-Security-Policy: default-src 'none' +Content-Type: application/json +Etag: W/"2fbd24efd95ba4bff096d7176a06f03c" +Gitlab-Lb: haproxy-main-13-lb-gprd +Gitlab-Sv: api-gke-us-east1-b +Link: ; rel="first", ; rel="last" +Ratelimit-Limit: 2000 +Ratelimit-Name: throttle_authenticated_api +Ratelimit-Observed: 9 +Ratelimit-Remaining: 1991 +Ratelimit-Reset: 1779789300 +Referrer-Policy: strict-origin-when-cross-origin +Strict-Transport-Security: max-age=31536000 +Vary: Origin, Accept-Encoding +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Next-Page: +X-Page: 1 +X-Per-Page: 100 +X-Prev-Page: +X-Runtime: 0.142777 +X-Total: 2 +X-Total-Pages: 1 + +[{"id":"e3fd72a0a026c57218994979ba686d7ebdc32ce4","individual_note":true,"resolvable":false,"notes":[{"id":3384409453,"type":null,"body":"Internal note","author":{"id":3974632,"username":"mahlzahn","public_email":"","name":"mahlzahn","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/3974632/avatar.png","web_url":"https://gitlab.com/mahlzahn"},"created_at":"2026-05-26T08:58:52.374Z","updated_at":"2026-05-26T08:58:52.374Z","system":false,"noteable_id":191028598,"noteable_type":"Issue","project_id":82554980,"resolvable":false,"confidential":true,"internal":true,"imported":false,"imported_from":"none","noteable_iid":1,"commands_changes":{}}]},{"id":"06234a3146c02649facca69551660ea0c058176e","individual_note":true,"resolvable":false,"notes":[{"id":3384552626,"type":null,"body":"Normal comment","author":{"id":3974632,"username":"mahlzahn","public_email":"","name":"mahlzahn","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/3974632/avatar.png","web_url":"https://gitlab.com/mahlzahn"},"created_at":"2026-05-26T09:32:49.748Z","updated_at":"2026-05-26T09:32:49.748Z","system":false,"noteable_id":191028598,"noteable_type":"Issue","project_id":82554980,"resolvable":false,"confidential":false,"internal":false,"imported":false,"imported_from":"none","noteable_iid":1,"commands_changes":{}}]}] \ No newline at end of file diff --git a/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fissues%2F1%2Fresource_state_events%3Fpage=1&per_page=100 b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fissues%2F1%2Fresource_state_events%3Fpage=1&per_page=100 new file mode 100644 index 0000000000..04329ae935 --- /dev/null +++ b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fissues%2F1%2Fresource_state_events%3Fpage=1&per_page=100 @@ -0,0 +1,28 @@ +Cache-Control: max-age=0, private, must-revalidate +Cf-Cache-Status: MISS +Content-Length: 2 +Content-Security-Policy: default-src 'none' +Content-Type: application/json +Etag: W/"4f53cda18c2baa0c0354bb5f9a3ecbe5" +Gitlab-Lb: haproxy-main-57-lb-gprd +Gitlab-Sv: api-gke-us-east1-d +Link: ; rel="first", ; rel="last" +Ratelimit-Limit: 2000 +Ratelimit-Name: throttle_authenticated_api +Ratelimit-Observed: 10 +Ratelimit-Remaining: 1990 +Ratelimit-Reset: 1779789300 +Referrer-Policy: strict-origin-when-cross-origin +Strict-Transport-Security: max-age=31536000 +Vary: Origin, Accept-Encoding +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Next-Page: +X-Page: 1 +X-Per-Page: 100 +X-Prev-Page: +X-Runtime: 0.098598 +X-Total: 0 +X-Total-Pages: 1 + +[] \ No newline at end of file diff --git a/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fissues%3Forder_by=created_at&page=1&per_page=10&sort=desc&state=all b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fissues%3Forder_by=created_at&page=1&per_page=10&sort=desc&state=all new file mode 100644 index 0000000000..4b922cae8f --- /dev/null +++ b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fissues%3Forder_by=created_at&page=1&per_page=10&sort=desc&state=all @@ -0,0 +1,27 @@ +Cache-Control: max-age=0, private, must-revalidate +Cf-Cache-Status: MISS +Content-Security-Policy: default-src 'none' +Content-Type: application/json +Etag: W/"79478b7d2ca6de15cebecfdde62e7dec" +Gitlab-Lb: haproxy-main-55-lb-gprd +Gitlab-Sv: api-gke-us-east1-b +Link: ; rel="first", ; rel="last" +Ratelimit-Limit: 2000 +Ratelimit-Name: throttle_authenticated_api +Ratelimit-Observed: 4 +Ratelimit-Remaining: 1996 +Ratelimit-Reset: 1779789300 +Referrer-Policy: strict-origin-when-cross-origin +Strict-Transport-Security: max-age=31536000 +Vary: Origin, Accept-Encoding +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Next-Page: +X-Page: 1 +X-Per-Page: 10 +X-Prev-Page: +X-Runtime: 0.177626 +X-Total: 2 +X-Total-Pages: 1 + +[{"id":191028619,"iid":2,"project_id":82554980,"title":"Confidential issue","description":"","state":"opened","created_at":"2026-05-26T08:55:44.918Z","updated_at":"2026-05-26T08:55:44.918Z","closed_at":null,"closed_by":null,"labels":[],"milestone":null,"assignees":[],"author":{"id":3974632,"username":"mahlzahn","public_email":"","name":"mahlzahn","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/3974632/avatar.png","web_url":"https://gitlab.com/mahlzahn"},"type":"ISSUE","assignee":null,"user_notes_count":0,"merge_requests_count":0,"upvotes":0,"downvotes":0,"start_date":null,"due_date":null,"confidential":true,"discussion_locked":null,"issue_type":"issue","web_url":"https://gitlab.com/forgejo/test_repo-confidential/-/work_items/2","time_stats":{"time_estimate":0,"total_time_spent":0,"human_time_estimate":null,"human_total_time_spent":null},"task_completion_status":{"count":0,"completed_count":0},"blocking_issues_count":0,"has_tasks":true,"task_status":"","_links":{"self":"https://gitlab.com/api/v4/projects/82554980/issues/2","notes":"https://gitlab.com/api/v4/projects/82554980/issues/2/notes","award_emoji":"https://gitlab.com/api/v4/projects/82554980/issues/2/award_emoji","project":"https://gitlab.com/api/v4/projects/82554980","closed_as_duplicate_of":null},"references":{"short":"#2","relative":"#2","full":"forgejo/test_repo-confidential#2"},"severity":"UNKNOWN","moved_to_id":null,"imported":false,"imported_from":"none","service_desk_reply_to":null},{"id":191028598,"iid":1,"project_id":82554980,"title":"Normal issue","description":"","state":"opened","created_at":"2026-05-26T08:55:25.760Z","updated_at":"2026-05-26T09:32:49.776Z","closed_at":null,"closed_by":null,"labels":[],"milestone":null,"assignees":[],"author":{"id":3974632,"username":"mahlzahn","public_email":"","name":"mahlzahn","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/3974632/avatar.png","web_url":"https://gitlab.com/mahlzahn"},"type":"ISSUE","assignee":null,"user_notes_count":2,"merge_requests_count":0,"upvotes":0,"downvotes":0,"start_date":null,"due_date":null,"confidential":false,"discussion_locked":null,"issue_type":"issue","web_url":"https://gitlab.com/forgejo/test_repo-confidential/-/work_items/1","time_stats":{"time_estimate":0,"total_time_spent":0,"human_time_estimate":null,"human_total_time_spent":null},"task_completion_status":{"count":0,"completed_count":0},"blocking_issues_count":0,"has_tasks":true,"task_status":"","_links":{"self":"https://gitlab.com/api/v4/projects/82554980/issues/1","notes":"https://gitlab.com/api/v4/projects/82554980/issues/1/notes","award_emoji":"https://gitlab.com/api/v4/projects/82554980/issues/1/award_emoji","project":"https://gitlab.com/api/v4/projects/82554980","closed_as_duplicate_of":null},"references":{"short":"#1","relative":"#1","full":"forgejo/test_repo-confidential#1"},"severity":"UNKNOWN","moved_to_id":null,"imported":false,"imported_from":"none","service_desk_reply_to":null}] \ No newline at end of file diff --git a/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fmerge_requests%2F1 b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fmerge_requests%2F1 new file mode 100644 index 0000000000..c2584394e7 --- /dev/null +++ b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fmerge_requests%2F1 @@ -0,0 +1,20 @@ +Cache-Control: max-age=0, private, must-revalidate +Cf-Cache-Status: MISS +Content-Security-Policy: default-src 'none' +Content-Type: application/json +Etag: W/"b9c76d03ff5614caf10a4c57360357cd" +Gitlab-Lb: haproxy-main-06-lb-gprd +Gitlab-Sv: api-gke-us-east1-d +Ratelimit-Limit: 2000 +Ratelimit-Name: throttle_authenticated_api +Ratelimit-Observed: 7 +Ratelimit-Remaining: 1993 +Ratelimit-Reset: 1779789300 +Referrer-Policy: strict-origin-when-cross-origin +Strict-Transport-Security: max-age=31536000 +Vary: Origin, Accept-Encoding +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Runtime: 0.169552 + +{"id":488879616,"iid":1,"project_id":82554980,"title":"chore: fix typo","description":"","state":"opened","created_at":"2026-05-26T09:02:35.641Z","updated_at":"2026-05-26T09:40:10.508Z","merged_by":null,"merge_user":null,"merged_at":null,"closed_by":null,"closed_at":null,"target_branch":"main","source_branch":"fix_typo","user_notes_count":1,"upvotes":0,"downvotes":0,"author":{"id":3974632,"username":"mahlzahn","public_email":"","name":"mahlzahn","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/3974632/avatar.png","web_url":"https://gitlab.com/mahlzahn"},"assignees":[],"assignee":null,"reviewers":[],"source_project_id":82554980,"target_project_id":82554980,"labels":[],"draft":false,"imported":false,"imported_from":"none","work_in_progress":false,"milestone":null,"merge_when_pipeline_succeeds":false,"merge_status":"cannot_be_merged","detailed_merge_status":"conflict","merge_after":null,"sha":"ca7060858fda4c3bca198462a2a907a417ab7759","merge_commit_sha":null,"squash_commit_sha":null,"discussion_locked":null,"should_remove_source_branch":null,"force_remove_source_branch":true,"prepared_at":"2026-05-26T09:02:37.178Z","reference":"!1","references":{"short":"!1","relative":"!1","full":"forgejo/test_repo-confidential!1"},"web_url":"https://gitlab.com/forgejo/test_repo-confidential/-/merge_requests/1","time_stats":{"time_estimate":0,"total_time_spent":0,"human_time_estimate":null,"human_total_time_spent":null},"squash":false,"squash_on_merge":false,"task_completion_status":{"count":0,"completed_count":0},"has_conflicts":true,"blocking_discussions_resolved":true,"approvals_before_merge":null,"subscribed":true,"changes_count":"1","head_pipeline":null,"diff_refs":{"base_sha":"f19949326d3d51391e8f05a5f1cf96fa9dd99763","head_sha":"ca7060858fda4c3bca198462a2a907a417ab7759","start_sha":"f19949326d3d51391e8f05a5f1cf96fa9dd99763"},"merge_error":null,"first_contribution":true,"user":{"can_merge":false}} \ No newline at end of file diff --git a/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fmerge_requests%2F1%2Faward_emoji%3Fpage=1&per_page=10 b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fmerge_requests%2F1%2Faward_emoji%3Fpage=1&per_page=10 new file mode 100644 index 0000000000..e11380b737 --- /dev/null +++ b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fmerge_requests%2F1%2Faward_emoji%3Fpage=1&per_page=10 @@ -0,0 +1,28 @@ +Cache-Control: max-age=0, private, must-revalidate +Cf-Cache-Status: MISS +Content-Length: 2 +Content-Security-Policy: default-src 'none' +Content-Type: application/json +Etag: W/"4f53cda18c2baa0c0354bb5f9a3ecbe5" +Gitlab-Lb: haproxy-main-25-lb-gprd +Gitlab-Sv: api-gke-us-east1-b +Link: ; rel="first", ; rel="last" +Ratelimit-Limit: 2000 +Ratelimit-Name: throttle_authenticated_api +Ratelimit-Observed: 8 +Ratelimit-Remaining: 1992 +Ratelimit-Reset: 1779789300 +Referrer-Policy: strict-origin-when-cross-origin +Strict-Transport-Security: max-age=31536000 +Vary: Origin, Accept-Encoding +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Next-Page: +X-Page: 1 +X-Per-Page: 10 +X-Prev-Page: +X-Runtime: 0.097656 +X-Total: 0 +X-Total-Pages: 1 + +[] \ No newline at end of file diff --git a/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fmerge_requests%2F1%2Fdiscussions%3Fpage=1&per_page=100 b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fmerge_requests%2F1%2Fdiscussions%3Fpage=1&per_page=100 new file mode 100644 index 0000000000..1dfae3d2dd --- /dev/null +++ b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fmerge_requests%2F1%2Fdiscussions%3Fpage=1&per_page=100 @@ -0,0 +1,27 @@ +Cache-Control: max-age=0, private, must-revalidate +Cf-Cache-Status: MISS +Content-Security-Policy: default-src 'none' +Content-Type: application/json +Etag: W/"591e42a5f29fd322c1f77db90999e0f6" +Gitlab-Lb: haproxy-main-01-lb-gprd +Gitlab-Sv: api-gke-us-east1-b +Link: ; rel="first", ; rel="last" +Ratelimit-Limit: 2000 +Ratelimit-Name: throttle_authenticated_api +Ratelimit-Observed: 11 +Ratelimit-Remaining: 1989 +Ratelimit-Reset: 1779789300 +Referrer-Policy: strict-origin-when-cross-origin +Strict-Transport-Security: max-age=31536000 +Vary: Origin, Accept-Encoding +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Next-Page: +X-Page: 1 +X-Per-Page: 100 +X-Prev-Page: +X-Runtime: 0.132759 +X-Total: 1 +X-Total-Pages: 1 + +[{"id":"992a517dbd25b748c6aa8ce27bdc1e5a3ec239f6","individual_note":true,"resolvable":false,"notes":[{"id":3384581942,"type":null,"body":"Another internal note","author":{"id":3974632,"username":"mahlzahn","public_email":"","name":"mahlzahn","state":"active","locked":false,"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/3974632/avatar.png","web_url":"https://gitlab.com/mahlzahn"},"created_at":"2026-05-26T09:40:10.477Z","updated_at":"2026-05-26T09:40:10.477Z","system":false,"noteable_id":488879616,"noteable_type":"MergeRequest","project_id":82554980,"resolvable":false,"confidential":true,"internal":true,"imported":false,"imported_from":"none","noteable_iid":1,"commands_changes":{}}]}] \ No newline at end of file diff --git a/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fmerge_requests%2F1%2Fresource_state_events%3Fpage=1&per_page=100 b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fmerge_requests%2F1%2Fresource_state_events%3Fpage=1&per_page=100 new file mode 100644 index 0000000000..3a4d1b8841 --- /dev/null +++ b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fmerge_requests%2F1%2Fresource_state_events%3Fpage=1&per_page=100 @@ -0,0 +1,28 @@ +Cache-Control: max-age=0, private, must-revalidate +Cf-Cache-Status: MISS +Content-Length: 2 +Content-Security-Policy: default-src 'none' +Content-Type: application/json +Etag: W/"4f53cda18c2baa0c0354bb5f9a3ecbe5" +Gitlab-Lb: haproxy-main-51-lb-gprd +Gitlab-Sv: api-gke-us-east1-d +Link: ; rel="first", ; rel="last" +Ratelimit-Limit: 2000 +Ratelimit-Name: throttle_authenticated_api +Ratelimit-Observed: 12 +Ratelimit-Remaining: 1988 +Ratelimit-Reset: 1779789300 +Referrer-Policy: strict-origin-when-cross-origin +Strict-Transport-Security: max-age=31536000 +Vary: Origin, Accept-Encoding +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Next-Page: +X-Page: 1 +X-Per-Page: 100 +X-Prev-Page: +X-Runtime: 0.063179 +X-Total: 0 +X-Total-Pages: 1 + +[] \ No newline at end of file diff --git a/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fmerge_requests%3Fpage=1&per_page=10&view=simple b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fmerge_requests%3Fpage=1&per_page=10&view=simple new file mode 100644 index 0000000000..921724c4c9 --- /dev/null +++ b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2F82554980%2Fmerge_requests%3Fpage=1&per_page=10&view=simple @@ -0,0 +1,27 @@ +Cache-Control: max-age=0, private, must-revalidate +Cf-Cache-Status: MISS +Content-Security-Policy: default-src 'none' +Content-Type: application/json +Etag: W/"455960f9d3850d1ac04b6f21857873da" +Gitlab-Lb: haproxy-main-05-lb-gprd +Gitlab-Sv: api-gke-us-east1-c +Link: ; rel="first", ; rel="last" +Ratelimit-Limit: 2000 +Ratelimit-Name: throttle_authenticated_api +Ratelimit-Observed: 6 +Ratelimit-Remaining: 1994 +Ratelimit-Reset: 1779789300 +Referrer-Policy: strict-origin-when-cross-origin +Strict-Transport-Security: max-age=31536000 +Vary: Origin, Accept-Encoding +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Next-Page: +X-Page: 1 +X-Per-Page: 10 +X-Prev-Page: +X-Runtime: 0.086347 +X-Total: 1 +X-Total-Pages: 1 + +[{"id":488879616,"iid":1,"project_id":82554980,"title":"chore: fix typo","description":"","state":"opened","created_at":"2026-05-26T09:02:35.641Z","updated_at":"2026-05-26T09:40:10.508Z","web_url":"https://gitlab.com/forgejo/test_repo-confidential/-/merge_requests/1"}] \ No newline at end of file diff --git a/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2Fforgejo%252Ftest_repo-confidential b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2Fforgejo%252Ftest_repo-confidential new file mode 100644 index 0000000000..80a45da3ad --- /dev/null +++ b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fprojects%2Fforgejo%252Ftest_repo-confidential @@ -0,0 +1,20 @@ +Cache-Control: max-age=0, private, must-revalidate +Cf-Cache-Status: MISS +Content-Security-Policy: default-src 'none' +Content-Type: application/json +Etag: W/"97cea577ffb50ab0d0d5eae91cded085" +Gitlab-Lb: haproxy-main-04-lb-gprd +Gitlab-Sv: api-gke-us-east1-b +Ratelimit-Limit: 2000 +Ratelimit-Name: throttle_authenticated_api +Ratelimit-Observed: 2 +Ratelimit-Remaining: 1998 +Ratelimit-Reset: 1779789300 +Referrer-Policy: strict-origin-when-cross-origin +Strict-Transport-Security: max-age=31536000 +Vary: Origin, Accept-Encoding +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Runtime: 0.112912 + +{"id":82554980,"description":"","name":"test_repo-confidential","name_with_namespace":"Forgejo / test_repo-confidential","path":"test_repo-confidential","path_with_namespace":"forgejo/test_repo-confidential","created_at":"2026-05-26T08:54:51.953Z","default_branch":"main","tag_list":[],"topics":[],"ssh_url_to_repo":"git@gitlab.com:forgejo/test_repo-confidential.git","http_url_to_repo":"https://gitlab.com/forgejo/test_repo-confidential.git","web_url":"https://gitlab.com/forgejo/test_repo-confidential","readme_url":"https://gitlab.com/forgejo/test_repo-confidential/-/blob/main/README.md","forks_count":0,"avatar_url":null,"star_count":0,"last_activity_at":"2026-05-26T09:14:42.873Z","visibility":"public","namespace":{"id":64459497,"name":"Forgejo","path":"forgejo","kind":"group","full_path":"forgejo","parent_id":null,"avatar_url":"/uploads/-/system/group/avatar/64459497/73144-c883a242dec5299fbc06bbe3ee71d8c6.png","web_url":"https://gitlab.com/groups/forgejo"},"container_registry_image_prefix":"registry.gitlab.com/forgejo/test_repo-confidential","_links":{"self":"https://gitlab.com/api/v4/projects/82554980","issues":"https://gitlab.com/api/v4/projects/82554980/issues","merge_requests":"https://gitlab.com/api/v4/projects/82554980/merge_requests","repo_branches":"https://gitlab.com/api/v4/projects/82554980/repository/branches","labels":"https://gitlab.com/api/v4/projects/82554980/labels","events":"https://gitlab.com/api/v4/projects/82554980/events","members":"https://gitlab.com/api/v4/projects/82554980/members","cluster_agents":"https://gitlab.com/api/v4/projects/82554980/cluster_agents"},"marked_for_deletion_at":null,"marked_for_deletion_on":null,"packages_enabled":false,"empty_repo":false,"archived":true,"resolve_outdated_diff_discussions":false,"container_expiration_policy":{"cadence":"1d","enabled":false,"keep_n":10,"older_than":"90d","name_regex":".*","name_regex_keep":null,"next_run_at":"2026-05-27T08:54:51.971Z"},"repository_object_format":"sha1","issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":false,"jobs_enabled":false,"snippets_enabled":false,"container_registry_enabled":false,"service_desk_enabled":true,"can_create_merge_request_in":false,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"disabled","wiki_access_level":"disabled","builds_access_level":"disabled","snippets_access_level":"disabled","pages_access_level":"disabled","analytics_access_level":"disabled","container_registry_access_level":"disabled","security_and_compliance_access_level":"disabled","releases_access_level":"enabled","environments_access_level":"disabled","feature_flags_access_level":"disabled","infrastructure_access_level":"disabled","monitor_access_level":"disabled","model_experiments_access_level":"disabled","model_registry_access_level":"disabled","package_registry_access_level":"disabled","emails_disabled":true,"emails_enabled":false,"show_diff_preview_in_email":false,"shared_runners_enabled":true,"lfs_enabled":false,"creator_id":3974632,"import_url":null,"import_type":null,"import_status":"none","import_error":null,"open_issues_count":1,"description_html":"","updated_at":"2026-05-26T09:54:06.589Z","ci_default_git_depth":20,"ci_delete_pipelines_in_seconds":null,"ci_forward_deployment_enabled":true,"ci_forward_deployment_rollback_allowed":true,"ci_job_token_scope_enabled":false,"ci_separated_caches":true,"ci_allow_fork_pipelines_to_run_in_parent_project":true,"ci_id_token_sub_claim_components":["project_path","ref_type","ref"],"build_git_strategy":"fetch","keep_latest_artifact":true,"restrict_user_defined_variables":false,"ci_pipeline_variables_minimum_override_role":"developer","runner_token_expiration_interval":null,"group_runners_enabled":true,"resource_group_default_process_mode":"unordered","auto_cancel_pending_pipelines":"enabled","build_timeout":3600,"auto_devops_enabled":false,"auto_devops_deploy_strategy":"continuous","ci_push_repository_for_job_token_allowed":false,"protect_merge_request_pipelines":true,"ci_display_pipeline_variables":false,"ci_config_path":"","public_jobs":true,"shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"allow_merge_on_skipped_pipeline":null,"request_access_enabled":false,"only_allow_merge_if_all_discussions_are_resolved":false,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","squash_option":"default_off","enforce_auth_checks_on_uploads":true,"suggestion_commit_message":null,"merge_commit_template":null,"squash_commit_template":null,"mr_default_title_template":null,"issue_branch_template":null,"warn_about_potentially_unwanted_characters":false,"autoclose_referenced_issues":true,"max_artifacts_size":null,"external_authorization_classification_label":"","requirements_enabled":false,"requirements_access_level":"enabled","security_and_compliance_enabled":false,"compliance_frameworks":[],"web_based_commit_signing_enabled":false,"permissions":{"project_access":null,"group_access":{"access_level":50,"notification_level":3}}} \ No newline at end of file diff --git a/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fversion b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fversion new file mode 100644 index 0000000000..4223440766 --- /dev/null +++ b/services/migrations/testdata/gitlab/confidential/GET_%2Fapi%2Fv4%2Fversion @@ -0,0 +1,20 @@ +Cache-Control: max-age=0, private, must-revalidate +Cf-Cache-Status: MISS +Content-Security-Policy: default-src 'none' +Content-Type: application/json +Etag: W/"f4c5c4fb869a5286a8cc44a863504620" +Gitlab-Lb: haproxy-main-41-lb-gprd +Gitlab-Sv: api-gke-us-east1-c +Ratelimit-Limit: 2000 +Ratelimit-Name: throttle_authenticated_api +Ratelimit-Observed: 1 +Ratelimit-Remaining: 1999 +Ratelimit-Reset: 1779789300 +Referrer-Policy: strict-origin-when-cross-origin +Strict-Transport-Security: max-age=31536000 +Vary: Origin, Accept-Encoding +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Runtime: 0.050947 + +{"version":"19.1.0-pre","revision":"02f8641dbf3","kas":{"enabled":true,"externalUrl":"wss://kas.gitlab.com","externalK8sProxyUrl":"https://kas.gitlab.com/k8s-proxy","version":"19.1.0-rc1+772eacfab6e697eed51d7ebf031fdb25b1851c16"},"enterprise":true} \ No newline at end of file