Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-08-07 12:09:59 +00:00
parent 277fdda606
commit 5958e399de
44 changed files with 550 additions and 93 deletions

View File

@ -1 +1 @@
d6ded95a76876ff182d37cb33ed9515ed29d5c23
300980719a82ec3b40c5d938310cebd6fc3d3c37

View File

@ -659,9 +659,9 @@ GEM
thread_safe (~> 0.3, >= 0.3.1)
memory_profiler (0.9.14)
method_source (0.9.2)
mime-types (3.2.2)
mime-types (3.3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2019.0331)
mime-types-data (3.2020.0512)
mimemagic (0.3.5)
mini_histogram (0.1.3)
mini_magick (4.9.5)

View File

@ -282,7 +282,7 @@ export default {
@sort-changed="fetchSortedData"
>
<template #cell(title)="{ item }">
<div class="incident-management-list-title gl-display-flex gl-align-items-center">
<div :class="{ 'gl-display-flex gl-align-items-center': item.state === 'closed' }">
<div class="gl-max-w-full text-truncate" :title="item.title">{{ item.title }}</div>
<gl-icon
v-if="item.state === 'closed'"

View File

@ -19,10 +19,6 @@
@include gl-relative;
}
.sortable-cell {
padding-left: calc(0.75rem + 0.65em);
}
th {
@include gl-bg-transparent;
@include gl-font-weight-bold;
@ -42,6 +38,10 @@
}
}
}
.sortable-cell {
padding-left: calc(0.75rem + 0.65em);
}
}
}
@ -58,6 +58,11 @@
@include gl-bg-white;
@include gl-border-none;
}
th,
td {
@include gl-pt-6;
}
}
&.alert-management-table {
@ -77,8 +82,24 @@
}
}
.incident-management-list-title {
@include gl-flex-direction-row-reverse;
.b-table-empty-row {
td {
@include gl-border-b-0;
div {
text-align: unset !important;
}
}
}
.b-table-busy-slot {
td {
@include gl-border-b-0;
div {
text-align: center !important;
}
}
}
}
}

View File

@ -0,0 +1,14 @@
# frozen_string_literal: true
module Resolvers
class BoardListIssuesResolver < BaseResolver
type Types::IssueType, null: true
alias_method :list, :object
def resolve(**args)
service = Boards::Issues::ListService.new(list.board.resource_parent, context[:current_user], { board_id: list.board.id, id: list.id })
Gitlab::Graphql::Pagination::OffsetActiveRecordRelationConnection.new(service.execute)
end
end
end

View File

@ -94,8 +94,12 @@ module Types
field :metrics_dashboard_url,
GraphQL::STRING_TYPE,
null: true,
description: 'URL for metrics embed for the alert',
resolve: -> (alert, _args, _context) { alert.present.metrics_dashboard_url }
description: 'URL for metrics embed for the alert'
field :runbook,
GraphQL::STRING_TYPE,
null: true,
description: 'Runbook for the alert as defined in alert details'
field :todos,
Types::TodoType.connection_type,

View File

@ -19,6 +19,10 @@ module Types
field :collapsed, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Indicates if list is collapsed for this user',
resolve: -> (list, _args, ctx) { list.collapsed?(ctx[:current_user]) }
field :issues, ::Types::IssueType.connection_type, null: true,
description: 'Board issues',
resolver: ::Resolvers::BoardListIssuesResolver
end
# rubocop: enable Graphql/AuthorizeTypes
end

View File

@ -7,7 +7,17 @@ module Types
description: 'Total count of collection'
def count
object.items.size
# rubocop: disable CodeReuse/ActiveRecord
relation = object.items
# sometimes relation is an Array
relation = relation.reorder(nil) if relation.respond_to?(:reorder)
# rubocop: enable CodeReuse/ActiveRecord
if relation.try(:group_values)&.present?
relation.size.keys.size
else
relation.size
end
end
end
end

View File

@ -118,6 +118,7 @@ module AlertManagement
end
delegate :iid, to: :issue, prefix: true, allow_nil: true
delegate :metrics_dashboard_url, :runbook, to: :present
scope :for_iid, -> (iid) { where(iid: iid) }
scope :for_status, -> (status) { where(status: status) }

