Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
599047fe
Commit
599047fe
authored
Nov 13, 2020
by
Vitali Tatarintev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add OncallScheduleCreate GraphQL mutation
Add a GraphQL mutation to create on-call schedules for a project
parent
85f370f9
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
538 additions
and
2 deletions
+538
-2
doc/api/graphql/reference/gitlab_schema.graphql
doc/api/graphql/reference/gitlab_schema.graphql
+51
-0
doc/api/graphql/reference/gitlab_schema.json
doc/api/graphql/reference/gitlab_schema.json
+167
-0
doc/api/graphql/reference/index.md
doc/api/graphql/reference/index.md
+10
-0
ee/app/graphql/ee/types/mutation_type.rb
ee/app/graphql/ee/types/mutation_type.rb
+1
-0
ee/app/graphql/mutations/incident_management/oncall_schedule/create.rb
...l/mutations/incident_management/oncall_schedule/create.rb
+45
-0
ee/app/graphql/mutations/incident_management/oncall_schedule/oncall_schedule_base.rb
...cident_management/oncall_schedule/oncall_schedule_base.rb
+25
-0
ee/app/graphql/resolvers/incident_management/oncall_schedule_resolver.rb
...resolvers/incident_management/oncall_schedule_resolver.rb
+0
-1
ee/app/models/incident_management/oncall_schedule.rb
ee/app/models/incident_management/oncall_schedule.rb
+1
-1
ee/app/policies/ee/project_policy.rb
ee/app/policies/ee/project_policy.rb
+1
-0
ee/app/services/incident_management/oncall_schedules/create_service.rb
...es/incident_management/oncall_schedules/create_service.rb
+49
-0
ee/spec/graphql/mutations/incident_management/oncall_schedule/create_spec.rb
...ations/incident_management/oncall_schedule/create_spec.rb
+64
-0
ee/spec/requests/api/graphql/mutations/incident_management/oncall_schedule/create_spec.rb
...ations/incident_management/oncall_schedule/create_spec.rb
+64
-0
ee/spec/services/incident_management/oncall_schedules/create_service_spec.rb
...cident_management/oncall_schedules/create_service_spec.rb
+60
-0
No files found.
doc/api/graphql/reference/gitlab_schema.graphql
View file @
599047fe
...
...
@@ -13950,6 +13950,7 @@ type Mutation {
"""
mergeRequestUpdate
(
input
:
MergeRequestUpdateInput
!):
MergeRequestUpdatePayload
namespaceIncreaseStorageTemporarily
(
input
:
NamespaceIncreaseStorageTemporarilyInput
!):
NamespaceIncreaseStorageTemporarilyPayload
oncallScheduleCreate
(
input
:
OncallScheduleCreateInput
!):
OncallScheduleCreatePayload
pipelineCancel
(
input
:
PipelineCancelInput
!):
PipelineCancelPayload
pipelineDestroy
(
input
:
PipelineDestroyInput
!):
PipelineDestroyPayload
pipelineRetry
(
input
:
PipelineRetryInput
!):
PipelineRetryPayload
...
...
@@ -14526,6 +14527,56 @@ Identifier of Noteable
"""
scalar
NoteableID
"""
Autogenerated input type of OncallScheduleCreate
"""
input
OncallScheduleCreateInput
{
"""
A
unique
identifier
for
the
client
performing
the
mutation
.
"""
clientMutationId
:
String
"""
The
description
of
the
on
-
call
schedule
"""
description
:
String
"""
The
name
of
the
on
-
call
schedule
"""
name
:
String
!
"""
The
project
to
create
the
on
-
call
schedule
in
"""
projectPath
:
ID
!
"""
The
timezone
of
the
on
-
call
schedule
"""
timezone
:
String
!
}
"""
Autogenerated return type of OncallScheduleCreate
"""
type
OncallScheduleCreatePayload
{
"""
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
"""
...
...
doc/api/graphql/reference/gitlab_schema.json
View file @
599047fe
...
...
@@ -40443,6 +40443,33 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "oncallScheduleCreate",
"description": null,
"args": [
{
"name": "input",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "OncallScheduleCreateInput",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "OncallScheduleCreatePayload",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "pipelineCancel",
"description": null,
...
...
@@ -43026,6 +43053,146 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "OncallScheduleCreateInput",
"description": "Autogenerated input type of OncallScheduleCreate",
"fields": null,
"inputFields": [
{
"name": "projectPath",
"description": "The project to create the on-call schedule in",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "name",
"description": "The name of the on-call schedule",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"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": "NON_NULL",
"name": null,
"ofType": {
"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": "OncallScheduleCreatePayload",
"description": "Autogenerated return type of OncallScheduleCreate",
"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",
doc/api/graphql/reference/index.md
View file @
599047fe
...
...
@@ -2218,6 +2218,16 @@ Autogenerated return type of NamespaceIncreaseStorageTemporarily.
|
`repositionNote`
| Boolean! | Indicates the user can perform
`reposition_note`
on this resource |
|
`resolveNote`
| Boolean! | Indicates the user can perform
`resolve_note`
on this resource |
### OncallScheduleCreatePayload
Autogenerated return type of OncallScheduleCreate.
| 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.
...
...
ee/app/graphql/ee/types/mutation_type.rb
View file @
599047fe
...
...
@@ -48,6 +48,7 @@ module EE
mount_mutation
::
Mutations
::
Admin
::
Analytics
::
DevopsAdoption
::
Segments
::
Create
mount_mutation
::
Mutations
::
Admin
::
Analytics
::
DevopsAdoption
::
Segments
::
Update
mount_mutation
::
Mutations
::
Admin
::
Analytics
::
DevopsAdoption
::
Segments
::
Delete
mount_mutation
::
Mutations
::
IncidentManagement
::
OncallSchedule
::
Create
prepend
(
Types
::
DeprecatedMutations
)
end
...
...
ee/app/graphql/mutations/incident_management/oncall_schedule/create.rb
0 → 100644
View file @
599047fe
# frozen_string_literal: true
module
Mutations
module
IncidentManagement
module
OncallSchedule
class
Create
<
OncallScheduleBase
include
ResolvesProject
graphql_name
'OncallScheduleCreate'
argument
:project_path
,
GraphQL
::
ID_TYPE
,
required:
true
,
description:
'The project to create the on-call schedule in'
argument
:name
,
GraphQL
::
STRING_TYPE
,
required:
true
,
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:
true
,
description:
'The timezone of the on-call schedule'
def
resolve
(
args
)
project
=
authorized_find!
(
full_path:
args
[
:project_path
])
response
::
IncidentManagement
::
OncallSchedules
::
CreateService
.
new
(
project
,
current_user
,
args
.
slice
(
:name
,
:description
,
:timezone
)
).
execute
end
private
def
find_object
(
full_path
:)
resolve_project
(
full_path:
full_path
)
end
end
end
end
end
ee/app/graphql/mutations/incident_management/oncall_schedule/oncall_schedule_base.rb
0 → 100644
View file @
599047fe
# frozen_string_literal: true
module
Mutations
module
IncidentManagement
module
OncallSchedule
class
OncallScheduleBase
<
BaseMutation
field
:oncall_schedule
,
::
Types
::
IncidentManagement
::
OncallScheduleType
,
null:
true
,
description:
'The on-call schedule'
authorize
:modify_incident_management_oncall_schedule
private
def
response
(
result
)
{
oncall_schedule:
result
.
payload
[
:oncall_schedule
],
errors:
result
.
errors
}
end
end
end
end
end
ee/app/graphql/resolvers/incident_management/oncall_schedule_resolver.rb
View file @
599047fe
...
...
@@ -10,7 +10,6 @@ module Resolvers
def
resolve
(
**
args
)
return
[]
unless
Ability
.
allowed?
(
current_user
,
:read_incident_management_oncall_schedule
,
project
)
project
.
incident_management_oncall_schedules
end
end
...
...
ee/app/models/incident_management/oncall_schedule.rb
View file @
599047fe
...
...
@@ -14,7 +14,7 @@ module IncidentManagement
has_internal_id
:iid
,
scope: :project
validates
:name
,
presence:
true
,
length:
{
maximum:
NAME_LENGTH
}
validates
:name
,
presence:
true
,
uniqueness:
{
scope: :project
},
length:
{
maximum:
NAME_LENGTH
}
validates
:description
,
length:
{
maximum:
DESCRIPTION_LENGTH
}
validates
:timezone
,
presence:
true
,
inclusion:
{
in: :timezones
}
...
...
ee/app/policies/ee/project_policy.rb
View file @
599047fe
...
...
@@ -242,6 +242,7 @@ module EE
enable
:modify_merge_request_author_setting
enable
:modify_merge_request_committer_setting
enable
:read_incident_management_oncall_schedule
enable
:modify_incident_management_oncall_schedule
end
rule
{
license_scanning_enabled
&
can?
(
:maintainer_access
)
}.
enable
:admin_software_license_policy
...
...
ee/app/services/incident_management/oncall_schedules/create_service.rb
0 → 100644
View file @
599047fe
# frozen_string_literal: true
module
IncidentManagement
module
OncallSchedules
class
CreateService
# @param project [Project]
# @param user [User]
# @param params [Hash]
def
initialize
(
project
,
user
,
params
)
@project
=
project
@user
=
user
@params
=
params
end
def
execute
return
error_no_permissions
unless
allowed?
oncall_schedule
=
project
.
incident_management_oncall_schedules
.
create
(
params
)
return
error_in_create
(
oncall_schedule
)
unless
oncall_schedule
.
persisted?
success
(
oncall_schedule
)
end
private
attr_reader
:project
,
:user
,
:params
def
allowed?
user
&
.
can?
(
:modify_incident_management_oncall_schedule
,
project
)
end
def
error
(
message
)
ServiceResponse
.
error
(
message:
message
)
end
def
success
(
oncall_schedule
)
ServiceResponse
.
success
(
payload:
{
oncall_schedule:
oncall_schedule
})
end
def
error_no_permissions
error
(
_
(
'You have insufficient permissions to create an on-call schedule for this project'
))
end
def
error_in_create
(
oncall_schedule
)
error
(
oncall_schedule
.
errors
.
full_messages
.
to_sentence
)
end
end
end
end
ee/spec/graphql/mutations/incident_management/oncall_schedule/create_spec.rb
0 → 100644
View file @
599047fe
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Mutations
::
IncidentManagement
::
OncallSchedule
::
Create
do
let_it_be
(
:current_user
)
{
create
(
:user
)
}
let_it_be
(
:project
)
{
create
(
:project
)
}
let
(
:args
)
do
{
project_path:
project
.
full_path
,
name:
'On-call schedule'
,
description:
'On-call schedule description'
,
timezone:
'Europe/Berlin'
}
end
specify
{
expect
(
described_class
).
to
require_graphql_authorizations
(
:modify_incident_management_oncall_schedule
)
}
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::CreateService responds with success'
do
it
'returns the on-call schedule with no errors'
do
expect
(
resolve
).
to
eq
(
oncall_schedule:
::
IncidentManagement
::
OncallSchedule
.
last
,
errors:
[]
)
end
end
context
'when OncallSchedules::CreateService responds with an error'
do
before
do
allow_any_instance_of
(
::
IncidentManagement
::
OncallSchedules
::
CreateService
)
.
to
receive
(
:execute
)
.
and_return
(
ServiceResponse
.
error
(
payload:
{
oncall_schedule:
nil
},
message:
'An on-call schedule already exists'
))
end
it
'returns errors'
do
expect
(
resolve
).
to
eq
(
oncall_schedule:
nil
,
errors:
[
'An on-call schedule already exists'
]
)
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
ee/spec/requests/api/graphql/mutations/incident_management/oncall_schedule/create_spec.rb
0 → 100644
View file @
599047fe
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
'Creating a new on-call schedule'
do
include
GraphqlHelpers
let_it_be
(
:current_user
)
{
create
(
:user
)
}
let_it_be
(
:project
)
{
create
(
:project
)
}
let
(
:variables
)
do
{
project_path:
project
.
full_path
,
name:
'New on-call schedule'
,
description:
'on-call schedule description'
,
timezone:
'Europe/Berlin'
}
end
let
(
:mutation
)
do
graphql_mutation
(
:oncall_schedule_create
,
variables
)
do
<<~
QL
clientMutationId
errors
oncallSchedule {
iid
name
description
timezone
}
QL
end
end
let
(
:mutation_response
)
{
graphql_mutation_response
(
:oncall_schedule_create
)
}
before
do
project
.
add_maintainer
(
current_user
)
end
it
'create a new on-call schedule'
do
post_graphql_mutation
(
mutation
,
current_user:
current_user
)
new_oncall_schedule
=
::
IncidentManagement
::
OncallSchedule
.
last!
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'
=>
new_oncall_schedule
.
iid
.
to_s
,
'name'
=>
'New on-call schedule'
,
'description'
=>
'on-call schedule description'
,
'timezone'
=>
'Europe/Berlin'
)
end
%i[project_path name timezone]
.
each
do
|
argument
|
context
"without required argument
#{
argument
}
"
do
before
do
variables
.
delete
(
argument
)
end
it_behaves_like
'an invalid argument to the mutation'
,
argument_name:
argument
end
end
end
ee/spec/services/incident_management/oncall_schedules/create_service_spec.rb
0 → 100644
View file @
599047fe
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
IncidentManagement
::
OncallSchedules
::
CreateService
do
let_it_be
(
:user_with_permissions
)
{
create
(
:user
)
}
let_it_be
(
:user_without_permissions
)
{
create
(
:user
)
}
let_it_be_with_reload
(
:project
)
{
create
(
:project
)
}
let
(
:current_user
)
{
user_with_permissions
}
let
(
:params
)
{
{
name:
'On-call schedule'
,
description:
'On-call schedule description'
,
timezone:
'Europe/Berlin'
}
}
let
(
:service
)
{
described_class
.
new
(
project
,
current_user
,
params
)
}
before
do
project
.
add_maintainer
(
user_with_permissions
)
end
describe
'#execute'
do
shared_examples
'error response'
do
|
message
|
it
'has an informative message'
do
expect
(
execute
).
to
be_error
expect
(
execute
.
message
).
to
eq
(
message
)
end
end
subject
(
:execute
)
{
service
.
execute
}
context
'when the current_user is anonymous'
do
let
(
:current_user
)
{
nil
}
it_behaves_like
'error response'
,
'You have insufficient permissions to create an on-call schedule for this project'
end
context
'when the current_user does not have permissions to create on-call schedules'
do
let
(
:current_user
)
{
user_without_permissions
}
it_behaves_like
'error response'
,
'You have insufficient permissions to create an on-call schedule for this project'
end
context
'when an on-call schedule already exists'
do
let_it_be
(
:oncall_schedule
)
{
create
(
:incident_management_oncall_schedule
,
project:
project
,
name:
'On-call schedule'
)
}
it_behaves_like
'error response'
,
'Name has already been taken'
end
context
'with valid params'
do
it
'successfully creates an on-call schedule'
do
expect
(
execute
).
to
be_success
oncall_schedule
=
execute
.
payload
[
:oncall_schedule
]
expect
(
oncall_schedule
).
to
be_a
(
::
IncidentManagement
::
OncallSchedule
)
expect
(
oncall_schedule
.
name
).
to
eq
(
'On-call schedule'
)
expect
(
oncall_schedule
.
description
).
to
eq
(
'On-call schedule description'
)
expect
(
oncall_schedule
.
timezone
).
to
eq
(
'Europe/Berlin'
)
end
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment