From e642d738439bdc3ab09d7185937cb480dcb1d93f Mon Sep 17 00:00:00 2001 From: Jonas Waelter Date: Thu, 20 May 2021 15:29:58 +0200 Subject: [PATCH 1/6] Add 'topics' field to project entity in place of 'tag_list' Changelog: deprecated --- doc/api/boards.md | 3 +- doc/api/groups.md | 20 ++-- doc/api/project_clusters.md | 9 +- doc/api/projects.md | 94 +++++++++++++++---- doc/api/search.md | 6 +- .../modules/projects/data/mock_data.json | 1 + .../vue_shared/dashboards/mock_data.js | 1 + lib/api/entities/basic_project_details.rb | 17 ++-- .../api/schemas/public_api/v4/board.json | 2 + .../api/schemas/public_api/v4/project.json | 8 +- spec/frontend/fixtures/static/projects.json | 9 ++ spec/requests/api/projects_spec.rb | 11 ++- 12 files changed, 140 insertions(+), 41 deletions(-) diff --git a/doc/api/boards.md b/doc/api/boards.md index 3252036c8409cb..3cdd9552d6687e 100644 --- a/doc/api/boards.md +++ b/doc/api/boards.md @@ -250,7 +250,8 @@ Example response: "path_with_namespace": "diaspora/diaspora-project-site", "created_at": "2018-07-03T05:48:49.982Z", "default_branch": null, - "tag_list": [], + "tag_list": [], //deprecated, use `topics` instead + "topics": [], "ssh_url_to_repo": "ssh://user@example.com/diaspora/diaspora-project-site.git", "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", diff --git a/doc/api/groups.md b/doc/api/groups.md index 6bec6e0f6f8c1d..f80375f43b5514 100644 --- a/doc/api/groups.md +++ b/doc/api/groups.md @@ -302,7 +302,8 @@ Example response: "id": 9, "description": "foo", "default_branch": "master", - "tag_list": [], + "tag_list": [], //deprecated, use `topics` instead + "topics": [], "archived": false, "visibility": "internal", "ssh_url_to_repo": "git@gitlab.example.com/html5-boilerplate.git", @@ -381,9 +382,8 @@ Example response: "path_with_namespace":"h5bp/html5-boilerplate", "created_at":"2020-04-27T06:13:22.642Z", "default_branch":"master", - "tag_list":[ - - ], + "tag_list":[], //deprecated, use `topics` instead + "topics":[], "ssh_url_to_repo":"ssh://git@gitlab.com/h5bp/html5-boilerplate.git", "http_url_to_repo":"http://gitlab.com/h5bp/html5-boilerplate.git", "web_url":"http://gitlab.com/h5bp/html5-boilerplate", @@ -540,7 +540,8 @@ Example response: "id": 7, "description": "Voluptas veniam qui et beatae voluptas doloremque explicabo facilis.", "default_branch": "master", - "tag_list": [], + "tag_list": [], //deprecated, use `topics` instead + "topics": [], "archived": false, "visibility": "public", "ssh_url_to_repo": "git@gitlab.example.com:twitter/typeahead-js.git", @@ -578,7 +579,8 @@ Example response: "id": 6, "description": "Aspernatur omnis repudiandae qui voluptatibus eaque.", "default_branch": "master", - "tag_list": [], + "tag_list": [], //deprecated, use `topics` instead + "topics": [], "archived": false, "visibility": "internal", "ssh_url_to_repo": "git@gitlab.example.com:twitter/flight.git", @@ -618,7 +620,8 @@ Example response: "id": 8, "description": "Velit eveniet provident fugiat saepe eligendi autem.", "default_branch": "master", - "tag_list": [], + "tag_list": [], //deprecated, use `topics` instead + "topics": [], "archived": false, "visibility": "private", "ssh_url_to_repo": "git@gitlab.example.com:h5bp/html5-boilerplate.git", @@ -883,7 +886,8 @@ Example response: "id": 9, "description": "foo", "default_branch": "master", - "tag_list": [], + "tag_list": [], //deprecated, use `topics` instead + "topics": [], "public": false, "archived": false, "visibility": "internal", diff --git a/doc/api/project_clusters.md b/doc/api/project_clusters.md index ab7ad2416310d7..88a4d10a08a1e1 100644 --- a/doc/api/project_clusters.md +++ b/doc/api/project_clusters.md @@ -151,7 +151,8 @@ Example response: "path_with_namespace":"root/project-with-clusters-api", "created_at":"2019-01-02T20:13:32.600Z", "default_branch":null, - "tag_list":[], + "tag_list":[], //deprecated, use `topics` instead + "topics":[], "ssh_url_to_repo":"ssh://gitlab.example.com/root/project-with-clusters-api.git", "http_url_to_repo":"https://gitlab.example.com/root/project-with-clusters-api.git", "web_url":"https://gitlab.example.com/root/project-with-clusters-api", @@ -247,7 +248,8 @@ Example response: "path_with_namespace":"root/project-with-clusters-api", "created_at":"2019-01-02T20:13:32.600Z", "default_branch":null, - "tag_list":[], + "tag_list":[], //deprecated, use `topics` instead + "topics":[], "ssh_url_to_repo":"ssh:://gitlab.example.com/root/project-with-clusters-api.git", "http_url_to_repo":"https://gitlab.example.com/root/project-with-clusters-api.git", "web_url":"https://gitlab.example.com/root/project-with-clusters-api", @@ -357,7 +359,8 @@ Example response: "path_with_namespace":"root/project-with-clusters-api", "created_at":"2019-01-02T20:13:32.600Z", "default_branch":null, - "tag_list":[], + "tag_list":[], //deprecated, use `topics` instead + "topics":[], "ssh_url_to_repo":"ssh:://gitlab.example.com/root/project-with-clusters-api.git", "http_url_to_repo":"https://gitlab.example.com/root/project-with-clusters-api.git", "web_url":"https://gitlab.example.com/root/project-with-clusters-api", diff --git a/doc/api/projects.md b/doc/api/projects.md index 0f3d9cdd33451a..647659bd38ab78 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -59,7 +59,7 @@ GET /projects | `sort` | string | **{dotted-circle}** No | Return projects sorted in `asc` or `desc` order. Default is `desc`. | | `starred` | boolean | **{dotted-circle}** No | Limit by projects starred by the current user. | | `statistics` | boolean | **{dotted-circle}** No | Include project statistics. | -| `topic` | string | **{dotted-circle}** No | Comma-separated topic names. Limit results to projects that match all of given topics. See `tag_list` attribute. | +| `topic` | string | **{dotted-circle}** No | Comma-separated topic names. Limit results to projects that match all of given topics. See `topics` attribute. | | `visibility` | string | **{dotted-circle}** No | Limit by visibility `public`, `internal`, or `private`. | | `wiki_checksum_failed` **(PREMIUM)** | boolean | **{dotted-circle}** No | Limit projects where the wiki checksum calculation has failed ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6137) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2). | | `with_custom_attributes` | boolean | **{dotted-circle}** No | Include [custom attributes](custom_attributes.md) in response. _(admins only)_ | @@ -82,7 +82,11 @@ When `simple=true` or the user is unauthenticated this returns something like: "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git", "web_url": "http://example.com/diaspora/diaspora-client", "readme_url": "http://example.com/diaspora/diaspora-client/blob/master/README.md", - "tag_list": [ + "tag_list": [ //deprecated, use `topics` instead + "example", + "disapora client" + ], + "topics": [ "example", "disapora client" ], @@ -116,7 +120,11 @@ When the user is authenticated and `simple` is not set this returns something li "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git", "web_url": "http://example.com/diaspora/diaspora-client", "readme_url": "http://example.com/diaspora/diaspora-client/blob/master/README.md", - "tag_list": [ + "tag_list": [ //deprecated, use `topics` instead + "example", + "disapora client" + ], + "topics": [ "example", "disapora client" ], @@ -200,7 +208,11 @@ When the user is authenticated and `simple` is not set this returns something li "http_url_to_repo": "http://example.com/brightbox/puppet.git", "web_url": "http://example.com/brightbox/puppet", "readme_url": "http://example.com/brightbox/puppet/blob/master/README.md", - "tag_list": [ + "tag_list": [ //deprecated, use `topics` instead + "example", + "puppet" + ], + "topics": [ "example", "puppet" ], @@ -300,6 +312,10 @@ When the user is authenticated and `simple` is not set this returns something li ] ``` +NOTE: +The `tag_list` attribute has been deprecated +and is removed in API v5 in favor of the `topics` attribute. + NOTE: For users of [GitLab Premium or higher](https://about.gitlab.com/pricing/), the `marked_for_deletion_at` attribute has been deprecated, and is removed @@ -378,7 +394,11 @@ GET /users/:user_id/projects "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git", "web_url": "http://example.com/diaspora/diaspora-client", "readme_url": "http://example.com/diaspora/diaspora-client/blob/master/README.md", - "tag_list": [ + "tag_list": [ //deprecated, use `topics` instead + "example", + "disapora client" + ], + "topics": [ "example", "disapora client" ], @@ -462,7 +482,11 @@ GET /users/:user_id/projects "http_url_to_repo": "http://example.com/brightbox/puppet.git", "web_url": "http://example.com/brightbox/puppet", "readme_url": "http://example.com/brightbox/puppet/blob/master/README.md", - "tag_list": [ + "tag_list": [ //deprecated, use `topics` instead + "example", + "puppet" + ], + "topics": [ "example", "puppet" ], @@ -606,7 +630,11 @@ Example response: "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git", "web_url": "http://example.com/diaspora/diaspora-client", "readme_url": "http://example.com/diaspora/diaspora-client/blob/master/README.md", - "tag_list": [ + "tag_list": [ //deprecated, use `topics` instead + "example", + "disapora client" + ], + "topics": [ "example", "disapora client" ], @@ -683,7 +711,11 @@ Example response: "http_url_to_repo": "http://example.com/brightbox/puppet.git", "web_url": "http://example.com/brightbox/puppet", "readme_url": "http://example.com/brightbox/puppet/blob/master/README.md", - "tag_list": [ + "tag_list": [ //deprecated, use `topics` instead + "example", + "puppet" + ], + "topics": [ "example", "puppet" ], @@ -804,7 +836,11 @@ GET /projects/:id "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", - "tag_list": [ + "tag_list": [ //deprecated, use `topics` instead + "example", + "disapora project" + ], + "topics": [ "example", "disapora project" ], @@ -940,6 +976,10 @@ GET /projects/:id } ``` +NOTE: +The `tag_list` attribute has been deprecated +and is removed in API v5 in favor of the `topics` attribute. + Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/) can also see the `approvals_before_merge` parameter: @@ -974,7 +1014,8 @@ If the project is a fork, and you provide a valid token to authenticate, the "path_with_namespace":"gitlab-org/gitlab-foss", "created_at":"2013-09-26T06:02:36.000Z", "default_branch":"master", - "tag_list":[], + "tag_list":[], //deprecated, use `topics` instead + "topics":[], "ssh_url_to_repo":"git@gitlab.com:gitlab-org/gitlab-foss.git", "http_url_to_repo":"https://gitlab.com/gitlab-org/gitlab-foss.git", "web_url":"https://gitlab.com/gitlab-org/gitlab-foss", @@ -1393,7 +1434,11 @@ Example responses: "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", - "tag_list": [ + "tag_list": [ //deprecated, use `topics` instead + "example", + "disapora project" + ], + "topics": [ "example", "disapora project" ], @@ -1480,7 +1525,11 @@ Example response: "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", - "tag_list": [ + "tag_list": [ //deprecated, use `topics` instead + "example", + "disapora project" + ], + "topics": [ "example", "disapora project" ], @@ -1573,7 +1622,11 @@ Example response: "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", - "tag_list": [ + "tag_list": [ //deprecated, use `topics` instead + "example", + "disapora project" + ], + "topics": [ "example", "disapora project" ], @@ -1741,7 +1794,11 @@ Example response: "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", - "tag_list": [ + "tag_list": [ //deprecated, use `topics` instead + "example", + "disapora project" + ], + "topics": [ "example", "disapora project" ], @@ -1855,7 +1912,11 @@ Example response: "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", "web_url": "http://example.com/diaspora/diaspora-project-site", "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", - "tag_list": [ + "tag_list": [ //deprecated, use `topics` instead + "example", + "disapora project" + ], + "topics": [ "example", "disapora project" ], @@ -2439,7 +2500,8 @@ Example response: "path_with_namespace": "cute-cats/hello-world", "created_at": "2020-10-15T16:25:22.415Z", "default_branch": "master", - "tag_list": [], + "tag_list": [], //deprecated, use `topics` instead + "topics": [], "ssh_url_to_repo": "git@gitlab.example.com:cute-cats/hello-world.git", "http_url_to_repo": "https://gitlab.example.com/cute-cats/hello-world.git", "web_url": "https://gitlab.example.com/cute-cats/hello-world", diff --git a/doc/api/search.md b/doc/api/search.md index c8f24c0924ab3c..cc5a23cd7a7a71 100644 --- a/doc/api/search.md +++ b/doc/api/search.md @@ -54,7 +54,8 @@ Example response: "path_with_namespace": "twitter/flight", "created_at": "2017-09-05T07:58:01.621Z", "default_branch": "master", - "tag_list":[], + "tag_list":[], //deprecated, use `topics` instead + "topics":[], "ssh_url_to_repo": "ssh://jarka@localhost:2222/twitter/flight.git", "http_url_to_repo": "http://localhost:3000/twitter/flight.git", "web_url": "http://localhost:3000/twitter/flight", @@ -475,7 +476,8 @@ Example response: "path_with_namespace": "twitter/flight", "created_at": "2017-09-05T07:58:01.621Z", "default_branch": "master", - "tag_list":[], + "tag_list":[], //deprecated, use `topics` instead + "topics":[], "ssh_url_to_repo": "ssh://jarka@localhost:2222/twitter/flight.git", "http_url_to_repo": "http://localhost:3000/twitter/flight.git", "web_url": "http://localhost:3000/twitter/flight", diff --git a/ee/spec/frontend/security_dashboard/store/modules/projects/data/mock_data.json b/ee/spec/frontend/security_dashboard/store/modules/projects/data/mock_data.json index e834a0c58f1c61..5085d2eeffcdf8 100644 --- a/ee/spec/frontend/security_dashboard/store/modules/projects/data/mock_data.json +++ b/ee/spec/frontend/security_dashboard/store/modules/projects/data/mock_data.json @@ -4,6 +4,7 @@ "description": "foo", "default_branch": "master", "tag_list": [], + "topics": [], "archived": false, "visibility": "internal", "ssh_url_to_repo": "git@gitlab.example.com/html5-boilerplate.git", diff --git a/ee/spec/frontend/vue_shared/dashboards/mock_data.js b/ee/spec/frontend/vue_shared/dashboards/mock_data.js index 5eb49348acdac4..fb54d771dcccbd 100644 --- a/ee/spec/frontend/vue_shared/dashboards/mock_data.js +++ b/ee/spec/frontend/vue_shared/dashboards/mock_data.js @@ -102,6 +102,7 @@ export function mockProjectData( created_at: '2019-02-01T15:40:27.522Z', default_branch: 'main', tag_list: [], + topics: [], avatar_url: null, web_url: 'https://mock-web_url/', namespace: { diff --git a/lib/api/entities/basic_project_details.rb b/lib/api/entities/basic_project_details.rb index 2de49d6ed40318..6fbe78436d2f63 100644 --- a/lib/api/entities/basic_project_details.rb +++ b/lib/api/entities/basic_project_details.rb @@ -7,11 +7,16 @@ class BasicProjectDetails < Entities::ProjectIdentity expose :default_branch, if: -> (project, options) { Ability.allowed?(options[:current_user], :download_code, project) } # Avoids an N+1 query: https://github.com/mbleigh/acts-as-taggable-on/issues/91#issuecomment-168273770 + expose :tag_list do |project| - # Tags is a preloaded association. If we perform then sorting + @topics ||= project.topics.pluck(:name).sort # rubocop:disable CodeReuse/ActiveRecord + end + + expose :topics do |project| + # Topics is a preloaded association. If we perform then sorting # through the database, it will trigger a new query, ending up # in an N+1 if we have several projects - project.tags.pluck(:name).sort # rubocop:disable CodeReuse/ActiveRecord + @topics ||= project.topics.pluck(:name).sort # rubocop:disable CodeReuse/ActiveRecord end expose :ssh_url_to_repo, :http_url_to_repo, :web_url, :readme_url @@ -40,12 +45,12 @@ class BasicProjectDetails < Entities::ProjectIdentity # rubocop: disable CodeReuse/ActiveRecord def self.preload_relation(projects_relation, options = {}) - # Preloading tags, should be done with using only `:tags`, - # as `:tags` are defined as: `has_many :tags, through: :taggings` - # N+1 is solved then by using `subject.tags.map(&:name)` + # Preloading topics, should be done with using only `:topics`, + # as `:topics` are defined as: `has_many :topics, through: :taggings` + # N+1 is solved then by using `subject.topics.map(&:name)` # MR describing the solution: https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/20555 projects_relation.preload(:project_feature, :route) - .preload(:import_state, :tags) + .preload(:import_state, :topics) .preload(:auto_devops) .preload(namespace: [:route, :owner]) end diff --git a/spec/fixtures/api/schemas/public_api/v4/board.json b/spec/fixtures/api/schemas/public_api/v4/board.json index c3a140c1bd7384..11dfa131e88161 100644 --- a/spec/fixtures/api/schemas/public_api/v4/board.json +++ b/spec/fixtures/api/schemas/public_api/v4/board.json @@ -15,6 +15,7 @@ "description", "default_branch", "tag_list", + "topics", "ssh_url_to_repo", "http_url_to_repo", "web_url", @@ -34,6 +35,7 @@ "description": { "type": ["string", "null"] }, "default_branch": { "type": ["string", "null"] }, "tag_list": { "type": "array" }, + "topics": { "type": "array" }, "ssh_url_to_repo": { "type": "string" }, "http_url_to_repo": { "type": "string" }, "web_url": { "type": "string" }, diff --git a/spec/fixtures/api/schemas/public_api/v4/project.json b/spec/fixtures/api/schemas/public_api/v4/project.json index 4a3149f2bdcddd..2f708538d96002 100644 --- a/spec/fixtures/api/schemas/public_api/v4/project.json +++ b/spec/fixtures/api/schemas/public_api/v4/project.json @@ -15,6 +15,12 @@ "type": "string" } }, + "topics": { + "type": "array", + "items": { + "type": "string" + } + }, "ssh_url_to_repo": { "type": "string" }, "http_url_to_repo": { "type": "string" }, "web_url": { "type": "string" }, @@ -37,7 +43,7 @@ }, "required": [ "id", "name", "name_with_namespace", "description", "path", - "path_with_namespace", "created_at", "default_branch", "tag_list", + "path_with_namespace", "created_at", "default_branch", "tag_list", "topics", "ssh_url_to_repo", "http_url_to_repo", "web_url", "readme_url", "avatar_url", "star_count", "forks_count", "last_activity_at", "namespace" ], diff --git a/spec/frontend/fixtures/static/projects.json b/spec/frontend/fixtures/static/projects.json index f28d9899099d0a..d843549039b1b1 100644 --- a/spec/frontend/fixtures/static/projects.json +++ b/spec/frontend/fixtures/static/projects.json @@ -3,6 +3,7 @@ "description": "", "default_branch": null, "tag_list": [], + "topics": [], "public": true, "archived": false, "visibility_level": 20, @@ -54,6 +55,7 @@ "description": "Voluptatem quae nulla eius numquam ullam voluptatibus quia modi.", "default_branch": "master", "tag_list": [], + "topics": [], "public": false, "archived": false, "visibility_level": 0, @@ -114,6 +116,7 @@ "description": "Modi odio mollitia dolorem qui.", "default_branch": "master", "tag_list": [], + "topics": [], "public": false, "archived": false, "visibility_level": 0, @@ -162,6 +165,7 @@ "description": "Omnis asperiores ipsa et beatae quidem necessitatibus quia.", "default_branch": "master", "tag_list": [], + "topics": [], "public": true, "archived": false, "visibility_level": 20, @@ -210,6 +214,7 @@ "description": "Voluptatem commodi voluptate placeat architecto beatae illum dolores fugiat.", "default_branch": "master", "tag_list": [], + "topics": [], "public": false, "archived": false, "visibility_level": 0, @@ -258,6 +263,7 @@ "description": "Aut molestias quas est ut aperiam officia quod libero.", "default_branch": "master", "tag_list": [], + "topics": [], "public": true, "archived": false, "visibility_level": 20, @@ -309,6 +315,7 @@ "description": "Excepturi molestiae quia repellendus omnis est illo illum eligendi.", "default_branch": "master", "tag_list": [], + "topics": [], "public": true, "archived": false, "visibility_level": 20, @@ -357,6 +364,7 @@ "description": "Adipisci quaerat dignissimos enim sed ipsam dolorem quia.", "default_branch": "master", "tag_list": [], + "topics": [], "public": false, "archived": false, "visibility_level": 10, @@ -408,6 +416,7 @@ "description": "Vel voluptatem maxime saepe ex quia.", "default_branch": "master", "tag_list": [], + "topics": [], "public": false, "archived": false, "visibility_level": 0, diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index e103aa3d6dee57..51b87a55b1e81b 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -184,13 +184,14 @@ end end - it 'includes the project labels as the tag_list' do + it 'includes project topics' do get api('/projects', user) expect(response).to have_gitlab_http_status(:ok) expect(response).to include_pagination_headers expect(json_response).to be_an Array - expect(json_response.first.keys).to include('tag_list') + expect(json_response.first.keys).to include('tag_list') # deprecated in favor of 'topics' + expect(json_response.first.keys).to include('topics') end it 'includes open_issues_count' do @@ -1892,7 +1893,8 @@ expect(json_response['id']).to eq(project.id) expect(json_response['description']).to eq(project.description) expect(json_response['default_branch']).to eq(project.default_branch) - expect(json_response['tag_list']).to be_an Array + expect(json_response['tag_list']).to be_an Array # deprecated in favor of 'topics' + expect(json_response['topics']).to be_an Array expect(json_response['archived']).to be_falsey expect(json_response['visibility']).to be_present expect(json_response['ssh_url_to_repo']).to be_present @@ -1969,7 +1971,8 @@ def failure_message(diff) expect(json_response['id']).to eq(project.id) expect(json_response['description']).to eq(project.description) expect(json_response['default_branch']).to eq(project.default_branch) - expect(json_response['tag_list']).to be_an Array + expect(json_response['tag_list']).to be_an Array # deprecated in favor of 'topics' + expect(json_response['topics']).to be_an Array expect(json_response['archived']).to be_falsey expect(json_response['visibility']).to be_present expect(json_response['ssh_url_to_repo']).to be_present -- GitLab From d2f2b43d0e920064e8054867a3648e0b4a02cf65 Mon Sep 17 00:00:00 2001 From: Jonas Waelter Date: Thu, 20 May 2021 17:12:11 +0200 Subject: [PATCH 2/6] Add changelog entry --- .../unreleased/project-topics-get-projects.yml | 5 +++++ lib/api/entities/basic_project_details.rb | 14 +++++++------- spec/requests/api/project_attributes.yml | 1 + 3 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 changelogs/unreleased/project-topics-get-projects.yml diff --git a/changelogs/unreleased/project-topics-get-projects.yml b/changelogs/unreleased/project-topics-get-projects.yml new file mode 100644 index 00000000000000..ac38a1092b7939 --- /dev/null +++ b/changelogs/unreleased/project-topics-get-projects.yml @@ -0,0 +1,5 @@ +--- +title: Add 'topics' field in place of 'tag_list' to 'project' API entity +merge_request: 62206 +author: Jonas Wälter @wwwjon +type: deprecated diff --git a/lib/api/entities/basic_project_details.rb b/lib/api/entities/basic_project_details.rb index 6fbe78436d2f63..57eb52c05f2b1f 100644 --- a/lib/api/entities/basic_project_details.rb +++ b/lib/api/entities/basic_project_details.rb @@ -9,14 +9,14 @@ class BasicProjectDetails < Entities::ProjectIdentity # Avoids an N+1 query: https://github.com/mbleigh/acts-as-taggable-on/issues/91#issuecomment-168273770 expose :tag_list do |project| - @topics ||= project.topics.pluck(:name).sort # rubocop:disable CodeReuse/ActiveRecord + @topics ||= project.tags.pluck(:name).sort # rubocop:disable CodeReuse/ActiveRecord end expose :topics do |project| - # Topics is a preloaded association. If we perform then sorting + # Tags is a preloaded association. If we perform then sorting # through the database, it will trigger a new query, ending up # in an N+1 if we have several projects - @topics ||= project.topics.pluck(:name).sort # rubocop:disable CodeReuse/ActiveRecord + @topics ||= project.tags.pluck(:name).sort # rubocop:disable CodeReuse/ActiveRecord end expose :ssh_url_to_repo, :http_url_to_repo, :web_url, :readme_url @@ -45,12 +45,12 @@ class BasicProjectDetails < Entities::ProjectIdentity # rubocop: disable CodeReuse/ActiveRecord def self.preload_relation(projects_relation, options = {}) - # Preloading topics, should be done with using only `:topics`, - # as `:topics` are defined as: `has_many :topics, through: :taggings` - # N+1 is solved then by using `subject.topics.map(&:name)` + # Preloading tags, should be done with using only `:tags`, + # as `:tags` are defined as: `has_many :tags, through: :taggings` + # N+1 is solved then by using `subject.tags.map(&:name)` # MR describing the solution: https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/20555 projects_relation.preload(:project_feature, :route) - .preload(:import_state, :topics) + .preload(:import_state, :tags) .preload(:auto_devops) .preload(namespace: [:route, :owner]) end diff --git a/spec/requests/api/project_attributes.yml b/spec/requests/api/project_attributes.yml index d28442bd692c3c..2f1cd009fbc8c1 100644 --- a/spec/requests/api/project_attributes.yml +++ b/spec/requests/api/project_attributes.yml @@ -69,6 +69,7 @@ itself: # project - shared_with_groups - ssh_url_to_repo - tag_list + - topics - web_url build_auto_devops: # auto_devops -- GitLab From a571b7d07db0fe758d0273abca9ac7ddb6ac7838 Mon Sep 17 00:00:00 2001 From: Jonas Waelter Date: Fri, 28 May 2021 09:46:37 +0200 Subject: [PATCH 3/6] Refactor topic_names in basic_project_details --- lib/api/entities/basic_project_details.rb | 28 ++++++++++++++--------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/lib/api/entities/basic_project_details.rb b/lib/api/entities/basic_project_details.rb index 57eb52c05f2b1f..91831fe2bdfdaa 100644 --- a/lib/api/entities/basic_project_details.rb +++ b/lib/api/entities/basic_project_details.rb @@ -4,20 +4,13 @@ module API module Entities class BasicProjectDetails < Entities::ProjectIdentity include ::API::ProjectsRelationBuilder + include Gitlab::Utils::StrongMemoize expose :default_branch, if: -> (project, options) { Ability.allowed?(options[:current_user], :download_code, project) } # Avoids an N+1 query: https://github.com/mbleigh/acts-as-taggable-on/issues/91#issuecomment-168273770 - expose :tag_list do |project| - @topics ||= project.tags.pluck(:name).sort # rubocop:disable CodeReuse/ActiveRecord - end - - expose :topics do |project| - # Tags is a preloaded association. If we perform then sorting - # through the database, it will trigger a new query, ending up - # in an N+1 if we have several projects - @topics ||= project.tags.pluck(:name).sort # rubocop:disable CodeReuse/ActiveRecord - end + expose :topic_names, as: :tag_list + expose :topic_names, as: :topics expose :ssh_url_to_repo, :http_url_to_repo, :web_url, :readme_url @@ -45,7 +38,7 @@ class BasicProjectDetails < Entities::ProjectIdentity # rubocop: disable CodeReuse/ActiveRecord def self.preload_relation(projects_relation, options = {}) - # Preloading tags, should be done with using only `:tags`, + # Preloading topics, should be done with using only `:tags`, # as `:tags` are defined as: `has_many :tags, through: :taggings` # N+1 is solved then by using `subject.tags.map(&:name)` # MR describing the solution: https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/20555 @@ -55,6 +48,19 @@ def self.preload_relation(projects_relation, options = {}) .preload(namespace: [:route, :owner]) end # rubocop: enable CodeReuse/ActiveRecord + + private + + alias_method :project, :object + + def topic_names + # Topics is a preloaded association. If we perform then sorting + # through the database, it will trigger a new query, ending up + # in an N+1 if we have several projects + strong_memoize(:topic_names) do + project.tags.pluck(:name).sort # rubocop:disable CodeReuse/ActiveRecord + end + end end end end -- GitLab From e802e1ffc981a7475440cddf7491e670f5645bb1 Mon Sep 17 00:00:00 2001 From: Marcin Sedlak-Jakubowski Date: Tue, 1 Jun 2021 16:36:09 +0000 Subject: [PATCH 4/6] Add version note to doc --- doc/api/projects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/projects.md b/doc/api/projects.md index 647659bd38ab78..881c0769827aa8 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -59,7 +59,7 @@ GET /projects | `sort` | string | **{dotted-circle}** No | Return projects sorted in `asc` or `desc` order. Default is `desc`. | | `starred` | boolean | **{dotted-circle}** No | Limit by projects starred by the current user. | | `statistics` | boolean | **{dotted-circle}** No | Include project statistics. | -| `topic` | string | **{dotted-circle}** No | Comma-separated topic names. Limit results to projects that match all of given topics. See `topics` attribute. | +| `topic` | string | **{dotted-circle}** No | Comma-separated topic names. Limit results to projects that match all of given topics. See `topics` attribute. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62206) in GitLab 14.0.) | | `visibility` | string | **{dotted-circle}** No | Limit by visibility `public`, `internal`, or `private`. | | `wiki_checksum_failed` **(PREMIUM)** | boolean | **{dotted-circle}** No | Limit projects where the wiki checksum calculation has failed ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6137) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2). | | `with_custom_attributes` | boolean | **{dotted-circle}** No | Include [custom attributes](custom_attributes.md) in response. _(admins only)_ | -- GitLab From cdead894fc73549fb4a192216159186619ef0a55 Mon Sep 17 00:00:00 2001 From: Jonas Waelter Date: Wed, 2 Jun 2021 08:10:15 +0200 Subject: [PATCH 5/6] Revert "Add version note to doc" This reverts commit 54b7e9530d73f23c04d1d59d1a7d215caad0e80c. --- doc/api/projects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/projects.md b/doc/api/projects.md index 881c0769827aa8..647659bd38ab78 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -59,7 +59,7 @@ GET /projects | `sort` | string | **{dotted-circle}** No | Return projects sorted in `asc` or `desc` order. Default is `desc`. | | `starred` | boolean | **{dotted-circle}** No | Limit by projects starred by the current user. | | `statistics` | boolean | **{dotted-circle}** No | Include project statistics. | -| `topic` | string | **{dotted-circle}** No | Comma-separated topic names. Limit results to projects that match all of given topics. See `topics` attribute. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62206) in GitLab 14.0.) | +| `topic` | string | **{dotted-circle}** No | Comma-separated topic names. Limit results to projects that match all of given topics. See `topics` attribute. | | `visibility` | string | **{dotted-circle}** No | Limit by visibility `public`, `internal`, or `private`. | | `wiki_checksum_failed` **(PREMIUM)** | boolean | **{dotted-circle}** No | Limit projects where the wiki checksum calculation has failed ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6137) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2). | | `with_custom_attributes` | boolean | **{dotted-circle}** No | Include [custom attributes](custom_attributes.md) in response. _(admins only)_ | -- GitLab From c5c16fa2382c41d5a54b56fc094adb615f14edeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20W=C3=A4lter?= Date: Thu, 3 Jun 2021 11:06:03 +0000 Subject: [PATCH 6/6] Remove project-topics-get-projects.yml --- changelogs/unreleased/project-topics-get-projects.yml | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 changelogs/unreleased/project-topics-get-projects.yml diff --git a/changelogs/unreleased/project-topics-get-projects.yml b/changelogs/unreleased/project-topics-get-projects.yml deleted file mode 100644 index ac38a1092b7939..00000000000000 --- a/changelogs/unreleased/project-topics-get-projects.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add 'topics' field in place of 'tag_list' to 'project' API entity -merge_request: 62206 -author: Jonas Wälter @wwwjon -type: deprecated -- GitLab