Commit 5890106c authored by Vitali Tatarintev's avatar Vitali Tatarintev

Add Update on-call schedule GraphQL mutation

Add a mutation to update on-call schedules
parent 2e0ab3a2
......@@ -14144,6 +14144,7 @@ type Mutation {
namespaceIncreaseStorageTemporarily(input: NamespaceIncreaseStorageTemporarilyInput!): NamespaceIncreaseStorageTemporarilyPayload
oncallScheduleCreate(input: OncallScheduleCreateInput!): OncallScheduleCreatePayload
oncallScheduleDestroy(input: OncallScheduleDestroyInput!): OncallScheduleDestroyPayload
oncallScheduleUpdate(input: OncallScheduleUpdateInput!): OncallScheduleUpdatePayload
pipelineCancel(input: PipelineCancelInput!): PipelineCancelPayload
pipelineDestroy(input: PipelineDestroyInput!): PipelineDestroyPayload
pipelineRetry(input: PipelineRetryInput!): PipelineRetryPayload
......@@ -14838,6 +14839,61 @@ type OncallScheduleDestroyPayload {
oncallSchedule: IncidentManagementOncallSchedule
}
"""
Autogenerated input type of OncallScheduleUpdate
"""
input OncallScheduleUpdateInput {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
The description of the on-call schedule
"""
description: String
"""
The on-call schedule internal ID to update
"""
iid: String!
"""
The name of the on-call schedule
"""
name: String
"""
The project to update the on-call schedule in
"""
projectPath: ID!
"""
The timezone of the on-call schedule
"""
timezone: String
}
"""
Autogenerated return type of OncallScheduleUpdate
"""
type OncallScheduleUpdatePayload {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
Errors encountered during execution of the mutation.
"""
errors: [String!]!
"""
The on-call schedule
"""
oncallSchedule: IncidentManagementOncallSchedule
}
"""
Represents a package
"""
......
......@@ -41158,6 +41158,33 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "oncallScheduleUpdate",
"description": null,
"args": [
{
"name": "input",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "OncallScheduleUpdateInput",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "OncallScheduleUpdatePayload",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "pipelineCancel",
"description": null,
......@@ -44104,6 +44131,152 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "OncallScheduleUpdateInput",
"description": "Autogenerated input type of OncallScheduleUpdate",
"fields": null,
"inputFields": [
{
"name": "projectPath",
"description": "The project to update the on-call schedule in",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "iid",
"description": "The on-call schedule internal ID to update",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "name",
"description": "The name of the on-call schedule",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "description",
"description": "The description of the on-call schedule",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "timezone",
"description": "The timezone of the on-call schedule",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "OncallScheduleUpdatePayload",
"description": "Autogenerated return type of OncallScheduleUpdate",
"fields": [
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "errors",
"description": "Errors encountered during execution of the mutation.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "oncallSchedule",
"description": "The on-call schedule",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "IncidentManagementOncallSchedule",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "Package",
......@@ -2272,6 +2272,16 @@ Autogenerated return type of OncallScheduleDestroy.
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `oncallSchedule` | IncidentManagementOncallSchedule | The on-call schedule |
### OncallScheduleUpdatePayload
Autogenerated return type of OncallScheduleUpdate.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `oncallSchedule` | IncidentManagementOncallSchedule | The on-call schedule |
### Package
Represents a package.
......
......@@ -49,6 +49,7 @@ module EE
mount_mutation ::Mutations::Admin::Analytics::DevopsAdoption::Segments::Update
mount_mutation ::Mutations::Admin::Analytics::DevopsAdoption::Segments::Delete
mount_mutation ::Mutations::IncidentManagement::OncallSchedule::Create
mount_mutation ::Mutations::IncidentManagement::OncallSchedule::Update
mount_mutation ::Mutations::IncidentManagement::OncallSchedule::Destroy
prepend(Types::DeprecatedMutations)
......
# frozen_string_literal: true
module Mutations
module IncidentManagement
module OncallSchedule
class Update < OncallScheduleBase
graphql_name 'OncallScheduleUpdate'
argument :project_path, GraphQL::ID_TYPE,
required: true,
description: 'The project to update the on-call schedule in'
argument :iid, GraphQL::STRING_TYPE,
required: true,
description: 'The on-call schedule internal ID to update'
argument :name, GraphQL::STRING_TYPE,
required: false,
description: 'The name of the on-call schedule'
argument :description, GraphQL::STRING_TYPE,
required: false,
description: 'The description of the on-call schedule'
argument :timezone, GraphQL::STRING_TYPE,
required: false,
description: 'The timezone of the on-call schedule'
def resolve(args)
oncall_schedule = authorized_find!(project_path: args[:project_path], iid: args[:iid])
response ::IncidentManagement::OncallSchedules::UpdateService.new(
oncall_schedule,
current_user,
args.slice(:name, :description, :timezone)
).execute
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Mutations::IncidentManagement::OncallSchedule::Update do
let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:oncall_schedule) { create(:incident_management_oncall_schedule, project: project) }
let(:args) do
{
project_path: project.full_path,
iid: oncall_schedule.iid.to_s,
name: 'Updated name',
description: 'Updated description',
timezone: 'America/New_York'
}
end
specify { expect(described_class).to require_graphql_authorizations(:admin_incident_management_oncall_schedule) }
before do
stub_licensed_features(oncall_schedules: true)
end
describe '#resolve' do
subject(:resolve) { mutation_for(project, current_user).resolve(args) }
context 'user has access to project' do
before do
project.add_maintainer(current_user)
end
context 'when OncallSchedules::UpdateService responds with success' do
it 'returns the on-call schedule with no errors' do
expect(resolve).to eq(
oncall_schedule: oncall_schedule,
errors: []
)
end
end
context 'when OncallSchedules::UpdateService responds with an error' do
before do
allow_any_instance_of(::IncidentManagement::OncallSchedules::UpdateService)
.to receive(:execute)
.and_return(ServiceResponse.error(payload: { oncall_schedule: nil }, message: 'Name has already been taken'))
end
it 'returns errors' do
expect(resolve).to eq(
oncall_schedule: nil,
errors: ['Name has already been taken']
)
end
end
end
context 'when resource is not accessible to the user' do
it 'raises an error' do
expect { resolve }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
end
private
def mutation_for(project, user)
described_class.new(object: project, context: { current_user: user }, field: nil)
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Updating an on-call schedule' do
include GraphqlHelpers
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:oncall_schedule) { create(:incident_management_oncall_schedule, project: project) }
let(:variables) do
{
project_path: project.full_path,
iid: oncall_schedule.iid.to_s,
name: 'Updated name',
description: 'Updated description',
timezone: 'America/New_York'
}
end
let(:mutation) do
graphql_mutation(:oncall_schedule_update, variables) do
<<~QL
clientMutationId
errors
oncallSchedule {
iid
name
description
timezone
}
QL
end
end
let(:mutation_response) { graphql_mutation_response(:oncall_schedule_update) }
before do
stub_licensed_features(oncall_schedules: true)
project.add_maintainer(user)
end
it 'updates the on-call schedule' do
post_graphql_mutation(mutation, current_user: user)
oncall_schedule_response = mutation_response['oncallSchedule']
expect(response).to have_gitlab_http_status(:success)
expect(oncall_schedule_response.slice(*%w[iid name description timezone])).to eq(
'iid' => oncall_schedule.iid.to_s,
'name' => variables[:name],
'description' => variables[:description],
'timezone' => variables[:timezone]
)
end
end
......@@ -6,7 +6,7 @@ RSpec.describe IncidentManagement::OncallSchedules::UpdateService do
let_it_be(:user_with_permissions) { create(:user) }
let_it_be(:user_without_permissions) { create(:user) }
let_it_be_with_refind(:project) { create(:project) }
let!(:oncall_schedule) { create(:incident_management_oncall_schedule, project: project) }
let_it_be_with_reload(:oncall_schedule) { create(:incident_management_oncall_schedule, project: project) }
let(:current_user) { user_with_permissions }
let(:params) { { name: 'Updated name', description: 'Updated description', timezone: 'America/New_York' } }
......
......@@ -31402,6 +31402,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
msgid "You have insufficient permissions to update this HTTP integration"
msgstr ""
......
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