Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
729e3765d5
commit
120f4aaedc
|
|
@ -0,0 +1,6 @@
|
||||||
|
import PersistentUserCallout from '~/persistent_user_callout';
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const callout = document.querySelector('.js-admin-integrations-moved');
|
||||||
|
PersistentUserCallout.factory(callout);
|
||||||
|
});
|
||||||
|
|
@ -3,7 +3,7 @@ import ZenMode from '~/zen_mode';
|
||||||
import LineHighlighter from '~/line_highlighter';
|
import LineHighlighter from '~/line_highlighter';
|
||||||
import BlobViewer from '~/blob/viewer';
|
import BlobViewer from '~/blob/viewer';
|
||||||
import snippetEmbed from '~/snippet/snippet_embed';
|
import snippetEmbed from '~/snippet/snippet_embed';
|
||||||
import initSnippetsApp from '~/snippets';
|
import { SnippetShowInit } from '~/snippets';
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
if (!gon.features.snippetsVue) {
|
if (!gon.features.snippetsVue) {
|
||||||
|
|
@ -13,7 +13,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
new ZenMode(); // eslint-disable-line no-new
|
new ZenMode(); // eslint-disable-line no-new
|
||||||
snippetEmbed();
|
snippetEmbed();
|
||||||
} else {
|
} else {
|
||||||
initSnippetsApp();
|
SnippetShowInit();
|
||||||
initNotes();
|
initNotes();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import BlobViewer from '~/blob/viewer';
|
||||||
import ZenMode from '~/zen_mode';
|
import ZenMode from '~/zen_mode';
|
||||||
import initNotes from '~/init_notes';
|
import initNotes from '~/init_notes';
|
||||||
import snippetEmbed from '~/snippet/snippet_embed';
|
import snippetEmbed from '~/snippet/snippet_embed';
|
||||||
import initSnippetsApp from '~/snippets';
|
import { SnippetShowInit } from '~/snippets';
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
if (!gon.features.snippetsVue) {
|
if (!gon.features.snippetsVue) {
|
||||||
|
|
@ -13,7 +13,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
new ZenMode(); // eslint-disable-line no-new
|
new ZenMode(); // eslint-disable-line no-new
|
||||||
snippetEmbed();
|
snippetEmbed();
|
||||||
} else {
|
} else {
|
||||||
initSnippetsApp();
|
SnippetShowInit();
|
||||||
initNotes();
|
initNotes();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,11 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="table-section section-10 d-none d-sm-none d-md-block pipeline-tags">
|
<div class="table-section section-10 d-none d-sm-none d-md-block pipeline-tags">
|
||||||
<gl-link :href="pipeline.path" class="js-pipeline-url-link js-onboarding-pipeline-item">
|
<gl-link
|
||||||
|
:href="pipeline.path"
|
||||||
|
class="js-pipeline-url-link js-onboarding-pipeline-item"
|
||||||
|
data-qa-selector="pipeline_url_link"
|
||||||
|
>
|
||||||
<span class="pipeline-id">#{{ pipeline.id }}</span>
|
<span class="pipeline-id">#{{ pipeline.id }}</span>
|
||||||
</gl-link>
|
</gl-link>
|
||||||
<div class="label-container">
|
<div class="label-container">
|
||||||
|
|
|
||||||
|
|
@ -3,19 +3,16 @@ import Translate from '~/vue_shared/translate';
|
||||||
import VueApollo from 'vue-apollo';
|
import VueApollo from 'vue-apollo';
|
||||||
import createDefaultClient from '~/lib/graphql';
|
import createDefaultClient from '~/lib/graphql';
|
||||||
|
|
||||||
import SnippetsApp from './components/app.vue';
|
import SnippetsApp from './components/show.vue';
|
||||||
|
|
||||||
Vue.use(VueApollo);
|
Vue.use(VueApollo);
|
||||||
Vue.use(Translate);
|
Vue.use(Translate);
|
||||||
|
|
||||||
export default () => {
|
function appFactory(el, Component) {
|
||||||
const el = document.getElementById('js-snippet-view');
|
|
||||||
|
|
||||||
if (!el) {
|
if (!el) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { snippetGid } = el.dataset;
|
|
||||||
const apolloProvider = new VueApollo({
|
const apolloProvider = new VueApollo({
|
||||||
defaultClient: createDefaultClient(),
|
defaultClient: createDefaultClient(),
|
||||||
});
|
});
|
||||||
|
|
@ -24,11 +21,17 @@ export default () => {
|
||||||
el,
|
el,
|
||||||
apolloProvider,
|
apolloProvider,
|
||||||
render(createElement) {
|
render(createElement) {
|
||||||
return createElement(SnippetsApp, {
|
return createElement(Component, {
|
||||||
props: {
|
props: {
|
||||||
snippetGid,
|
...el.dataset,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SnippetShowInit = () => {
|
||||||
|
appFactory(document.getElementById('js-snippet-view'), SnippetsApp);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default () => {};
|
||||||
|
|
|
||||||
|
|
@ -81,3 +81,8 @@
|
||||||
.gl-text-green-700 { @include gl-text-green-700; }
|
.gl-text-green-700 { @include gl-text-green-700; }
|
||||||
|
|
||||||
.gl-align-items-center { @include gl-align-items-center; }
|
.gl-align-items-center { @include gl-align-items-center; }
|
||||||
|
.d-sm-table-column {
|
||||||
|
@include media-breakpoint-up(sm) {
|
||||||
|
display: table-column !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,16 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
|
||||||
define_method(action) { perform_update if submitted? }
|
define_method(action) { perform_update if submitted? }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def integrations
|
||||||
|
if Feature.enabled?(:instance_level_integrations)
|
||||||
|
# TODO: Update this with actual integrations
|
||||||
|
# To be fixed with https://gitlab.com/gitlab-org/gitlab/-/issues/199388
|
||||||
|
@integrations = []
|
||||||
|
end
|
||||||
|
|
||||||
|
perform_update if submitted?
|
||||||
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
perform_update
|
perform_update
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ module BroadcastMessagesHelper
|
||||||
|
|
||||||
def render_broadcast_message(broadcast_message)
|
def render_broadcast_message(broadcast_message)
|
||||||
if Feature.enabled?(:broadcast_message_placeholders)
|
if Feature.enabled?(:broadcast_message_placeholders)
|
||||||
Banzai.render_and_post_process(broadcast_message.message, {
|
Banzai.render_field_and_post_process(broadcast_message, :message, {
|
||||||
current_user: current_user,
|
current_user: current_user,
|
||||||
skip_project_check: true,
|
skip_project_check: true,
|
||||||
broadcast_message_placeholders: true
|
broadcast_message_placeholders: true
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,10 @@ module ServicesHelper
|
||||||
!current_controller?("admin/services") && service.deprecated?
|
!current_controller?("admin/services") && service.deprecated?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def edit_integration_path(integration)
|
||||||
|
edit_admin_application_settings_integration_path(integration)
|
||||||
|
end
|
||||||
|
|
||||||
extend self
|
extend self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,17 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module UserCalloutsHelper
|
module UserCalloutsHelper
|
||||||
|
ADMIN_INTEGRATIONS_MOVED = 'admin_integrations_moved'
|
||||||
GKE_CLUSTER_INTEGRATION = 'gke_cluster_integration'
|
GKE_CLUSTER_INTEGRATION = 'gke_cluster_integration'
|
||||||
GCP_SIGNUP_OFFER = 'gcp_signup_offer'
|
GCP_SIGNUP_OFFER = 'gcp_signup_offer'
|
||||||
SUGGEST_POPOVER_DISMISSED = 'suggest_popover_dismissed'
|
SUGGEST_POPOVER_DISMISSED = 'suggest_popover_dismissed'
|
||||||
TABS_POSITION_HIGHLIGHT = 'tabs_position_highlight'
|
TABS_POSITION_HIGHLIGHT = 'tabs_position_highlight'
|
||||||
WEBHOOKS_MOVED = 'webhooks_moved'
|
WEBHOOKS_MOVED = 'webhooks_moved'
|
||||||
|
|
||||||
|
def show_admin_integrations_moved?
|
||||||
|
!user_dismissed?(ADMIN_INTEGRATIONS_MOVED)
|
||||||
|
end
|
||||||
|
|
||||||
def show_gke_cluster_integration_callout?(project)
|
def show_gke_cluster_integration_callout?(project)
|
||||||
can?(current_user, :create_cluster, project) &&
|
can?(current_user, :create_cluster, project) &&
|
||||||
!user_dismissed?(GKE_CLUSTER_INTEGRATION)
|
!user_dismissed?(GKE_CLUSTER_INTEGRATION)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ module OptionallySearch
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
class_methods do
|
class_methods do
|
||||||
def search(*)
|
def search(query, **options)
|
||||||
raise(
|
raise(
|
||||||
NotImplementedError,
|
NotImplementedError,
|
||||||
'Your model must implement the "search" class method'
|
'Your model must implement the "search" class method'
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ class Label < ApplicationRecord
|
||||||
# query - The search query as a String.
|
# query - The search query as a String.
|
||||||
#
|
#
|
||||||
# Returns an ActiveRecord::Relation.
|
# Returns an ActiveRecord::Relation.
|
||||||
def self.search(query)
|
def self.search(query, **options)
|
||||||
fuzzy_search(query, [:title, :description])
|
fuzzy_search(query, [:title, :description])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -274,7 +274,7 @@ class Namespace < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def has_parent?
|
def has_parent?
|
||||||
parent_id.present? || parent.present?
|
parent.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
def root_ancestor
|
def root_ancestor
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
require "discordrb/webhooks"
|
require "discordrb/webhooks"
|
||||||
|
|
||||||
class DiscordService < ChatNotificationService
|
class DiscordService < ChatNotificationService
|
||||||
|
ATTACHMENT_REGEX = /: (?<entry>.*?)\n - (?<name>.*)\n*/.freeze
|
||||||
|
|
||||||
def title
|
def title
|
||||||
s_("DiscordService|Discord Notifications")
|
s_("DiscordService|Discord Notifications")
|
||||||
end
|
end
|
||||||
|
|
@ -52,7 +54,10 @@ class DiscordService < ChatNotificationService
|
||||||
client = Discordrb::Webhooks::Client.new(url: webhook)
|
client = Discordrb::Webhooks::Client.new(url: webhook)
|
||||||
|
|
||||||
client.execute do |builder|
|
client.execute do |builder|
|
||||||
builder.content = message.pretext
|
builder.add_embed do |embed|
|
||||||
|
embed.author = Discordrb::Webhooks::EmbedAuthor.new(name: message.user_name, icon_url: message.user_avatar)
|
||||||
|
embed.description = (message.pretext + "\n" + Array.wrap(message.attachments).join("\n")).gsub(ATTACHMENT_REGEX, " \\k<entry> - \\k<name>\n")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -511,7 +511,7 @@ class User < ApplicationRecord
|
||||||
# query - The search query as a String
|
# query - The search query as a String
|
||||||
#
|
#
|
||||||
# Returns an ActiveRecord::Relation.
|
# Returns an ActiveRecord::Relation.
|
||||||
def search(query)
|
def search(query, **options)
|
||||||
query = query&.delete_prefix('@')
|
query = query&.delete_prefix('@')
|
||||||
return none if query.blank?
|
return none if query.blank?
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ module UserCalloutEnums
|
||||||
cluster_security_warning: 3,
|
cluster_security_warning: 3,
|
||||||
suggest_popover_dismissed: 9,
|
suggest_popover_dismissed: 9,
|
||||||
tabs_position_highlight: 10,
|
tabs_position_highlight: 10,
|
||||||
webhooks_moved: 13
|
webhooks_moved: 13,
|
||||||
|
admin_integrations_moved: 15
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -103,3 +103,12 @@
|
||||||
= s_('IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation.')
|
= s_('IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation.')
|
||||||
|
|
||||||
= f.submit _('Save changes'), class: "btn btn-success"
|
= f.submit _('Save changes'), class: "btn btn-success"
|
||||||
|
|
||||||
|
- if Feature.enabled?(:instance_level_integrations)
|
||||||
|
= render_if_exists 'admin/application_settings/elasticsearch_form'
|
||||||
|
= render 'admin/application_settings/plantuml'
|
||||||
|
= render 'admin/application_settings/sourcegraph'
|
||||||
|
= render_if_exists 'admin/application_settings/slack'
|
||||||
|
= render 'admin/application_settings/third_party_offers'
|
||||||
|
= render 'admin/application_settings/snowplow'
|
||||||
|
= render 'admin/application_settings/eks'
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,30 @@
|
||||||
- breadcrumb_title _("Integrations")
|
- breadcrumb_title _('Integrations')
|
||||||
- page_title _("Integrations")
|
- page_title _('Integrations')
|
||||||
- @content_class = "limit-container-width" unless fluid_layout
|
- @content_class = 'limit-container-width' unless fluid_layout
|
||||||
|
|
||||||
= render_if_exists 'admin/application_settings/elasticsearch_form'
|
- if Feature.enabled?(:instance_level_integrations)
|
||||||
= render 'admin/application_settings/plantuml'
|
- if show_admin_integrations_moved?
|
||||||
= render 'admin/application_settings/sourcegraph'
|
.gl-alert.gl-alert-info.js-admin-integrations-moved.mt-3{ role: 'alert', data: { feature_id: UserCalloutsHelper::ADMIN_INTEGRATIONS_MOVED, dismiss_endpoint: user_callouts_path } }
|
||||||
= render_if_exists 'admin/application_settings/slack'
|
= sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
|
||||||
= render 'admin/application_settings/third_party_offers'
|
%button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') }
|
||||||
= render 'admin/application_settings/snowplow'
|
= sprite_icon('close', size: 16, css_class: 'gl-icon')
|
||||||
= render 'admin/application_settings/eks'
|
.gl-alert-body
|
||||||
|
%h4.gl-alert-title= s_('AdminSettings|Some settings have moved')
|
||||||
|
= s_('AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings > General.')
|
||||||
|
.gl-alert-actions
|
||||||
|
= link_to s_('AdminSettings|Go to General Settings'), admin_application_settings_path, class: 'btn gl-alert-action btn-info new-gl-button'
|
||||||
|
|
||||||
|
%h4= s_('AdminSettings|Apply integration settings to all Projects')
|
||||||
|
%p
|
||||||
|
= s_('AdminSettings|Integrations configured here will automatically apply to all projects on this instance.')
|
||||||
|
= link_to _('Learn more'), '#'
|
||||||
|
= render 'projects/services/integrations'
|
||||||
|
|
||||||
|
- else
|
||||||
|
= render_if_exists 'admin/application_settings/elasticsearch_form'
|
||||||
|
= render 'admin/application_settings/plantuml'
|
||||||
|
= render 'admin/application_settings/sourcegraph'
|
||||||
|
= render_if_exists 'admin/application_settings/slack'
|
||||||
|
= render 'admin/application_settings/third_party_offers'
|
||||||
|
= render 'admin/application_settings/snowplow'
|
||||||
|
= render 'admin/application_settings/eks'
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
- add_to_breadcrumbs _('Integrations'), admin_application_settings_integration_path
|
- add_to_breadcrumbs _('Integrations'), integrations_admin_application_settings_path
|
||||||
- breadcrumb_title @service.title
|
- breadcrumb_title @service.title
|
||||||
- page_title @service.title, _('Integrations')
|
- page_title @service.title, _('Integrations')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
%table.table.b-table.gl-table.mt-3{ role: 'table', 'aria-busy': false, 'aria-colcount': 4 }
|
||||||
|
%colgroup
|
||||||
|
%col
|
||||||
|
%col
|
||||||
|
%col.d-none.d-sm-table-column
|
||||||
|
%col{ width: 120 }
|
||||||
|
%thead{ role: 'rowgroup' }
|
||||||
|
%tr{ role: 'row' }
|
||||||
|
%th{ role: 'columnheader', scope: 'col', 'aria-colindex': 1 }
|
||||||
|
%th{ role: 'columnheader', scope: 'col', 'aria-colindex': 2 }= _('Integration')
|
||||||
|
%th.d-none.d-sm-block{ role: 'columnheader', scope: 'col', 'aria-colindex': 3 }= _('Description')
|
||||||
|
%th{ role: 'columnheader', scope: 'col', 'aria-colindex': 4 }= _('Last updated')
|
||||||
|
|
||||||
|
%tbody{ role: 'rowgroup' }
|
||||||
|
- @integrations&.each do |integration|
|
||||||
|
%tr{ role: 'row' }
|
||||||
|
%td{ role: 'cell', 'aria-colindex': 1 }
|
||||||
|
= boolean_to_icon integration.activated?
|
||||||
|
%td{ role: 'cell', 'aria-colindex': 2 }
|
||||||
|
= link_to edit_integration_path(integration) do
|
||||||
|
%strong= integration.title
|
||||||
|
%td.d-none.d-sm-block{ role: 'cell', 'aria-colindex': 3 }
|
||||||
|
= integration.description
|
||||||
|
%td{ role: 'cell', 'aria-colindex': 4 }
|
||||||
|
- if integration.updated_at.present?
|
||||||
|
= time_ago_with_tooltip integration.updated_at
|
||||||
|
|
@ -928,7 +928,7 @@
|
||||||
:weight: 2
|
:weight: 2
|
||||||
:idempotent: true
|
:idempotent: true
|
||||||
- :name: background_migration
|
- :name: background_migration
|
||||||
:feature_category: :not_owned
|
:feature_category: :database
|
||||||
:has_external_dependencies:
|
:has_external_dependencies:
|
||||||
:urgency: :low
|
:urgency: :low
|
||||||
:resource_boundary: :unknown
|
:resource_boundary: :unknown
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
class BackgroundMigrationWorker # rubocop:disable Scalability/IdempotentWorker
|
class BackgroundMigrationWorker # rubocop:disable Scalability/IdempotentWorker
|
||||||
include ApplicationWorker
|
include ApplicationWorker
|
||||||
|
|
||||||
feature_category_not_owned!
|
feature_category :database
|
||||||
|
|
||||||
# The minimum amount of time between processing two jobs of the same migration
|
# The minimum amount of time between processing two jobs of the same migration
|
||||||
# class.
|
# class.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Optimize usage ping queries by using batch counting
|
||||||
|
merge_request: 27455
|
||||||
|
author:
|
||||||
|
type: performance
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Update discord notifications to be a single embed and include log messages
|
||||||
|
merge_request: 27812
|
||||||
|
author: Sam Bingner
|
||||||
|
type: fixed
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Use id instead of cve where possible when parsing remediations
|
||||||
|
merge_request: 27815
|
||||||
|
author:
|
||||||
|
type: other
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
---
|
---
|
||||||
- accessibility_testing
|
- accessibility_testing
|
||||||
- analysis
|
- analysis
|
||||||
|
- api
|
||||||
- attack_emulation
|
- attack_emulation
|
||||||
- audit_events
|
- audit_events
|
||||||
- audit_reports
|
- audit_reports
|
||||||
|
|
@ -24,14 +25,16 @@
|
||||||
- code_analytics
|
- code_analytics
|
||||||
- code_quality
|
- code_quality
|
||||||
- code_review
|
- code_review
|
||||||
|
- code_testing
|
||||||
- collection
|
- collection
|
||||||
- compliance_management
|
- compliance_management
|
||||||
|
- container_behavior_analytics
|
||||||
- container_network_security
|
- container_network_security
|
||||||
- container_registry
|
- container_registry
|
||||||
- container_scanning
|
- container_scanning
|
||||||
- continuous_delivery
|
- continuous_delivery
|
||||||
- continuous_integration
|
- continuous_integration
|
||||||
- ddos_protection
|
- database
|
||||||
- dependency_firewall
|
- dependency_firewall
|
||||||
- dependency_proxy
|
- dependency_proxy
|
||||||
- dependency_scanning
|
- dependency_scanning
|
||||||
|
|
@ -43,8 +46,8 @@
|
||||||
- epics
|
- epics
|
||||||
- error_tracking
|
- error_tracking
|
||||||
- feature_flags
|
- feature_flags
|
||||||
- frontend_foundation
|
- foundations
|
||||||
- fuzzing
|
- fuzz-testing
|
||||||
- gdk
|
- gdk
|
||||||
- geo_replication
|
- geo_replication
|
||||||
- git_lfs
|
- git_lfs
|
||||||
|
|
@ -72,6 +75,7 @@
|
||||||
- load_testing
|
- load_testing
|
||||||
- logging
|
- logging
|
||||||
- malware_scanning
|
- malware_scanning
|
||||||
|
- merge_trains
|
||||||
- metrics
|
- metrics
|
||||||
- omnibus_package
|
- omnibus_package
|
||||||
- package_registry
|
- package_registry
|
||||||
|
|
@ -87,8 +91,6 @@
|
||||||
- roadmaps
|
- roadmaps
|
||||||
- runbooks
|
- runbooks
|
||||||
- runner
|
- runner
|
||||||
- runtime_application_self_protection
|
|
||||||
- sdk
|
|
||||||
- secret_detection
|
- secret_detection
|
||||||
- secrets_management
|
- secrets_management
|
||||||
- serverless
|
- serverless
|
||||||
|
|
@ -100,10 +102,8 @@
|
||||||
- status_page
|
- status_page
|
||||||
- subgroups
|
- subgroups
|
||||||
- templates
|
- templates
|
||||||
- threat_detection
|
|
||||||
- time_tracking
|
- time_tracking
|
||||||
- tracing
|
- tracing
|
||||||
- unit_testing
|
|
||||||
- usability_testing
|
- usability_testing
|
||||||
- users
|
- users
|
||||||
- value_stream_management
|
- value_stream_management
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,10 @@ module Banzai
|
||||||
post_process(render(text, context), context)
|
post_process(render(text, context), context)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.render_field_and_post_process(object, field, context = {})
|
||||||
|
post_process(render_field(object, field, context), context)
|
||||||
|
end
|
||||||
|
|
||||||
def self.render(text, context = {})
|
def self.render(text, context = {})
|
||||||
Renderer.render(text, context)
|
Renderer.render(text, context)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,12 @@ module Gitlab
|
||||||
VALIDATION_REQUEST_TIMEOUT = 5
|
VALIDATION_REQUEST_TIMEOUT = 5
|
||||||
|
|
||||||
def perform!
|
def perform!
|
||||||
error('External validation failed', drop_reason: :external_validation_failure) unless validate_external
|
pipeline_authorized = validate_external
|
||||||
|
|
||||||
|
log_message = pipeline_authorized ? 'authorized' : 'not authorized'
|
||||||
|
Gitlab::AppLogger.info(message: "Pipeline #{log_message}", project_id: @pipeline.project.id, user_id: @pipeline.user.id)
|
||||||
|
|
||||||
|
error('External validation failed', drop_reason: :external_validation_failure) unless pipeline_authorized
|
||||||
end
|
end
|
||||||
|
|
||||||
def break?
|
def break?
|
||||||
|
|
|
||||||
|
|
@ -218,9 +218,9 @@ module Gitlab
|
||||||
results[:projects_jira_server_active] += counts[:server].count if counts[:server]
|
results[:projects_jira_server_active] += counts[:server].count if counts[:server]
|
||||||
results[:projects_jira_cloud_active] += counts[:cloud].count if counts[:cloud]
|
results[:projects_jira_cloud_active] += counts[:cloud].count if counts[:cloud]
|
||||||
if results[:projects_jira_active] == -1
|
if results[:projects_jira_active] == -1
|
||||||
results[:projects_jira_active] = count(services, batch: false)
|
results[:projects_jira_active] = services.size
|
||||||
else
|
else
|
||||||
results[:projects_jira_active] += count(services, batch: false)
|
results[:projects_jira_active] += services.size
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1346,15 +1346,27 @@ msgstr ""
|
||||||
msgid "AdminProjects|Delete project"
|
msgid "AdminProjects|Delete project"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "AdminSettings|Apply integration settings to all Projects"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "AdminSettings|Auto DevOps domain"
|
msgid "AdminSettings|Auto DevOps domain"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings > General."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "AdminSettings|Enable shared runners for new projects"
|
msgid "AdminSettings|Enable shared runners for new projects"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "AdminSettings|Environment variables are protected by default"
|
msgid "AdminSettings|Environment variables are protected by default"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "AdminSettings|Go to General Settings"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "AdminSettings|Integrations configured here will automatically apply to all projects on this instance."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "AdminSettings|No required pipeline"
|
msgid "AdminSettings|No required pipeline"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -1370,6 +1382,9 @@ msgstr ""
|
||||||
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
|
msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "AdminSettings|Some settings have moved"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
|
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -8458,6 +8473,9 @@ msgstr ""
|
||||||
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
|
msgid "Failed to load errors from Sentry. Error message: %{errorMessage}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Failed to load group activity metrics. Please try again."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Failed to load groups & users."
|
msgid "Failed to load groups & users."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -10015,6 +10033,15 @@ msgstr ""
|
||||||
msgid "Group: %{name}"
|
msgid "Group: %{name}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "GroupActivyMetrics|Issues created"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "GroupActivyMetrics|Merge Requests created"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "GroupActivyMetrics|Recent activity (last 90 days)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "GroupRoadmap|%{dateWord} – No end date"
|
msgid "GroupRoadmap|%{dateWord} – No end date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -10943,6 +10970,9 @@ msgstr ""
|
||||||
msgid "Instance license"
|
msgid "Instance license"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Integration"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Integration Settings"
|
msgid "Integration Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
||||||
2
qa/qa.rb
2
qa/qa.rb
|
|
@ -478,7 +478,7 @@ module QA
|
||||||
autoload :Configure, 'qa/vendor/jenkins/page/configure'
|
autoload :Configure, 'qa/vendor/jenkins/page/configure'
|
||||||
autoload :NewCredentials, 'qa/vendor/jenkins/page/new_credentials'
|
autoload :NewCredentials, 'qa/vendor/jenkins/page/new_credentials'
|
||||||
autoload :NewJob, 'qa/vendor/jenkins/page/new_job'
|
autoload :NewJob, 'qa/vendor/jenkins/page/new_job'
|
||||||
autoload :Job, 'qa/vendor/jenkins/page/job'
|
autoload :LastJobConsole, 'qa/vendor/jenkins/page/last_job_console'
|
||||||
autoload :ConfigureJob, 'qa/vendor/jenkins/page/configure_job'
|
autoload :ConfigureJob, 'qa/vendor/jenkins/page/configure_job'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ module QA::Page
|
||||||
module Project::Pipeline
|
module Project::Pipeline
|
||||||
class Index < QA::Page::Base
|
class Index < QA::Page::Base
|
||||||
view 'app/assets/javascripts/pipelines/components/pipeline_url.vue' do
|
view 'app/assets/javascripts/pipelines/components/pipeline_url.vue' do
|
||||||
element :pipeline_link, 'class="js-pipeline-url-link' # rubocop:disable QA/ElementWithPattern
|
element :pipeline_url_link
|
||||||
end
|
end
|
||||||
|
|
||||||
view 'app/assets/javascripts/pipelines/components/pipelines_table_row.vue' do
|
view 'app/assets/javascripts/pipelines/components/pipelines_table_row.vue' do
|
||||||
|
|
@ -13,9 +13,7 @@ module QA::Page
|
||||||
end
|
end
|
||||||
|
|
||||||
def click_on_latest_pipeline
|
def click_on_latest_pipeline
|
||||||
css = '.js-pipeline-url-link'
|
all_elements(:pipeline_url_link, minimum: 1, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME).first.click
|
||||||
|
|
||||||
first(css, wait: 60).click
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def wait_for_latest_pipeline_success
|
def wait_for_latest_pipeline_success
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ module QA
|
||||||
click_build_when_change_is_pushed_to_gitlab
|
click_build_when_change_is_pushed_to_gitlab
|
||||||
set_publish_status_to_gitlab
|
set_publish_status_to_gitlab
|
||||||
click_save
|
click_save
|
||||||
|
wait_for_configuration_to_save
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
@ -55,6 +56,12 @@ module QA
|
||||||
def select_publish_build_status_to_gitlab
|
def select_publish_build_status_to_gitlab
|
||||||
click_link "Publish build status to GitLab"
|
click_link "Publish build status to GitLab"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def wait_for_configuration_to_save
|
||||||
|
QA::Support::Waiter.wait_until(sleep_interval: 1.0) do
|
||||||
|
!page.current_url.include?(@path)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,19 @@ module QA
|
||||||
module Vendor
|
module Vendor
|
||||||
module Jenkins
|
module Jenkins
|
||||||
module Page
|
module Page
|
||||||
class Job < Page::Base
|
class LastJobConsole < Page::Base
|
||||||
attr_accessor :job_name
|
attr_accessor :job_name
|
||||||
|
|
||||||
def path
|
def path
|
||||||
"/job/#{@job_name}"
|
"/job/#{@job_name}/lastBuild/console"
|
||||||
end
|
end
|
||||||
|
|
||||||
def has_successful_build?
|
def has_successful_build?
|
||||||
page.has_text?("Last successful build")
|
page.has_text?('Finished: SUCCESS')
|
||||||
|
end
|
||||||
|
|
||||||
|
def no_failed_status_update?
|
||||||
|
page.has_no_text?('Failed to update Gitlab commit status')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -3,5 +3,6 @@
|
||||||
FactoryBot.define do
|
FactoryBot.define do
|
||||||
factory :application_setting do
|
factory :application_setting do
|
||||||
default_projects_limit { 42 }
|
default_projects_limit { 42 }
|
||||||
|
import_sources { [] }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -194,12 +194,6 @@ describe 'Admin updates settings', :clean_gitlab_redis_shared_state, :do_not_moc
|
||||||
expect(page).to have_content "Application settings saved successfully"
|
expect(page).to have_content "Application settings saved successfully"
|
||||||
expect(current_settings.terminal_max_session_time).to eq(15)
|
expect(current_settings.terminal_max_session_time).to eq(15)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
context 'Integrations page' do
|
|
||||||
before do
|
|
||||||
visit integrations_admin_application_settings_path
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'Enable hiding third party offers' do
|
it 'Enable hiding third party offers' do
|
||||||
page.within('.as-third-party-offers') do
|
page.within('.as-third-party-offers') do
|
||||||
|
|
@ -241,6 +235,25 @@ describe 'Admin updates settings', :clean_gitlab_redis_shared_state, :do_not_moc
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'Integration page', :js do
|
||||||
|
before do
|
||||||
|
visit integrations_admin_application_settings_path
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'allows user to dismiss deprecation notice' do
|
||||||
|
expect(page).to have_content('Some settings have moved')
|
||||||
|
|
||||||
|
click_button 'Dismiss'
|
||||||
|
wait_for_requests
|
||||||
|
|
||||||
|
expect(page).not_to have_content('Some settings have moved')
|
||||||
|
|
||||||
|
visit integrations_admin_application_settings_path
|
||||||
|
|
||||||
|
expect(page).not_to have_content('Some settings have moved')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'CI/CD page' do
|
context 'CI/CD page' do
|
||||||
it 'Change CI/CD settings' do
|
it 'Change CI/CD settings' do
|
||||||
visit ci_cd_admin_application_settings_path
|
visit ci_cd_admin_application_settings_path
|
||||||
|
|
|
||||||
|
|
@ -68,4 +68,16 @@ describe 'Broadcast Messages' do
|
||||||
|
|
||||||
expect(page).to have_content "Hi #{user.name}"
|
expect(page).to have_content "Hi #{user.name}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'renders broadcast message with placeholders and styled links' do
|
||||||
|
create(:broadcast_message, broadcast_type: 'notification', message: "Hi {{name}} <a href='gitlab.com' style='color: purple'>click</a>")
|
||||||
|
|
||||||
|
user = create(:user)
|
||||||
|
sign_in(user)
|
||||||
|
|
||||||
|
visit root_path
|
||||||
|
|
||||||
|
expected_html = "<p>Hi #{user.name} <a href=\"gitlab.com\" style=\"color: purple\">click</a></p>"
|
||||||
|
expect(page.body).to include(expected_html)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -208,7 +208,7 @@ describe 'Gcp Cluster', :js, :do_not_mock_admin_mode do
|
||||||
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
|
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
|
||||||
sign_in(admin)
|
sign_in(admin)
|
||||||
gitlab_enable_admin_mode_sign_in(admin)
|
gitlab_enable_admin_mode_sign_in(admin)
|
||||||
visit integrations_admin_application_settings_path
|
visit general_admin_application_settings_path
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'user does not see the offer' do
|
it 'user does not see the offer' do
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import SnippetApp from '~/snippets/components/app.vue';
|
import SnippetApp from '~/snippets/components/show.vue';
|
||||||
import SnippetHeader from '~/snippets/components/snippet_header.vue';
|
import SnippetHeader from '~/snippets/components/snippet_header.vue';
|
||||||
import SnippetTitle from '~/snippets/components/snippet_title.vue';
|
import SnippetTitle from '~/snippets/components/snippet_title.vue';
|
||||||
import SnippetBlob from '~/snippets/components/snippet_blob_view.vue';
|
import SnippetBlob from '~/snippets/components/snippet_blob_view.vue';
|
||||||
|
|
@ -47,6 +47,26 @@ describe UserCalloutsHelper do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '.show_admin_integrations_moved?' do
|
||||||
|
subject { helper.show_admin_integrations_moved? }
|
||||||
|
|
||||||
|
context 'when user has not dismissed' do
|
||||||
|
before do
|
||||||
|
allow(helper).to receive(:user_dismissed?).with(described_class::ADMIN_INTEGRATIONS_MOVED) { false }
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to be true }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when user dismissed' do
|
||||||
|
before do
|
||||||
|
allow(helper).to receive(:user_dismissed?).with(described_class::ADMIN_INTEGRATIONS_MOVED) { true }
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to be false }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '.render_flash_user_callout' do
|
describe '.render_flash_user_callout' do
|
||||||
it 'renders the flash_user_callout partial' do
|
it 'renders the flash_user_callout partial' do
|
||||||
expect(helper).to receive(:render)
|
expect(helper).to receive(:render)
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,12 @@ describe Gitlab::Ci::Pipeline::Chain::Validate::External do
|
||||||
|
|
||||||
expect(step.break?).to be false
|
expect(step.break?).to be false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'logs the authorization' do
|
||||||
|
expect(Gitlab::AppLogger).to receive(:info).with(message: 'Pipeline authorized', project_id: project.id, user_id: user.id)
|
||||||
|
|
||||||
|
perform!
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when validation return false' do
|
context 'when validation return false' do
|
||||||
|
|
@ -86,6 +92,12 @@ describe Gitlab::Ci::Pipeline::Chain::Validate::External do
|
||||||
|
|
||||||
expect(step.break?).to be true
|
expect(step.break?).to be true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'logs the authorization' do
|
||||||
|
expect(Gitlab::AppLogger).to receive(:info).with(message: 'Pipeline not authorized', project_id: project.id, user_id: user.id)
|
||||||
|
|
||||||
|
perform!
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,28 +3,39 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
describe OptionallySearch do
|
describe OptionallySearch do
|
||||||
|
describe '.search' do
|
||||||
let(:model) do
|
let(:model) do
|
||||||
Class.new(ActiveRecord::Base) do
|
Class.new do
|
||||||
self.table_name = 'users'
|
|
||||||
|
|
||||||
include OptionallySearch
|
include OptionallySearch
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '.search' do
|
|
||||||
it 'raises NotImplementedError' do
|
it 'raises NotImplementedError' do
|
||||||
expect { model.search('foo') }.to raise_error(NotImplementedError)
|
expect { model.search('foo') }.to raise_error(NotImplementedError)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '.optionally_search' do
|
describe '.optionally_search' do
|
||||||
|
let(:model) do
|
||||||
|
Class.new(ActiveRecord::Base) do
|
||||||
|
self.table_name = 'users'
|
||||||
|
|
||||||
|
include OptionallySearch
|
||||||
|
|
||||||
|
def self.search(query, **options)
|
||||||
|
[query, options]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'when a query is given' do
|
context 'when a query is given' do
|
||||||
it 'delegates to the search method' do
|
it 'delegates to the search method' do
|
||||||
expect(model)
|
expect(model)
|
||||||
.to receive(:search)
|
.to receive(:search)
|
||||||
.with('foo', {})
|
.with('foo', {})
|
||||||
|
.and_call_original
|
||||||
|
|
||||||
model.optionally_search('foo')
|
expect(model.optionally_search('foo')).to eq(['foo', {}])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -33,8 +44,9 @@ describe OptionallySearch do
|
||||||
expect(model)
|
expect(model)
|
||||||
.to receive(:search)
|
.to receive(:search)
|
||||||
.with('foo', some_option: true)
|
.with('foo', some_option: true)
|
||||||
|
.and_call_original
|
||||||
|
|
||||||
model.optionally_search('foo', some_option: true)
|
expect(model.optionally_search('foo', some_option: true)).to eq(['foo', { some_option: true }])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,24 @@ describe DiscordService do
|
||||||
WebMock.stub_request(:post, webhook_url)
|
WebMock.stub_request(:post, webhook_url)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'uses the right embed parameters' do
|
||||||
|
builder = Discordrb::Webhooks::Builder.new
|
||||||
|
|
||||||
|
allow_next_instance_of(Discordrb::Webhooks::Client) do |client|
|
||||||
|
allow(client).to receive(:execute).and_yield(builder)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject.execute(sample_data)
|
||||||
|
|
||||||
|
expect(builder.to_json_hash[:embeds].first).to include(
|
||||||
|
description: start_with("#{user.name} pushed to branch [master](http://localhost/#{project.namespace.path}/#{project.path}/commits/master) of"),
|
||||||
|
author: hash_including(
|
||||||
|
icon_url: start_with('https://www.gravatar.com/avatar/'),
|
||||||
|
name: user.name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
context 'DNS rebind to local address' do
|
context 'DNS rebind to local address' do
|
||||||
before do
|
before do
|
||||||
stub_dns(webhook_url, ip_address: '192.168.2.120')
|
stub_dns(webhook_url, ip_address: '192.168.2.120')
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
describe 'admin/application_settings/integrations.html.haml' do
|
describe 'admin/application_settings/general.html.haml' do
|
||||||
let(:app_settings) { build(:application_setting) }
|
let(:app_settings) { build(:application_setting) }
|
||||||
|
let(:user) { create(:admin) }
|
||||||
|
|
||||||
describe 'sourcegraph integration' do
|
describe 'sourcegraph integration' do
|
||||||
let(:sourcegraph_flag) { true }
|
let(:sourcegraph_flag) { true }
|
||||||
|
|
@ -11,6 +12,7 @@ describe 'admin/application_settings/integrations.html.haml' do
|
||||||
before do
|
before do
|
||||||
assign(:application_setting, app_settings)
|
assign(:application_setting, app_settings)
|
||||||
allow(Gitlab::Sourcegraph).to receive(:feature_available?).and_return(sourcegraph_flag)
|
allow(Gitlab::Sourcegraph).to receive(:feature_available?).and_return(sourcegraph_flag)
|
||||||
|
allow(view).to receive(:current_user).and_return(user)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when sourcegraph feature is enabled' do
|
context 'when sourcegraph feature is enabled' do
|
||||||
Loading…
Reference in New Issue