Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-03-24 15:08:44 +00:00
parent 729e3765d5
commit 120f4aaedc
47 changed files with 318 additions and 69 deletions

View File

@ -0,0 +1,6 @@
import PersistentUserCallout from '~/persistent_user_callout';
document.addEventListener('DOMContentLoaded', () => {
const callout = document.querySelector('.js-admin-integrations-moved');
PersistentUserCallout.factory(callout);
});

View File

@ -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();
} }
}); });

View File

@ -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();
} }
}); });

View File

@ -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">

View File

@ -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 () => {};

View File

@ -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;
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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?

View File

@ -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

View File

@ -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'

View File

@ -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'

View File

@ -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')

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -0,0 +1,5 @@
---
title: Optimize usage ping queries by using batch counting
merge_request: 27455
author:
type: performance

View File

@ -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

View File

@ -0,0 +1,5 @@
---
title: Use id instead of cve where possible when parsing remediations
merge_request: 27815
author:
type: other

View File

@ -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

View File

@ -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

View File

@ -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?

View File

@ -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

View File

@ -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 ""

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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';

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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')

View File

@ -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

0
vendor/gitignore/C++.gitignore vendored Executable file → Normal file
View File

0
vendor/gitignore/Java.gitignore vendored Executable file → Normal file
View File