Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-01-25 15:09:00 +00:00
parent 6bc190088e
commit 10cc2d7a72
108 changed files with 336 additions and 396 deletions

View File

@ -71,7 +71,7 @@ export default {
</template>
</blob-filepath>
<div class="gl-display-none gl-display-sm-flex">
<div class="gl-display-none gl-sm-display-flex">
<viewer-switcher v-if="showViewerSwitcher" v-model="viewer" />
<slot name="actions"></slot>

View File

@ -197,7 +197,7 @@ export default {
<gl-button
v-if="canRenderPipelineButton"
block
class="gl-mt-3 gl-mb-0 gl-display-md-none"
class="gl-mt-3 gl-mb-0 gl-md-display-none"
variant="success"
data-testid="run_pipeline_button_mobile"
:loading="state.isRunningMergeRequestPipeline"

View File

@ -59,7 +59,7 @@ export default {
:loading="isLoading"
:title="title"
:aria-label="title"
class="gl-display-none gl-display-md-block"
class="gl-display-none gl-md-display-block"
variant="danger"
category="primary"
icon="remove"

View File

@ -549,7 +549,7 @@ export default {
upcomingDeploymentCellClasses() {
return [
this.tableData.upcoming.spacing,
{ 'gl-display-none gl-display-md-block': !this.upcomingDeployment },
{ 'gl-display-none gl-md-display-block': !this.upcomingDeployment },
];
},
},

View File

@ -30,7 +30,7 @@ export default {
:href="monitoringUrl"
:title="title"
:aria-label="title"
class="monitoring-url gl-display-none gl-display-sm-none gl-display-md-block"
class="monitoring-url gl-display-none gl-sm-display-none gl-md-display-block"
icon="chart"
rel="noopener noreferrer nofollow"
variant="default"

View File

@ -68,7 +68,7 @@ export default {
<gl-button
v-gl-tooltip
v-gl-modal.confirm-rollback-modal
class="gl-display-none gl-display-md-block text-secondary"
class="gl-display-none gl-md-display-block text-secondary"
:loading="isLoading"
:title="title"
:icon="isLastDeployment ? 'repeat' : 'redo'"

View File

@ -133,7 +133,7 @@ export default {
<confirm-rollback-modal :environment="environmentInRollbackModal" />
<div class="gl-w-full">
<div class="gl-display-flex gl-flex-direction-column gl-mt-3 gl-display-md-none!">
<div class="gl-display-flex gl-flex-direction-column gl-mt-3 gl-md-display-none!">
<gl-button
v-if="state.reviewAppDetails.can_setup_review_app"
v-gl-modal="$options.modal.id"
@ -167,7 +167,7 @@ export default {
</gl-tab>
<template #tabs-end>
<div
class="gl-display-none gl-display-md-flex gl-lg-align-items-center gl-lg-flex-direction-row gl-lg-flex-fill-1 gl-lg-justify-content-end gl-lg-mt-0"
class="gl-display-none gl-md-display-flex gl-lg-align-items-center gl-lg-flex-direction-row gl-lg-flex-fill-1 gl-lg-justify-content-end gl-lg-mt-0"
>
<gl-button
v-if="state.reviewAppDetails.can_setup_review_app"

View File

@ -198,7 +198,7 @@ export default {
@token="rotateInstanceId()"
/>
<div :class="topAreaBaseClasses">
<div class="gl-display-flex gl-flex-direction-column gl-display-md-none!">
<div class="gl-display-flex gl-flex-direction-column gl-md-display-none!">
<gl-button
v-if="canUserConfigure"
v-gl-modal="'configure-feature-flags'"
@ -285,7 +285,7 @@ export default {
</feature-flags-tab>
<template #tabs-end>
<li
class="gl-display-none gl-display-md-flex gl-align-items-center gl-flex-fill-1 gl-justify-content-end"
class="gl-display-none gl-md-display-flex gl-align-items-center gl-flex-fill-1 gl-justify-content-end"
>
<gl-button
v-if="canUserConfigure"

View File

@ -196,7 +196,7 @@ export default {
<li
v-if="showDiscussions"
data-testid="issuable-discussions"
class="issuable-comments gl-display-none gl-display-sm-block"
class="issuable-comments gl-display-none gl-sm-display-block"
>
<gl-link
v-gl-tooltip:tooltipcontainer.top

View File

@ -112,7 +112,7 @@ export default {
</div>
<div
data-testid="header-actions"
class="detail-page-header-actions gl-display-flex gl-display-md-block"
class="detail-page-header-actions gl-display-flex gl-md-display-block"
>
<slot name="header-actions"></slot>
</div>

View File

@ -193,7 +193,7 @@ export default {
<template>
<div class="detail-page-header-actions">
<gl-dropdown
class="gl-display-block gl-display-sm-none!"
class="gl-display-block gl-sm-display-none!"
block
:text="dropdownText"
:loading="isToggleStateButtonLoading"
@ -222,7 +222,7 @@ export default {
<gl-button
v-if="showToggleIssueStateButton"
class="gl-display-none gl-display-sm-inline-flex!"
class="gl-display-none gl-sm-display-inline-flex!"
category="secondary"
:data-qa-selector="qaSelector"
:loading="isToggleStateButtonLoading"
@ -233,7 +233,7 @@ export default {
</gl-button>
<gl-dropdown
class="gl-display-none gl-display-sm-inline-flex!"
class="gl-display-none gl-sm-display-inline-flex!"
toggle-class="gl-border-0! gl-shadow-none!"
no-caret
right

View File

@ -414,7 +414,7 @@ export default {
v-if="meta.visible"
:key="meta.key"
v-gl-tooltip
class="gl-display-none gl-display-sm-flex gl-align-items-center gl-ml-3"
class="gl-display-none gl-sm-display-flex gl-align-items-center gl-ml-3"
:class="meta.class"
:data-testid="meta.dataTestId"
:title="meta.title"

View File

@ -19,7 +19,7 @@ export default {
<li class="gl-border-b-1 gl-border-b-solid gl-border-b-gray-200">
<div class="gl-display-flex gl-align-items-center gl-py-3">
<gl-icon name="folder-o" class="gl-mr-3" />
<div class="gl-display-none gl-flex-shrink-0 gl-display-sm-flex gl-mr-3">
<div class="gl-display-none gl-flex-shrink-0 gl-sm-display-flex gl-mr-3">
<gl-avatar :size="32" shape="rect" :entity-name="group.name" :src="group.avatar_url" />
</div>
<div class="gl-min-w-0 gl-display-flex gl-flex-grow-1 gl-flex-shrink-1 gl-align-items-center">

View File

@ -110,7 +110,7 @@ export default {
<gl-button
:aria-label="$options.i18n.toggleSidebar"
category="tertiary"
class="gl-display-md-none gl-ml-2 js-sidebar-build-toggle"
class="gl-md-display-none gl-ml-2 js-sidebar-build-toggle"
icon="chevron-double-lg-right"
@click="toggleSidebar"
/>

View File

@ -176,7 +176,7 @@ export default {
id="environments-dropdown"
:text="environments.current || managedApps.current"
:disabled="environments.isLoading"
class="gl-mr-3 gl-mb-3 gl-display-flex gl-display-md-block js-environments-dropdown"
class="gl-mr-3 gl-mb-3 gl-display-flex gl-md-display-block js-environments-dropdown"
>
<gl-dropdown-section-header>
{{ s__('Environments|Environments') }}

View File

@ -42,7 +42,7 @@ export default {
ref="podsDropdown"
:text="podDropdownText"
:disabled="disabled"
class="gl-mr-3 gl-mb-3 gl-display-flex gl-display-md-block qa-pods-dropdown"
class="gl-mr-3 gl-mb-3 gl-display-flex gl-md-display-block qa-pods-dropdown"
>
<gl-dropdown-section-header>
{{ s__('Environments|Select pod') }}

View File

@ -19,7 +19,7 @@ export default {
</script>
<template>
<div v-if="showContainer" class="gl-bg-gray-10 gl-p-3 gl-display-md-flex">
<div v-if="showContainer" class="gl-bg-gray-10 gl-p-3 gl-md-display-flex">
<members-filtered-search-bar v-if="filteredSearchBar.show" class="gl-p-3 gl-flex-grow-1" />
<sort-dropdown v-if="showSortDropdown" class="gl-p-3 gl-flex-shrink-0" />
</div>

View File

@ -80,7 +80,7 @@ export default {
return 'col-actions';
}
return ['col-actions', 'gl-display-none!', 'gl-display-lg-table-cell!'];
return ['col-actions', 'gl-display-none!', 'gl-lg-display-table-cell!'];
},
tbodyTrAttr(member) {
return {

View File

@ -61,10 +61,10 @@ export default {
<div :class="statusBoxClass" class="issuable-status-box status-box">
<gl-icon
:name="statusIconName"
class="gl-display-block gl-display-sm-none!"
class="gl-display-block gl-sm-display-none!"
data-testid="status-icon"
/>
<span class="gl-display-none gl-display-sm-block">
<span class="gl-display-none gl-sm-display-block">
{{ statusHumanName }}
</span>
</div>

View File

@ -15,12 +15,12 @@ export default {
<template>
<div
ref="linksSection"
class="gl-display-sm-flex gl-flex-sm-wrap gl-mt-5 gl-p-3 gl-bg-gray-10 border gl-rounded-base links-section"
class="gl-sm-display-flex gl-flex-sm-wrap gl-mt-5 gl-p-3 gl-bg-gray-10 border gl-rounded-base links-section"
>
<div
v-for="(link, key) in links"
:key="key"
class="gl-mb-1 gl-mr-5 gl-display-flex gl-display-sm-block gl-hover-text-blue-600-children gl-word-break-all"
class="gl-mb-1 gl-mr-5 gl-display-flex gl-sm-display-block gl-hover-text-blue-600-children gl-word-break-all"
>
<gl-link :href="link.url" class="gl-text-gray-900 gl-text-decoration-none!"
><gl-icon name="link" class="gl-text-gray-500 gl-vertical-align-text-bottom gl-mr-2" />{{

View File

@ -88,7 +88,7 @@ export default {
<div class="gl-display-flex">
<span>{{ packageEntity.version }}</span>
<div v-if="hasPipeline" class="gl-display-none gl-display-sm-flex gl-ml-2">
<div v-if="hasPipeline" class="gl-display-none gl-sm-display-flex gl-ml-2">
<gl-sprintf :message="s__('PackageRegistry|published by %{author}')">
<template #author>{{ packageEntity.pipeline.user.name }}</template>
</gl-sprintf>

View File

@ -91,7 +91,7 @@ export default {
variant="muted"
:title="moreTagsTooltip"
size="sm"
class="gl-display-none gl-display-md-flex gl-ml-2"
class="gl-display-none gl-md-display-flex gl-ml-2"
><gl-sprintf :message="__('+%{tags} more')">
<template #tags>
{{ moreTagsDisplay }}
@ -103,7 +103,7 @@ export default {
v-if="moreTagsDisplay && hideLabel"
data-testid="moreBadge"
variant="muted"
class="gl-display-md-none gl-ml-2"
class="gl-md-display-none gl-ml-2"
>{{ tagsDisplay }}</gl-badge
>
</div>

View File

@ -21,7 +21,7 @@ export default {
<template>
<div>
<div class="gl-flex-direction-column gl-display-sm-none" data-testid="mobile-loader">
<div class="gl-flex-direction-column gl-sm-display-none" data-testid="mobile-loader">
<gl-skeleton-loader
v-for="index in $options.rowsToRender.mobile"
:key="index"
@ -37,7 +37,7 @@ export default {
</gl-skeleton-loader>
</div>
<div
class="gl-display-none gl-display-sm-flex gl-flex-direction-column"
class="gl-display-none gl-sm-display-flex gl-flex-direction-column"
data-testid="desktop-loader"
>
<gl-skeleton-loader

View File

@ -94,7 +94,7 @@ export default {
</div>
<gl-link
:href="group.relative_path"
class="gl-display-none gl-flex-shrink-0 gl-display-sm-flex gl-mr-3"
class="gl-display-none gl-flex-shrink-0 gl-sm-display-flex gl-mr-3"
>
<gl-avatar :size="32" shape="rect" :entity-name="group.name" :src="group.avatarUrl" />
</gl-link>
@ -113,7 +113,7 @@ export default {
<gl-badge
v-if="isGroupPendingRemoval"
variant="warning"
class="gl-display-none gl-display-sm-flex gl-mt-3 gl-mr-1"
class="gl-display-none gl-sm-display-flex gl-mt-3 gl-mr-1"
>{{ __('pending removal') }}</gl-badge
>
<span v-if="group.permission" class="user-access-role gl-mt-3">

View File

@ -302,7 +302,7 @@ export default {
<gl-loading-icon v-if="isBlobContentLoading" size="lg" class="gl-m-3" />
<div v-else-if="!isBlobContentError" class="gl-mt-4">
<div class="file-editor gl-mb-3">
<div class="info-well gl-display-none gl-display-sm-block">
<div class="info-well gl-display-none gl-sm-display-block">
<validation-segment
class="well-segment"
:loading="isCiConfigDataLoading"

View File

@ -436,12 +436,12 @@ export default {
category="secondary"
@click="removeVariable(index)"
>
<gl-icon class="gl-mr-0! gl-display-none gl-display-md-block" name="clear" />
<span class="gl-display-md-none">{{ s__('CiVariables|Remove variable') }}</span>
<gl-icon class="gl-mr-0! gl-display-none gl-md-display-block" name="clear" />
<span class="gl-md-display-none">{{ s__('CiVariables|Remove variable') }}</span>
</gl-button>
<gl-button
v-else
class="gl-md-ml-3 gl-mb-3 gl-display-none gl-display-md-block gl-visibility-hidden"
class="gl-md-ml-3 gl-mb-3 gl-display-none gl-md-display-block gl-visibility-hidden"
icon="clear"
/>
</template>

View File

@ -47,7 +47,7 @@ export default {
<template>
<gl-form class="search-page-form" @submit.prevent="applyQuery">
<section class="gl-display-lg-flex gl-align-items-flex-end">
<section class="gl-lg-display-flex gl-align-items-flex-end">
<div class="gl-flex-fill-1 gl-mb-4 gl-lg-mb-0 gl-lg-mr-2">
<label>{{ __('What are you searching for?') }}</label>
<gl-search-box-by-type

View File

@ -57,7 +57,7 @@ export default {
<div class="gl-display-flex gl-align-items-center gl-py-3">
<div
v-if="$slots['left-action']"
class="gl-w-7 gl-display-none gl-display-sm-flex gl-justify-content-start gl-pl-2"
class="gl-w-7 gl-display-none gl-sm-display-flex gl-justify-content-start gl-pl-2"
>
<slot name="left-action"></slot>
</div>
@ -75,7 +75,7 @@ export default {
:selected="isDetailsShown"
icon="ellipsis_h"
size="small"
class="gl-ml-2 gl-display-none gl-display-sm-block"
class="gl-ml-2 gl-display-none gl-sm-display-block"
@click="toggleDetails"
/>
</div>
@ -105,7 +105,7 @@ export default {
</div>
<div
v-if="$slots['right-action']"
class="gl-w-9 gl-display-none gl-display-sm-flex gl-justify-content-end gl-pr-1"
class="gl-w-9 gl-display-none gl-sm-display-flex gl-justify-content-end gl-pr-1"
>
<slot name="right-action"></slot>
</div>

View File

@ -138,6 +138,13 @@
}
}
.social-provider-btn-image {
> img {
width: 16px;
vertical-align: inherit;
}
}
.provider-btn-image {
display: inline-block;
padding: 5px 10px;

View File

@ -14,7 +14,7 @@ class ProjectsController < Projects::ApplicationController
around_action :allow_gitaly_ref_name_caching, only: [:index, :show]
before_action :whitelist_query_limiting, only: [:create]
before_action :whitelist_query_limiting, only: [:show, :create]
before_action :authenticate_user!, except: [:index, :show, :activity, :refs, :resolve, :unfoldered_environment_names]
before_action :redirect_git_extension, only: [:show]
before_action :project, except: [:index, :new, :create, :resolve]
@ -503,7 +503,7 @@ class ProjectsController < Projects::ApplicationController
end
def whitelist_query_limiting
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42440')
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/-/issues/20826')
end
def present_project

View File

@ -17,7 +17,7 @@ class UsersController < ApplicationController
skip_before_action :authenticate_user!
prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) }
before_action :user, except: [:exists, :suggests]
before_action :user, except: [:exists, :suggests, :ssh_keys]
before_action :authorize_read_user_profile!,
only: [:calendar, :calendar_activities, :groups, :projects, :contributed, :starred, :snippets]
@ -41,7 +41,12 @@ class UsersController < ApplicationController
# Get all keys of a user(params[:username]) in a text format
# Helpful for sysadmins to put in respective servers
#
# Uses `UserFinder` rather than `find_routable!` because this endpoint should
# be publicly available regardless of instance visibility settings.
def ssh_keys
user = UserFinder.new(params[:username]).find_by_username
render plain: user.all_ssh_keys.join("\n")
end

View File

@ -88,9 +88,6 @@ module Featurable
end
def feature_available?(feature, user)
# This feature might not be behind a feature flag at all, so default to true
return false unless ::Feature.enabled?(feature, user, default_enabled: true)
get_permission(user, feature)
end

View File

@ -15,15 +15,6 @@ module HasRepository
delegate :base_dir, :disk_path, to: :storage
class_methods do
def pick_repository_storage
# We need to ensure application settings are fresh when we pick
# a repository storage to use.
Gitlab::CurrentSettings.expire_current_application_settings
Gitlab::CurrentSettings.pick_repository_storage
end
end
def valid_repo?
repository.exists?
rescue

View File

@ -20,7 +20,7 @@ module RepositoryStorageMovable
validate :container_repository_writable, on: :create
default_value_for(:destination_storage_name, allows_nil: false) do
pick_repository_storage
Repository.pick_storage_shard
end
state_machine initial: :initial do
@ -82,16 +82,6 @@ module RepositoryStorageMovable
end
end
class_methods do
private
def pick_repository_storage
container_klass = reflect_on_association(:container).class_name.constantize
container_klass.pick_repository_storage
end
end
# Projects, snippets, and group wikis has different db structure. In projects,
# we need to update some columns in this step, but we don't with the other resources.
#

View File

@ -75,7 +75,7 @@ class Project < ApplicationRecord
default_value_for :resolve_outdated_diff_discussions, false
default_value_for :container_registry_enabled, gitlab_config_features.container_registry
default_value_for(:repository_storage) do
pick_repository_storage
Repository.pick_storage_shard
end
default_value_for(:shared_runners_enabled) { Gitlab::CurrentSettings.shared_runners_enabled }

View File

@ -12,14 +12,22 @@ class DatadogService < Service
prop_accessor :datadog_site, :api_url, :api_key, :datadog_service, :datadog_env
with_options presence: true, if: :activated? do
validates :api_key, format: { with: /\A\w+\z/ }
validates :datadog_site, format: { with: /\A[\w\.]+\z/ }, unless: :api_url
validates :api_url, public_url: true, unless: :datadog_site
with_options if: :activated? do
validates :api_key, presence: true, format: { with: /\A\w+\z/ }
validates :datadog_site, format: { with: /\A[\w\.]+\z/, allow_blank: true }
validates :api_url, public_url: { allow_blank: true }
validates :datadog_site, presence: true, unless: -> (obj) { obj.api_url.present? }
validates :api_url, presence: true, unless: -> (obj) { obj.datadog_site.present? }
end
after_save :compose_service_hook, if: :activated?
def initialize_properties
super
self.datadog_site ||= DEFAULT_SITE
end
def self.supported_events
SUPPORTED_EVENTS
end
@ -54,27 +62,37 @@ class DatadogService < Service
def fields
[
{
type: 'text', name: 'datadog_site',
placeholder: DEFAULT_SITE, default: DEFAULT_SITE,
type: 'text',
name: 'datadog_site',
placeholder: DEFAULT_SITE,
help: 'Choose the Datadog site to send data to. Set to "datadoghq.eu" to send data to the EU site',
required: false
},
{
type: 'text', name: 'api_url', title: 'Custom URL',
type: 'text',
name: 'api_url',
title: 'API URL',
help: '(Advanced) Define the full URL for your Datadog site directly',
required: false
},
{
type: 'password', name: 'api_key', title: 'API key',
type: 'password',
name: 'api_key',
title: 'API key',
help: "<a href=\"#{api_keys_url}\" target=\"_blank\">API key</a> used for authentication with Datadog",
required: true
},
{
type: 'text', name: 'datadog_service', title: 'Service', placeholder: 'gitlab-ci',
type: 'text',
name: 'datadog_service',
title: 'Service',
placeholder: 'gitlab-ci',
help: 'Name of this GitLab instance that all data will be tagged with'
},
{
type: 'text', name: 'datadog_env', title: 'Env',
type: 'text',
name: 'datadog_env',
title: 'Env',
help: 'The environment tag that traces will be tagged with'
}
]
@ -90,7 +108,7 @@ class DatadogService < Service
url = api_url.presence || sprintf(URL_TEMPLATE, datadog_site: datadog_site)
url = URI.parse(url)
url.path = File.join(url.path || '/', api_key)
query = { service: datadog_service, env: datadog_env }.compact
query = { service: datadog_service.presence, env: datadog_env.presence }.compact
url.query = query.to_query unless query.empty?
url.to_s
end

View File

@ -1143,6 +1143,13 @@ class Repository
end
end
# Choose one of the available repository storage options based on a normalized weighted probability.
# We should always use the latest settings, to avoid picking a deleted shard.
def self.pick_storage_shard(expire: true)
Gitlab::CurrentSettings.expire_current_application_settings if expire
Gitlab::CurrentSettings.pick_repository_storage
end
private
# TODO Genericize finder, later split this on finders by Ref or Oid

View File

@ -317,7 +317,7 @@ class Snippet < ApplicationRecord
end
def repository_storage
snippet_repository&.shard_name || self.class.pick_repository_storage
snippet_repository&.shard_name || Repository.pick_storage_shard
end
# Repositories are created by default with the `master` branch.

View File

@ -26,7 +26,7 @@ module Ci
end
def valid_statuses_for_build(build)
if ::Feature.enabled?(:skip_dag_manual_and_delayed_jobs, default_enabled: :yaml)
if ::Feature.enabled?(:skip_dag_manual_and_delayed_jobs, build.project, default_enabled: :yaml)
current_valid_statuses_for_build(build)
else
legacy_valid_statuses_for_build(build)

View File

@ -8,8 +8,7 @@ module Users
def execute(user)
return error(_('You are not allowed to approve a user'), :forbidden) unless allowed?
return error(_('The user you are trying to approve is not pending an approval'), :conflict) if user.active?
return error(_('The user you are trying to approve is not pending an approval'), :conflict) unless approval_required?(user)
return error(_('The user you are trying to approve is not pending approval'), :conflict) if user.active? || !approval_required?(user)
if user.activate
# Resends confirmation email if the user isn't confirmed yet.

View File

@ -13,7 +13,7 @@
%td
%strong.subheading.d-block.d-sm-none
= _('Reported by %{reporter}').html_safe % { reporter: reporter ? link_to(reporter.name, reporter) : _('(removed)') }
.light.gl-display-none.gl-display-sm-block
.light.gl-display-none.gl-sm-display-block
= link_to(reporter.name, reporter)
.light.small
= time_ago_with_tooltip(abuse_report.created_at)

View File

@ -14,7 +14,7 @@
.description
= markdown_field(group, :description)
.stats.gl-text-gray-500.gl-flex-shrink-0.gl-display-none.gl-display-sm-flex
.stats.gl-text-gray-500.gl-flex-shrink-0.gl-display-none.gl-sm-display-flex
%span.badge.badge-pill
= storage_counter(group.storage_size)

View File

@ -5,7 +5,7 @@
- if show_customize_homepage_banner?(@customize_homepage)
= content_for :customize_homepage_banner do
.gl-display-none.gl-display-md-block{ class: "gl-pt-6! gl-pb-2! #{(container_class unless @no_container)} #{@content_class}" }
.gl-display-none.gl-md-display-block{ class: "gl-pt-6! gl-pb-2! #{(container_class unless @no_container)} #{@content_class}" }
.js-customize-homepage-banner{ data: { svg_path: image_path('illustrations/monitoring/getting_started.svg'),
preferences_behavior_path: profile_preferences_path(anchor: 'behavior'),
callouts_path: user_callouts_path,

View File

@ -1,3 +1,5 @@
- button_class = 'btn btn-default gl-button'
%label.label-bold
= s_('Profiles|Connected Accounts')
%p= s_('Profiles|Click on icon to activate signin with one of the following services')
@ -5,17 +7,19 @@
- unlink_allowed = unlink_provider_allowed?(provider)
- link_allowed = link_provider_allowed?(provider)
- if unlink_allowed || link_allowed
.provider-btn-group
.provider-btn-image
= provider_image_tag(provider)
- if auth_active?(provider)
- if unlink_allowed
= link_to unlink_profile_account_path(provider: provider), method: :delete, class: 'provider-btn' do
- if auth_active?(provider)
- if unlink_allowed
= link_to unlink_profile_account_path(provider: provider), method: :delete, class: button_class do
.social-provider-btn-image.gl-button-icon= provider_image_tag(provider)
.gl-button-text
= s_('Profiles|Disconnect %{provider}') % { provider: label_for_provider(provider) }
- else
%a.provider-btn
- else
%a{ class: button_class }
.gl-button-text
= s_('Profiles|%{provider} Active') % { provider: label_for_provider(provider) }
- elsif link_allowed
= link_to omniauth_authorize_path(:user, provider), method: :post, class: 'provider-btn gl-text-blue-500' do
- elsif link_allowed
= link_to omniauth_authorize_path(:user, provider), method: :post, class: button_class do
.social-provider-btn-image.gl-button-icon= provider_image_tag(provider)
.gl-button-text
= s_('Profiles|Connect %{provider}') % { provider: label_for_provider(provider) }
= render_if_exists 'profiles/accounts/group_saml_unlink_buttons', group_saml_identities: group_saml_identities

View File

@ -11,7 +11,7 @@
= render 'projects/tree/tree_header', tree: @tree
#js-last-commit
.info-well.gl-display-none.gl-display-sm-flex.project-last-commit
.info-well.gl-display-none.gl-sm-display-flex.project-last-commit
.gl-spinner-container.m-auto
= loading_icon(size: 'md', color: 'dark', css_class: 'align-text-bottom')

View File

@ -3,7 +3,7 @@
- button_class = "btn gl-button #{!@merge_request.closed? && 'js-draft-toggle-button'}"
- toggle_class = "btn gl-button dropdown-toggle"
.float-left.btn-group.gl-ml-3.gl-display-none.gl-display-md-flex
.float-left.btn-group.gl-ml-3.gl-display-none.gl-md-display-flex
= link_to @merge_request.closed? ? reopen_issuable_path(@merge_request) : toggle_draft_merge_request_path(@merge_request), method: :put, class: "#{button_class} #{button_action_class}" do
- if @merge_request.closed?
= _('Reopen')

View File

@ -13,8 +13,8 @@
.detail-page-header.border-bottom-0.pt-0.pb-0
.detail-page-header-body
.issuable-status-box.status-box.js-mr-status-box{ class: status_box_class(@merge_request), data: { state: @merge_request.state } }
= sprite_icon(state_icon_name, css_class: 'gl-display-block gl-display-sm-none!')
%span.gl-display-none.gl-display-sm-block
= sprite_icon(state_icon_name, css_class: 'gl-display-block gl-sm-display-none!')
%span.gl-display-none.gl-sm-display-block
= state_human_name
.issuable-meta
@ -26,7 +26,7 @@
.detail-page-header-actions.js-issuable-actions
.clearfix.dropdown
%button.gl-button.btn.btn-default.float-left.gl-display-md-none.gl-w-full{ type: "button", data: { toggle: "dropdown" } }
%button.gl-button.btn.btn-default.float-left.gl-md-display-none.gl-w-full{ type: "button", data: { toggle: "dropdown" } }
Options
= sprite_icon('chevron-down', css_class: 'gl-text-gray-500')
.dropdown-menu.dropdown-menu-right
@ -50,4 +50,4 @@
- if can_update_merge_request && !are_close_and_open_buttons_hidden
= render 'projects/merge_requests/close_reopen_draft_report_toggle'
- elsif !@merge_request.merged?
= link_to _('Report abuse'), new_abuse_report_path(user_id: @merge_request.author.id, ref_url: merge_request_url(@merge_request)), class: 'gl-display-none gl-display-md-block gl-button btn btn-warning-secondary float-right gl-ml-3', title: _('Report abuse')
= link_to _('Report abuse'), new_abuse_report_path(user_id: @merge_request.author.id, ref_url: merge_request_url(@merge_request)), class: 'gl-display-none gl-md-display-block gl-button btn btn-warning-secondary float-right gl-ml-3', title: _('Report abuse')

View File

@ -1,7 +1,7 @@
- search_bar_classes = 'search-sidebar gl-display-flex gl-flex-direction-column gl-mr-4'
- if @search_objects.to_a.empty?
.gl-display-md-flex
.gl-md-display-flex
- if %w(issues merge_requests).include?(@scope)
#js-search-sidebar{ class: search_bar_classes }
.gl-w-full.gl-flex-fill-1.gl-overflow-x-hidden
@ -11,7 +11,7 @@
= render partial: 'search/results_status', locals: { search_service: @search_service }
= render_if_exists 'shared/promotions/promote_advanced_search'
.results.gl-display-md-flex.gl-mt-3
.results.gl-md-display-flex.gl-mt-3
- if %w(issues merge_requests).include?(@scope)
#js-search-sidebar{ class: search_bar_classes }
.gl-w-full.gl-flex-fill-1.gl-overflow-x-hidden

View File

@ -4,7 +4,7 @@
.search-results-status
.row-content-block.gl-display-flex
.gl-display-md-flex.gl-text-left.gl-align-items-center.gl-flex-grow-1
.gl-md-display-flex.gl-text-left.gl-align-items-center.gl-flex-grow-1
- unless search_service.without_count?
= search_entries_info(search_service.search_objects, search_service.scope, params[:search])
- unless search_service.show_snippets?
@ -21,5 +21,5 @@
- link_to_group = link_to(search_service.group.name, search_service.group, class: 'ml-md-1')
= _("in group %{link_to_group}").html_safe % { link_to_group: link_to_group }
- if search_service.show_sort_dropdown?
.gl-display-md-flex.gl-flex-direction-column
.gl-md-display-flex.gl-flex-direction-column
= render partial: 'search/sort_dropdown'

View File

@ -5,23 +5,23 @@
- issuable_mr = @issuable_meta_data[issuable.id].merge_requests_count
- if issuable_mr > 0
%li.issuable-mr.gl-display-none.gl-display-sm-block.has-tooltip{ title: _('Related merge requests') }
%li.issuable-mr.gl-display-none.gl-sm-display-block.has-tooltip{ title: _('Related merge requests') }
= sprite_icon('merge-request', css_class: "gl-vertical-align-middle")
= issuable_mr
- if upvotes > 0
%li.issuable-upvotes.gl-display-none.gl-display-sm-block.has-tooltip{ title: _('Upvotes') }
%li.issuable-upvotes.gl-display-none.gl-sm-display-block.has-tooltip{ title: _('Upvotes') }
= sprite_icon('thumb-up', css_class: "gl-vertical-align-middle")
= upvotes
- if downvotes > 0
%li.issuable-downvotes.gl-display-none.gl-display-sm-block.has-tooltip{ title: _('Downvotes') }
%li.issuable-downvotes.gl-display-none.gl-sm-display-block.has-tooltip{ title: _('Downvotes') }
= sprite_icon('thumb-down', css_class: "gl-vertical-align-middle")
= downvotes
= render_if_exists 'shared/issuable/blocking_issues_count', issuable: issuable
%li.issuable-comments.gl-display-none.gl-display-sm-block
%li.issuable-comments.gl-display-none.gl-sm-display-block
= link_to issuable_path, class: ['has-tooltip', ('no-comments' if note_count == 0)], title: _('Comments') do
= sprite_icon('comments', css_class: 'gl-vertical-align-text-bottom')
= note_count

View File

@ -1,5 +1,5 @@
- if cookies[:hide_project_limit_message].blank? && !current_user.hide_project_limit && !current_user.can_create_project? && current_user.projects_limit > 0
.project-limit-message.gl-alert.gl-alert-warning.gl-display-none.gl-display-sm-block
.project-limit-message.gl-alert.gl-alert-warning.gl-display-none.gl-sm-display-block
= _("You won't be able to create new projects because you have reached your project limit.")
.float-right

View File

@ -1,12 +1,12 @@
.detail-page-header
.detail-page-header-body
.issuable-status-box.status-box.status-box-issue-closed{ class: issue_status_visibility(issuable, status_box: :closed) }
= sprite_icon('mobile-issue-close', css_class: 'gl-display-block gl-display-sm-none!')
.gl-display-none.gl-display-sm-block!
= sprite_icon('mobile-issue-close', css_class: 'gl-display-block gl-sm-display-none!')
.gl-display-none.gl-sm-display-block!
= issue_closed_text(issuable, current_user)
.issuable-status-box.status-box.status-box-open{ class: issue_status_visibility(issuable, status_box: :open) }
= sprite_icon('issue-open-m', css_class: 'gl-display-block gl-display-sm-none!')
%span.gl-display-none.gl-display-sm-block!
= sprite_icon('issue-open-m', css_class: 'gl-display-block gl-sm-display-none!')
%span.gl-display-none.gl-sm-display-block!
= _('Open')
.issuable-meta

View File

@ -0,0 +1,5 @@
---
title: Change error message for user approval error
merge_request: 52103
author:
type: changed

View File

@ -0,0 +1,5 @@
---
title: Render WebP attachments as image by default
merge_request: 51088
author: Kev @KevSlashNull
type: changed

View File

@ -0,0 +1,5 @@
---
title: Add btn-default to settings toggle button in push rules
merge_request: 52430
author: Yogi (@yo)
type: other

View File

@ -0,0 +1,5 @@
---
title: Allow user SSH public key endpoint to be publicly accessible again
merge_request: 52227
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Remove implicit FF check on `Featurable`
merge_request: 52223
author:
type: removed

View File

@ -0,0 +1,5 @@
---
title: Move Social connect button to new GitLab UI
merge_request: 51835
author: Yogi (@yo)
type: fixed

View File

@ -1,8 +0,0 @@
---
name: builds
introduced_by_url:
rollout_issue_url:
milestone:
type: development
group:
default_enabled: true

View File

@ -1,8 +0,0 @@
---
name: forking
introduced_by_url:
rollout_issue_url:
milestone:
type: development
group: group::source code
default_enabled: true

View File

@ -1,8 +0,0 @@
---
name: issues
introduced_by_url:
rollout_issue_url:
milestone:
type: development
group:
default_enabled: true

View File

@ -1,8 +0,0 @@
---
name: merge_requests
introduced_by_url:
rollout_issue_url:
milestone:
type: development
group: group::code review
default_enabled: true

View File

@ -1,8 +0,0 @@
---
name: metrics_dashboard
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29634
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/257902
milestone: '13.0'
type: development
group: group::monitor
default_enabled: true

View File

@ -1,8 +0,0 @@
---
name: operations
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48347
rollout_issue_url:
milestone: '13.7'
type: development
group: group::editor
default_enabled: true

View File

@ -1,8 +0,0 @@
---
name: pages
introduced_by_url:
rollout_issue_url:
milestone:
type: development
group:
default_enabled: true

View File

@ -1,8 +0,0 @@
---
name: repository
introduced_by_url:
rollout_issue_url:
milestone:
type: development
group: group::source code
default_enabled: true

View File

@ -1,8 +0,0 @@
---
name: snippets
introduced_by_url:
rollout_issue_url:
milestone:
type: development
group:
default_enabled: true

View File

@ -1,8 +0,0 @@
---
name: webperf_experiment
introduced_by_url:
rollout_issue_url:
milestone:
type: development
group: group::editor
default_enabled: false

View File

@ -1,8 +0,0 @@
---
name: wiki
introduced_by_url:
rollout_issue_url:
milestone:
type: development
group: group::editor
default_enabled: true

View File

@ -2,4 +2,3 @@
filenames:
- ee/app/assets/javascripts/on_demand_scans/graphql/dast_scan_create.mutation.graphql
- ee/app/assets/javascripts/oncall_schedules/graphql/mutations/update_oncall_schedule_rotation.mutation.graphql
- ee/app/assets/javascripts/oncall_schedules/graphql/mutations/destroy_oncall_rotation.mutation.graphql

View File

@ -5095,12 +5095,12 @@ input CreateIterationInput {
dueDate: String
"""
The target group for the iteration.
Full path of the group with which the resource is associated.
"""
groupPath: ID
"""
The target project for the iteration.
Full path of the project with which the resource is associated.
"""
projectPath: ID

View File

@ -13827,8 +13827,8 @@
"fields": null,
"inputFields": [
{
"name": "groupPath",
"description": "The target group for the iteration.",
"name": "projectPath",
"description": "Full path of the project with which the resource is associated.",
"type": {
"kind": "SCALAR",
"name": "ID",
@ -13837,8 +13837,8 @@
"defaultValue": null
},
{
"name": "projectPath",
"description": "The target project for the iteration.",
"name": "groupPath",
"description": "Full path of the group with which the resource is associated.",
"type": {
"kind": "SCALAR",
"name": "ID",

View File

@ -1374,7 +1374,7 @@ Example Responses:
```
```json
{ "message": "The user you are trying to approve is not pending an approval" }
{ "message": "The user you are trying to approve is not pending approval" }
```
## Get an impersonation token of a user

View File

@ -107,7 +107,7 @@ graph RL;
class 1-6 criticalPath;
end
2_1-1["graphql-reference-verify (5 minutes)"];
2_1-1["graphql-verify (4 minutes)"];
click 2_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356715&udv=0"
2_1-2["memory-static (4.75 minutes)"];
click 2_1-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356721&udv=0"
@ -212,7 +212,7 @@ graph RL;
class 1-6 criticalPath;
end
2_1-1["graphql-reference-verify (5 minutes)"];
2_1-1["graphql-verify (4 minutes)"];
click 2_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356715&udv=0"
2_1-2["memory-static (4.75 minutes)"];
click 2_1-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356721&udv=0"
@ -341,7 +341,7 @@ graph RL;
class 1-5 criticalPath;
end
2_1-1["graphql-reference-verify (5 minutes)"];
2_1-1["graphql-verify (4 minutes)"];
click 2_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356715&udv=0"
subgraph "Needs `setup-test-env`";
2_1-1 --> 1-6;

View File

@ -186,9 +186,9 @@ the GitLab handbook information for the [shared 1Password account](https://about
### Find my Review App slug
1. Open the `review-deploy` job.
1. Look for `Checking for previous deployment of review-*`.
1. For instance for `Checking for previous deployment of review-qa-raise-e-12chm0`,
your Review App slug would be `review-qa-raise-e-12chm0` in this case.
1. Look for `** Deploying review-*`.
1. For instance for `** Deploying review-1234-abc-defg... **`,
your Review App slug would be `review-1234-abc-defg` in this case.
### Run a Rails console

View File

@ -41,6 +41,7 @@ toggle the list of the milestone bars.
> - Filtering roadmaps by milestone is enabled on GitLab.com.
> - Filtering roadmaps by milestone is recommended for production use.
> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-filtering-roadmaps-by-milestone). **(PREMIUM ONLY)**
> - Filtering by epic confidentiality [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218624) in GitLab 13.8.
WARNING:
Filtering roadmaps by milestone might not be available to you. Check the **version history** note above for details.
@ -62,12 +63,12 @@ You can sort epics in the Roadmap view by:
Each option contains a button that toggles the sort order between **ascending** and **descending**.
The sort option and order persist when browsing Epics, including the [epics list view](../epics/index.md).
You can also filter epics in the Roadmap view by:
You can also filter epics in the Roadmap view by the epics':
- Author
- Label
- Milestone
- Confidentiality of epics
- Confidentiality
![roadmap date range in weeks](img/roadmap_filters_v13_8.png)

View File

@ -46,7 +46,7 @@ If the requirements are not met, the **Designs** tab displays a message to the u
## Supported files
Files uploaded must have a file extension of either `png`, `jpg`, `jpeg`,
`gif`, `bmp`, `tiff`, `ico`, or `svg`.
`gif`, `bmp`, `tiff`, `ico`, `webp`, or `svg`.
Support for [PDF](https://gitlab.com/gitlab-org/gitlab/issues/32811) is planned for a future release.

View File

@ -22,10 +22,6 @@ module BulkImports
@loaders ||= instantiate(self.class.get_loader)
end
def after_run
@after_run ||= self.class.after_run_callback
end
def pipeline
@pipeline ||= self.class.name
end
@ -52,10 +48,6 @@ module BulkImports
class_attributes[:loader] = { klass: klass, options: options }
end
def after_run(&block)
class_attributes[:after_run] = block
end
def get_extractor
class_attributes[:extractor]
end
@ -68,10 +60,6 @@ module BulkImports
class_attributes[:loader]
end
def after_run_callback
class_attributes[:after_run]
end
def abort_on_failure!
class_attributes[:abort_on_failure] = true
end

View File

@ -19,7 +19,7 @@
# `Content-Type` and `Content-Disposition` to the one we get from the detection.
module Gitlab
module FileTypeDetection
SAFE_IMAGE_EXT = %w[png jpg jpeg gif bmp tiff ico].freeze
SAFE_IMAGE_EXT = %w[png jpg jpeg gif bmp tiff ico webp].freeze
SAFE_IMAGE_FOR_SCALING_EXT = %w[png jpg jpeg].freeze
PDF_EXT = 'pdf'

View File

@ -43,7 +43,6 @@ module Gitlab
# Initialize gon.features with any flags that should be
# made globally available to the frontend
push_frontend_feature_flag(:webperf_experiment, default_enabled: false)
push_frontend_feature_flag(:snippets_binary_blob, default_enabled: false)
push_frontend_feature_flag(:usage_data_api, default_enabled: true)
push_frontend_feature_flag(:security_auto_fix, default_enabled: false)

View File

@ -3,7 +3,7 @@
module Gitlab
module Tracking
class StandardContext
GITLAB_STANDARD_SCHEMA_URL = 'iglu:com.gitlab/gitlab_standard/jsonschema/1-0-1'.freeze
GITLAB_STANDARD_SCHEMA_URL = 'iglu:com.gitlab/gitlab_standard/jsonschema/1-0-2'.freeze
def initialize(namespace: nil, project: nil, **data)
@namespace = namespace
@ -15,6 +15,14 @@ module Gitlab
SnowplowTracker::SelfDescribingJson.new(GITLAB_STANDARD_SCHEMA_URL, to_h)
end
def environment
return 'production' if Gitlab.com_and_canary?
return 'staging' if Gitlab.staging?
'development'
end
private
def to_h

View File

@ -28460,7 +28460,7 @@ msgstr ""
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr ""
msgid "The user you are trying to approve is not pending an approval"
msgid "The user you are trying to approve is not pending approval"
msgstr ""
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"

View File

@ -45,7 +45,7 @@
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/svgs": "1.179.0",
"@gitlab/tributejs": "1.0.0",
"@gitlab/ui": "26.3.0",
"@gitlab/ui": "27.0.0",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "^6.0.3-4",
"@rails/ujs": "^6.0.3-4",

View File

@ -180,7 +180,7 @@ RSpec.describe Admin::UsersController do
it 'displays the error' do
subject
expect(flash[:alert]).to eq('The user you are trying to approve is not pending an approval')
expect(flash[:alert]).to eq('The user you are trying to approve is not pending approval')
end
it 'does not activate the user' do

View File

@ -52,12 +52,10 @@ RSpec.describe Repositories::GitHttpController do
}.from(0).to(1)
end
it 'records an onboarding progress action' do
expect_next_instance_of(OnboardingProgressService) do |service|
expect(service).to receive(:execute).with(action: :git_read)
end
it_behaves_like 'records an onboarding progress action', :git_read do
let(:namespace) { project.namespace }
send_request
subject { send_request }
end
end
end

View File

@ -9,7 +9,7 @@ exports[`Blob Header Default Actions rendering matches the snapshot 1`] = `
/>
<div
class="gl-display-none gl-display-sm-flex"
class="gl-display-none gl-sm-display-flex"
>
<viewer-switcher-stub
value="simple"

View File

@ -154,7 +154,7 @@ describe('MembersTable', () => {
expect(findTableCellByMemberId('Actions', members[0].id).classes()).toStrictEqual([
'col-actions',
'gl-display-none!',
'gl-display-lg-table-cell!',
'gl-lg-display-table-cell!',
]);
expect(findTableCellByMemberId('Actions', members[1].id).classes()).toStrictEqual([
'col-actions',

View File

@ -97,7 +97,7 @@ exports[`packages_list_row renders 1`] = `
</div>
<div
class="gl-w-9 gl-display-none gl-display-sm-flex gl-justify-content-end gl-pr-1"
class="gl-w-9 gl-display-none gl-sm-display-flex gl-justify-content-end gl-pr-1"
>
<gl-button-stub
aria-label="Remove package"

View File

@ -30,7 +30,7 @@ describe('PackagesListLoader', () => {
it('has the correct classes', () => {
expect(findDesktopShapes().classes()).toEqual([
'gl-display-none',
'gl-display-sm-flex',
'gl-sm-display-flex',
'gl-flex-direction-column',
]);
});
@ -44,7 +44,7 @@ describe('PackagesListLoader', () => {
it('has the correct classes', () => {
expect(findMobileShapes().classes()).toEqual([
'gl-flex-direction-column',
'gl-display-sm-none',
'gl-sm-display-none',
]);
});
});

View File

@ -10,9 +10,31 @@ RSpec.describe Gitlab::Tracking::StandardContext do
describe '#to_context' do
context 'with no arguments' do
it 'creates a Snowplow context with no data' do
snowplow_context.to_json[:data].each do |_, v|
expect(v).to be_nil
context 'environment' do
shared_examples 'contains environment' do |expected_environment|
it 'contains environment' do
expect(snowplow_context.to_json.dig(:data, :environment)).to eq(expected_environment)
end
end
context 'development or test' do
include_examples 'contains environment', 'development'
end
context 'staging' do
before do
allow(Gitlab).to receive(:staging?).and_return(true)
end
include_examples 'contains environment', 'staging'
end
context 'production' do
before do
allow(Gitlab).to receive(:com_and_canary?).and_return(true)
end
include_examples 'contains environment', 'production'
end
end
end

View File

@ -134,22 +134,6 @@ RSpec.describe Featurable do
expect(project.feature_available?(:issues, user)).to eq(true)
end
end
context 'when feature is disabled by a feature flag' do
it 'returns false' do
stub_feature_flags(issues: false)
expect(project.feature_available?(:issues, user)).to eq(false)
end
end
context 'when feature is enabled by a feature flag' do
it 'returns true' do
stub_feature_flags(issues: true)
expect(project.feature_available?(:issues, user)).to eq(true)
end
end
end
describe '#*_enabled?' do

View File

@ -410,7 +410,7 @@ RSpec.describe Group do
it "is false if avatar is html page" do
group.update_attribute(:avatar, 'uploads/avatar.html')
expect(group.avatar_type).to eq(["file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico"])
expect(group.avatar_type).to eq(["file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico, webp"])
end
end

View File

@ -11,7 +11,7 @@ RSpec.describe DatadogService, :model do
let(:active) { true }
let(:dd_site) { 'datadoghq.com' }
let(:default_url) { 'https://webhooks-http-intake.logs.datadoghq.com/v1/input/' }
let(:api_url) { nil }
let(:api_url) { '' }
let(:api_key) { SecureRandom.hex(32) }
let(:dd_env) { 'ci' }
let(:dd_service) { 'awesome-gitlab' }
@ -22,13 +22,11 @@ RSpec.describe DatadogService, :model do
described_class.new(
active: active,
project: project,
properties: {
datadog_site: dd_site,
api_url: api_url,
api_key: api_key,
datadog_env: dd_env,
datadog_service: dd_service
}
datadog_site: dd_site,
api_url: api_url,
api_key: api_key,
datadog_env: dd_env,
datadog_service: dd_service
)
end
@ -58,7 +56,7 @@ RSpec.describe DatadogService, :model do
context 'when selecting site' do
let(:dd_site) { 'datadoghq.com' }
let(:api_url) { nil }
let(:api_url) { '' }
it { is_expected.to validate_presence_of(:datadog_site) }
it { is_expected.not_to validate_presence_of(:api_url) }
@ -66,7 +64,7 @@ RSpec.describe DatadogService, :model do
end
context 'with custom api_url' do
let(:dd_site) { nil }
let(:dd_site) { '' }
let(:api_url) { 'https://webhooks-http-intake.logs.datad0g.com/v1/input/' }
it { is_expected.not_to validate_presence_of(:datadog_site) }
@ -76,13 +74,21 @@ RSpec.describe DatadogService, :model do
end
context 'when missing site and api_url' do
let(:dd_site) { nil }
let(:api_url) { nil }
let(:dd_site) { '' }
let(:api_url) { '' }
it { is_expected.not_to be_valid }
it { is_expected.to validate_presence_of(:datadog_site) }
it { is_expected.to validate_presence_of(:api_url) }
end
context 'when providing both site and api_url' do
let(:dd_site) { 'datadoghq.com' }
let(:api_url) { default_url }
it { is_expected.not_to allow_value('datadog hq.com').for(:datadog_site) }
it { is_expected.not_to allow_value('example.com').for(:api_url) }
end
end
context 'when service is not active' do
@ -113,8 +119,8 @@ RSpec.describe DatadogService, :model do
end
context 'without optional params' do
let(:dd_service) { nil }
let(:dd_env) { nil }
let(:dd_service) { '' }
let(:dd_env) { '' }
it { is_expected.to eq(default_url + api_key) }
end
@ -126,7 +132,7 @@ RSpec.describe DatadogService, :model do
it { is_expected.to eq("https://app.#{dd_site}/account/settings#api") }
context 'with unset datadog_site' do
let(:dd_site) { nil }
let(:dd_site) { '' }
it { is_expected.to eq("https://docs.datadoghq.com/account_management/api-app-keys/") }
end

View File

@ -1256,7 +1256,7 @@ RSpec.describe Project, factory_default: :keep do
it 'is false if avatar is html page' do
project.update_attribute(:avatar, 'uploads/avatar.html')
expect(project.avatar_type).to eq(['file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico'])
expect(project.avatar_type).to eq(['file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico, webp'])
end
end
@ -1551,10 +1551,7 @@ RSpec.describe Project, factory_default: :keep do
let(:project) { build(:project) }
it 'picks storage from ApplicationSetting' do
expect_next_instance_of(ApplicationSetting) do |instance|
expect(instance).to receive(:pick_repository_storage).and_return('picked')
end
expect(described_class).to receive(:pick_repository_storage).and_call_original
expect(Repository).to receive(:pick_storage_shard).and_return('picked')
expect(project.repository_storage).to eq('picked')
end

View File

@ -3049,4 +3049,51 @@ RSpec.describe Repository do
end
end
end
describe '.pick_storage_shard', :request_store do
before do
storages = {
'default' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/repositories'),
'picked' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/repositories')
}
allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
Gitlab::CurrentSettings.current_application_settings
update_storages({ 'picked' => 0, 'default' => 100 })
end
context 'when expire is false' do
it 'does not expire existing repository storage value' do
previous_storage = described_class.pick_storage_shard
expect(previous_storage).to eq('default')
expect(Gitlab::CurrentSettings).not_to receive(:expire_current_application_settings)
update_storages({ 'picked' => 100, 'default' => 0 })
new_storage = described_class.pick_storage_shard(expire: false)
expect(new_storage).to eq(previous_storage)
end
end
context 'when expire is true' do
it 'expires existing repository storage value' do
previous_storage = described_class.pick_storage_shard
expect(previous_storage).to eq('default')
expect(Gitlab::CurrentSettings).to receive(:expire_current_application_settings).and_call_original
update_storages({ 'picked' => 100, 'default' => 0 })
new_storage = described_class.pick_storage_shard(expire: true)
expect(new_storage).to eq('picked')
end
end
def update_storages(storage_hash)
settings = ApplicationSetting.last
settings.repository_storages_weighted = storage_hash
settings.save!
end
end
end

View File

@ -630,14 +630,10 @@ RSpec.describe Snippet do
subject { snippet.repository_storage }
before do
expect_next_instance_of(ApplicationSetting) do |instance|
expect(instance).to receive(:pick_repository_storage).and_return('picked')
end
expect(Repository).to receive(:pick_storage_shard).and_return('picked')
end
it 'returns repository storage from ApplicationSetting' do
expect(described_class).to receive(:pick_repository_storage).and_call_original
expect(subject).to eq 'picked'
end

View File

@ -2477,7 +2477,7 @@ RSpec.describe User do
it 'is false if avatar is html page' do
user.update_attribute(:avatar, 'uploads/avatar.html')
expect(user.avatar_type).to eq(['file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico'])
expect(user.avatar_type).to eq(['file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico, webp'])
end
end

View File

@ -2565,7 +2565,7 @@ RSpec.describe API::Users do
it 'does not approve a deactivated user' do
expect { approve }.not_to change { deactivated_user.reload.state }
expect(response).to have_gitlab_http_status(:conflict)
expect(json_response['message']).to eq('The user you are trying to approve is not pending an approval')
expect(json_response['message']).to eq('The user you are trying to approve is not pending approval')
end
end
@ -2585,7 +2585,7 @@ RSpec.describe API::Users do
it 'returns 201' do
expect { approve }.not_to change { user.reload.state }
expect(response).to have_gitlab_http_status(:conflict)
expect(json_response['message']).to eq('The user you are trying to approve is not pending an approval')
expect(json_response['message']).to eq('The user you are trying to approve is not pending approval')
end
end
@ -2595,7 +2595,7 @@ RSpec.describe API::Users do
it 'returns 403' do
expect { approve }.not_to change { blocked_user.reload.state }
expect(response).to have_gitlab_http_status(:conflict)
expect(json_response['message']).to eq('The user you are trying to approve is not pending an approval')
expect(json_response['message']).to eq('The user you are trying to approve is not pending approval')
end
end
@ -2605,7 +2605,7 @@ RSpec.describe API::Users do
it 'returns 403' do
expect { approve }.not_to change { ldap_blocked_user.reload.state }
expect(response).to have_gitlab_http_status(:conflict)
expect(json_response['message']).to eq('The user you are trying to approve is not pending an approval')
expect(json_response['message']).to eq('The user you are trying to approve is not pending approval')
end
end

View File

@ -268,6 +268,14 @@ RSpec.describe UsersController do
end
it_behaves_like 'renders all public keys'
context 'when public visibility is restricted' do
before do
stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
end
it_behaves_like 'renders all public keys'
end
end
end
end

View File

@ -146,9 +146,11 @@ RSpec.describe Ci::ProcessBuildService, '#execute' do
end
end
context 'when FF skip_dag_manual_and_delayed_jobs is disabled' do
context 'when FF skip_dag_manual_and_delayed_jobs is disabled on the project' do
let_it_be(:other_project) { create(:project) }
before do
stub_feature_flags(skip_dag_manual_and_delayed_jobs: false)
stub_feature_flags(skip_dag_manual_and_delayed_jobs: other_project)
end
where(:build_when, :current_status, :after_status) do

Some files were not shown because too many files have changed in this diff Show More