View File

@ -857,8 +857,7 @@ module Ci
end
def multi_build_steps?
options.dig(:release)&.any? &&
Gitlab::Ci::Features.release_generation_enabled?
options.dig(:release)&.any?
end
def hide_secrets(trace)

View File

@ -37,6 +37,12 @@ module AlertManagement
MARKDOWN
end
def runbook
strong_memoize(:runbook) do
payload&.dig('runbook')
end
end
def metrics_dashboard_url; end
private

View File

@ -2,6 +2,12 @@
module AlertManagement
class PrometheusAlertPresenter < AlertManagement::AlertPresenter
def runbook
strong_memoize(:runbook) do
payload&.dig('annotations', 'runbook')
end
end
def metrics_dashboard_url
alerting_alert.metrics_dashboard_url
end

View File

@ -34,7 +34,7 @@ module Metrics
# Returns an un-processed dashboard from the cache.
def raw_dashboard
Gitlab::Metrics::Dashboard::Cache.fetch(cache_key) { get_raw_dashboard }
Gitlab::Metrics::Dashboard::Cache.for(project).fetch(cache_key) { get_raw_dashboard }
end
# Should return true if this dashboard service is for an out-of-the-box

View File

@ -30,6 +30,11 @@ module Metrics
end
end
# Returns an un-processed dashboard from the cache.
def raw_dashboard
Gitlab::Metrics::Dashboard::Cache.fetch(cache_key) { get_raw_dashboard }
end
private
def dashboard_version

View File

@ -0,0 +1,5 @@
---
title: Fix Incident and Alert mobile CSS and alignment
merge_request: 38577
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Expose board list issues via GraphQL
merge_request: 36259
author:
type: added

View File

@ -0,0 +1,5 @@
---
title: Expose runbook field in alert_management_alert GraphQL API
merge_request: 38510
author:
type: added

View File

@ -294,6 +294,11 @@ type AlertManagementAlert implements Noteable {
last: Int
): NoteConnection!
"""
Runbook for the alert as defined in alert details
"""
runbook: String
"""
Service the alert came from
"""
@ -1087,6 +1092,31 @@ type BoardList {
"""
id: ID!
"""
Board issues
"""
issues(
"""
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
): IssueConnection
"""
Label of the list
"""

View File

@ -801,6 +801,20 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "runbook",
"description": "Runbook for the alert as defined in alert details",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "service",
"description": "Service the alert came from",
@ -2927,6 +2941,59 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "issues",
"description": "Board issues",
"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": "IssueConnection",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "label",
"description": "Label of the list",

View File

@ -71,6 +71,7 @@ Describes an alert from the project's Alert Management
| `issueIid` | ID | Internal ID of the GitLab issue attached to the alert |
| `metricsDashboardUrl` | String | URL for metrics embed for the alert |
| `monitoringTool` | String | Monitoring tool the alert came from |
| `runbook` | String | Runbook for the alert as defined in alert details |
| `service` | String | Service the alert came from |
| `severity` | AlertManagementSeverity | Severity of the alert |
| `startedAt` | Time | Timestamp the alert was raised |

View File

@ -82,7 +82,7 @@ path to point to your ECR image.
### Deploy your application to the AWS Elastic Container Service (ECS)
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207962) in GitLab 12.9.
> - The `Deploy-ECS.gitlab-ci.yml` template was deprecated in favor of `AWS/Deploy-ECS.gitlab-ci.yml` template in GitLab 13.2.
> - The `Deploy-ECS.gitlab-ci.yml` template was [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/220821) to `AWS/Deploy-ECS.gitlab-ci.yml` in GitLab 13.2.
GitLab provides a series of [CI templates that you can include in your project](../yaml/README.md#include).
To automate deployments of your application to your [Amazon Elastic Container Service](https://aws.amazon.com/ecs/) (AWS ECS)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

@ -90,15 +90,20 @@ When a link of a commit reference is found in a thread inside a merge
request, it will be automatically converted to a link in the context of the
current merge request.
### Jumping between unresolved threads
### Jumping between unresolved threads (deprecated)
> - [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/199718) in GitLab 13.3.
> - This button's removal is behind a feature flag enabled by default.
> - For GitLab self-managed instances, GitLab administrators with access to the
[GitLab Rails console](../../administration/feature_flags.md) can opt to disable it by running
`Feature.disable(:hide_jump_to_next_unresolved_in_threads)` (for the instance) or
`Feature.disable(:hide_jump_to_next_unresolved_in_threads, Project.find(<project id>))`
(per project.) **(CORE ONLY)**
When a merge request has a large number of comments it can be difficult to track
what remains unresolved. You can jump between unresolved threads with the
Jump button next to the Reply field on a thread.
You can also jump to the next unresolved thread from the button next to the
resolved threads tracker.
You can also use keyboard shortcuts to navigate among threads:
- Use <kbd>n</kbd> to jump to the next unresolved thread.
@ -111,7 +116,7 @@ You can also use keyboard shortcuts to navigate among threads:
You can mark a thread as resolved by clicking the **Resolve thread**
button at the bottom of the thread.
!["Resolve thread" button](img/resolve_thread_button.png)
!["Resolve thread" button](img/resolve_thread_button_v13_3.png)
Alternatively, you can mark each comment as resolved individually.

View File

@ -21,8 +21,6 @@ module Gitlab
end
def from_release(job)
return unless Gitlab::Ci::Features.release_generation_enabled?
release = job.options[:release]
return unless release

View File

@ -22,12 +22,6 @@ module Gitlab
validates :config, allowed_keys: ALLOWED_KEYS + PROCESSABLE_ALLOWED_KEYS
validates :config, required_keys: REQUIRED_BY_NEEDS, if: :has_needs?
validates :script, presence: true
validates :config,
disallowed_keys: {
in: %i[release],
message: 'release features are not enabled'
},
unless: -> { Gitlab::Ci::Features.release_generation_enabled? }
with_options allow_nil: true do
validates :allow_failure, boolean: true

View File

@ -34,10 +34,6 @@ module Gitlab
Feature.enabled?(:ci_pipeline_status_omit_commit_sha_in_cache_key, project, default_enabled: true)
end
def self.release_generation_enabled?
::Feature.enabled?(:ci_release_generation, default_enabled: true)
end
# Remove in https://gitlab.com/gitlab-org/gitlab/-/issues/224199
def self.store_pipeline_messages?(project)
::Feature.enabled?(:ci_store_pipeline_messages, project, default_enabled: true)

View File

@ -115,7 +115,7 @@ module Gitlab
end
def release(job)
job[:release] if Gitlab::Ci::Features.release_generation_enabled?
job[:release]
end
def stage_builds_attributes(stage)

View File

@ -9,34 +9,53 @@ module Gitlab
CACHE_KEYS = 'all_cached_metric_dashboards'
class << self
# Stores a dashboard in the cache, documenting the key
# so the cached can be cleared in bulk at another time.
def fetch(key)
register_key(key)
# This class method (Gitlab::Metrics::Dashboard::Cache.fetch) can be used
# when the key does not need to be deleted by `delete_all!`.
# For example, out of the box dashboard caches do not need to be deleted.
delegate :fetch, to: :"Rails.cache"
Rails.cache.fetch(key) { yield }
end
alias_method :for, :new
end
# Resets all dashboard caches, such that all
# dashboard content will be loaded from source on
# subsequent dashboard calls.
def delete_all!
all_keys.each { |key| Rails.cache.delete(key) }
def initialize(project)
@project = project
end
Rails.cache.delete(CACHE_KEYS)
end
# Stores a dashboard in the cache, documenting the key
# so the cache can be cleared in bulk at another time.
def fetch(key)
register_key(key)
private
Rails.cache.fetch(key) { yield }
end
def register_key(key)
new_keys = all_keys.add(key).to_a.join('|')
# Resets all dashboard caches, such that all
# dashboard content will be loaded from source on
# subsequent dashboard calls.
def delete_all!
all_keys.each { |key| Rails.cache.delete(key) }
Rails.cache.write(CACHE_KEYS, new_keys)
end
Rails.cache.delete(catalog_key)
end
def all_keys
Set.new(Rails.cache.read(CACHE_KEYS)&.split('|'))
end
private
def register_key(key)
new_keys = all_keys.add(key).to_a.join('|')
Rails.cache.write(catalog_key, new_keys)
end
def all_keys
keys = Rails.cache.read(catalog_key)&.split('|')
Set.new(keys)
end
# One key to store them all...
# This key is used to store the names of all the keys that contain this
# project's dashboards.
def catalog_key
"#{CACHE_KEYS}_#{@project.id}"
end
end
end

View File

@ -14,7 +14,7 @@ module Gitlab
# Also deletes all dashboard cache entries.
# @return [Array] ex) ['.gitlab/dashboards/dashboard1.yml']
def list_dashboards(project)
Gitlab::Metrics::Dashboard::Cache.delete_all!
Gitlab::Metrics::Dashboard::Cache.for(project).delete_all!
file_finder(project).list_files_for(DASHBOARD_ROOT)
end

View File

@ -10369,12 +10369,18 @@ msgstr ""
msgid "FeatureFlags|Flag becomes read only soon"
msgstr ""
msgid "FeatureFlags|Flag is read-only"
msgstr ""
msgid "FeatureFlags|Get started with feature flags"
msgstr ""
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags, and in 13.4, this feature flag will become read-only. Please create a new feature flag."
msgstr ""
msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
msgstr ""
msgid "FeatureFlags|ID"
msgstr ""
@ -21294,7 +21300,10 @@ msgstr ""
msgid "SecurityConfiguration|Configure"
msgstr ""
msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be excluded from automatic updates. We've provided guidance for some easily configurable variables below, but our docs go into even more depth. %{linkStart}Read more%{linkEnd}"
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@ -21330,9 +21339,6 @@ msgstr ""
msgid "SecurityConfiguration|Testing & Compliance"
msgstr ""
msgid "SecurityConfiguration|There was an error loading the configuration. Please reload the page to try again."
msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""

View File

@ -0,0 +1,58 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Resolvers::BoardListIssuesResolver do
include GraphqlHelpers
let_it_be(:user) { create(:user) }
let_it_be(:unauth_user) { create(:user) }
let_it_be(:user_project) { create(:project, creator_id: user.id, namespace: user.namespace ) }
let_it_be(:group) { create(:group, :private) }
shared_examples_for 'group and project board list issues resolver' do
let!(:board) { create(:board, resource_parent: board_parent) }
before do
board_parent.add_developer(user)
end
# auth is handled by the parent object
context 'when authorized' do
let!(:list) { create(:list, board: board, label: label) }
it 'returns the issues in the correct order' do
issue1 = create(:issue, project: project, labels: [label], relative_position: 10)
issue2 = create(:issue, project: project, labels: [label], relative_position: 12)
issue3 = create(:issue, project: project, labels: [label], relative_position: 10)
# by relative_position and then ID
issues = resolve_board_list_issues.items
expect(issues.map(&:id)).to eq [issue3.id, issue1.id, issue2.id]
end
end
end
describe '#resolve' do
context 'when project boards' do
let(:board_parent) { user_project }
let!(:label) { create(:label, project: project, name: 'project label') }
let(:project) { user_project }
it_behaves_like 'group and project board list issues resolver'
end
context 'when group boards' do
let(:board_parent) { group }
let!(:label) { create(:group_label, group: group, name: 'group label') }
let!(:project) { create(:project, :private, group: group) }
it_behaves_like 'group and project board list issues resolver'
end
end
def resolve_board_list_issues(args: {}, current_user: user)
resolve(described_class, obj: list, args: args, ctx: { current_user: current_user })
end
end

View File

@ -28,6 +28,7 @@ RSpec.describe GitlabSchema.types['AlertManagementAlert'] do
notes
discussions
metrics_dashboard_url
runbook
todos
]

View File

@ -6,7 +6,7 @@ RSpec.describe GitlabSchema.types['BoardList'] do
specify { expect(described_class.graphql_name).to eq('BoardList') }
it 'has specific fields' do
expected_fields = %w[id list_type position label]
expected_fields = %w[id list_type position label issues]
expect(described_class).to include_graphql_fields(*expected_fields)
end

View File

@ -1641,26 +1641,9 @@ module Gitlab
}
end
context 'with feature flag active' do
before do
stub_feature_flags(ci_release_generation: true)
end
it "returns release info" do
expect(processor.stage_builds_attributes('release').first[:options])
.to eq(config[:release].except(:stage, :only))
end
end
context 'with feature flag inactive' do
before do
stub_feature_flags(ci_release_generation: false)
end
it 'raises error' do
expect { processor }.to raise_error(
'jobs:release config release features are not enabled: release')
end
it "returns release info" do
expect(processor.stage_builds_attributes('release').first[:options])
.to eq(config[:release].except(:stage, :only))
end
end

