Commit 3a4a46bd authored by Kamil Trzciński's avatar Kamil Trzciński

Merge branch '240874-expose-alert-via-issues-type' into 'master'

Resolve "Expose Alert via Issues Type"

Closes #240874

See merge request gitlab-org/gitlab!40214
parents e456c59d 4496045d
......@@ -4,6 +4,8 @@ module IssueResolverFields
extend ActiveSupport::Concern
prepended do
include LooksAhead
argument :iid, GraphQL::STRING_TYPE,
required: false,
description: 'IID of the issue. For example, "1"'
......@@ -49,7 +51,7 @@ module IssueResolverFields
required: false
end
def resolve(**args)
def resolve_with_lookahead(**args)
# The project could have been loaded in batch by `BatchLoader`.
# At this point we need the `id` of the project to query for issues, so
# make sure it's loaded and not `nil` before continuing.
......
......@@ -7,7 +7,7 @@ module Resolvers
type Types::IssueStatusCountsType, null: true
def continue_issue_resolve(parent, finder, **args)
Gitlab::IssuablesCountForState.new(finder, parent)
apply_lookahead(Gitlab::IssuablesCountForState.new(finder, parent))
end
end
end
......@@ -19,7 +19,7 @@ module Resolvers
milestone_due_asc milestone_due_desc].freeze
def continue_issue_resolve(parent, finder, **args)
issues = Gitlab::Graphql::Loaders::IssuableLoader.new(parent, finder).batching_find_all
issues = apply_lookahead(Gitlab::Graphql::Loaders::IssuableLoader.new(parent, finder).batching_find_all)
if non_stable_cursor_sort?(args[:sort])
# Certain complex sorts are not supported by the stable cursor pagination yet.
......@@ -30,6 +30,14 @@ module Resolvers
end
end
private
def preloads
{
alert_management_alert: [:alert_management_alert]
}
end
def non_stable_cursor_sort?(sort)
NON_STABLE_CURSOR_SORTS.include?(sort)
end
......
......@@ -101,6 +101,11 @@ module Types
field :type, Types::IssueTypeEnum, null: true,
method: :issue_type,
description: 'Type of the issue'
field :alert_management_alert,
Types::AlertManagement::AlertType,
null: true,
description: 'Alert associated to this issue'
end
end
......
......@@ -146,12 +146,14 @@ module Types
Types::IssueType.connection_type,
null: true,
description: 'Issues of the project',
extras: [:lookahead],
resolver: Resolvers::IssuesResolver
field :issue_status_counts,
Types::IssueStatusCountsType,
null: true,
description: 'Counts of issues by status for the project',
extras: [:lookahead],
resolver: Resolvers::IssueStatusCountsResolver
field :milestones, Types::MilestoneType.connection_type, null: true,
......
---
title: Add alert to Issue type in GraphQL
merge_request: 40214
author:
type: added
......@@ -5152,6 +5152,11 @@ type EpicHealthStatus {
Relationship between an epic and an issue
"""
type EpicIssue implements Noteable {
"""
Alert associated to this issue
"""
alertManagementAlert: AlertManagementAlert
"""
Assignees of the issue
"""
......@@ -6871,6 +6876,11 @@ enum IssuableState {
}
type Issue implements Noteable {
"""
Alert associated to this issue
"""
alertManagementAlert: AlertManagementAlert
"""
Assignees of the issue
"""
......
......@@ -14374,6 +14374,20 @@
"name": "EpicIssue",
"description": "Relationship between an epic and an issue",
"fields": [
{
"name": "alertManagementAlert",
"description": "Alert associated to this issue",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "AlertManagementAlert",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "assignees",
"description": "Assignees of the issue",
......@@ -18951,6 +18965,20 @@
"name": "Issue",
"description": null,
"fields": [
{
"name": "alertManagementAlert",
"description": "Alert associated to this issue",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "AlertManagementAlert",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "assignees",
"description": "Assignees of the issue",
......@@ -866,6 +866,7 @@ Relationship between an epic and an issue
| Name | Type | Description |
| --- | ---- | ---------- |
| `alertManagementAlert` | AlertManagementAlert | Alert associated to this issue |
| `author` | User! | User that created the issue |
| `blocked` | Boolean! | Indicates the issue is blocked |
| `closedAt` | Time | Timestamp of when the issue was closed |
......@@ -1038,6 +1039,7 @@ Represents a Group Membership
| Name | Type | Description |
| --- | ---- | ---------- |
| `alertManagementAlert` | AlertManagementAlert | Alert associated to this issue |
| `author` | User! | User that created the issue |
| `blocked` | Boolean! | Indicates the issue is blocked |
| `closedAt` | Time | Timestamp of when the issue was closed |
......
......@@ -26,6 +26,12 @@ FactoryBot.define do
closed_at { Time.now }
end
trait :with_alert do
after(:create) do |issue|
create(:alert_management_alert, project: issue.project, issue: issue)
end
end
after(:build) do |issue, evaluator|
issue.state_id = Issue.available_states[evaluator.state]
end
......
......@@ -15,7 +15,7 @@ RSpec.describe GitlabSchema.types['Issue'] do
fields = %i[id iid title description state reference author assignees participants labels milestone due_date
confidential discussion_locked upvotes downvotes user_notes_count web_path web_url relative_position
subscribed time_estimate total_time_spent closed_at created_at updated_at task_completion_status
designs design_collection]
designs design_collection alert_management_alert]
fields.each do |field_name|
expect(described_class).to have_graphql_field(field_name)
......
......@@ -10,7 +10,7 @@ RSpec.describe 'getting an issue list for a project' do
let(:issues_data) { graphql_data['project']['issues']['edges'] }
let!(:issues) do
[create(:issue, project: project, discussion_locked: true),
create(:issue, project: project)]
create(:issue, :with_alert, project: project)]
end
let(:fields) do
......@@ -256,6 +256,40 @@ RSpec.describe 'getting an issue list for a project' do
end
end
context 'fetching alert management alert' do
let(:fields) do
<<~QUERY
edges {
node {
id
alertManagementAlert {
title
}
}
}
QUERY
end
# Alerts need to reporter and above
before do
project.add_reporter(current_user)
end
it 'avoids N+1 queries' do
control = ActiveRecord::QueryRecorder.new { post_graphql(query, current_user: current_user) }
create(:alert_management_alert, :with_issue, project: project )
expect { post_graphql(query, current_user: current_user) }.not_to exceed_query_limit(control)
end
it 'returns the alert data' do
post_graphql(query, current_user: current_user)
issues_data
end
end
def grab_iids(data = issues_data)
data.map do |issue|
issue.dig('node', 'iid').to_i
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment