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
a0c53384
Commit
a0c53384
authored
Nov 19, 2020
by
Adam Hegyi
Committed by
Peter Leitzen
Nov 19, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
GraphQL mutations for Devops Adoption Segment
This change adds mutations for Devops Adoption Segment
parent
e3f99409
Changes
24
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
1271 additions
and
6 deletions
+1271
-6
app/models/analytics/devops_adoption/segment.rb
app/models/analytics/devops_adoption/segment.rb
+1
-1
app/models/analytics/devops_adoption/segment_selection.rb
app/models/analytics/devops_adoption/segment_selection.rb
+4
-4
changelogs/unreleased/262395-devops-adoption-mutations.yml
changelogs/unreleased/262395-devops-adoption-mutations.yml
+5
-0
doc/api/graphql/reference/gitlab_schema.graphql
doc/api/graphql/reference/gitlab_schema.graphql
+123
-0
doc/api/graphql/reference/gitlab_schema.json
doc/api/graphql/reference/gitlab_schema.json
+433
-0
doc/api/graphql/reference/index.md
doc/api/graphql/reference/index.md
+29
-0
ee/app/graphql/ee/types/mutation_type.rb
ee/app/graphql/ee/types/mutation_type.rb
+3
-0
ee/app/graphql/mutations/admin/analytics/devops_adoption/segments/create.rb
...ations/admin/analytics/devops_adoption/segments/create.rb
+28
-0
ee/app/graphql/mutations/admin/analytics/devops_adoption/segments/delete.rb
...ations/admin/analytics/devops_adoption/segments/delete.rb
+29
-0
ee/app/graphql/mutations/admin/analytics/devops_adoption/segments/mixins.rb
...ations/admin/analytics/devops_adoption/segments/mixins.rb
+61
-0
ee/app/graphql/mutations/admin/analytics/devops_adoption/segments/update.rb
...ations/admin/analytics/devops_adoption/segments/update.rb
+32
-0
ee/app/policies/ee/global_policy.rb
ee/app/policies/ee/global_policy.rb
+1
-0
ee/app/services/analytics/devops_adoption/segments/create_service.rb
...ices/analytics/devops_adoption/segments/create_service.rb
+51
-0
ee/app/services/analytics/devops_adoption/segments/delete_service.rb
...ices/analytics/devops_adoption/segments/delete_service.rb
+37
-0
ee/app/services/analytics/devops_adoption/segments/update_service.rb
...ices/analytics/devops_adoption/segments/update_service.rb
+35
-0
ee/spec/models/analytics/devops_adoption/segment_spec.rb
ee/spec/models/analytics/devops_adoption/segment_spec.rb
+20
-0
ee/spec/requests/api/graphql/mutations/admin/analytics/devops_adoption/segments/create_spec.rb
...s/admin/analytics/devops_adoption/segments/create_spec.rb
+66
-0
ee/spec/requests/api/graphql/mutations/admin/analytics/devops_adoption/segments/delete_spec.rb
...s/admin/analytics/devops_adoption/segments/delete_spec.rb
+41
-0
ee/spec/requests/api/graphql/mutations/admin/analytics/devops_adoption/segments/update_spec.rb
...s/admin/analytics/devops_adoption/segments/update_spec.rb
+80
-0
ee/spec/services/analytics/devops_adoption/segments/create_service_spec.rb
...analytics/devops_adoption/segments/create_service_spec.rb
+70
-0
ee/spec/services/analytics/devops_adoption/segments/delete_service_spec.rb
...analytics/devops_adoption/segments/delete_service_spec.rb
+41
-0
ee/spec/services/analytics/devops_adoption/segments/update_service_spec.rb
...analytics/devops_adoption/segments/update_service_spec.rb
+59
-0
ee/spec/support/shared_examples/graphql/mutations/analytics/devops_adoption/top_level_errors_shared_examples.rb
...ytics/devops_adoption/top_level_errors_shared_examples.rb
+19
-0
spec/models/analytics/devops_adoption/segment_selection_spec.rb
...odels/analytics/devops_adoption/segment_selection_spec.rb
+3
-1
No files found.
app/models/analytics/devops_adoption/segment.rb
View file @
a0c53384
...
...
@@ -7,7 +7,7 @@ class Analytics::DevopsAdoption::Segment < ApplicationRecord
has_many
:groups
,
through: :segment_selections
validates
:name
,
presence:
true
,
uniqueness:
true
,
length:
{
maximum:
255
}
validate
:validate_segment_count
validate
:validate_segment_count
,
on: :create
accepts_nested_attributes_for
:segment_selections
,
allow_destroy:
true
...
...
app/models/analytics/devops_adoption/segment_selection.rb
View file @
a0c53384
...
...
@@ -14,7 +14,7 @@ class Analytics::DevopsAdoption::SegmentSelection < ApplicationRecord
validates
:group_id
,
uniqueness:
{
scope: :segment_id
,
if: :group
}
validate
:exclusive_project_or_group
validate
:validate_selection_count
validate
:validate_selection_count
,
on: :create
private
...
...
@@ -27,9 +27,9 @@ class Analytics::DevopsAdoption::SegmentSelection < ApplicationRecord
def
validate_selection_count
return
unless
segment
selection_count_for_segment
=
self
.
class
.
where
(
segment:
segment
).
count
if
selection
_count_for_segment
>=
ALLOWED_SELECTIONS_PER_SEGMENT
# handle single model creation and bulk creation from accepts_nested_attributes_for
selections
=
segment
.
segment_selections
+
[
self
]
if
selection
s
.
reject
(
&
:marked_for_destruction?
).
uniq
.
size
>
ALLOWED_SELECTIONS_PER_SEGMENT
errors
.
add
(
:segment
,
s_
(
'DevopsAdoptionSegmentSelection|The maximum number of selections has been reached'
))
end
end
...
...
changelogs/unreleased/262395-devops-adoption-mutations.yml
0 → 100644
View file @
a0c53384
---
title
:
Add GraphQL mutations for Devops Adoption Segment
merge_request
:
47066
author
:
type
:
added
doc/api/graphql/reference/gitlab_schema.graphql
View file @
a0c53384
...
...
@@ -932,6 +932,11 @@ type AlertTodoCreatePayload {
todo
:
Todo
}
"""
Identifier of Analytics::DevopsAdoption::Segment
"""
scalar
AnalyticsDevopsAdoptionSegmentID
"""
User availability status
"""
...
...
@@ -3894,6 +3899,46 @@ type CreateCustomEmojiPayload {
errors
:
[
String
!]!
}
"""
Autogenerated input type of CreateDevopsAdoptionSegment
"""
input
CreateDevopsAdoptionSegmentInput
{
"""
A
unique
identifier
for
the
client
performing
the
mutation
.
"""
clientMutationId
:
String
"""
The
array
of
group
IDs
to
set
for
the
segment
"""
groupIds
:
[
GroupID
!]
"""
Name
of
the
segment
"""
name
:
String
!
}
"""
Autogenerated return type of CreateDevopsAdoptionSegment
"""
type
CreateDevopsAdoptionSegmentPayload
{
"""
A
unique
identifier
for
the
client
performing
the
mutation
.
"""
clientMutationId
:
String
"""
Errors
encountered
during
execution
of
the
mutation
.
"""
errors
:
[
String
!]!
"""
The
segment
after
mutation
"""
segment
:
DevopsAdoptionSegment
}
"""
Autogenerated input type of CreateDiffNote
"""
...
...
@@ -5298,6 +5343,36 @@ type DeleteAnnotationPayload {
errors
:
[
String
!]!
}
"""
Autogenerated input type of DeleteDevopsAdoptionSegment
"""
input
DeleteDevopsAdoptionSegmentInput
{
"""
A
unique
identifier
for
the
client
performing
the
mutation
.
"""
clientMutationId
:
String
"""
ID
of
the
segment
"""
id
:
AnalyticsDevopsAdoptionSegmentID
!
}
"""
Autogenerated return type of DeleteDevopsAdoptionSegment
"""
type
DeleteDevopsAdoptionSegmentPayload
{
"""
A
unique
identifier
for
the
client
performing
the
mutation
.
"""
clientMutationId
:
String
"""
Errors
encountered
during
execution
of
the
mutation
.
"""
errors
:
[
String
!]!
}
"""
The response from the AdminSidekiqQueuesDeleteJobs mutation
"""
...
...
@@ -13704,6 +13779,7 @@ type Mutation {
.
Available
only
when
feature
flag
`
custom_emoji
`
is
enabled
"""
createCustomEmoji
(
input
:
CreateCustomEmojiInput
!):
CreateCustomEmojiPayload
createDevopsAdoptionSegment
(
input
:
CreateDevopsAdoptionSegmentInput
!):
CreateDevopsAdoptionSegmentPayload
createDiffNote
(
input
:
CreateDiffNoteInput
!):
CreateDiffNotePayload
createEpic
(
input
:
CreateEpicInput
!):
CreateEpicPayload
createImageDiffNote
(
input
:
CreateImageDiffNoteInput
!):
CreateImageDiffNotePayload
...
...
@@ -13723,6 +13799,7 @@ type Mutation {
dastSiteTokenCreate
(
input
:
DastSiteTokenCreateInput
!):
DastSiteTokenCreatePayload
dastSiteValidationCreate
(
input
:
DastSiteValidationCreateInput
!):
DastSiteValidationCreatePayload
deleteAnnotation
(
input
:
DeleteAnnotationInput
!):
DeleteAnnotationPayload
deleteDevopsAdoptionSegment
(
input
:
DeleteDevopsAdoptionSegmentInput
!):
DeleteDevopsAdoptionSegmentPayload
designManagementDelete
(
input
:
DesignManagementDeleteInput
!):
DesignManagementDeletePayload
designManagementMove
(
input
:
DesignManagementMoveInput
!):
DesignManagementMovePayload
designManagementUpload
(
input
:
DesignManagementUploadInput
!):
DesignManagementUploadPayload
...
...
@@ -13804,6 +13881,7 @@ type Mutation {
updateBoardEpicUserPreferences
(
input
:
UpdateBoardEpicUserPreferencesInput
!):
UpdateBoardEpicUserPreferencesPayload
updateBoardList
(
input
:
UpdateBoardListInput
!):
UpdateBoardListPayload
updateContainerExpirationPolicy
(
input
:
UpdateContainerExpirationPolicyInput
!):
UpdateContainerExpirationPolicyPayload
updateDevopsAdoptionSegment
(
input
:
UpdateDevopsAdoptionSegmentInput
!):
UpdateDevopsAdoptionSegmentPayload
updateEpic
(
input
:
UpdateEpicInput
!):
UpdateEpicPayload
"""
...
...
@@ -22167,6 +22245,51 @@ type UpdateContainerExpirationPolicyPayload {
errors
:
[
String
!]!
}
"""
Autogenerated input type of UpdateDevopsAdoptionSegment
"""
input
UpdateDevopsAdoptionSegmentInput
{
"""
A
unique
identifier
for
the
client
performing
the
mutation
.
"""
clientMutationId
:
String
"""
The
array
of
group
IDs
to
set
for
the
segment
"""
groupIds
:
[
GroupID
!]
"""
ID
of
the
segment
"""
id
:
AnalyticsDevopsAdoptionSegmentID
!
"""
Name
of
the
segment
"""
name
:
String
!
}
"""
Autogenerated return type of UpdateDevopsAdoptionSegment
"""
type
UpdateDevopsAdoptionSegmentPayload
{
"""
A
unique
identifier
for
the
client
performing
the
mutation
.
"""
clientMutationId
:
String
"""
Errors
encountered
during
execution
of
the
mutation
.
"""
errors
:
[
String
!]!
"""
The
segment
after
mutation
"""
segment
:
DevopsAdoptionSegment
}
input
UpdateDiffImagePositionInput
{
"""
Total
height
of
the
image
...
...
doc/api/graphql/reference/gitlab_schema.json
View file @
a0c53384
...
...
@@ -2401,6 +2401,16 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "SCALAR",
"name": "AnalyticsDevopsAdoptionSegmentID",
"description": "Identifier of Analytics::DevopsAdoption::Segment",
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "ENUM",
"name": "AvailabilityEnum",
...
...
@@ -10627,6 +10637,126 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "CreateDevopsAdoptionSegmentInput",
"description": "Autogenerated input type of CreateDevopsAdoptionSegment",
"fields": null,
"inputFields": [
{
"name": "name",
"description": "Name of the segment",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "groupIds",
"description": "The array of group IDs to set for the segment",
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "GroupID",
"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": "CreateDevopsAdoptionSegmentPayload",
"description": "Autogenerated return type of CreateDevopsAdoptionSegment",
"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": "segment",
"description": "The segment after mutation",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "DevopsAdoptionSegment",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "CreateDiffNoteInput",
...
...
@@ -14498,6 +14628,94 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "DeleteDevopsAdoptionSegmentInput",
"description": "Autogenerated input type of DeleteDevopsAdoptionSegment",
"fields": null,
"inputFields": [
{
"name": "id",
"description": "ID of the segment",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "AnalyticsDevopsAdoptionSegmentID",
"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": "DeleteDevopsAdoptionSegmentPayload",
"description": "Autogenerated return type of DeleteDevopsAdoptionSegment",
"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
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "DeleteJobsResponse",
...
...
@@ -38192,6 +38410,33 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "createDevopsAdoptionSegment",
"description": null,
"args": [
{
"name": "input",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "CreateDevopsAdoptionSegmentInput",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "CreateDevopsAdoptionSegmentPayload",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "createDiffNote",
"description": null,
...
...
@@ -38705,6 +38950,33 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "deleteDevopsAdoptionSegment",
"description": null,
"args": [
{
"name": "input",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "DeleteDevopsAdoptionSegmentInput",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "DeleteDevopsAdoptionSegmentPayload",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "designManagementDelete",
"description": null,
...
...
@@ -40568,6 +40840,33 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "updateDevopsAdoptionSegment",
"description": null,
"args": [
{
"name": "input",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "UpdateDevopsAdoptionSegmentInput",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "UpdateDevopsAdoptionSegmentPayload",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "updateEpic",
"description": null,
...
...
@@ -64429,6 +64728,140 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "UpdateDevopsAdoptionSegmentInput",
"description": "Autogenerated input type of UpdateDevopsAdoptionSegment",
"fields": null,
"inputFields": [
{
"name": "name",
"description": "Name of the segment",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "groupIds",
"description": "The array of group IDs to set for the segment",
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "GroupID",
"ofType": null
}
}
},
"defaultValue": null
},
{
"name": "id",
"description": "ID of the segment",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "AnalyticsDevopsAdoptionSegmentID",
"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": "UpdateDevopsAdoptionSegmentPayload",
"description": "Autogenerated return type of UpdateDevopsAdoptionSegment",
"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": "segment",
"description": "The segment after mutation",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "DevopsAdoptionSegment",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "UpdateDiffImagePositionInput",
doc/api/graphql/reference/index.md
View file @
a0c53384
...
...
@@ -643,6 +643,16 @@ Autogenerated return type of CreateCustomEmoji.
|
`customEmoji`
| CustomEmoji | The new custom emoji |
|
`errors`
| String! => Array | Errors encountered during execution of the mutation. |
### CreateDevopsAdoptionSegmentPayload
Autogenerated return type of CreateDevopsAdoptionSegment.
| Field | Type | Description |
| ----- | ---- | ----------- |
|
`clientMutationId`
| String | A unique identifier for the client performing the mutation. |
|
`errors`
| String! => Array | Errors encountered during execution of the mutation. |
|
`segment`
| DevopsAdoptionSegment | The segment after mutation |
### CreateDiffNotePayload
Autogenerated return type of CreateDiffNote.
...
...
@@ -892,6 +902,15 @@ Autogenerated return type of DeleteAnnotation.
|
`clientMutationId`
| String | A unique identifier for the client performing the mutation. |
|
`errors`
| String! => Array | Errors encountered during execution of the mutation. |
### DeleteDevopsAdoptionSegmentPayload
Autogenerated return type of DeleteDevopsAdoptionSegment.
| Field | Type | Description |
| ----- | ---- | ----------- |
|
`clientMutationId`
| String | A unique identifier for the client performing the mutation. |
|
`errors`
| String! => Array | Errors encountered during execution of the mutation. |
### DeleteJobsResponse
The response from the AdminSidekiqQueuesDeleteJobs mutation.
...
...
@@ -3325,6 +3344,16 @@ Autogenerated return type of UpdateContainerExpirationPolicy.
|
`containerExpirationPolicy`
| ContainerExpirationPolicy | The container expiration policy after mutation |
|
`errors`
| String! => Array | Errors encountered during execution of the mutation. |
### UpdateDevopsAdoptionSegmentPayload
Autogenerated return type of UpdateDevopsAdoptionSegment.
| Field | Type | Description |
| ----- | ---- | ----------- |
|
`clientMutationId`
| String | A unique identifier for the client performing the mutation. |
|
`errors`
| String! => Array | Errors encountered during execution of the mutation. |
|
`segment`
| DevopsAdoptionSegment | The segment after mutation |
### UpdateEpicPayload
Autogenerated return type of UpdateEpic.
...
...
ee/app/graphql/ee/types/mutation_type.rb
View file @
a0c53384
...
...
@@ -45,6 +45,9 @@ module EE
mount_mutation
::
Mutations
::
Security
::
CiConfiguration
::
ConfigureSast
mount_mutation
::
Mutations
::
Namespaces
::
IncreaseStorageTemporarily
mount_mutation
::
Mutations
::
QualityManagement
::
TestCases
::
Create
mount_mutation
::
Mutations
::
Admin
::
Analytics
::
DevopsAdoption
::
Segments
::
Create
mount_mutation
::
Mutations
::
Admin
::
Analytics
::
DevopsAdoption
::
Segments
::
Update
mount_mutation
::
Mutations
::
Admin
::
Analytics
::
DevopsAdoption
::
Segments
::
Delete
prepend
(
Types
::
DeprecatedMutations
)
end
...
...
ee/app/graphql/mutations/admin/analytics/devops_adoption/segments/create.rb
0 → 100644
View file @
a0c53384
# frozen_string_literal: true
module
Mutations
module
Admin
module
Analytics
module
DevopsAdoption
module
Segments
class
Create
<
BaseMutation
include
Mixins
::
CommonMethods
include
Mixins
::
CommonArguments
graphql_name
'CreateDevopsAdoptionSegment'
def
resolve
(
name
:,
group_ids:
[],
**
)
groups
=
GlobalID
::
Locator
.
locate_many
(
group_ids
)
response
=
::
Analytics
::
DevopsAdoption
::
Segments
::
CreateService
.
new
(
current_user:
current_user
,
params:
{
name:
name
,
groups:
groups
})
.
execute
resolve_segment
(
response
)
end
end
end
end
end
end
end
ee/app/graphql/mutations/admin/analytics/devops_adoption/segments/delete.rb
0 → 100644
View file @
a0c53384
# frozen_string_literal: true
module
Mutations
module
Admin
module
Analytics
module
DevopsAdoption
module
Segments
class
Delete
<
BaseMutation
include
Mixins
::
CommonMethods
graphql_name
'DeleteDevopsAdoptionSegment'
argument
:id
,
::
Types
::
GlobalIDType
[
::
Analytics
::
DevopsAdoption
::
Segment
],
required:
true
,
description:
"ID of the segment"
def
resolve
(
id
:,
**
)
response
=
::
Analytics
::
DevopsAdoption
::
Segments
::
DeleteService
.
new
(
segment:
id
.
find
,
current_user:
current_user
)
.
execute
{
errors:
errors_on_object
(
response
.
payload
[
:segment
])
}
end
end
end
end
end
end
end
ee/app/graphql/mutations/admin/analytics/devops_adoption/segments/mixins.rb
0 → 100644
View file @
a0c53384
# frozen_string_literal: true
module
Mutations
module
Admin
module
Analytics
module
DevopsAdoption
module
Segments
module
Mixins
# This module ensures that the mutations are admin only
module
CommonMethods
ADMIN_MESSAGE
=
'You must be an admin to use this mutation'
FEATURE_UNAVAILABLE_MESSAGE
=
'Feature is not available'
def
ready?
(
**
args
)
unless
License
.
feature_available?
(
:instance_level_devops_adoption
)
raise
::
Gitlab
::
Graphql
::
Errors
::
ResourceNotAvailable
,
FEATURE_UNAVAILABLE_MESSAGE
end
unless
current_user
&
.
admin?
raise
Gitlab
::
Graphql
::
Errors
::
ResourceNotAvailable
,
ADMIN_MESSAGE
end
super
end
private
def
resolve_segment
(
response
)
segment
=
response
.
payload
.
fetch
(
:segment
)
{
segment:
response
.
success?
?
response
.
payload
.
fetch
(
:segment
)
:
nil
,
errors:
errors_on_object
(
segment
)
}
end
end
module
CommonArguments
extend
ActiveSupport
::
Concern
included
do
argument
:name
,
GraphQL
::
STRING_TYPE
,
required:
true
,
description:
'Name of the segment'
argument
:group_ids
,
[
::
Types
::
GlobalIDType
[
::
Group
]],
required:
false
,
description:
'The array of group IDs to set for the segment'
field
:segment
,
Types
::
Admin
::
Analytics
::
DevopsAdoption
::
SegmentType
,
null:
true
,
description:
'The segment after mutation'
end
end
end
end
end
end
end
end
ee/app/graphql/mutations/admin/analytics/devops_adoption/segments/update.rb
0 → 100644
View file @
a0c53384
# frozen_string_literal: true
module
Mutations
module
Admin
module
Analytics
module
DevopsAdoption
module
Segments
class
Update
<
BaseMutation
include
Mixins
::
CommonMethods
include
Mixins
::
CommonArguments
graphql_name
'UpdateDevopsAdoptionSegment'
argument
:id
,
::
Types
::
GlobalIDType
[
::
Analytics
::
DevopsAdoption
::
Segment
],
required:
true
,
description:
"ID of the segment"
def
resolve
(
id
:,
name
:,
group_ids:
nil
,
**
)
groups
=
GlobalID
::
Locator
.
locate_many
(
group_ids
)
if
group_ids
segment
=
::
Analytics
::
DevopsAdoption
::
Segments
::
UpdateService
.
new
(
current_user:
current_user
,
segment:
id
.
find
,
params:
{
name:
name
,
groups:
groups
})
.
execute
resolve_segment
(
segment
)
end
end
end
end
end
end
end
ee/app/policies/ee/global_policy.rb
View file @
a0c53384
...
...
@@ -23,6 +23,7 @@ module EE
enable
:read_licenses
enable
:destroy_licenses
enable
:read_all_geo
enable
:manage_devops_adoption_segments
end
rule
{
admin
&
pages_size_limit_available
}.
enable
:update_max_pages_size
...
...
ee/app/services/analytics/devops_adoption/segments/create_service.rb
0 → 100644
View file @
a0c53384
# frozen_string_literal: true
module
Analytics
module
DevopsAdoption
module
Segments
class
CreateService
include
Gitlab
::
Allowable
def
initialize
(
segment:
Analytics
::
DevopsAdoption
::
Segment
.
new
,
params:
{},
current_user
:)
@segment
=
segment
@params
=
params
@current_user
=
current_user
end
def
execute
unless
can?
(
current_user
,
:manage_devops_adoption_segments
,
:global
)
return
ServiceResponse
.
error
(
message:
'Forbidden'
,
payload:
response_payload
)
end
segment
.
assign_attributes
(
attributes
)
if
segment
.
save
ServiceResponse
.
success
(
payload:
response_payload
)
else
ServiceResponse
.
error
(
message:
'Validation error'
,
payload:
response_payload
)
end
end
private
attr_reader
:segment
,
:params
,
:current_user
def
response_payload
{
segment:
@segment
}
end
def
attributes
{
name:
params
[
:name
],
segment_selections_attributes:
segment_selections_attributes
}.
compact
end
def
segment_selections_attributes
groups
.
map
{
|
group
|
{
group:
group
}
}
end
def
groups
@groups
||=
Array
(
params
[
:groups
]).
uniq
end
end
end
end
end
ee/app/services/analytics/devops_adoption/segments/delete_service.rb
0 → 100644
View file @
a0c53384
# frozen_string_literal: true
module
Analytics
module
DevopsAdoption
module
Segments
class
DeleteService
include
Gitlab
::
Allowable
def
initialize
(
segment
:,
current_user
:)
@segment
=
segment
@current_user
=
current_user
end
def
execute
unless
can?
(
current_user
,
:manage_devops_adoption_segments
,
:global
)
return
ServiceResponse
.
error
(
message:
'Forbidden'
,
payload:
response_payload
)
end
begin
segment
.
destroy!
ServiceResponse
.
success
(
payload:
response_payload
)
rescue
ActiveRecord
::
RecordNotDestroyed
ServiceResponse
.
error
(
message:
'Devops Adoption Segment deletion error'
,
payload:
response_payload
)
end
end
private
attr_reader
:segment
,
:current_user
def
response_payload
{
segment:
@segment
}
end
end
end
end
end
ee/app/services/analytics/devops_adoption/segments/update_service.rb
0 → 100644
View file @
a0c53384
# frozen_string_literal: true
module
Analytics
module
DevopsAdoption
module
Segments
class
UpdateService
<
CreateService
extend
::
Gitlab
::
Utils
::
Override
private
override
:segment_selections_attributes
def
segment_selections_attributes
return
if
params
[
:groups
].
nil?
existing_selections_by_group_id
=
segment
.
segment_selections
.
index_by
(
&
:group_id
)
groups_by_id
=
groups
.
index_by
(
&
:id
)
selection_attributes
=
groups
.
map
do
|
group
|
{
group:
group
}.
tap
do
|
attrs
|
attrs
[
:id
]
=
existing_selections_by_group_id
[
group
.
id
].
id
if
existing_selections_by_group_id
[
group
.
id
]
end
end
existing_selections_by_group_id
.
each
do
|
group_id
,
selection
|
unless
groups_by_id
[
group_id
]
selection_attributes
<<
{
id:
selection
.
id
,
_destroy:
'1'
}
end
end
selection_attributes
end
end
end
end
end
ee/spec/models/analytics/devops_adoption/segment_spec.rb
View file @
a0c53384
...
...
@@ -37,4 +37,24 @@ RSpec.describe Analytics::DevopsAdoption::Segment, type: :model do
expect
(
subject
).
to
eq
([
segment_2
,
segment_1
])
end
end
describe
'length validation on accepts_nested_attributes_for for segment_selections'
do
let
(
:group_1
)
{
create
(
:group
)
}
let
(
:group_2
)
{
create
(
:group
)
}
subject
{
described_class
.
create!
(
name:
'test'
,
segment_selections_attributes:
[{
group:
group_1
}])
}
before
do
stub_const
(
"Analytics::DevopsAdoption::SegmentSelection::ALLOWED_SELECTIONS_PER_SEGMENT"
,
1
)
end
it
'validates the number of segment_selections'
do
selections
=
[{
group:
group_1
,
_destroy:
1
},
{
group:
group_2
}]
subject
.
assign_attributes
(
segment_selections_attributes:
selections
)
expect
(
subject
).
to
be_invalid
expect
(
subject
.
errors
[
:"segment_selections.segment"
]).
to
eq
([
s_
(
'DevopsAdoptionSegmentSelection|The maximum number of selections has been reached'
)])
end
end
end
ee/spec/requests/api/graphql/mutations/admin/analytics/devops_adoption/segments/create_spec.rb
0 → 100644
View file @
a0c53384
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Mutations
::
Admin
::
Analytics
::
DevopsAdoption
::
Segments
::
Create
do
include
GraphqlHelpers
let_it_be
(
:admin
)
{
create
(
:admin
)
}
let_it_be
(
:group_1
)
{
create
(
:group
,
name:
'bbbb'
)
}
let_it_be
(
:group_2
)
{
create
(
:group
,
name:
'cccc'
)
}
let_it_be
(
:group_3
)
{
create
(
:group
,
name:
'aaaa'
)
}
let
(
:variables
)
{
{
name:
'my segment'
,
group_ids:
[
group_1
.
to_gid
.
to_s
,
group_2
.
to_gid
.
to_s
,
group_3
.
to_gid
.
to_s
]
}
}
let
(
:mutation
)
do
graphql_mutation
(
:create_devops_adoption_segment
,
variables
)
do
<<-
QL
.
strip_heredoc
clientMutationId
errors
segment {
id
name
groups {
nodes {
id
name
}
}
}
QL
end
end
def
mutation_response
graphql_mutation_response
(
:create_devops_adoption_segment
)
end
before
do
stub_licensed_features
(
instance_level_devops_adoption:
true
)
end
it_behaves_like
'DevOps Adoption top level errors'
it
'creates the segment with the groups'
do
post_graphql_mutation
(
mutation
,
current_user:
admin
)
expect
(
mutation_response
[
'errors'
]).
to
be_empty
segment
=
mutation_response
[
'segment'
]
expect
(
segment
[
'name'
]).
to
eq
(
'my segment'
)
group_names
=
segment
[
'groups'
][
'nodes'
].
map
{
|
node
|
node
[
'name'
]
}
expect
(
group_names
).
to
match_array
(
%w[aaaa bbbb cccc]
)
end
context
'when group_ids is missing'
do
before
do
variables
.
delete
(
:group_ids
)
post_graphql_mutation
(
mutation
,
current_user:
admin
)
end
it
'creates an empty segment'
do
expect
(
mutation_response
[
'segment'
][
'groups'
][
'nodes'
]).
to
be_empty
end
end
end
ee/spec/requests/api/graphql/mutations/admin/analytics/devops_adoption/segments/delete_spec.rb
0 → 100644
View file @
a0c53384
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Mutations
::
Admin
::
Analytics
::
DevopsAdoption
::
Segments
::
Delete
do
include
GraphqlHelpers
let_it_be
(
:admin
)
{
create
(
:admin
)
}
let_it_be
(
:group_1
)
{
create
(
:group
,
name:
'bbbb'
)
}
let
(
:segment
)
{
create
(
:devops_adoption_segment
,
name:
'my segment'
)
}
let
(
:variables
)
{
{
id:
segment
.
to_gid
.
to_s
}
}
let
(
:mutation
)
do
graphql_mutation
(
:delete_devops_adoption_segment
,
variables
)
do
<<~
QL
clientMutationId
errors
QL
end
end
before
do
stub_licensed_features
(
instance_level_devops_adoption:
true
)
create
(
:devops_adoption_segment_selection
,
:group
,
segment:
segment
,
group:
group_1
)
end
def
mutation_response
graphql_mutation_response
(
:delete_devops_adoption_segment
)
end
it_behaves_like
'DevOps Adoption top level errors'
it
'deletes the segment'
do
post_graphql_mutation
(
mutation
,
current_user:
admin
)
expect
(
mutation_response
[
'errors'
]).
to
be_empty
expect
(
::
Analytics
::
DevopsAdoption
::
Segment
.
find_by_id
(
segment
.
id
)).
to
eq
(
nil
)
end
end
ee/spec/requests/api/graphql/mutations/admin/analytics/devops_adoption/segments/update_spec.rb
0 → 100644
View file @
a0c53384
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Mutations
::
Admin
::
Analytics
::
DevopsAdoption
::
Segments
::
Update
do
include
GraphqlHelpers
let_it_be
(
:admin
)
{
create
(
:admin
)
}
let_it_be
(
:group_1
)
{
create
(
:group
,
name:
'bbbb'
)
}
let_it_be
(
:group_2
)
{
create
(
:group
,
name:
'cccc'
)
}
let_it_be
(
:group_3
)
{
create
(
:group
,
name:
'aaaa'
)
}
let
(
:segment
)
{
create
(
:devops_adoption_segment
,
name:
'my segment'
)
}
let
(
:variables
)
{
{
id:
segment
.
to_gid
.
to_s
,
name:
'new name'
,
group_ids:
[
group_1
.
to_gid
.
to_s
,
group_2
.
to_gid
.
to_s
,
group_3
.
to_gid
.
to_s
]
}
}
let
(
:mutation
)
do
graphql_mutation
(
:update_devops_adoption_segment
,
variables
)
do
<<-
QL
.
strip_heredoc
clientMutationId
errors
segment {
id
name
groups {
nodes {
id
name
}
}
}
QL
end
end
before
do
stub_licensed_features
(
instance_level_devops_adoption:
true
)
create
(
:devops_adoption_segment_selection
,
:group
,
segment:
segment
,
group:
group_1
)
end
def
mutation_response
graphql_mutation_response
(
:update_devops_adoption_segment
)
end
it_behaves_like
'DevOps Adoption top level errors'
it
'updates the segment name and the groups'
do
post_graphql_mutation
(
mutation
,
current_user:
admin
)
expect
(
mutation_response
[
'errors'
]).
to
be_empty
segment
=
mutation_response
[
'segment'
]
expect
(
segment
[
'name'
]).
to
eq
(
'new name'
)
group_names
=
segment
[
'groups'
][
'nodes'
].
map
{
|
node
|
node
[
'name'
]
}
expect
(
group_names
).
to
match_array
(
%w[aaaa bbbb cccc]
)
end
context
'when group_ids is missing'
do
before
do
variables
.
delete
(
:group_ids
)
end
it
'does not update the group ids'
do
expect
{
post_graphql_mutation
(
mutation
,
current_user:
admin
)
}.
not_to
change
{
segment
.
segment_selections
}
end
end
context
'when group_ids is empty'
do
before
do
variables
[
:group_ids
]
=
[]
post_graphql_mutation
(
mutation
,
current_user:
admin
)
end
it
'removes all selections'
do
expect
(
mutation_response
[
'segment'
][
'groups'
][
'nodes'
]).
to
be_empty
end
end
end
ee/spec/services/analytics/devops_adoption/segments/create_service_spec.rb
0 → 100644
View file @
a0c53384
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Analytics
::
DevopsAdoption
::
Segments
::
CreateService
do
include
AdminModeHelper
let_it_be
(
:admin
)
{
create
(
:user
,
:admin
)
}
let_it_be
(
:group
)
{
create
(
:group
)
}
let
(
:params
)
{
{
name:
'my service'
,
groups:
[
group
]
}
}
let
(
:segment
)
{
subject
.
payload
[
:segment
]
}
subject
{
described_class
.
new
(
params:
params
,
current_user:
admin
).
execute
}
before
do
enable_admin_mode!
(
admin
)
end
it
'persists the segment'
do
expect
(
subject
).
to
be_success
expect
(
segment
.
name
).
to
eq
(
'my service'
)
expect
(
segment
.
groups
).
to
eq
([
group
])
end
context
'when user is not an admin'
do
let
(
:user
)
{
build
(
:user
)
}
subject
{
described_class
.
new
(
params:
params
,
current_user:
user
).
execute
}
it
'does not persist the segment'
do
expect
(
subject
).
to
be_error
expect
(
subject
.
message
).
to
eq
(
'Forbidden'
)
expect
(
segment
).
not_to
be_persisted
end
end
context
'when params are invalid'
do
before
do
params
.
delete
(
:name
)
end
it
'does not persist the segment'
do
expect
(
subject
).
to
be_error
expect
(
segment
.
errors
[
:name
]).
not_to
be_empty
end
end
context
'when groups are not given'
do
before
do
params
.
delete
(
:groups
)
end
it
'persists the segment without groups'
do
expect
(
subject
).
to
be_success
expect
(
segment
.
segment_selections
).
to
be_empty
end
end
context
'when duplicated groups are given'
do
before
do
params
[
:groups
]
=
[
group
]
*
5
end
it
'persists the segments with unique groups'
do
expect
(
subject
).
to
be_success
expect
(
segment
.
groups
).
to
eq
([
group
])
end
end
end
ee/spec/services/analytics/devops_adoption/segments/delete_service_spec.rb
0 → 100644
View file @
a0c53384
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Analytics
::
DevopsAdoption
::
Segments
::
DeleteService
do
include
AdminModeHelper
let_it_be
(
:user
)
{
create
(
:user
,
:admin
)
}
let_it_be
(
:group
)
{
create
(
:group
)
}
let_it_be
(
:other_group
)
{
create
(
:group
)
}
let
(
:segment
)
{
create
(
:devops_adoption_segment
,
name:
'segment'
,
segment_selections:
[
build
(
:devops_adoption_segment_selection
,
:group
,
group:
group
)])
}
subject
{
described_class
.
new
(
segment:
segment
,
current_user:
user
).
execute
}
before
do
enable_admin_mode!
(
user
)
end
it
'deletes the segment'
do
expect
(
subject
).
to
be_success
expect
(
segment
).
not_to
be_persisted
end
context
'when deletion fails'
do
it
'returns error response'
do
expect
(
segment
).
to
receive
(
:destroy
).
and_raise
(
ActiveRecord
::
RecordNotDestroyed
)
expect
(
subject
).
to
be_error
expect
(
subject
.
message
).
to
eq
(
'Devops Adoption Segment deletion error'
)
end
end
context
'when the user is not admin'
do
let
(
:user
)
{
build
(
:user
)
}
it
'returns error response'
do
expect
(
subject
).
to
be_error
expect
(
subject
.
message
).
to
eq
(
'Forbidden'
)
end
end
end
ee/spec/services/analytics/devops_adoption/segments/update_service_spec.rb
0 → 100644
View file @
a0c53384
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Analytics
::
DevopsAdoption
::
Segments
::
UpdateService
do
include
AdminModeHelper
let_it_be
(
:admin
)
{
create
(
:user
,
:admin
)
}
let_it_be
(
:group
)
{
create
(
:group
)
}
let_it_be
(
:other_group
)
{
create
(
:group
)
}
let_it_be_with_refind
(
:segment
)
{
create
(
:devops_adoption_segment
,
name:
'segment'
,
segment_selections:
[
build
(
:devops_adoption_segment_selection
,
:group
,
group:
group
)])
}
let
(
:params
)
{
{
name:
'new name'
,
groups:
[
group
,
other_group
]
}
}
subject
{
described_class
.
new
(
segment:
segment
,
params:
params
,
current_user:
admin
).
execute
}
before
do
enable_admin_mode!
(
admin
)
end
it
'persists the segment'
do
expect
(
subject
).
to
be_success
expect
(
segment
.
name
).
to
eq
(
'new name'
)
expect
(
segment
.
groups
).
to
eq
([
group
,
other_group
])
end
context
'when user is not an admin'
do
let
(
:user
)
{
build
(
:user
)
}
subject
{
described_class
.
new
(
params:
params
,
current_user:
user
).
execute
}
it
'does not persist the segment'
do
expect
(
subject
).
to
be_error
expect
(
subject
.
message
).
to
eq
(
'Forbidden'
)
end
end
context
'when params are invalid'
do
before
do
params
[
:name
]
=
''
end
it
'does not persist the segment'
do
expect
(
subject
).
to
be_error
expect
(
segment
.
errors
[
:name
]).
not_to
be_empty
end
end
context
'when groups are not given'
do
before
do
params
.
delete
(
:groups
)
end
it
'does not change the groups'
do
expect
(
subject
).
to
be_success
expect
(
segment
.
groups
).
to
eq
([
group
])
end
end
end
ee/spec/support/shared_examples/graphql/mutations/analytics/devops_adoption/top_level_errors_shared_examples.rb
0 → 100644
View file @
a0c53384
# frozen_string_literal: true
RSpec
.
shared_examples_for
'DevOps Adoption top level errors'
do
context
'when the user is not an admin'
do
let
(
:current_user
)
{
create
(
:user
)
}
it_behaves_like
'a mutation that returns top-level errors'
,
errors:
[
described_class
::
ADMIN_MESSAGE
]
end
context
'when the feature is not available'
do
let
(
:current_user
)
{
admin
}
before
do
stub_licensed_features
(
instance_level_devops_adoption:
false
)
end
it_behaves_like
'a mutation that returns top-level errors'
,
errors:
[
described_class
::
FEATURE_UNAVAILABLE_MESSAGE
]
end
end
spec/models/analytics/devops_adoption/segment_selection_spec.rb
View file @
a0c53384
...
...
@@ -51,11 +51,13 @@ RSpec.describe Analytics::DevopsAdoption::SegmentSelection, type: :model do
context
'limit the number of segment selections'
do
let_it_be
(
:segment
)
{
create
(
:devops_adoption_segment
)
}
subject
{
build
(
:devops_adoption_segment_selection
,
segment:
segment
,
project:
projec
t
)
}
subject
{
build
(
:devops_adoption_segment_selection
,
project:
project
,
segment:
segmen
t
)
}
before
do
create
(
:devops_adoption_segment_selection
,
:project
,
segment:
segment
)
segment
.
reload
stub_const
(
"
#{
described_class
}
::ALLOWED_SELECTIONS_PER_SEGMENT"
,
1
)
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