View File

@ -0,0 +1,86 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Metrics::Dashboard::Cache, :use_clean_rails_memory_store_caching do
let_it_be(:project1) { build_stubbed(:project) }
let_it_be(:project2) { build_stubbed(:project) }
let(:project1_key1) { "#{project1.id}_key1" }
let(:project1_key2) { "#{project1.id}_key2" }
let(:project2_key1) { "#{project2.id}_key1" }
let(:cache1) { described_class.for(project1) }
let(:cache2) { described_class.for(project2) }
before do
cache1.fetch(project1_key1) { 'data1' }
cache1.fetch(project1_key2) { 'data2' }
cache2.fetch(project2_key1) { 'data3' }
end
describe '.fetch' do
it 'stores data correctly' do
described_class.fetch('key1') { 'data1' }
described_class.fetch('key2') { 'data2' }
expect(described_class.fetch('key1')).to eq('data1')
expect(described_class.fetch('key2')).to eq('data2')
end
end
describe '.for' do
it 'returns a new instance' do
expect(described_class.for(project1)).to be_instance_of(described_class)
end
end
describe '#fetch' do
it 'stores data correctly' do
expect(cache1.fetch(project1_key1)).to eq('data1')
expect(cache1.fetch(project1_key2)).to eq('data2')
expect(cache2.fetch(project2_key1)).to eq('data3')
end
end
describe '#delete_all!' do
it 'deletes keys of the given project', :aggregate_failures do
cache1.delete_all!
expect(Rails.cache.exist?(project1_key1)).to be(false)
expect(Rails.cache.exist?(project1_key2)).to be(false)
expect(cache2.fetch(project2_key1)).to eq('data3')
cache2.delete_all!
expect(Rails.cache.exist?(project2_key1)).to be(false)
end
it 'does not fail when nothing to delete' do
project3 = build_stubbed(:project)
cache3 = described_class.for(project3)
expect { cache3.delete_all! }.not_to raise_error
end
end
context 'multiple fetches and deletes' do
specify :aggregate_failures do
cache1.delete_all!
expect(Rails.cache.exist?(project1_key1)).to be(false)
expect(Rails.cache.exist?(project1_key2)).to be(false)
cache1.fetch("#{project1.id}_key3") { 'data1' }
cache1.fetch("#{project1.id}_key4") { 'data2' }
expect(cache1.fetch("#{project1.id}_key3")).to eq('data1')
expect(cache1.fetch("#{project1.id}_key4")).to eq('data2')
cache1.delete_all!
expect(Rails.cache.exist?("#{project1.id}_key3")).to be(false)
expect(Rails.cache.exist?("#{project1.id}_key4")).to be(false)
end
end
end

