Commit 7c111426 authored by Shinya Maeda's avatar Shinya Maeda

Merge branch '238568-add-incident-severity-to-issue-graphql-query' into 'master'

Expose severity from GraphQL Issue Query

Closes #238568

See merge request gitlab-org/gitlab!40945
parents c984a04e 105498f7
# frozen_string_literal: true
module Types
class IssuableSeverityEnum < BaseEnum
graphql_name 'IssuableSeverity'
description 'Incident severity'
::IssuableSeverity.severities.keys.each do |severity|
value severity.upcase, value: severity, description: "#{severity.titleize} severity"
end
end
end
...@@ -105,6 +105,9 @@ module Types ...@@ -105,6 +105,9 @@ module Types
Types::AlertManagement::AlertType, Types::AlertManagement::AlertType,
null: true, null: true,
description: 'Alert associated to this issue' description: 'Alert associated to this issue'
field :severity, Types::IssuableSeverityEnum, null: true,
description: 'Severity level of the incident'
end end
end end
......
...@@ -189,6 +189,12 @@ module Issuable ...@@ -189,6 +189,12 @@ module Issuable
is_a?(Issue) && super is_a?(Issue) && super
end end
def severity
return IssuableSeverity::DEFAULT unless incident?
issuable_severity&.severity || IssuableSeverity::DEFAULT
end
private private
def description_max_length_for_new_records_is_valid def description_max_length_for_new_records_is_valid
......
# frozen_string_literal: true # frozen_string_literal: true
class IssuableSeverity < ApplicationRecord class IssuableSeverity < ApplicationRecord
DEFAULT = 'unknown'
belongs_to :issue belongs_to :issue
validates :issue, presence: true, uniqueness: true validates :issue, presence: true, uniqueness: true
......
...@@ -60,6 +60,7 @@ class Issue < ApplicationRecord ...@@ -60,6 +60,7 @@ class Issue < ApplicationRecord
end end
end end
has_one :issuable_severity
has_one :sentry_issue has_one :sentry_issue
has_one :alert_management_alert, class_name: 'AlertManagement::Alert' has_one :alert_management_alert, class_name: 'AlertManagement::Alert'
has_and_belongs_to_many :self_managed_prometheus_alert_events, join_table: :issues_self_managed_prometheus_alert_events # rubocop: disable Rails/HasAndBelongsToMany has_and_belongs_to_many :self_managed_prometheus_alert_events, join_table: :issues_self_managed_prometheus_alert_events # rubocop: disable Rails/HasAndBelongsToMany
......
---
title: Exposes Incident's severity via GraphQL
merge_request: 40945
author:
type: added
...@@ -5679,6 +5679,11 @@ type EpicIssue implements Noteable { ...@@ -5679,6 +5679,11 @@ type EpicIssue implements Noteable {
""" """
relativePosition: Int relativePosition: Int
"""
Severity level of the incident
"""
severity: IssuableSeverity
""" """
State of the issue State of the issue
""" """
...@@ -7268,6 +7273,36 @@ type InstanceSecurityDashboard { ...@@ -7268,6 +7273,36 @@ type InstanceSecurityDashboard {
): VulnerabilitySeveritiesCount ): VulnerabilitySeveritiesCount
} }
"""
Incident severity
"""
enum IssuableSeverity {
"""
Critical severity
"""
CRITICAL
"""
High severity
"""
HIGH
"""
Low severity
"""
LOW
"""
Medium severity
"""
MEDIUM
"""
Unknown severity
"""
UNKNOWN
}
""" """
State of a GitLab issue or merge request State of a GitLab issue or merge request
""" """
...@@ -7514,6 +7549,11 @@ type Issue implements Noteable { ...@@ -7514,6 +7549,11 @@ type Issue implements Noteable {
""" """
relativePosition: Int relativePosition: Int
"""
Severity level of the incident
"""
severity: IssuableSeverity
""" """
State of the issue State of the issue
""" """
......
...@@ -15844,6 +15844,20 @@ ...@@ -15844,6 +15844,20 @@
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "deprecationReason": null
}, },
{
"name": "severity",
"description": "Severity level of the incident",
"args": [
],
"type": {
"kind": "ENUM",
"name": "IssuableSeverity",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{ {
"name": "state", "name": "state",
"description": "State of the issue", "description": "State of the issue",
...@@ -20085,6 +20099,47 @@ ...@@ -20085,6 +20099,47 @@
"enumValues": null, "enumValues": null,
"possibleTypes": null "possibleTypes": null
}, },
{
"kind": "ENUM",
"name": "IssuableSeverity",
"description": "Incident severity",
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": [
{
"name": "UNKNOWN",
"description": "Unknown severity",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "LOW",
"description": "Low severity",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "MEDIUM",
"description": "Medium severity",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "HIGH",
"description": "High severity",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "CRITICAL",
"description": "Critical severity",
"isDeprecated": false,
"deprecationReason": null
}
],
"possibleTypes": null
},
{ {
"kind": "ENUM", "kind": "ENUM",
"name": "IssuableState", "name": "IssuableState",
...@@ -20737,6 +20792,20 @@ ...@@ -20737,6 +20792,20 @@
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "deprecationReason": null
}, },
{
"name": "severity",
"description": "Severity level of the incident",
"args": [
],
"type": {
"kind": "ENUM",
"name": "IssuableSeverity",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{ {
"name": "state", "name": "state",
"description": "State of the issue", "description": "State of the issue",
...@@ -950,6 +950,7 @@ Relationship between an epic and an issue ...@@ -950,6 +950,7 @@ Relationship between an epic and an issue
| `reference` | String! | Internal reference of the issue. Returned in shortened format by default | | `reference` | String! | Internal reference of the issue. Returned in shortened format by default |
| `relationPath` | String | URI path of the epic-issue relation | | `relationPath` | String | URI path of the epic-issue relation |
| `relativePosition` | Int | Relative position of the issue (used for positioning in epic tree and issue boards) | | `relativePosition` | Int | Relative position of the issue (used for positioning in epic tree and issue boards) |
| `severity` | IssuableSeverity | Severity level of the incident |
| `state` | IssueState! | State of the issue | | `state` | IssueState! | State of the issue |
| `statusPagePublishedIncident` | Boolean | Indicates whether an issue is published to the status page | | `statusPagePublishedIncident` | Boolean | Indicates whether an issue is published to the status page |
| `subscribed` | Boolean! | Indicates the currently logged in user is subscribed to the issue | | `subscribed` | Boolean! | Indicates the currently logged in user is subscribed to the issue |
...@@ -1123,6 +1124,7 @@ Represents a Group Membership ...@@ -1123,6 +1124,7 @@ Represents a Group Membership
| `milestone` | Milestone | Milestone of the issue | | `milestone` | Milestone | Milestone of the issue |
| `reference` | String! | Internal reference of the issue. Returned in shortened format by default | | `reference` | String! | Internal reference of the issue. Returned in shortened format by default |
| `relativePosition` | Int | Relative position of the issue (used for positioning in epic tree and issue boards) | | `relativePosition` | Int | Relative position of the issue (used for positioning in epic tree and issue boards) |
| `severity` | IssuableSeverity | Severity level of the incident |
| `state` | IssueState! | State of the issue | | `state` | IssueState! | State of the issue |
| `statusPagePublishedIncident` | Boolean | Indicates whether an issue is published to the status page | | `statusPagePublishedIncident` | Boolean | Indicates whether an issue is published to the status page |
| `subscribed` | Boolean! | Indicates the currently logged in user is subscribed to the issue | | `subscribed` | Boolean! | Indicates the currently logged in user is subscribed to the issue |
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Types::IssuableSeverityEnum do
specify { expect(described_class.graphql_name).to eq('IssuableSeverity') }
it 'exposes all the existing issuable severity values' do
expect(described_class.values.keys).to contain_exactly(
*%w[UNKNOWN LOW MEDIUM HIGH CRITICAL]
)
end
end
...@@ -15,7 +15,7 @@ RSpec.describe GitlabSchema.types['Issue'] do ...@@ -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 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 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 subscribed time_estimate total_time_spent closed_at created_at updated_at task_completion_status
designs design_collection alert_management_alert] designs design_collection alert_management_alert severity]
fields.each do |field_name| fields.each do |field_name|
expect(described_class).to have_graphql_field(field_name) expect(described_class).to have_graphql_field(field_name)
......
...@@ -15,6 +15,7 @@ issues: ...@@ -15,6 +15,7 @@ issues:
- resource_iteration_events - resource_iteration_events
- sent_notifications - sent_notifications
- sentry_issue - sentry_issue
- issuable_severity
- label_links - label_links
- labels - labels
- last_edited_by - last_edited_by
...@@ -649,6 +650,8 @@ zoom_meetings: ...@@ -649,6 +650,8 @@ zoom_meetings:
- issue - issue
sentry_issue: sentry_issue:
- issue - issue
issuable_severity:
- issue
design_versions: *version design_versions: *version
epic: epic:
- subscriptions - subscriptions
......
...@@ -854,4 +854,41 @@ RSpec.describe Issuable do ...@@ -854,4 +854,41 @@ RSpec.describe Issuable do
it { is_expected.to eq(incident) } it { is_expected.to eq(incident) }
end end
end end
describe '#severity' do
subject { issuable.severity }
context 'when issuable is not an incident' do
using RSpec::Parameterized::TableSyntax
where(:issuable_type, :severity) do
:issue | 'unknown'
:merge_request | 'unknown'
end
with_them do
let(:issuable) { build_stubbed(issuable_type) }
it { is_expected.to eq(severity) }
end
end
context 'when issuable type is an incident' do
let!(:issuable) { build_stubbed(:incident) }
context 'when incident does not have issuable_severity' do
it 'returns default serverity' do
is_expected.to eq(IssuableSeverity::DEFAULT)
end
end
context 'when incident has issuable_severity' do
let!(:issuable_severity) { build_stubbed(:issuable_severity, issue: issuable, severity: 'critical') }
it 'returns issuable serverity' do
is_expected.to eq('critical')
end
end
end
end
end end
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