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
d2f70ab6
Commit
d2f70ab6
authored
Feb 18, 2020
by
Robert Speicher
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'bw-graphql-board-type' into 'master'
GraphQL: Add Board type See merge request gitlab-org/gitlab!22497
parents
df90667f
a9da2b10
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
624 additions
and
1 deletion
+624
-1
app/graphql/types/group_type.rb
app/graphql/types/group_type.rb
+6
-0
app/graphql/types/project_type.rb
app/graphql/types/project_type.rb
+6
-0
changelogs/unreleased/bw-graphql-board-type.yml
changelogs/unreleased/bw-graphql-board-type.yml
+5
-0
doc/api/graphql/reference/gitlab_schema.graphql
doc/api/graphql/reference/gitlab_schema.graphql
+105
-0
doc/api/graphql/reference/gitlab_schema.json
doc/api/graphql/reference/gitlab_schema.json
+277
-0
doc/api/graphql/reference/index.md
doc/api/graphql/reference/index.md
+10
-0
ee/spec/graphql/ee/types/board_type_spec.rb
ee/spec/graphql/ee/types/board_type_spec.rb
+9
-0
ee/spec/requests/api/graphql/boards/boards_query_spec.rb
ee/spec/requests/api/graphql/boards/boards_query_spec.rb
+20
-0
spec/graphql/types/board_type_spec.rb
spec/graphql/types/board_type_spec.rb
+15
-0
spec/graphql/types/group_type_spec.rb
spec/graphql/types/group_type_spec.rb
+9
-1
spec/graphql/types/project_type_spec.rb
spec/graphql/types/project_type_spec.rb
+7
-0
spec/requests/api/graphql/boards/boards_query_spec.rb
spec/requests/api/graphql/boards/boards_query_spec.rb
+27
-0
spec/support/shared_contexts/requests/api/graphql/group_and_project_boards_query_shared_context.rb
.../graphql/group_and_project_boards_query_shared_context.rb
+36
-0
spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb
...graphql/group_and_project_boards_query_shared_examples.rb
+92
-0
No files found.
app/graphql/types/group_type.rb
View file @
d2f70ab6
...
...
@@ -46,6 +46,12 @@ module Types
field
:milestones
,
Types
::
MilestoneType
.
connection_type
,
null:
true
,
description:
'Find milestones'
,
resolver:
Resolvers
::
MilestoneResolver
field
:boards
,
Types
::
BoardType
.
connection_type
,
null:
true
,
description:
'Boards of the group'
,
resolver:
Resolvers
::
BoardsResolver
end
end
...
...
app/graphql/types/project_type.rb
View file @
d2f70ab6
...
...
@@ -179,6 +179,12 @@ module Types
null:
true
,
description:
'Paginated collection of Sentry errors on the project'
,
resolver:
Resolvers
::
ErrorTracking
::
SentryErrorCollectionResolver
field
:boards
,
Types
::
BoardType
.
connection_type
,
null:
true
,
description:
'Boards of the project'
,
resolver:
Resolvers
::
BoardsResolver
end
end
...
...
changelogs/unreleased/bw-graphql-board-type.yml
0 → 100644
View file @
d2f70ab6
---
title
:
'
GraphQL:
Add
Board
type'
merge_request
:
22497
author
:
Alexander Koval
type
:
added
doc/api/graphql/reference/gitlab_schema.graphql
View file @
d2f70ab6
...
...
@@ -159,6 +159,61 @@ enum BlobViewersType {
simple
}
"""
Represents a project or group board
"""
type
Board
{
"""
ID
(
global
ID
)
of
the
board
"""
id
:
ID
!
"""
Name
of
the
board
"""
name
:
String
"""
Weight
of
the
board
"""
weight
:
Int
}
"""
The connection type for Board.
"""
type
BoardConnection
{
"""
A
list
of
edges
.
"""
edges
:
[
BoardEdge
]
"""
A
list
of
nodes
.
"""
nodes
:
[
Board
]
"""
Information
to
aid
in
pagination
.
"""
pageInfo
:
PageInfo
!
}
"""
An edge in a connection.
"""
type
BoardEdge
{
"""
A
cursor
for
use
in
pagination
.
"""
cursor
:
String
!
"""
The
item
at
the
end
of
the
edge
.
"""
node
:
Board
}
type
Commit
{
"""
Author
of
the
commit
...
...
@@ -2715,6 +2770,31 @@ type Group {
"""
avatarUrl
:
String
"""
Boards
of
the
group
"""
boards
(
"""
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
):
BoardConnection
"""
Description
of
the
namespace
"""
...
...
@@ -5174,6 +5254,31 @@ type Project {
"""
avatarUrl
:
String
"""
Boards
of
the
project
"""
boards
(
"""
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
):
BoardConnection
"""
Indicates
if
the
project
stores
Docker
container
images
in
a
container
registry
"""
...
...
doc/api/graphql/reference/gitlab_schema.json
View file @
d2f70ab6
...
...
@@ -368,6 +368,59 @@
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"boards"
,
"description"
:
"Boards of the project"
,
"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"
:
"BoardConnection"
,
"ofType"
:
null
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"containerRegistryEnabled"
,
"description"
:
"Indicates if the project stores Docker container images in a container registry"
,
...
...
@@ -3122,6 +3175,59 @@
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"boards"
,
"description"
:
"Boards of the group"
,
"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"
:
"BoardConnection"
,
"ofType"
:
null
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"description"
,
"description"
:
"Description of the namespace"
,
...
...
@@ -4322,6 +4428,177 @@
],
"possibleTypes"
:
null
},
{
"kind"
:
"OBJECT"
,
"name"
:
"BoardConnection"
,
"description"
:
"The connection type for Board."
,
"fields"
:
[
{
"name"
:
"edges"
,
"description"
:
"A list of edges."
,
"args"
:
[
],
"type"
:
{
"kind"
:
"LIST"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"OBJECT"
,
"name"
:
"BoardEdge"
,
"ofType"
:
null
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"nodes"
,
"description"
:
"A list of nodes."
,
"args"
:
[
],
"type"
:
{
"kind"
:
"LIST"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"OBJECT"
,
"name"
:
"Board"
,
"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"
:
"BoardEdge"
,
"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"
:
"Board"
,
"ofType"
:
null
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
}
],
"inputFields"
:
null
,
"interfaces"
:
[
],
"enumValues"
:
null
,
"possibleTypes"
:
null
},
{
"kind"
:
"OBJECT"
,
"name"
:
"Board"
,
"description"
:
"Represents a project or group board"
,
"fields"
:
[
{
"name"
:
"id"
,
"description"
:
"ID (global ID) of the board"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"NON_NULL"
,
"name"
:
null
,
"ofType"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"ID"
,
"ofType"
:
null
}
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"name"
,
"description"
:
"Name of the board"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"String"
,
"ofType"
:
null
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
},
{
"name"
:
"weight"
,
"description"
:
"Weight of the board"
,
"args"
:
[
],
"type"
:
{
"kind"
:
"SCALAR"
,
"name"
:
"Int"
,
"ofType"
:
null
},
"isDeprecated"
:
false
,
"deprecationReason"
:
null
}
],
"inputFields"
:
null
,
"interfaces"
:
[
],
"enumValues"
:
null
,
"possibleTypes"
:
null
},
{
"kind"
:
"OBJECT"
,
"name"
:
"Epic"
,
...
...
doc/api/graphql/reference/index.md
View file @
d2f70ab6
...
...
@@ -49,6 +49,16 @@ An emoji awarded by a user.
|
`type`
| EntryType! | Type of tree entry |
|
`webUrl`
| String | Web URL of the blob |
## Board
Represents a project or group board
| Name | Type | Description |
| --- | ---- | ---------- |
|
`id`
| ID! | ID (global ID) of the board |
|
`name`
| String | Name of the board |
|
`weight`
| Int | Weight of the board |
## Commit
| Name | Type | Description |
...
...
ee/spec/graphql/ee/types/board_type_spec.rb
0 → 100644
View file @
d2f70ab6
# frozen_string_literal: true
require
'spec_helper'
describe
GitlabSchema
.
types
[
'Board'
]
do
it
'includes the ee specific fields'
do
expect
(
described_class
).
to
have_graphql_field
(
'weight'
)
end
end
ee/spec/requests/api/graphql/boards/boards_query_spec.rb
0 → 100644
View file @
d2f70ab6
# frozen_string_literal: true
require
'spec_helper'
describe
'get list of boards'
do
include
GraphqlHelpers
include_context
'group and project boards query context'
before
do
stub_licensed_features
(
multiple_group_issue_boards:
true
)
end
describe
'for a group'
do
let
(
:board_parent
)
{
create
(
:group
,
:private
)
}
let
(
:boards_data
)
{
graphql_data
[
'group'
][
'boards'
][
'edges'
]
}
it_behaves_like
'group and project boards query'
end
end
spec/graphql/types/board_type_spec.rb
0 → 100644
View file @
d2f70ab6
# frozen_string_literal: true
require
'spec_helper'
describe
GitlabSchema
.
types
[
'Board'
]
do
it
{
expect
(
described_class
.
graphql_name
).
to
eq
(
'Board'
)
}
it
{
expect
(
described_class
).
to
require_graphql_authorizations
(
:read_board
)
}
it
'has specific fields'
do
expected_fields
=
%w[id name]
is_expected
.
to
include_graphql_fields
(
*
expected_fields
)
end
end
spec/graphql/types/group_type_spec.rb
View file @
d2f70ab6
...
...
@@ -16,9 +16,17 @@ describe GitlabSchema.types['Group'] do
web_url avatar_url share_with_group_lock project_creation_level
subgroup_creation_level require_two_factor_authentication
two_factor_grace_period auto_devops_enabled emails_disabled
mentions_disabled parent
mentions_disabled parent
boards
]
is_expected
.
to
include_graphql_fields
(
*
expected_fields
)
end
describe
'boards field'
do
subject
{
described_class
.
fields
[
'boards'
]
}
it
'returns boards'
do
is_expected
.
to
have_graphql_type
(
Types
::
BoardType
.
connection_type
)
end
end
end
spec/graphql/types/project_type_spec.rb
View file @
d2f70ab6
...
...
@@ -24,6 +24,7 @@ describe GitlabSchema.types['Project'] do
namespace group statistics repository merge_requests merge_request issues
issue pipelines removeSourceBranchAfterMerge sentryDetailedError snippets
grafanaIntegration autocloseReferencedIssues suggestion_commit_message environments
boards
]
is_expected
.
to
include_graphql_fields
(
*
expected_fields
)
...
...
@@ -77,4 +78,10 @@ describe GitlabSchema.types['Project'] do
it
{
is_expected
.
to
have_graphql_type
(
Types
::
EnvironmentType
.
connection_type
)
}
it
{
is_expected
.
to
have_graphql_resolver
(
Resolvers
::
EnvironmentsResolver
)
}
end
describe
'boards field'
do
subject
{
described_class
.
fields
[
'boards'
]
}
it
{
is_expected
.
to
have_graphql_type
(
Types
::
BoardType
.
connection_type
)
}
end
end
spec/requests/api/graphql/boards/boards_query_spec.rb
0 → 100644
View file @
d2f70ab6
# frozen_string_literal: true
require
'spec_helper'
describe
'get list of boards'
do
include
GraphqlHelpers
include_context
'group and project boards query context'
describe
'for a project'
do
let
(
:board_parent
)
{
create
(
:project
,
:repository
,
:private
)
}
let
(
:boards_data
)
{
graphql_data
[
'project'
][
'boards'
][
'edges'
]
}
it_behaves_like
'group and project boards query'
end
describe
'for a group'
do
let
(
:board_parent
)
{
create
(
:group
,
:private
)
}
let
(
:boards_data
)
{
graphql_data
[
'group'
][
'boards'
][
'edges'
]
}
before
do
allow
(
board_parent
).
to
receive
(
:multiple_issue_boards_available?
).
and_return
(
false
)
end
it_behaves_like
'group and project boards query'
end
end
spec/support/shared_contexts/requests/api/graphql/group_and_project_boards_query_shared_context.rb
0 → 100644
View file @
d2f70ab6
# frozen_string_literal: true
RSpec
.
shared_context
'group and project boards query context'
do
let_it_be
(
:user
)
{
create
:user
}
let
(
:current_user
)
{
user
}
let
(
:params
)
{
''
}
let
(
:board_parent_type
)
{
board_parent
.
class
.
to_s
.
downcase
}
let
(
:start_cursor
)
{
graphql_data
[
board_parent_type
][
'boards'
][
'pageInfo'
][
'startCursor'
]
}
let
(
:end_cursor
)
{
graphql_data
[
board_parent_type
][
'boards'
][
'pageInfo'
][
'endCursor'
]
}
def
query
(
board_params
=
params
)
graphql_query_for
(
board_parent_type
,
{
'fullPath'
=>
board_parent
.
full_path
},
<<~
BOARDS
boards(
#{
board_params
}
) {
pageInfo {
startCursor
endCursor
}
edges {
node {
#{
all_graphql_fields_for
(
'boards'
.
classify
)
}
}
}
}
BOARDS
)
end
def
grab_names
(
data
=
boards_data
)
data
.
map
do
|
board
|
board
.
dig
(
'node'
,
'name'
)
end
end
end
spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb
0 → 100644
View file @
d2f70ab6
# frozen_string_literal: true
RSpec
.
shared_examples
'group and project boards query'
do
include
GraphqlHelpers
it_behaves_like
'a working graphql query'
do
before
do
post_graphql
(
query
,
current_user:
current_user
)
end
end
context
'when the user does not have access to the board parent'
do
it
'returns nil'
do
create
(
:board
,
resource_parent:
board_parent
,
name:
'A'
)
post_graphql
(
query
)
expect
(
graphql_data
[
board_parent_type
]).
to
be_nil
end
end
context
'when no permission to read board'
do
it
'does not return any boards'
do
board_parent
.
add_guest
(
current_user
)
board
=
create
(
:board
,
resource_parent:
board_parent
,
name:
'A'
)
allow
(
Ability
).
to
receive
(
:allowed?
).
and_call_original
allow
(
Ability
).
to
receive
(
:allowed?
).
with
(
user
,
:read_board
,
board
).
and_return
(
false
)
post_graphql
(
query
,
current_user:
current_user
)
expect
(
boards_data
).
to
be_empty
end
end
context
'when user can read the board parent'
do
before
do
board_parent
.
add_reporter
(
current_user
)
end
it
'does not create a default board'
do
post_graphql
(
query
,
current_user:
current_user
)
expect
(
boards_data
).
to
be_empty
end
describe
'sorting and pagination'
do
context
'when using default sorting'
do
let!
(
:board_B
)
{
create
(
:board
,
resource_parent:
board_parent
,
name:
'B'
)
}
let!
(
:board_C
)
{
create
(
:board
,
resource_parent:
board_parent
,
name:
'C'
)
}
let!
(
:board_a
)
{
create
(
:board
,
resource_parent:
board_parent
,
name:
'a'
)
}
let!
(
:board_A
)
{
create
(
:board
,
resource_parent:
board_parent
,
name:
'A'
)
}
before
do
post_graphql
(
query
,
current_user:
current_user
)
end
it_behaves_like
'a working graphql query'
context
'when ascending'
do
let
(
:boards
)
{
[
board_a
,
board_A
,
board_B
,
board_C
]
}
let
(
:expected_boards
)
do
if
board_parent
.
multiple_issue_boards_available?
boards
else
[
boards
.
first
]
end
end
it
'sorts boards'
do
expect
(
grab_names
).
to
eq
expected_boards
.
map
(
&
:name
)
end
context
'when paginating'
do
let
(
:params
)
{
'first: 2'
}
it
'sorts boards'
do
expect
(
grab_names
).
to
eq
expected_boards
.
first
(
2
).
map
(
&
:name
)
cursored_query
=
query
(
"after:
\"
#{
end_cursor
}
\"
"
)
post_graphql
(
cursored_query
,
current_user:
current_user
)
response_data
=
JSON
.
parse
(
response
.
body
)[
'data'
][
board_parent_type
][
'boards'
][
'edges'
]
expect
(
grab_names
(
response_data
)).
to
eq
expected_boards
.
drop
(
2
).
first
(
2
).
map
(
&
:name
)
end
end
end
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