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
93c1b5da
Commit
93c1b5da
authored
Nov 04, 2020
by
Adam Hegyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Expose Devops Adoption segments via GraphQL
This change exposes Devops Adoption segments via Graphql.
parent
f1bdac24
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
679 additions
and
0 deletions
+679
-0
app/models/analytics/devops_adoption/segment.rb
app/models/analytics/devops_adoption/segment.rb
+6
-0
doc/api/graphql/reference/gitlab_schema.graphql
doc/api/graphql/reference/gitlab_schema.graphql
+135
-0
doc/api/graphql/reference/gitlab_schema.json
doc/api/graphql/reference/gitlab_schema.json
+379
-0
doc/api/graphql/reference/index.md
doc/api/graphql/reference/index.md
+10
-0
ee/app/graphql/ee/types/query_type.rb
ee/app/graphql/ee/types/query_type.rb
+5
-0
ee/app/graphql/resolvers/admin/analytics/devops_adoption/segments_resolver.rb
...vers/admin/analytics/devops_adoption/segments_resolver.rb
+39
-0
ee/app/graphql/types/admin/analytics/devops_adoption/segment_type.rb
...hql/types/admin/analytics/devops_adoption/segment_type.rb
+24
-0
ee/app/models/license.rb
ee/app/models/license.rb
+1
-0
ee/changelogs/unreleased/262395-devops-adoption-read-api.yml
ee/changelogs/unreleased/262395-devops-adoption-read-api.yml
+5
-0
ee/spec/graphql/resolvers/admin/analytics/devops_adoption/segments_resolver_spec.rb
...admin/analytics/devops_adoption/segments_resolver_spec.rb
+64
-0
ee/spec/models/analytics/devops_adoption/segment_spec.rb
ee/spec/models/analytics/devops_adoption/segment_spec.rb
+11
-0
No files found.
app/models/analytics/devops_adoption/segment.rb
View file @
93c1b5da
...
...
@@ -4,10 +4,16 @@ class Analytics::DevopsAdoption::Segment < ApplicationRecord
ALLOWED_SEGMENT_COUNT
=
20
has_many
:segment_selections
has_many
:groups
,
through: :segment_selections
validates
:name
,
presence:
true
,
uniqueness:
true
,
length:
{
maximum:
255
}
validate
:validate_segment_count
accepts_nested_attributes_for
:segment_selections
,
allow_destroy:
true
scope
:ordered_by_name
,
->
{
order
(
:name
)
}
scope
:with_groups
,
->
{
preload
(
:groups
)
}
private
def
validate_segment_count
...
...
doc/api/graphql/reference/gitlab_schema.graphql
View file @
93c1b5da
...
...
@@ -6025,6 +6025,81 @@ type DetailedStatus {
tooltip
:
String
}
"""
Segment
"""
type
DevopsAdoptionSegment
{
"""
Assigned
groups
"""
groups
(
"""
Returns
the
elements
in
the
list
that
come
after
the
specified
cursor
.
"""
after
:
String
"""
Returns
the
elements
in
the
list
that
come
before
the
specified
cursor
.
"""
before
:
String
"""
Returns
the
first
_n_
elements
from
the
list
.
"""
first
:
Int
"""
Returns
the
last
_n_
elements
from
the
list
.
"""
last
:
Int
):
GroupConnection
"""
ID
of
the
segment
"""
id
:
ID
!
"""
Name
of
the
segment
"""
name
:
String
!
}
"""
The connection type for DevopsAdoptionSegment.
"""
type
DevopsAdoptionSegmentConnection
{
"""
A
list
of
edges
.
"""
edges
:
[
DevopsAdoptionSegmentEdge
]
"""
A
list
of
nodes
.
"""
nodes
:
[
DevopsAdoptionSegment
]
"""
Information
to
aid
in
pagination
.
"""
pageInfo
:
PageInfo
!
}
"""
An edge in a connection.
"""
type
DevopsAdoptionSegmentEdge
{
"""
A
cursor
for
use
in
pagination
.
"""
cursor
:
String
!
"""
The
item
at
the
end
of
the
edge
.
"""
node
:
DevopsAdoptionSegment
}
input
DiffImagePositionInput
{
"""
Merge
base
of
the
branch
the
comment
was
made
on
...
...
@@ -9165,6 +9240,41 @@ type Group {
webUrl
:
String
!
}
"""
The connection type for Group.
"""
type
GroupConnection
{
"""
A
list
of
edges
.
"""
edges
:
[
GroupEdge
]
"""
A
list
of
nodes
.
"""
nodes
:
[
Group
]
"""
Information
to
aid
in
pagination
.
"""
pageInfo
:
PageInfo
!
}
"""
An edge in a connection.
"""
type
GroupEdge
{
"""
A
cursor
for
use
in
pagination
.
"""
cursor
:
String
!
"""
The
item
at
the
end
of
the
edge
.
"""
node
:
Group
}
"""
Identifier of Group
"""
...
...
@@ -16540,6 +16650,31 @@ type Query {
"""
designManagement
:
DesignManagement
!
"""
Get
configured
DevOps
adoption
segments
on
the
instance
"""
devopsAdoptionSegments
(
"""
Returns
the
elements
in
the
list
that
come
after
the
specified
cursor
.
"""
after
:
String
"""
Returns
the
elements
in
the
list
that
come
before
the
specified
cursor
.
"""
before
:
String
"""
Returns
the
first
_n_
elements
from
the
list
.
"""
first
:
Int
"""
Returns
the
last
_n_
elements
from
the
list
.
"""
last
:
Int
):
DevopsAdoptionSegmentConnection
"""
Text
to
echo
back
"""
...
...
doc/api/graphql/reference/gitlab_schema.json
View file @
93c1b5da
...
...
@@ -16527,6 +16527,220 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "DevopsAdoptionSegment",
"description": "Segment",
"fields": [
{
"name": "groups",
"description": "Assigned groups",
"args": [
{
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "before",
"description": "Returns the elements in the list that come before the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "first",
"description": "Returns the first _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
},
{
"name": "last",
"description": "Returns the last _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "GroupConnection",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "id",
"description": "ID of the segment",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"description": "Name of the segment",
"args": [
],
"type": {
"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": "DevopsAdoptionSegmentConnection",
"description": "The connection type for DevopsAdoptionSegment.",
"fields": [
{
"name": "edges",
"description": "A list of edges.",
"args": [
],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "DevopsAdoptionSegmentEdge",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "nodes",
"description": "A list of nodes.",
"args": [
],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "DevopsAdoptionSegment",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "pageInfo",
"description": "Information to aid in pagination.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "PageInfo",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "DevopsAdoptionSegmentEdge",
"description": "An edge in a connection.",
"fields": [
{
"name": "cursor",
"description": "A cursor for use in pagination.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "node",
"description": "The item at the end of the edge.",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "DevopsAdoptionSegment",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "DiffImagePositionInput",
...
...
@@ -24901,6 +25115,118 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "GroupConnection",
"description": "The connection type for Group.",
"fields": [
{
"name": "edges",
"description": "A list of edges.",
"args": [
],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "GroupEdge",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "nodes",
"description": "A list of nodes.",
"args": [
],
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "Group",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "pageInfo",
"description": "Information to aid in pagination.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "PageInfo",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "GroupEdge",
"description": "An edge in a connection.",
"fields": [
{
"name": "cursor",
"description": "A cursor for use in pagination.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "node",
"description": "The item at the end of the edge.",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "Group",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "SCALAR",
"name": "GroupID",
...
...
@@ -48034,6 +48360,59 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "devopsAdoptionSegments",
"description": "Get configured DevOps adoption segments on the instance",
"args": [
{
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "before",
"description": "Returns the elements in the list that come before the specified cursor.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "first",
"description": "Returns the first _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
},
{
"name": "last",
"description": "Returns the last _n_ elements from the list.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "DevopsAdoptionSegmentConnection",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "echo",
"description": "Text to echo back",
doc/api/graphql/reference/index.md
View file @
93c1b5da
...
...
@@ -1000,6 +1000,16 @@ Autogenerated return type of DestroySnippet.
|
`text`
| String | Text of the status |
|
`tooltip`
| String | Tooltip associated with the status |
### DevopsAdoptionSegment
Segment.
| Field | Type | Description |
| ----- | ---- | ----------- |
|
`groups`
| GroupConnection | Assigned groups |
|
`id`
| ID! | ID of the segment |
|
`name`
| String! | Name of the segment |
### DiffPosition
| Field | Type | Description |
...
...
ee/app/graphql/ee/types/query_type.rb
View file @
93c1b5da
...
...
@@ -51,6 +51,11 @@ module EE
null:
true
,
resolver:
::
Resolvers
::
InstanceSecurityDashboardResolver
,
description:
'Fields related to Instance Security Dashboard'
field
:devops_adoption_segments
,
::
Types
::
Admin
::
Analytics
::
DevopsAdoption
::
SegmentType
.
connection_type
,
null:
true
,
description:
'Get configured DevOps adoption segments on the instance'
,
resolver:
::
Resolvers
::
Admin
::
Analytics
::
DevopsAdoption
::
SegmentsResolver
end
def
vulnerability
(
id
:)
...
...
ee/app/graphql/resolvers/admin/analytics/devops_adoption/segments_resolver.rb
0 → 100644
View file @
93c1b5da
# frozen_string_literal: true
module
Resolvers
module
Admin
module
Analytics
module
DevopsAdoption
class
SegmentsResolver
<
BaseResolver
include
Gitlab
::
Graphql
::
Authorize
::
AuthorizeResource
type
Types
::
Admin
::
Analytics
::
DevopsAdoption
::
SegmentType
,
null:
true
def
resolve
authorize!
if
segments_feature_available?
::
Analytics
::
DevopsAdoption
::
Segment
.
with_groups
.
ordered_by_name
else
::
Analytics
::
DevopsAdoption
::
Segment
.
none
end
end
private
def
segments_feature_available?
License
.
feature_available?
(
:instance_level_devops_adoption
)
end
def
authorize!
admin?
||
raise_resource_not_available_error!
end
def
admin?
context
[
:current_user
].
present?
&&
context
[
:current_user
].
admin?
end
end
end
end
end
end
ee/app/graphql/types/admin/analytics/devops_adoption/segment_type.rb
0 → 100644
View file @
93c1b5da
# frozen_string_literal: true
# rubocop:disable Graphql/AuthorizeTypes
module
Types
module
Admin
module
Analytics
module
DevopsAdoption
class
SegmentType
<
BaseObject
graphql_name
'DevopsAdoptionSegment'
description
'Segment'
field
:id
,
GraphQL
::
ID_TYPE
,
null:
false
,
description:
"ID of the segment"
field
:name
,
GraphQL
::
STRING_TYPE
,
null:
false
,
description:
'Name of the segment'
field
:groups
,
Types
::
GroupType
.
connection_type
,
null:
true
,
description:
'Assigned groups'
end
end
end
end
end
ee/app/models/license.rb
View file @
93c1b5da
...
...
@@ -19,6 +19,7 @@ class License < ApplicationRecord
group_activity_analytics
group_bulk_edit
group_webhooks
instance_level_devops_adoption
issuable_default_templates
issue_weights
iterations
...
...
ee/changelogs/unreleased/262395-devops-adoption-read-api.yml
0 → 100644
View file @
93c1b5da
---
title
:
Expose Devops Adoption segments via GraphQL
merge_request
:
46879
author
:
type
:
added
ee/spec/graphql/resolvers/admin/analytics/devops_adoption/segments_resolver_spec.rb
0 → 100644
View file @
93c1b5da
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Resolvers
::
Admin
::
Analytics
::
DevopsAdoption
::
SegmentsResolver
do
include
GraphqlHelpers
let_it_be
(
:admin_user
)
{
create
(
:user
,
:admin
)
}
let
(
:current_user
)
{
admin_user
}
def
resolve_segments
(
args
=
{},
context
=
{})
resolve
(
described_class
,
args:
args
,
ctx:
context
)
end
describe
'#resolve'
do
let_it_be
(
:user
)
{
create
(
:user
)
}
let_it_be
(
:segment_1
)
{
create
(
:devops_adoption_segment
,
name:
'bbb'
)
}
let_it_be
(
:segment_2
)
{
create
(
:devops_adoption_segment
,
name:
'aaa'
)
}
subject
{
resolve_segments
({},
{
current_user:
current_user
})
}
before
do
stub_licensed_features
(
instance_level_devops_adoption:
true
)
end
context
'when requesting project count measurements'
do
context
'as an admin user'
do
let
(
:current_user
)
{
admin_user
}
it
'returns the records, ordered by name'
do
expect
(
subject
).
to
eq
([
segment_2
,
segment_1
])
end
end
context
'when the feature is not available'
do
let
(
:current_user
)
{
admin_user
}
before
do
stub_licensed_features
(
instance_level_devops_adoption:
false
)
end
it
'returns the records, ordered by name'
do
expect
(
subject
).
to
be_empty
end
end
context
'as a non-admin user'
do
let
(
:current_user
)
{
user
}
it
'raises ResourceNotAvailable error'
do
expect
{
subject
}.
to
raise_error
(
Gitlab
::
Graphql
::
Errors
::
ResourceNotAvailable
)
end
end
context
'as an unauthenticated user'
do
let
(
:current_user
)
{
nil
}
it
'raises ResourceNotAvailable error'
do
expect
{
subject
}.
to
raise_error
(
Gitlab
::
Graphql
::
Errors
::
ResourceNotAvailable
)
end
end
end
end
end
spec/models/analytics/devops_adoption/segment_spec.rb
→
ee/
spec/models/analytics/devops_adoption/segment_spec.rb
View file @
93c1b5da
...
...
@@ -26,4 +26,15 @@ RSpec.describe Analytics::DevopsAdoption::Segment, type: :model do
end
end
end
describe
'.ordered_by_name'
do
let
(
:segment_1
)
{
create
(
:devops_adoption_segment
,
name:
'bbb'
)
}
let
(
:segment_2
)
{
create
(
:devops_adoption_segment
,
name:
'aaa'
)
}
subject
{
described_class
.
ordered_by_name
}
it
'orders segments by name'
do
expect
(
subject
).
to
eq
([
segment_2
,
segment_1
])
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