View File

@ -9,7 +9,10 @@ RSpec.describe Gitlab::Metrics::Dashboard::RepoDashboardFinder do
describe '.list_dashboards' do
it 'deletes dashboard cache entries' do
expect(Gitlab::Metrics::Dashboard::Cache).to receive(:delete_all!).and_call_original
cache = instance_double(Gitlab::Metrics::Dashboard::Cache)
allow(Gitlab::Metrics::Dashboard::Cache).to receive(:for).and_return(cache)
expect(cache).to receive(:delete_all!)
described_class.list_dashboards(project)
end

View File

@ -8,11 +8,12 @@ RSpec.describe AlertManagement::AlertPresenter do
{
'title' => 'Alert title',
'start_time' => '2020-04-27T10:10:22.265949279Z',
'custom' => { 'param' => 73 }
'custom' => { 'param' => 73 },
'runbook' => 'https://runbook.com'
}
end
let_it_be(:alert) do
create(:alert_management_alert, :with_description, :with_host, :with_service, :with_monitoring_tool, project: project, payload: generic_payload)
build(:alert_management_alert, :with_description, :with_host, :with_service, :with_monitoring_tool, project: project, payload: generic_payload)
end
subject(:presenter) { described_class.new(alert) }
@ -34,7 +35,8 @@ RSpec.describe AlertManagement::AlertPresenter do
#### Alert Details
**custom.param:** 73
**custom.param:** 73#{markdown_line_break}
**runbook:** https://runbook.com
MARKDOWN
)
end
@ -45,4 +47,10 @@ RSpec.describe AlertManagement::AlertPresenter do
expect(presenter.metrics_dashboard_url).to be_nil
end
end
describe '#runbook' do
it 'shows the runbook from the payload' do
expect(presenter.runbook).to eq('https://runbook.com')
end
end
end

View File

@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe AlertManagement::PrometheusAlertPresenter do
let_it_be(:project) { create(:project) }
let_it_be(:payload) do
let(:payload) do
{
'annotations' => {
'title' => 'Alert title',
@ -15,6 +15,7 @@ RSpec.describe AlertManagement::PrometheusAlertPresenter do
'generatorURL' => 'http://8d467bd4607a:9090/graph?g0.expr=vector%281%29&g0.tab=1'
}
end
let(:alert) do
create(:alert_management_alert, :prometheus, project: project, payload: payload)
end
@ -65,4 +66,17 @@ RSpec.describe AlertManagement::PrometheusAlertPresenter do
it { is_expected.to eq(dashboard_url_for_alert) }
end
end
describe '#runbook' do
subject { presenter.runbook }
it { is_expected.to be_nil }
context 'with runbook in payload' do
let(:expected_runbook) { 'https://awesome-runbook.com' }
let(:payload) { { 'annotations' => { 'runbook' => expected_runbook } } }
it { is_expected.to eq(expected_runbook) }
end
end
end

View File

@ -0,0 +1,101 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'get board lists' do
include GraphqlHelpers
let_it_be(:user) { create(:user) }
let_it_be(:unauth_user) { create(:user) }
let_it_be(:project) { create(:project, creator_id: user.id, namespace: user.namespace ) }
let_it_be(:group) { create(:group, :private) }
let_it_be(:project_label) { create(:label, project: project, name: 'Development') }
let_it_be(:project_label2) { create(:label, project: project, name: 'Testing') }
let_it_be(:group_label) { create(:group_label, group: group, name: 'Development') }
let_it_be(:group_label2) { create(:group_label, group: group, name: 'Testing') }
let(:params) { '' }
let(:board) { }
let(:board_parent_type) { board_parent.class.to_s.downcase }
let(:board_data) { graphql_data[board_parent_type]['boards']['nodes'][0] }
let(:lists_data) { board_data['lists']['nodes'][0] }
let(:issues_data) { lists_data['issues']['nodes'] }
def query(list_params = params)
graphql_query_for(
board_parent_type,
{ 'fullPath' => board_parent.full_path },
<<~BOARDS
boards(first: 1) {
nodes {
lists {
nodes {
issues {
count
nodes {
#{all_graphql_fields_for('issues'.classify)}
}
}
}
}
}
}
BOARDS
)
end
def issue_titles
issues_data.map { |i| i['title'] }
end
shared_examples 'group and project board list issues query' do
let!(:board) { create(:board, resource_parent: board_parent) }
let!(:label_list) { create(:list, board: board, label: label, position: 10) }
let!(:issue1) { create(:issue, project: issue_project, labels: [label], relative_position: 9) }
let!(:issue2) { create(:issue, project: issue_project, labels: [label], relative_position: 2) }
let!(:issue3) { create(:issue, project: issue_project, labels: [label], relative_position: 9) }
let!(:issue4) { create(:issue, project: issue_project, labels: [label2], relative_position: 432) }
context 'when the user does not have access to the board' do
it 'returns nil' do
post_graphql(query, current_user: unauth_user)
expect(graphql_data[board_parent_type]).to be_nil
end
end
context 'when user can read the board' do
before do
board_parent.add_reporter(user)
end
it 'can access the issues' do
post_graphql(query("id: \"#{global_id_of(label_list)}\""), current_user: user)
expect(issue_titles).to eq([issue2.title, issue3.title, issue1.title])
end
end
end
describe 'for a project' do
let(:board_parent) { project }
let(:label) { project_label }
let(:label2) { project_label2 }
let(:issue_project) { project }
it_behaves_like 'group and project board list issues query'
end
describe 'for a group' do
let(:board_parent) { group }
let(:label) { group_label }
let(:label2) { group_label2 }
let(:issue_project) { create(:project, :private, group: group) }
before do
allow(board_parent).to receive(:multiple_issue_boards_available?).and_return(false)
end
it_behaves_like 'group and project board list issues query'
end
end

View File

@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'getting Alert Management Alerts' do
include GraphqlHelpers
let_it_be(:payload) { { 'custom' => { 'alert' => 'payload' } } }
let_it_be(:payload) { { 'custom' => { 'alert' => 'payload' }, 'runbook' => 'runbook' } }
let_it_be(:project) { create(:project, :repository) }
let_it_be(:current_user) { create(:user) }
let_it_be(:resolved_alert) { create(:alert_management_alert, :all_fields, :resolved, project: project, issue: nil, severity: :low) }
@ -71,10 +71,11 @@ RSpec.describe 'getting Alert Management Alerts' do
'eventCount' => triggered_alert.events,
'startedAt' => triggered_alert.started_at.strftime('%Y-%m-%dT%H:%M:%SZ'),
'endedAt' => nil,
'details' => { 'custom.alert' => 'payload' },
'details' => { 'custom.alert' => 'payload', 'runbook' => 'runbook' },
'createdAt' => triggered_alert.created_at.strftime('%Y-%m-%dT%H:%M:%SZ'),
'updatedAt' => triggered_alert.updated_at.strftime('%Y-%m-%dT%H:%M:%SZ'),
'metricsDashboardUrl' => nil
'metricsDashboardUrl' => nil,
'runbook' => 'runbook'
)
expect(second_alert).to include(

View File

@ -982,7 +982,6 @@ RSpec.describe Ci::CreatePipelineService do
context 'with release' do
shared_examples_for 'a successful release pipeline' do
before do
stub_feature_flags(ci_release_generation: true)
stub_ci_pipeline_yaml_file(YAML.dump(config))
end

View File

@ -111,7 +111,8 @@ RSpec.describe Metrics::Dashboard::CustomMetricEmbedService do
it_behaves_like 'valid embedded dashboard service response'
it 'does not cache the unprocessed dashboard' do
expect(Gitlab::Metrics::Dashboard::Cache).not_to receive(:fetch)
# Fail spec if any method of Cache class is called.
stub_const('Gitlab::Metrics::Dashboard::Cache', double)
described_class.new(*service_params).get_dashboard
end

View File

@ -87,7 +87,8 @@ RSpec.describe Metrics::Dashboard::GitlabAlertEmbedService do
end
it 'does not cache the unprocessed dashboard' do
expect(Gitlab::Metrics::Dashboard::Cache).not_to receive(:fetch)
# Fail spec if any method of Cache class is called.
stub_const('Gitlab::Metrics::Dashboard::Cache', double)
described_class.new(*service_params).get_dashboard
end