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
4aaabd8d
Commit
4aaabd8d
authored
Jul 31, 2020
by
Jan Provaznik
Committed by
Jarka Košanová
Jul 31, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Graphql mutation for issue subscribe
Allows setting of issue's subscribe status in GraphQL API.
parent
4291fd79
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
398 additions
and
109 deletions
+398
-109
app/graphql/mutations/concerns/mutations/resolves_subscription.rb
...hql/mutations/concerns/mutations/resolves_subscription.rb
+25
-0
app/graphql/mutations/issues/set_subscription.rb
app/graphql/mutations/issues/set_subscription.rb
+11
-0
app/graphql/mutations/merge_requests/set_subscription.rb
app/graphql/mutations/merge_requests/set_subscription.rb
+1
-16
app/graphql/types/mutation_type.rb
app/graphql/types/mutation_type.rb
+1
-0
changelogs/unreleased/graphql-issue-subscribe.yml
changelogs/unreleased/graphql-issue-subscribe.yml
+5
-0
doc/api/graphql/reference/gitlab_schema.graphql
doc/api/graphql/reference/gitlab_schema.graphql
+46
-0
doc/api/graphql/reference/gitlab_schema.json
doc/api/graphql/reference/gitlab_schema.json
+157
-0
doc/api/graphql/reference/index.md
doc/api/graphql/reference/index.md
+10
-0
spec/graphql/mutations/issues/set_subscription_spec.rb
spec/graphql/mutations/issues/set_subscription_spec.rb
+10
-0
spec/graphql/mutations/merge_requests/set_subscription_spec.rb
...graphql/mutations/merge_requests/set_subscription_spec.rb
+3
-39
spec/requests/api/graphql/mutations/issues/set_subscription_spec.rb
...sts/api/graphql/mutations/issues/set_subscription_spec.rb
+12
-0
spec/requests/api/graphql/mutations/merge_requests/set_subscription_spec.rb
...graphql/mutations/merge_requests/set_subscription_spec.rb
+3
-54
spec/support/shared_examples/graphql/mutations/resolves_subscription_shared_examples.rb
...raphql/mutations/resolves_subscription_shared_examples.rb
+45
-0
spec/support/shared_examples/requests/api/graphql/mutations/subscription_shared_examples.rb
...sts/api/graphql/mutations/subscription_shared_examples.rb
+69
-0
No files found.
app/graphql/mutations/concerns/mutations/resolves_subscription.rb
0 → 100644
View file @
4aaabd8d
# frozen_string_literal: true
module
Mutations
module
ResolvesSubscription
extend
ActiveSupport
::
Concern
included
do
argument
:subscribed_state
,
GraphQL
::
BOOLEAN_TYPE
,
required:
true
,
description:
'The desired state of the subscription'
end
def
resolve
(
project_path
:,
iid
:,
subscribed_state
:)
resource
=
authorized_find!
(
project_path:
project_path
,
iid:
iid
)
project
=
resource
.
project
resource
.
set_subscription
(
current_user
,
subscribed_state
,
project
)
{
resource
.
class
.
name
.
underscore
.
to_sym
=>
resource
,
errors:
errors_on_object
(
resource
)
}
end
end
end
app/graphql/mutations/issues/set_subscription.rb
0 → 100644
View file @
4aaabd8d
# frozen_string_literal: true
module
Mutations
module
Issues
class
SetSubscription
<
Base
graphql_name
'IssueSetSubscription'
include
ResolvesSubscription
end
end
end
app/graphql/mutations/merge_requests/set_subscription.rb
View file @
4aaabd8d
...
@@ -5,22 +5,7 @@ module Mutations
...
@@ -5,22 +5,7 @@ module Mutations
class
SetSubscription
<
Base
class
SetSubscription
<
Base
graphql_name
'MergeRequestSetSubscription'
graphql_name
'MergeRequestSetSubscription'
argument
:subscribed_state
,
include
ResolvesSubscription
GraphQL
::
BOOLEAN_TYPE
,
required:
true
,
description:
'The desired state of the subscription'
def
resolve
(
project_path
:,
iid
:,
subscribed_state
:)
merge_request
=
authorized_find!
(
project_path:
project_path
,
iid:
iid
)
project
=
merge_request
.
project
merge_request
.
set_subscription
(
current_user
,
subscribed_state
,
project
)
{
merge_request:
merge_request
,
errors:
errors_on_object
(
merge_request
)
}
end
end
end
end
end
end
end
app/graphql/types/mutation_type.rb
View file @
4aaabd8d
...
@@ -20,6 +20,7 @@ module Types
...
@@ -20,6 +20,7 @@ module Types
mount_mutation
Mutations
::
Issues
::
SetConfidential
mount_mutation
Mutations
::
Issues
::
SetConfidential
mount_mutation
Mutations
::
Issues
::
SetLocked
mount_mutation
Mutations
::
Issues
::
SetLocked
mount_mutation
Mutations
::
Issues
::
SetDueDate
mount_mutation
Mutations
::
Issues
::
SetDueDate
mount_mutation
Mutations
::
Issues
::
SetSubscription
mount_mutation
Mutations
::
Issues
::
Update
mount_mutation
Mutations
::
Issues
::
Update
mount_mutation
Mutations
::
MergeRequests
::
Create
mount_mutation
Mutations
::
MergeRequests
::
Create
mount_mutation
Mutations
::
MergeRequests
::
Update
mount_mutation
Mutations
::
MergeRequests
::
Update
...
...
changelogs/unreleased/graphql-issue-subscribe.yml
0 → 100644
View file @
4aaabd8d
---
title
:
Allows setting of issue subscribe status in GraphQL API.
merge_request
:
38051
author
:
type
:
added
doc/api/graphql/reference/gitlab_schema.graphql
View file @
4aaabd8d
...
@@ -6428,6 +6428,51 @@ type IssueSetLockedPayload {
...
@@ -6428,6 +6428,51 @@ type IssueSetLockedPayload {
issue
:
Issue
issue
:
Issue
}
}
"""
Autogenerated input type of IssueSetSubscription
"""
input
IssueSetSubscriptionInput
{
"""
A
unique
identifier
for
the
client
performing
the
mutation
.
"""
clientMutationId
:
String
"""
The
IID
of
the
issue
to
mutate
"""
iid
:
String
!
"""
The
project
the
issue
to
mutate
is
in
"""
projectPath
:
ID
!
"""
The
desired
state
of
the
subscription
"""
subscribedState
:
Boolean
!
}
"""
Autogenerated return type of IssueSetSubscription
"""
type
IssueSetSubscriptionPayload
{
"""
A
unique
identifier
for
the
client
performing
the
mutation
.
"""
clientMutationId
:
String
"""
Errors
encountered
during
execution
of
the
mutation
.
"""
errors
:
[
String
!]!
"""
The
issue
after
mutation
"""
issue
:
Issue
}
"""
"""
Autogenerated input type of IssueSetWeight
Autogenerated input type of IssueSetWeight
"""
"""
...
@@ -8346,6 +8391,7 @@ type Mutation {
...
@@ -8346,6 +8391,7 @@ type Mutation {
issueSetDueDate
(
input
:
IssueSetDueDateInput
!):
IssueSetDueDatePayload
issueSetDueDate
(
input
:
IssueSetDueDateInput
!):
IssueSetDueDatePayload
issueSetIteration
(
input
:
IssueSetIterationInput
!):
IssueSetIterationPayload
issueSetIteration
(
input
:
IssueSetIterationInput
!):
IssueSetIterationPayload
issueSetLocked
(
input
:
IssueSetLockedInput
!):
IssueSetLockedPayload
issueSetLocked
(
input
:
IssueSetLockedInput
!):
IssueSetLockedPayload
issueSetSubscription
(
input
:
IssueSetSubscriptionInput
!):
IssueSetSubscriptionPayload
issueSetWeight
(
input
:
IssueSetWeightInput
!):
IssueSetWeightPayload
issueSetWeight
(
input
:
IssueSetWeightInput
!):
IssueSetWeightPayload
jiraImportStart
(
input
:
JiraImportStartInput
!):
JiraImportStartPayload
jiraImportStart
(
input
:
JiraImportStartInput
!):
JiraImportStartPayload
jiraImportUsers
(
input
:
JiraImportUsersInput
!):
JiraImportUsersPayload
jiraImportUsers
(
input
:
JiraImportUsersInput
!):
JiraImportUsersPayload
...
...
doc/api/graphql/reference/gitlab_schema.json
View file @
4aaabd8d
...
@@ -17834,6 +17834,136 @@
...
@@ -17834,6 +17834,136 @@
"enumValues": null,
"enumValues": null,
"possibleTypes": null
"possibleTypes": null
},
},
{
"kind": "INPUT_OBJECT",
"name": "IssueSetSubscriptionInput",
"description": "Autogenerated input type of IssueSetSubscription",
"fields": null,
"inputFields": [
{
"name": "projectPath",
"description": "The project the issue to mutate is in",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "iid",
"description": "The IID of the issue to mutate",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "subscribedState",
"description": "The desired state of the subscription",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Boolean",
"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": "IssueSetSubscriptionPayload",
"description": "Autogenerated return type of IssueSetSubscription",
"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": "issue",
"description": "The issue after mutation",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "Issue",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
{
"kind": "INPUT_OBJECT",
"kind": "INPUT_OBJECT",
"name": "IssueSetWeightInput",
"name": "IssueSetWeightInput",
...
@@ -24339,6 +24469,33 @@
...
@@ -24339,6 +24469,33 @@
"isDeprecated": false,
"isDeprecated": false,
"deprecationReason": null
"deprecationReason": null
},
},
{
"name": "issueSetSubscription",
"description": null,
"args": [
{
"name": "input",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "IssueSetSubscriptionInput",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "IssueSetSubscriptionPayload",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
{
"name": "issueSetWeight",
"name": "issueSetWeight",
"description": null,
"description": null,
doc/api/graphql/reference/index.md
View file @
4aaabd8d
...
@@ -985,6 +985,16 @@ Autogenerated return type of IssueSetLocked
...
@@ -985,6 +985,16 @@ Autogenerated return type of IssueSetLocked
|
`errors`
| String! => Array | Errors encountered during execution of the mutation. |
|
`errors`
| String! => Array | Errors encountered during execution of the mutation. |
|
`issue`
| Issue | The issue after mutation |
|
`issue`
| Issue | The issue after mutation |
## IssueSetSubscriptionPayload
Autogenerated return type of IssueSetSubscription
| Name | Type | Description |
| --- | ---- | ---------- |
|
`clientMutationId`
| String | A unique identifier for the client performing the mutation. |
|
`errors`
| String! => Array | Errors encountered during execution of the mutation. |
|
`issue`
| Issue | The issue after mutation |
## IssueSetWeightPayload
## IssueSetWeightPayload
Autogenerated return type of IssueSetWeight
Autogenerated return type of IssueSetWeight
...
...
spec/graphql/mutations/issues/set_subscription_spec.rb
0 → 100644
View file @
4aaabd8d
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Mutations
::
Issues
::
SetSubscription
do
it_behaves_like
'a subscribeable graphql resource'
do
let_it_be
(
:resource
)
{
create
(
:issue
)
}
let
(
:permission_name
)
{
:update_issue
}
end
end
spec/graphql/mutations/merge_requests/set_subscription_spec.rb
View file @
4aaabd8d
...
@@ -3,44 +3,8 @@
...
@@ -3,44 +3,8 @@
require
'spec_helper'
require
'spec_helper'
RSpec
.
describe
Mutations
::
MergeRequests
::
SetSubscription
do
RSpec
.
describe
Mutations
::
MergeRequests
::
SetSubscription
do
let
(
:merge_request
)
{
create
(
:merge_request
)
}
it_behaves_like
'a subscribeable graphql resource'
do
let
(
:project
)
{
merge_request
.
project
}
let_it_be
(
:resource
)
{
create
(
:merge_request
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:permission_name
)
{
:update_merge_request
}
subject
(
:mutation
)
{
described_class
.
new
(
object:
nil
,
context:
{
current_user:
user
},
field:
nil
)
}
specify
{
expect
(
described_class
).
to
require_graphql_authorizations
(
:update_merge_request
)
}
describe
'#resolve'
do
let
(
:subscribe
)
{
true
}
let
(
:mutated_merge_request
)
{
subject
[
:merge_request
]
}
subject
{
mutation
.
resolve
(
project_path:
merge_request
.
project
.
full_path
,
iid:
merge_request
.
iid
,
subscribed_state:
subscribe
)
}
it
'raises an error if the resource is not accessible to the user'
do
expect
{
subject
}.
to
raise_error
(
Gitlab
::
Graphql
::
Errors
::
ResourceNotAvailable
)
end
context
'when the user can update the merge request'
do
before
do
merge_request
.
project
.
add_developer
(
user
)
end
it
'returns the merge request as discussion locked'
do
expect
(
mutated_merge_request
).
to
eq
(
merge_request
)
expect
(
mutated_merge_request
.
subscribed?
(
user
,
project
)).
to
eq
(
true
)
expect
(
subject
[
:errors
]).
to
be_empty
end
context
'when passing subscribe as false'
do
let
(
:subscribe
)
{
false
}
it
'unsubscribes from the discussion'
do
merge_request
.
subscribe
(
user
,
project
)
expect
(
mutated_merge_request
.
subscribed?
(
user
,
project
)).
to
eq
(
false
)
end
end
end
end
end
end
end
spec/requests/api/graphql/mutations/issues/set_subscription_spec.rb
0 → 100644
View file @
4aaabd8d
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
'Setting subscribed status of an issue'
do
include
GraphqlHelpers
it_behaves_like
'a subscribable resource api'
do
let_it_be
(
:resource
)
{
create
(
:issue
)
}
let
(
:mutation_name
)
{
:issue_set_subscription
}
end
end
spec/requests/api/graphql/mutations/merge_requests/set_subscription_spec.rb
View file @
4aaabd8d
...
@@ -5,59 +5,8 @@ require 'spec_helper'
...
@@ -5,59 +5,8 @@ require 'spec_helper'
RSpec
.
describe
'Setting subscribed status of a merge request'
do
RSpec
.
describe
'Setting subscribed status of a merge request'
do
include
GraphqlHelpers
include
GraphqlHelpers
let
(
:current_user
)
{
create
(
:user
)
}
it_behaves_like
'a subscribable resource api'
do
let
(
:merge_request
)
{
create
(
:merge_request
)
}
let_it_be
(
:resource
)
{
create
(
:merge_request
)
}
let
(
:project
)
{
merge_request
.
project
}
let
(
:mutation_name
)
{
:merge_request_set_subscription
}
let
(
:input
)
{
{
subscribed_state:
true
}
}
let
(
:mutation
)
do
variables
=
{
project_path:
project
.
full_path
,
iid:
merge_request
.
iid
.
to_s
}
graphql_mutation
(
:merge_request_set_subscription
,
variables
.
merge
(
input
),
<<-
QL
.
strip_heredoc
clientMutationId
errors
mergeRequest {
id
subscribed
}
QL
)
end
def
mutation_response
graphql_mutation_response
(
:merge_request_set_subscription
)[
'mergeRequest'
][
'subscribed'
]
end
before
do
project
.
add_developer
(
current_user
)
end
it
'returns an error if the user is not allowed to update the merge request'
do
post_graphql_mutation
(
mutation
,
current_user:
create
(
:user
))
expect
(
graphql_errors
).
not_to
be_empty
end
it
'marks the merge request as WIP'
do
post_graphql_mutation
(
mutation
,
current_user:
current_user
)
expect
(
response
).
to
have_gitlab_http_status
(
:success
)
expect
(
mutation_response
).
to
eq
(
true
)
end
context
'when passing subscribe false as input'
do
let
(
:input
)
{
{
subscribed_state:
false
}
}
it
'unmarks the merge request as subscribed'
do
merge_request
.
subscribe
(
current_user
,
project
)
post_graphql_mutation
(
mutation
,
current_user:
current_user
)
expect
(
response
).
to
have_gitlab_http_status
(
:success
)
expect
(
mutation_response
).
to
eq
(
false
)
end
end
end
end
end
spec/support/shared_examples/graphql/mutations/resolves_subscription_shared_examples.rb
0 → 100644
View file @
4aaabd8d
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
shared_examples
'a subscribeable graphql resource'
do
let
(
:project
)
{
resource
.
project
}
let_it_be
(
:user
)
{
create
(
:user
)
}
subject
(
:mutation
)
{
described_class
.
new
(
object:
nil
,
context:
{
current_user:
user
},
field:
nil
)
}
specify
{
expect
(
described_class
).
to
require_graphql_authorizations
(
permission_name
)
}
describe
'#resolve'
do
let
(
:subscribe
)
{
true
}
let
(
:mutated_resource
)
{
subject
[
resource
.
class
.
name
.
underscore
.
to_sym
]
}
subject
{
mutation
.
resolve
(
project_path:
resource
.
project
.
full_path
,
iid:
resource
.
iid
,
subscribed_state:
subscribe
)
}
it
'raises an error if the resource is not accessible to the user'
do
expect
{
subject
}.
to
raise_error
(
Gitlab
::
Graphql
::
Errors
::
ResourceNotAvailable
)
end
context
'when the user can update the resource'
do
before
do
resource
.
project
.
add_developer
(
user
)
end
it
'subscribes to the resource'
do
expect
(
mutated_resource
).
to
eq
(
resource
)
expect
(
mutated_resource
.
subscribed?
(
user
,
project
)).
to
eq
(
true
)
expect
(
subject
[
:errors
]).
to
be_empty
end
context
'when passing subscribe as false'
do
let
(
:subscribe
)
{
false
}
it
'unsubscribes from the discussion'
do
resource
.
subscribe
(
user
,
project
)
expect
(
mutated_resource
.
subscribed?
(
user
,
project
)).
to
eq
(
false
)
end
end
end
end
end
spec/support/shared_examples/requests/api/graphql/mutations/subscription_shared_examples.rb
0 → 100644
View file @
4aaabd8d
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
shared_examples
'a subscribable resource api'
do
include
GraphqlHelpers
let_it_be
(
:current_user
)
{
create
(
:user
)
}
let
(
:project
)
{
resource
.
project
}
let
(
:input
)
{
{
subscribed_state:
true
}
}
let
(
:resource_ref
)
{
resource
.
class
.
name
.
camelize
(
:lower
)
}
let
(
:mutation
)
do
variables
=
{
project_path:
project
.
full_path
,
iid:
resource
.
iid
.
to_s
}
graphql_mutation
(
mutation_name
,
variables
.
merge
(
input
),
<<-
QL
.
strip_heredoc
clientMutationId
errors
#{
resource_ref
}
{
id
subscribed
}
QL
)
end
def
mutation_response
graphql_mutation_response
(
mutation_name
)[
resource_ref
][
'subscribed'
]
end
context
'when the user is not authorized'
do
it_behaves_like
'a mutation that returns top-level errors'
,
errors:
[
"The resource that you are attempting to access "
\
"does not exist or you don't have permission to "
\
"perform this action"
]
end
context
'when user is authorized'
do
before
do
project
.
add_developer
(
current_user
)
end
it
'marks the resource as subscribed'
do
post_graphql_mutation
(
mutation
,
current_user:
current_user
)
expect
(
response
).
to
have_gitlab_http_status
(
:success
)
expect
(
mutation_response
).
to
eq
(
true
)
end
context
'when passing subscribe false as input'
do
let
(
:input
)
{
{
subscribed_state:
false
}
}
it
'unmarks the resource as subscribed'
do
resource
.
subscribe
(
current_user
,
project
)
post_graphql_mutation
(
mutation
,
current_user:
current_user
)
expect
(
response
).
to
have_gitlab_http_status
(
:success
)
expect
(
mutation_response
).
to
eq
(
false
)
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