Commit 02378293 authored by Imre Farkas's avatar Imre Farkas

Merge branch '31919-graphql-MR-sidebar-mutations' into 'master'

GraphQL: Add Merge Request milestone mutation

See merge request gitlab-org/gitlab!19257
parents 2aa19681 ebd8a931
...@@ -46,7 +46,7 @@ class GitlabSchema < GraphQL::Schema ...@@ -46,7 +46,7 @@ class GitlabSchema < GraphQL::Schema
super(query_str, **kwargs) super(query_str, **kwargs)
end end
def id_from_object(object) def id_from_object(object, _type = nil, _ctx = nil)
unless object.respond_to?(:to_global_id) unless object.respond_to?(:to_global_id)
# This is an error in our schema and needs to be solved. So raise a # This is an error in our schema and needs to be solved. So raise a
# more meaningful error message # more meaningful error message
...@@ -57,7 +57,7 @@ class GitlabSchema < GraphQL::Schema ...@@ -57,7 +57,7 @@ class GitlabSchema < GraphQL::Schema
object.to_global_id object.to_global_id
end end
def object_from_id(global_id) def object_from_id(global_id, _ctx = nil)
gid = GlobalID.parse(global_id) gid = GlobalID.parse(global_id)
unless gid unless gid
......
# frozen_string_literal: true
module Mutations
module MergeRequests
class SetMilestone < Base
graphql_name 'MergeRequestSetMilestone'
argument :milestone_id,
GraphQL::ID_TYPE,
required: false,
loads: Types::MilestoneType,
description: <<~DESC
The milestone to assign to the merge request.
DESC
def resolve(project_path:, iid:, milestone: nil)
merge_request = authorized_find!(project_path: project_path, iid: iid)
project = merge_request.project
::MergeRequests::UpdateService.new(project, current_user, milestone: milestone)
.execute(merge_request)
{
merge_request: merge_request,
errors: merge_request.errors.full_messages
}
end
end
end
end
...@@ -6,6 +6,8 @@ module Types ...@@ -6,6 +6,8 @@ module Types
authorize :read_milestone authorize :read_milestone
field :id, GraphQL::ID_TYPE, null: false,
description: 'ID of the milestone'
field :description, GraphQL::STRING_TYPE, null: true, field :description, GraphQL::STRING_TYPE, null: true,
description: 'Description of the milestone' description: 'Description of the milestone'
field :title, GraphQL::STRING_TYPE, null: false, field :title, GraphQL::STRING_TYPE, null: false,
......
...@@ -9,6 +9,7 @@ module Types ...@@ -9,6 +9,7 @@ module Types
mount_mutation Mutations::AwardEmojis::Add mount_mutation Mutations::AwardEmojis::Add
mount_mutation Mutations::AwardEmojis::Remove mount_mutation Mutations::AwardEmojis::Remove
mount_mutation Mutations::AwardEmojis::Toggle mount_mutation Mutations::AwardEmojis::Toggle
mount_mutation Mutations::MergeRequests::SetMilestone
mount_mutation Mutations::MergeRequests::SetWip, calls_gitaly: true mount_mutation Mutations::MergeRequests::SetWip, calls_gitaly: true
mount_mutation Mutations::Notes::Create::Note, calls_gitaly: true mount_mutation Mutations::Notes::Create::Note, calls_gitaly: true
mount_mutation Mutations::Notes::Create::DiffNote, calls_gitaly: true mount_mutation Mutations::Notes::Create::DiffNote, calls_gitaly: true
......
---
title: 'GraphQL: Add Merge Request milestone mutation'
merge_request: 19257
author:
type: added
...@@ -473,6 +473,14 @@ The API can be explored interactively using the [GraphiQL IDE](../index.md#graph ...@@ -473,6 +473,14 @@ The API can be explored interactively using the [GraphiQL IDE](../index.md#graph
| `cherryPickOnCurrentMergeRequest` | Boolean! | Whether or not a user can perform `cherry_pick_on_current_merge_request` on this resource | | `cherryPickOnCurrentMergeRequest` | Boolean! | Whether or not a user can perform `cherry_pick_on_current_merge_request` on this resource |
| `revertOnCurrentMergeRequest` | Boolean! | Whether or not a user can perform `revert_on_current_merge_request` on this resource | | `revertOnCurrentMergeRequest` | Boolean! | Whether or not a user can perform `revert_on_current_merge_request` on this resource |
### MergeRequestSetMilestonePayload
| Name | Type | Description |
| --- | ---- | ---------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Reasons why the mutation failed. |
| `mergeRequest` | MergeRequest | The merge request after mutation |
### MergeRequestSetWipPayload ### MergeRequestSetWipPayload
| Name | Type | Description | | Name | Type | Description |
...@@ -492,6 +500,7 @@ The API can be explored interactively using the [GraphiQL IDE](../index.md#graph ...@@ -492,6 +500,7 @@ The API can be explored interactively using the [GraphiQL IDE](../index.md#graph
| Name | Type | Description | | Name | Type | Description |
| --- | ---- | ---------- | | --- | ---- | ---------- |
| `id` | ID! | ID of the milestone |
| `description` | String | Description of the milestone | | `description` | String | Description of the milestone |
| `title` | String! | Title of the milestone | | `title` | String! | Title of the milestone |
| `state` | String! | State of the milestone | | `state` | String! | State of the milestone |
......
# frozen_string_literal: true
require 'spec_helper'
describe Mutations::MergeRequests::SetMilestone do
let(:merge_request) { create(:merge_request) }
let(:user) { create(:user) }
subject(:mutation) { described_class.new(object: nil, context: { current_user: user }) }
describe '#resolve' do
let(:milestone) { create(:milestone, project: merge_request.project) }
let(:mutated_merge_request) { subject[:merge_request] }
subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, milestone: milestone) }
it 'raises an error if the resource is not accessible to the user' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
context 'when the user can update the merge request' do
before do
merge_request.project.add_developer(user)
end
it 'returns the merge request with the milestone' do
expect(mutated_merge_request).to eq(merge_request)
expect(mutated_merge_request.milestone).to eq(milestone)
expect(subject[:errors]).to be_empty
end
it 'returns errors merge request could not be updated' do
# Make the merge request invalid
merge_request.allow_broken = true
merge_request.update!(source_project: nil)
expect(subject[:errors]).not_to be_empty
end
context 'when passing milestone_id as nil' do
let(:milestone) { nil }
it 'removes the milestone' do
merge_request.update!(milestone: create(:milestone, project: merge_request.project))
expect(mutated_merge_request.milestone).to eq(nil)
end
it 'does not do anything if the MR already does not have a milestone' do
expect(mutated_merge_request.milestone).to eq(nil)
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe 'Setting milestone of a merge request' do
include GraphqlHelpers
let(:current_user) { create(:user) }
let(:merge_request) { create(:merge_request) }
let(:project) { merge_request.project }
let(:milestone) { create(:milestone, project: project) }
let(:input) { { milestone_id: GitlabSchema.id_from_object(milestone).to_s } }
let(:mutation) do
variables = {
project_path: project.full_path,
iid: merge_request.iid.to_s
}
graphql_mutation(:merge_request_set_milestone, variables.merge(input),
<<-QL.strip_heredoc
clientMutationId
errors
mergeRequest {
id
milestone {
id
}
}
QL
)
end
def mutation_response
graphql_mutation_response(:merge_request_set_milestone)
end
before do
project.add_developer(current_user)
end
it 'returns an error if the user is not allowed to update the merge request' do
post_graphql_mutation(mutation, current_user: create(:user))
expect(graphql_errors).not_to be_empty
end
it 'sets the merge request milestone' do
post_graphql_mutation(mutation, current_user: current_user)
expect(response).to have_gitlab_http_status(:success)
expect(mutation_response['mergeRequest']['milestone']['id']).to eq(milestone.to_global_id.to_s)
end
context 'when passing milestone_id nil as input' do
let(:input) { { milestone_id: nil } }
it 'removes the merge request milestone' do
merge_request.update!(milestone: milestone)
post_graphql_mutation(mutation, current_user: current_user)
expect(response).to have_gitlab_http_status(:success)
expect(mutation_response['mergeRequest']['milestone']).to be_nil
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment