diff --git a/app/graphql/types/commit_type.rb b/app/graphql/types/commit_type.rb index 5dd862c7388902e1828a08b529184adee1daac6b..2a2c8af5468511d2f73a535d9a35c1f6ad2c160d 100644 --- a/app/graphql/types/commit_type.rb +++ b/app/graphql/types/commit_type.rb @@ -59,6 +59,14 @@ class CommitType < BaseObject field :author, type: Types::UserType, null: true, description: 'Author of the commit.' + field :diffs, [Types::DiffType], null: true, calls_gitaly: true, + description: 'Diffs contained within the commit. ' \ + 'This field can only be resolved for 10 diffs in any single request.' do + # Limited to 10 calls per GraphQL request as calling `diffs` multiple times will + # lead to N+1 queries to Gitaly. + extension ::Gitlab::Graphql::Limit::FieldCallCount, limit: 10 + end + field :pipelines, null: true, description: 'Pipelines of the commit ordered latest first.', @@ -68,6 +76,10 @@ class CommitType < BaseObject markdown_field :full_title_html, null: true markdown_field :description_html, null: true + def diffs + object.diffs.diffs + end + def author_gravatar GravatarService.new.execute(object.author_email, 40) end diff --git a/app/graphql/types/diff_type.rb b/app/graphql/types/diff_type.rb new file mode 100644 index 0000000000000000000000000000000000000000..1c67c8c645a4595b181b8ce142953db7f255858d --- /dev/null +++ b/app/graphql/types/diff_type.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module Types + # rubocop: disable Graphql/AuthorizeTypes + class DiffType < BaseObject + graphql_name 'Diff' + + field :a_mode, GraphQL::Types::String, null: true, + description: 'Old file mode of the file.' + field :b_mode, GraphQL::Types::String, null: true, + description: 'New file mode of the file.' + field :deleted_file, GraphQL::Types::String, null: true, + description: 'Indicates if the file has been removed. ' + field :diff, GraphQL::Types::String, null: true, + description: 'Diff representation of the changes made to the file.' + field :new_file, GraphQL::Types::String, null: true, + description: 'Indicates if the file has just been added. ' + field :new_path, GraphQL::Types::String, null: true, + description: 'New path of the file.' + field :old_path, GraphQL::Types::String, null: true, + description: 'Old path of the file.' + field :renamed_file, GraphQL::Types::String, null: true, + description: 'Indicates if the file has been renamed.' + end + # rubocop: enable Graphql/AuthorizeTypes +end diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 2bb170c47da91bc7ece6bce27e097bd301ab1e09..43cec187232d4561817fbba89ad26ac56eb7177a 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -13194,6 +13194,7 @@ Code Quality report for a pipeline. | <a id="commitauthoreddate"></a>`authoredDate` | [`Time`](#time) | Timestamp of when the commit was authored. | | <a id="commitdescription"></a>`description` | [`String`](#string) | Description of the commit message. | | <a id="commitdescriptionhtml"></a>`descriptionHtml` | [`String`](#string) | GitLab Flavored Markdown rendering of `description`. | +| <a id="commitdiffs"></a>`diffs` | [`[Diff!]`](#diff) | Diffs contained within the commit. This field can only be resolved for 10 diffs in any single request. | | <a id="commitfulltitle"></a>`fullTitle` | [`String`](#string) | Full title of the commit message. | | <a id="commitfulltitlehtml"></a>`fullTitleHtml` | [`String`](#string) | GitLab Flavored Markdown rendering of `full_title`. | | <a id="commitid"></a>`id` | [`ID!`](#id) | ID (global ID) of the commit. | @@ -14366,6 +14367,21 @@ Snapshot. | <a id="devopsadoptionsnapshottotalprojectscount"></a>`totalProjectsCount` | [`Int`](#int) | Total number of projects. | | <a id="devopsadoptionsnapshotvulnerabilitymanagementusedcount"></a>`vulnerabilityManagementUsedCount` | [`Int`](#int) | Total number of projects with vulnerability management used at least once. | +### `Diff` + +#### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| <a id="diffamode"></a>`aMode` | [`String`](#string) | Old file mode of the file. | +| <a id="diffbmode"></a>`bMode` | [`String`](#string) | New file mode of the file. | +| <a id="diffdeletedfile"></a>`deletedFile` | [`String`](#string) | Indicates if the file has been removed. | +| <a id="diffdiff"></a>`diff` | [`String`](#string) | Diff representation of the changes made to the file. | +| <a id="diffnewfile"></a>`newFile` | [`String`](#string) | Indicates if the file has just been added. | +| <a id="diffnewpath"></a>`newPath` | [`String`](#string) | New path of the file. | +| <a id="diffoldpath"></a>`oldPath` | [`String`](#string) | Old path of the file. | +| <a id="diffrenamedfile"></a>`renamedFile` | [`String`](#string) | Indicates if the file has been renamed. | + ### `DiffPosition` #### Fields diff --git a/spec/graphql/types/commit_type_spec.rb b/spec/graphql/types/commit_type_spec.rb index 561d165148bb153dba3eb1780a946641cfde545d..3912b0905e3299a47a720ddfabe3286ac3406bb1 100644 --- a/spec/graphql/types/commit_type_spec.rb +++ b/spec/graphql/types/commit_type_spec.rb @@ -12,8 +12,14 @@ it 'contains attributes related to commit' do expect(described_class).to have_graphql_fields( :id, :sha, :short_id, :title, :full_title, :full_title_html, :description, :description_html, :message, :title_html, :authored_date, - :author_name, :author_email, :author_gravatar, :author, :web_url, :web_path, + :author_name, :author_email, :author_gravatar, :author, :diffs, :web_url, :web_path, :pipelines, :signature_html, :signature ) end + + describe 'diffs' do + it 'limits field call count' do + expect(described_class.fields['diffs'].extensions).to include(a_kind_of(::Gitlab::Graphql::Limit::FieldCallCount)) + end + end end diff --git a/spec/graphql/types/diff_type_spec.rb b/spec/graphql/types/diff_type_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..04f4ff9feeda1b4bd4349d4fb62664763d9156df --- /dev/null +++ b/spec/graphql/types/diff_type_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['Diff'], feature_category: :code_review_workflow do + include RepoHelpers + include GraphqlHelpers + + specify { expect(described_class.graphql_name).to eq('Diff') } + + it 'contains attributes related to diff' do + expect(described_class).to have_graphql_fields( + :a_mode, :b_mode, :deleted_file, :diff, :new_file, :new_path, :old_path, :renamed_file + ) + end + + describe '#diff' do + subject { resolve_field(:diff, diff, object_type: described_class) } + + let(:merge_request_diff) { create(:merge_request).merge_request_diff } + let(:diff) { merge_request_diff.diffs.diffs.first } + + it 'returns the diff of the passed commit' do + is_expected.to eq(diff.diff) + end + end +end