Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-11-13 15:09:03 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-11-13 15:09:03 +0300
commit7f59234892f27812dc91044cd63a6a4655e26263 (patch)
treec9261d822970270d7c5711e2028d5422fb1fdcd4
parentc21064ccfd3c8d40e82ee92cc709bf0c8bf5bac7 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml8
-rw-r--r--.rubocop_manual_todo.yml3
-rw-r--r--GITLAB_WORKHORSE_VERSION2
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_item.vue27
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_list_root.vue3
-rw-r--r--app/assets/javascripts/repository/components/tree_action_link.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/actions_button.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/web_ide_link.vue2
-rw-r--r--app/assets/stylesheets/pages/tree.scss2
-rw-r--r--app/graphql/resolvers/assigned_merge_requests_resolver.rb3
-rw-r--r--app/graphql/resolvers/authored_merge_requests_resolver.rb3
-rw-r--r--app/graphql/resolvers/user_merge_requests_resolver_base.rb (renamed from app/graphql/resolvers/user_merge_requests_resolver.rb)2
-rw-r--r--app/graphql/types/user_type.rb4
-rw-r--r--app/models/ci/build_trace_chunk.rb11
-rw-r--r--app/models/ci/build_trace_chunks/legacy_fog.rb77
-rw-r--r--app/views/devise/registrations/new.html.haml2
-rw-r--r--app/views/devise/shared/_signup_box.html.haml21
-rw-r--r--app/views/projects/_find_file_link.html.haml2
-rw-r--r--app/views/projects/buttons/_clone.html.haml2
-rw-r--r--app/views/projects/buttons/_download.html.haml2
-rw-r--r--app/views/projects/buttons/_xcode_link.html.haml2
-rw-r--r--app/views/projects/tree/_tree_header.html.haml2
-rw-r--r--changelogs/unreleased/280811-mr-analytics-chart-tooltip-overlays-filter-dropdown.yml5
-rw-r--r--changelogs/unreleased/alipniagov-update-workhorse-to-8-54.yml5
-rw-r--r--changelogs/unreleased/ps-fix-repo-tree-header-button-styles.yml5
-rw-r--r--changelogs/unreleased/remove-ci_always_refresh_merge_requests_from_beginning-flag.yml6
-rw-r--r--changelogs/unreleased/sh-remove-legacy-fog-ff.yml5
-rw-r--r--config/feature_flags/development/ci_always_refresh_merge_requests_from_beginning.yml8
-rw-r--r--config/feature_flags/development/ci_trace_new_fog_store.yml8
-rw-r--r--doc/api/boards.md1
-rw-r--r--doc/subscriptions/self_managed/index.md19
-rw-r--r--doc/user/admin_area/settings/sign_up_restrictions.md8
-rw-r--r--locale/gitlab.pot78
-rw-r--r--package.json2
-rw-r--r--spec/frontend/issuable_list/components/issuable_item_spec.js58
-rw-r--r--spec/frontend/issuable_list/mock_data.js1
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js1
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js1
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js1
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js1
-rw-r--r--spec/models/ci/build_trace_chunk_spec.rb26
-rw-r--r--spec/models/ci/build_trace_chunks/legacy_fog_spec.rb164
-rw-r--r--yarn.lock8
44 files changed, 241 insertions, 359 deletions
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index 3827fff079c..7f469221da2 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -164,7 +164,7 @@
- "vendor/assets/**/*"
- ".gitlab/ci/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,scss-lint}.yml"
+ - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,rubocop_manual_todo,scss-lint}.yml"
- "*_VERSION"
- "Gemfile{,.lock}"
- "Rakefile"
@@ -186,7 +186,7 @@
- "vendor/assets/**/*"
- ".gitlab/ci/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,scss-lint}.yml"
+ - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,rubocop_manual_todo,scss-lint}.yml"
- "*_VERSION"
- "Gemfile{,.lock}"
- "Rakefile"
@@ -210,7 +210,7 @@
- "vendor/assets/**/*"
- ".gitlab/ci/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,scss-lint}.yml"
+ - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,rubocop_manual_todo,scss-lint}.yml"
- "*_VERSION"
- "Gemfile{,.lock}"
- "Rakefile"
@@ -231,7 +231,7 @@
- "vendor/assets/**/*"
- ".gitlab/ci/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,scss-lint}.yml"
+ - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,rubocop_manual_todo,scss-lint}.yml"
- "*_VERSION"
- "Gemfile{,.lock}"
- "Rakefile"
diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml
index 3fe46000e5e..330c7906895 100644
--- a/.rubocop_manual_todo.yml
+++ b/.rubocop_manual_todo.yml
@@ -43,8 +43,6 @@ Graphql/IDType:
Graphql/ResolverType:
Exclude:
- - 'app/graphql/resolvers/assigned_merge_requests_resolver.rb'
- - 'app/graphql/resolvers/authored_merge_requests_resolver.rb'
- 'app/graphql/resolvers/base_resolver.rb'
- 'app/graphql/resolvers/ci/pipeline_stages_resolver.rb'
- 'app/graphql/resolvers/commit_pipelines_resolver.rb'
@@ -61,7 +59,6 @@ Graphql/ResolverType:
- 'app/graphql/resolvers/project_pipelines_resolver.rb'
- 'app/graphql/resolvers/projects/snippets_resolver.rb'
- 'app/graphql/resolvers/snippets_resolver.rb'
- - 'app/graphql/resolvers/user_merge_requests_resolver.rb'
- 'app/graphql/resolvers/users/group_count_resolver.rb'
- 'app/graphql/resolvers/users/snippets_resolver.rb'
- 'ee/app/graphql/resolvers/ci/jobs_resolver.rb'
diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION
index d9b7ec5a2f7..a99caf2cdef 100644
--- a/GITLAB_WORKHORSE_VERSION
+++ b/GITLAB_WORKHORSE_VERSION
@@ -1 +1 @@
-8.53.0
+8.54.0
diff --git a/app/assets/javascripts/issuable_list/components/issuable_item.vue b/app/assets/javascripts/issuable_list/components/issuable_item.vue
index 05bc3185cc8..1ee794ab208 100644
--- a/app/assets/javascripts/issuable_list/components/issuable_item.vue
+++ b/app/assets/javascripts/issuable_list/components/issuable_item.vue
@@ -84,6 +84,14 @@ export default {
}
return {};
},
+ showDiscussions() {
+ return typeof this.issuable.userDiscussionsCount === 'number';
+ },
+ showIssuableMeta() {
+ return Boolean(
+ this.hasSlotContents('status') || this.showDiscussions || this.issuable.assignees,
+ );
+ },
},
methods: {
hasSlotContents(slotName) {
@@ -166,6 +174,7 @@ export default {
<span class="author">{{ author.name }}</span>
</gl-link>
</span>
+ <slot name="timeframe"></slot>
&nbsp;
<gl-label
v-for="(label, index) in labels"
@@ -181,10 +190,26 @@ export default {
</div>
</div>
<div class="issuable-meta">
- <ul v-if="hasSlotContents('status') || issuable.assignees" class="controls">
+ <ul v-if="showIssuableMeta" class="controls">
<li v-if="hasSlotContents('status')" class="issuable-status">
<slot name="status"></slot>
</li>
+ <li
+ v-if="showDiscussions"
+ data-testid="issuable-discussions"
+ class="issuable-comments gl-display-none gl-display-sm-block"
+ >
+ <gl-link
+ v-gl-tooltip:tooltipcontainer.top
+ :title="__('Comments')"
+ :href="`${issuable.webUrl}#notes`"
+ :class="{ 'no-comments': !issuable.userDiscussionsCount }"
+ class="gl-reset-color!"
+ >
+ <gl-icon name="comments" />
+ {{ issuable.userDiscussionsCount }}
+ </gl-link>
+ </li>
<li v-if="assignees.length" class="gl-display-flex">
<issuable-assignees
:assignees="issuable.assignees"
diff --git a/app/assets/javascripts/issuable_list/components/issuable_list_root.vue b/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
index 0ac51c81d6f..b2312c55f01 100644
--- a/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
+++ b/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
@@ -269,6 +269,9 @@ export default {
<template #author>
<slot name="author" :author="issuable.author"></slot>
</template>
+ <template #timeframe>
+ <slot name="timeframe" :issuable="issuable"></slot>
+ </template>
<template #status>
<slot name="status" :issuable="issuable"></slot>
</template>
diff --git a/app/assets/javascripts/repository/components/tree_action_link.vue b/app/assets/javascripts/repository/components/tree_action_link.vue
index 72764f3ccc9..c5ab150adaf 100644
--- a/app/assets/javascripts/repository/components/tree_action_link.vue
+++ b/app/assets/javascripts/repository/components/tree_action_link.vue
@@ -24,5 +24,5 @@ export default {
</script>
<template>
- <gl-link :href="path" :class="cssClass" class="btn">{{ text }}</gl-link>
+ <gl-link :href="path" :class="cssClass" class="btn gl-button">{{ text }}</gl-link>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/actions_button.vue b/app/assets/javascripts/vue_shared/components/actions_button.vue
index 9b21de19185..cb4c5f20377 100644
--- a/app/assets/javascripts/vue_shared/components/actions_button.vue
+++ b/app/assets/javascripts/vue_shared/components/actions_button.vue
@@ -61,7 +61,6 @@ export default {
<gl-dropdown
v-if="hasMultipleActions"
v-gl-tooltip="selectedAction.tooltip"
- class="gl-button-deprecated-adapter"
:text="selectedAction.text"
:split-href="selectedAction.href"
:variant="variant"
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
index 96dce959828..97b4ceda033 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
@@ -75,6 +75,11 @@ export default {
type: String,
required: true,
},
+ suggestionsListClass: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
data() {
let selectedSortOption = this.sortOptions[0]?.sortDirection?.descending;
@@ -315,6 +320,7 @@ export default {
:placeholder="searchInputPlaceholder"
:available-tokens="tokens"
:history-items="filteredRecentSearches"
+ :suggestions-list-class="suggestionsListClass"
class="flex-grow-1"
@history-item-selected="handleHistoryItemSelected"
@clear-history="handleClearHistory"
diff --git a/app/assets/javascripts/vue_shared/components/web_ide_link.vue b/app/assets/javascripts/vue_shared/components/web_ide_link.vue
index 877414519f7..dbb1a075e76 100644
--- a/app/assets/javascripts/vue_shared/components/web_ide_link.vue
+++ b/app/assets/javascripts/vue_shared/components/web_ide_link.vue
@@ -169,7 +169,7 @@ export default {
</script>
<template>
- <div class="d-inline-block gl-ml-3">
+ <div class="gl-sm-ml-3">
<actions-button
:actions="actions"
:selected-key="selection"
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index 73fe76f139f..429181c2ad4 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -62,7 +62,7 @@
.tree-controls {
margin-bottom: 10px;
- .btn,
+ .btn:not(.dropdown-toggle-split),
.dropdown,
.btn-group {
width: 100%;
diff --git a/app/graphql/resolvers/assigned_merge_requests_resolver.rb b/app/graphql/resolvers/assigned_merge_requests_resolver.rb
index 172a8e298ad..30415ef5d2d 100644
--- a/app/graphql/resolvers/assigned_merge_requests_resolver.rb
+++ b/app/graphql/resolvers/assigned_merge_requests_resolver.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
module Resolvers
- class AssignedMergeRequestsResolver < UserMergeRequestsResolver
+ class AssignedMergeRequestsResolver < UserMergeRequestsResolverBase
+ type ::Types::MergeRequestType.connection_type, null: true
accept_author
def user_role
diff --git a/app/graphql/resolvers/authored_merge_requests_resolver.rb b/app/graphql/resolvers/authored_merge_requests_resolver.rb
index bc796f8685a..1426ca83c06 100644
--- a/app/graphql/resolvers/authored_merge_requests_resolver.rb
+++ b/app/graphql/resolvers/authored_merge_requests_resolver.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
module Resolvers
- class AuthoredMergeRequestsResolver < UserMergeRequestsResolver
+ class AuthoredMergeRequestsResolver < UserMergeRequestsResolverBase
+ type ::Types::MergeRequestType.connection_type, null: true
accept_assignee
def user_role
diff --git a/app/graphql/resolvers/user_merge_requests_resolver.rb b/app/graphql/resolvers/user_merge_requests_resolver_base.rb
index af3ad48e8aa..47967fe69f9 100644
--- a/app/graphql/resolvers/user_merge_requests_resolver.rb
+++ b/app/graphql/resolvers/user_merge_requests_resolver_base.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Resolvers
- class UserMergeRequestsResolver < MergeRequestsResolver
+ class UserMergeRequestsResolverBase < MergeRequestsResolver
include ResolvesProject
argument :project_path, GraphQL::STRING_TYPE,
diff --git a/app/graphql/types/user_type.rb b/app/graphql/types/user_type.rb
index 735bf06337b..11c5369f726 100644
--- a/app/graphql/types/user_type.rb
+++ b/app/graphql/types/user_type.rb
@@ -46,10 +46,10 @@ module Types
resolver: Resolvers::UserStarredProjectsResolver
# Merge request field: MRs can be either authored or assigned:
- field :authored_merge_requests, Types::MergeRequestType.connection_type, null: true,
+ field :authored_merge_requests,
resolver: Resolvers::AuthoredMergeRequestsResolver,
description: 'Merge Requests authored by the user'
- field :assigned_merge_requests, Types::MergeRequestType.connection_type, null: true,
+ field :assigned_merge_requests,
resolver: Resolvers::AssignedMergeRequestsResolver,
description: 'Merge Requests assigned to the user'
diff --git a/app/models/ci/build_trace_chunk.rb b/app/models/ci/build_trace_chunk.rb
index 4b36b7c2a75..1fb8e74269d 100644
--- a/app/models/ci/build_trace_chunk.rb
+++ b/app/models/ci/build_trace_chunk.rb
@@ -54,9 +54,6 @@ module Ci
raise "Unknown store type: #{store}" unless STORE_TYPES.key?(store)
- # Can't memoize this because the feature flag may alter this
- return fog_store_class.new if store == :fog
-
STORE_TYPES[store].new
end
@@ -86,14 +83,6 @@ module Ci
def metadata_attributes
attribute_names - %w[raw_data]
end
-
- def fog_store_class
- if Feature.enabled?(:ci_trace_new_fog_store, default_enabled: true)
- Ci::BuildTraceChunks::Fog
- else
- Ci::BuildTraceChunks::LegacyFog
- end
- end
end
def data
diff --git a/app/models/ci/build_trace_chunks/legacy_fog.rb b/app/models/ci/build_trace_chunks/legacy_fog.rb
deleted file mode 100644
index b710ed2890b..00000000000
--- a/app/models/ci/build_trace_chunks/legacy_fog.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-# frozen_string_literal: true
-
-module Ci
- module BuildTraceChunks
- class LegacyFog
- def available?
- object_store.enabled
- end
-
- def data(model)
- connection.get_object(bucket_name, key(model))[:body]
- rescue Excon::Error::NotFound
- # If the object does not exist in the object storage, this method returns nil.
- end
-
- def set_data(model, new_data)
- connection.put_object(bucket_name, key(model), new_data)
- end
-
- def append_data(model, new_data, offset)
- if offset > 0
- truncated_data = data(model).to_s.byteslice(0, offset)
- new_data = truncated_data + new_data
- end
-
- set_data(model, new_data)
- new_data.bytesize
- end
-
- def size(model)
- data(model).to_s.bytesize
- end
-
- def delete_data(model)
- delete_keys([[model.build_id, model.chunk_index]])
- end
-
- def keys(relation)
- return [] unless available?
-
- relation.pluck(:build_id, :chunk_index)
- end
-
- def delete_keys(keys)
- keys.each do |key|
- connection.delete_object(bucket_name, key_raw(*key))
- end
- end
-
- private
-
- def key(model)
- key_raw(model.build_id, model.chunk_index)
- end
-
- def key_raw(build_id, chunk_index)
- "tmp/builds/#{build_id.to_i}/chunks/#{chunk_index.to_i}.log"
- end
-
- def bucket_name
- return unless available?
-
- object_store.remote_directory
- end
-
- def connection
- return unless available?
-
- @connection ||= ::Fog::Storage.new(object_store.connection.to_hash.deep_symbolize_keys)
- end
-
- def object_store
- Gitlab.config.artifacts.object_store
- end
- end
- end
-end
diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml
index a1e6e701c79..6782e1576b5 100644
--- a/app/views/devise/registrations/new.html.haml
+++ b/app/views/devise/registrations/new.html.haml
@@ -2,5 +2,5 @@
- add_page_specific_style 'page_bundles/signup'
.signup-page
- = render 'devise/shared/signup_box'
+ = render 'devise/shared/signup_box', url: registration_path(resource_name), button_text: _('Register'), show_omniauth_providers: omniauth_enabled? && button_based_providers_enabled?
= render 'devise/shared/sign_in_link'
diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml
index b5c2adb0b9a..0dc98001881 100644
--- a/app/views/devise/shared/_signup_box.html.haml
+++ b/app/views/devise/shared/_signup_box.html.haml
@@ -2,37 +2,36 @@
- max_username_length = 255
- min_username_length = 2
.gl-mb-3.gl-p-4.gl-border-gray-100.gl-border-1.gl-border-solid.gl-rounded-base
- = form_for(resource, as: "new_#{resource_name}", url: registration_path(resource_name), html: { class: "new_new_user gl-show-field-errors", "aria-live" => "assertive" }) do |f|
+ = form_for(resource, as: "new_#{resource_name}", url: url, html: { class: 'new_user gl-show-field-errors', 'aria-live' => 'assertive' }) do |f|
.devise-errors
- = render "devise/shared/error_messages", resource: resource
+ = render 'devise/shared/error_messages', resource: resource
- if Feature.enabled?(:invisible_captcha)
= invisible_captcha
.name.form-row
.col.form-group
= f.label :first_name, _('First name'), for: 'new_user_first_name', class: 'label-bold'
- = f.text_field :first_name, class: 'form-control top js-block-emoji js-validate-length', :data => { :max_length => max_first_name_length, :max_length_message => _("First name is too long (maximum is %{max_length} characters).") % { max_length: max_first_name_length }, :qa_selector => 'new_user_first_name_field' }, required: true, title: _("This field is required.")
+ = f.text_field :first_name, class: 'form-control top js-block-emoji js-validate-length', :data => { :max_length => max_first_name_length, :max_length_message => s_('SignUp|First name is too long (maximum is %{max_length} characters).') % { max_length: max_first_name_length }, :qa_selector => 'new_user_first_name_field' }, required: true, title: _('This field is required.')
.col.form-group
= f.label :last_name, _('Last name'), for: 'new_user_last_name', class: 'label-bold'
- = f.text_field :last_name, class: "form-control top js-block-emoji js-validate-length", :data => { :max_length => max_last_name_length, :max_length_message => _("Last name is too long (maximum is %{max_length} characters).") % { max_length: max_last_name_length }, :qa_selector => 'new_user_last_name_field' }, required: true, title: _("This field is required.")
+ = f.text_field :last_name, class: 'form-control top js-block-emoji js-validate-length', :data => { :max_length => max_last_name_length, :max_length_message => s_('SignUp|Last name is too long (maximum is %{max_length} characters).') % { max_length: max_last_name_length }, :qa_selector => 'new_user_last_name_field' }, required: true, title: _('This field is required.')
.username.form-group
= f.label :username, class: 'label-bold'
- = f.text_field :username, class: "form-control middle js-block-emoji js-validate-length js-validate-username", :data => { :min_length => min_username_length, :min_length_message => s_("SignUp|Username is too short (minimum is %{min_length} characters).") % { min_length: min_username_length }, :max_length => max_username_length, :max_length_message => s_("SignUp|Username is too long (maximum is %{max_length} characters).") % { max_length: max_username_length }, :qa_selector => 'new_user_username_field' }, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _("Please create a username with only alphanumeric characters.")
+ = f.text_field :username, class: 'form-control middle js-block-emoji js-validate-length js-validate-username', :data => { :api_path => suggestion_path, :min_length => min_username_length, :min_length_message => s_('SignUp|Username is too short (minimum is %{min_length} characters).') % { min_length: min_username_length }, :max_length => max_username_length, :max_length_message => s_('SignUp|Username is too long (maximum is %{max_length} characters).') % { max_length: max_username_length }, :qa_selector => 'new_user_username_field' }, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _('Please create a username with only alphanumeric characters.')
%p.validation-error.gl-text-red-500.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Username is already taken.')
%p.validation-success.gl-text-green-600.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Username is available.')
%p.validation-pending.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Checking username availability...')
.form-group
= f.label :email, class: 'label-bold'
- = f.email_field :email, value: @invite_email, class: "form-control middle", data: { qa_selector: 'new_user_email_field' }, required: true, title: _("Please provide a valid email address.")
+ = f.email_field :email, value: @invite_email, class: 'form-control middle', data: { qa_selector: 'new_user_email_field' }, required: true, title: _('Please provide a valid email address.')
.form-group.append-bottom-20#password-strength
= f.label :password, class: 'label-bold'
- = f.password_field :password, class: "form-control bottom", data: { qa_selector: 'new_user_password_field' }, required: true, pattern: ".{#{@minimum_password_length},}", title: _("Minimum length is %{minimum_password_length} characters.") % { minimum_password_length: @minimum_password_length }
- %p.gl-field-hint.text-secondary= _('Minimum length is %{minimum_password_length} characters') % { minimum_password_length: @minimum_password_length }
+ = f.password_field :password, class: 'form-control bottom', data: { qa_selector: 'new_user_password_field' }, required: true, pattern: ".{#{@minimum_password_length},}", title: s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
+ %p.gl-field-hint.text-secondary= s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
%div
- if show_recaptcha_sign_up?
= recaptcha_tags
.submit-container
- = f.submit _("Register"), class: "btn gl-button btn-success", data: { qa_selector: 'new_user_register_button' }
+ = f.submit button_text, class: 'btn gl-button btn-success', data: { qa_selector: 'new_user_register_button' }
= render 'devise/shared/terms_of_service_notice'
- - if omniauth_enabled? && button_based_providers_enabled?
+ - if show_omniauth_providers
= render 'devise/shared/signup_omniauth_providers'
-
diff --git a/app/views/projects/_find_file_link.html.haml b/app/views/projects/_find_file_link.html.haml
index 74cdb0f7409..c3b4a61c28a 100644
--- a/app/views/projects/_find_file_link.html.haml
+++ b/app/views/projects/_find_file_link.html.haml
@@ -1,2 +1,2 @@
-= link_to project_find_file_path(@project, @ref), class: 'btn shortcuts-find-file', rel: 'nofollow' do
+= link_to project_find_file_path(@project, @ref), class: 'gl-button btn shortcuts-find-file', rel: 'nofollow' do
= _('Find file')
diff --git a/app/views/projects/buttons/_clone.html.haml b/app/views/projects/buttons/_clone.html.haml
index 7ce143a86b3..cf58cff7445 100644
--- a/app/views/projects/buttons/_clone.html.haml
+++ b/app/views/projects/buttons/_clone.html.haml
@@ -2,7 +2,7 @@
- dropdown_class = local_assigns.fetch(:dropdown_class, '')
.git-clone-holder.js-git-clone-holder
- %a#clone-dropdown.btn.btn-primary.clone-dropdown-btn.qa-clone-dropdown{ href: '#', data: { toggle: 'dropdown' } }
+ %a#clone-dropdown.gl-button.btn.btn-primary.clone-dropdown-btn.qa-clone-dropdown{ href: '#', data: { toggle: 'dropdown' } }
%span.gl-mr-2.js-clone-dropdown-label
= _('Clone')
= sprite_icon("chevron-down", css_class: "icon")
diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml
index c04687bd846..0fcbf2ca1eb 100644
--- a/app/views/projects/buttons/_download.html.haml
+++ b/app/views/projects/buttons/_download.html.haml
@@ -3,7 +3,7 @@
- if !project.empty_repo? && can?(current_user, :download_code, project)
- archive_prefix = "#{project.path}-#{ref.tr('/', '-')}"
.project-action-button.dropdown.inline>
- %button.btn.has-tooltip{ title: s_('DownloadSource|Download'), 'data-toggle' => 'dropdown', 'aria-label' => s_('DownloadSource|Download'), 'data-display' => 'static', data: { qa_selector: 'download_source_code_button' } }
+ %button.gl-button.btn.has-tooltip{ title: s_('DownloadSource|Download'), 'data-toggle' => 'dropdown', 'aria-label' => s_('DownloadSource|Download'), 'data-display' => 'static', data: { qa_selector: 'download_source_code_button' } }
= sprite_icon('download')
%span.sr-only= _('Select Archive Format')
= sprite_icon("chevron-down")
diff --git a/app/views/projects/buttons/_xcode_link.html.haml b/app/views/projects/buttons/_xcode_link.html.haml
index a8b32fb0ef5..e0f47f1ca3d 100644
--- a/app/views/projects/buttons/_xcode_link.html.haml
+++ b/app/views/projects/buttons/_xcode_link.html.haml
@@ -1,2 +1,2 @@
-%a.btn.btn-default{ href: xcode_uri_to_repo(@project) }
+%a.gl-button.btn.btn-default{ href: xcode_uri_to_repo(@project) }
= _("Open in Xcode")
diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml
index dc9fb9e7792..cd6e85d60ed 100644
--- a/app/views/projects/tree/_tree_header.html.haml
+++ b/app/views/projects/tree/_tree_header.html.haml
@@ -13,7 +13,7 @@
= render 'shared/web_ide_button', blob: nil
- if show_xcode_link?(@project)
- .project-action-button.project-xcode.inline<
+ .project-action-button.project-xcode<
= render "projects/buttons/xcode_link"
= render 'projects/buttons/download', project: @project, ref: @ref
diff --git a/changelogs/unreleased/280811-mr-analytics-chart-tooltip-overlays-filter-dropdown.yml b/changelogs/unreleased/280811-mr-analytics-chart-tooltip-overlays-filter-dropdown.yml
new file mode 100644
index 00000000000..87236ab3e2b
--- /dev/null
+++ b/changelogs/unreleased/280811-mr-analytics-chart-tooltip-overlays-filter-dropdown.yml
@@ -0,0 +1,5 @@
+---
+title: 'MR Analytics: Fix chart tooltip covering filter dropdown'
+merge_request: 47274
+author:
+type: changed
diff --git a/changelogs/unreleased/alipniagov-update-workhorse-to-8-54.yml b/changelogs/unreleased/alipniagov-update-workhorse-to-8-54.yml
new file mode 100644
index 00000000000..c57e1e5ef7d
--- /dev/null
+++ b/changelogs/unreleased/alipniagov-update-workhorse-to-8-54.yml
@@ -0,0 +1,5 @@
+---
+title: Update Workhorse version to 8.54.0
+merge_request: 47625
+author:
+type: other
diff --git a/changelogs/unreleased/ps-fix-repo-tree-header-button-styles.yml b/changelogs/unreleased/ps-fix-repo-tree-header-button-styles.yml
new file mode 100644
index 00000000000..222884a7960
--- /dev/null
+++ b/changelogs/unreleased/ps-fix-repo-tree-header-button-styles.yml
@@ -0,0 +1,5 @@
+---
+title: Update button styles in project tree header
+merge_request: 47562
+author:
+type: other
diff --git a/changelogs/unreleased/remove-ci_always_refresh_merge_requests_from_beginning-flag.yml b/changelogs/unreleased/remove-ci_always_refresh_merge_requests_from_beginning-flag.yml
new file mode 100644
index 00000000000..54879f5fc4f
--- /dev/null
+++ b/changelogs/unreleased/remove-ci_always_refresh_merge_requests_from_beginning-flag.yml
@@ -0,0 +1,6 @@
+---
+title: Make the Merge Train process flow more resilient by always refreshing merge
+ requests from beginning
+merge_request: 46768
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-remove-legacy-fog-ff.yml b/changelogs/unreleased/sh-remove-legacy-fog-ff.yml
new file mode 100644
index 00000000000..9d8aaa321b2
--- /dev/null
+++ b/changelogs/unreleased/sh-remove-legacy-fog-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Remove ci_trace_new_fog_store feature flag
+merge_request: 47522
+author:
+type: changed
diff --git a/config/feature_flags/development/ci_always_refresh_merge_requests_from_beginning.yml b/config/feature_flags/development/ci_always_refresh_merge_requests_from_beginning.yml
deleted file mode 100644
index 387c921cb5b..00000000000
--- a/config/feature_flags/development/ci_always_refresh_merge_requests_from_beginning.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_always_refresh_merge_requests_from_beginning
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45232
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/268215
-milestone: '13.5'
-type: development
-group: group::continuous integration
-default_enabled: false
diff --git a/config/feature_flags/development/ci_trace_new_fog_store.yml b/config/feature_flags/development/ci_trace_new_fog_store.yml
deleted file mode 100644
index b7da65be57b..00000000000
--- a/config/feature_flags/development/ci_trace_new_fog_store.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_trace_new_fog_store
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46209
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/273405
-milestone: '13.6'
-type: development
-group: group::testing
-default_enabled: true
diff --git a/doc/api/boards.md b/doc/api/boards.md
index fca22596c58..228c0ca322b 100644
--- a/doc/api/boards.md
+++ b/doc/api/boards.md
@@ -33,6 +33,7 @@ Example response:
[
{
"id" : 1,
+ "name": "board1",
"project": {
"id": 5,
"name": "Diaspora Project Site",
diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md
index 5bb4ae569fb..a63c2830909 100644
--- a/doc/subscriptions/self_managed/index.md
+++ b/doc/subscriptions/self_managed/index.md
@@ -52,8 +52,23 @@ and blocked, go to **Admin Area > Overview > Dashboard** and select **Users stat
in the **Users** section. For more details, see
[Users statistics](../../user/admin_area/index.md#users-statistics).
-NOTE: **Note:**
-If you have LDAP integration enabled, anyone in the configured domain can sign up for a GitLab account. This can result in an unexpected bill at time of renewal. Consider [disabling new signups](../../user/admin_area/settings/sign_up_restrictions.md) and managing new users manually instead.
+### Tips for managing users and subscription seats
+
+Managing the number of users against the number of subscription seats can be a challenge:
+
+- If LDAP integration is enabled, anyone in the configured domain can sign up for a GitLab account.
+ This can result in an unexpected bill at time of renewal.
+- If sign-up is enabled on your instance, anyone who can access the instance can sign up for an
+ account.
+
+GitLab has several features which can help you manage the number of users:
+
+- Enable the [**Require administrator approval for new sign ups**](../../user/admin_area/settings/sign_up_restrictions.md#require-administrator-approval-for-new-sign-ups)
+ option.
+- Enable the [User cap](../../user/admin_area/settings/sign_up_restrictions.md#user-cap)
+ option. **Available in GitLab 13.6 and later**.
+- [Disable new sign-ups](../../user/admin_area/settings/sign_up_restrictions.md), and instead manage new
+ users manually.
## Obtain a subscription
diff --git a/doc/user/admin_area/settings/sign_up_restrictions.md b/doc/user/admin_area/settings/sign_up_restrictions.md
index 39056ed804a..7bf05f00552 100644
--- a/doc/user/admin_area/settings/sign_up_restrictions.md
+++ b/doc/user/admin_area/settings/sign_up_restrictions.md
@@ -46,6 +46,14 @@ To enforce confirmation of the email address used for new sign ups:
1. Go to **Admin Area > Settings > General** and expand **Sign-up restrictions**.
1. Select the **Enable email restrictions for sign ups** checkbox, then select **Save changes**.
+## User cap **(CORE ONLY)**
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4315) in GitLab 13.6.
+
+When the number of users reaches the user cap, any user who is added or requests access must be
+[approved](../approving_users.md#approving-a-user) by an administrator before they can start using
+their account.
+
## Soft email confirmation
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47003) in GitLab 12.2.
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 6a973a7647f..5537412f1b8 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -543,6 +543,12 @@ msgstr ""
msgid "%{issuesSize} with a limit of %{maxIssueCount}"
msgstr ""
+msgid "%{labelStart}Actual response:%{labelEnd} %{headers}"
+msgstr ""
+
+msgid "%{labelStart}Assert:%{labelEnd} %{assertion}"
+msgstr ""
+
msgid "%{labelStart}Class:%{labelEnd} %{class}"
msgstr ""
@@ -558,9 +564,6 @@ msgstr ""
msgid "%{labelStart}File:%{labelEnd} %{file}"
msgstr ""
-msgid "%{labelStart}Headers:%{labelEnd} %{headers}"
-msgstr ""
-
msgid "%{labelStart}Image:%{labelEnd} %{image}"
msgstr ""
@@ -576,13 +579,13 @@ msgstr ""
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr ""
-msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
+msgid "%{labelStart}Sent request:%{labelEnd} %{headers}"
msgstr ""
-msgid "%{labelStart}Status:%{labelEnd} %{status}"
+msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
msgstr ""
-msgid "%{labelStart}URL:%{labelEnd} %{url}"
+msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
msgstr ""
msgid "%{label_for_message} unavailable"
@@ -9457,9 +9460,33 @@ msgstr ""
msgid "DevopsAdoption|Add new segment"
msgstr ""
+msgid "DevopsAdoption|Approvals"
+msgstr ""
+
+msgid "DevopsAdoption|Deploys"
+msgstr ""
+
msgid "DevopsAdoption|DevOps adoption uses segments to track adoption across key features. Segments are a way to track multiple related projects and groups at once. For example, you could create a segment for the engineering department or a particular product team."
msgstr ""
+msgid "DevopsAdoption|Issues"
+msgstr ""
+
+msgid "DevopsAdoption|MRs"
+msgstr ""
+
+msgid "DevopsAdoption|Pipelines"
+msgstr ""
+
+msgid "DevopsAdoption|Runners"
+msgstr ""
+
+msgid "DevopsAdoption|Scanning"
+msgstr ""
+
+msgid "DevopsAdoption|Segment"
+msgstr ""
+
msgid "DevopsReport|Adoption"
msgstr ""
@@ -11950,9 +11977,6 @@ msgstr ""
msgid "First name"
msgstr ""
-msgid "First name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "First seen"
msgstr ""
@@ -15697,9 +15721,6 @@ msgstr ""
msgid "Last name"
msgstr ""
-msgid "Last name is too long (maximum is %{max_length} characters)."
-msgstr ""
-
msgid "Last reply by"
msgstr ""
@@ -17572,12 +17593,6 @@ msgstr ""
msgid "Minimum interval in days"
msgstr ""
-msgid "Minimum length is %{minimum_password_length} characters"
-msgstr ""
-
-msgid "Minimum length is %{minimum_password_length} characters."
-msgstr ""
-
msgid "Minimum password length (number of characters)"
msgstr ""
@@ -22414,9 +22429,6 @@ msgstr ""
msgid "Remediations"
msgstr ""
-msgid "Remember me"
-msgstr ""
-
msgid "Remind later"
msgstr ""
@@ -24984,10 +24996,13 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
-msgid "SignUp|First Name is too long (maximum is %{max_length} characters)."
+msgid "SignUp|First name is too long (maximum is %{max_length} characters)."
msgstr ""
-msgid "SignUp|Last Name is too long (maximum is %{max_length} characters)."
+msgid "SignUp|Last name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Minimum length is %{minimum_password_length} characters."
msgstr ""
msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
@@ -30051,6 +30066,12 @@ msgstr ""
msgid "Vulnerability|Activity"
msgstr ""
+msgid "Vulnerability|Actual received response is the one received when this fault was detected"
+msgstr ""
+
+msgid "Vulnerability|Additional Info"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
@@ -30099,10 +30120,7 @@ msgstr ""
msgid "Vulnerability|Project"
msgstr ""
-msgid "Vulnerability|Request"
-msgstr ""
-
-msgid "Vulnerability|Response"
+msgid "Vulnerability|Request/Response"
msgstr ""
msgid "Vulnerability|Scanner"
@@ -30117,6 +30135,9 @@ msgstr ""
msgid "Vulnerability|Status"
msgstr ""
+msgid "Vulnerability|The unmodified response is the original response that had no mutations done to the request"
+msgstr ""
+
msgid "Wait for the file to load to copy its contents"
msgstr ""
@@ -31627,6 +31648,9 @@ msgstr ""
msgid "ciReport|: Loading resulted in an error"
msgstr ""
+msgid "ciReport|API Fuzzing"
+msgstr ""
+
msgid "ciReport|All projects"
msgstr ""
diff --git a/package.json b/package.json
index f9a0c721f12..c8ade903791 100644
--- a/package.json
+++ b/package.json
@@ -44,7 +44,7 @@
"@babel/preset-env": "^7.10.1",
"@gitlab/at.js": "1.5.5",
"@gitlab/svgs": "1.175.0",
- "@gitlab/ui": "23.6.1",
+ "@gitlab/ui": "23.8.0",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "^6.0.3-3",
"@rails/ujs": "^6.0.3-2",
diff --git a/spec/frontend/issuable_list/components/issuable_item_spec.js b/spec/frontend/issuable_list/components/issuable_item_spec.js
index 27c3a746090..3a9a0d3fd59 100644
--- a/spec/frontend/issuable_list/components/issuable_item_spec.js
+++ b/spec/frontend/issuable_list/components/issuable_item_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlLink, GlLabel, GlFormCheckbox } from '@gitlab/ui';
+import { GlLink, GlLabel, GlIcon, GlFormCheckbox } from '@gitlab/ui';
import IssuableItem from '~/issuable_list/components/issuable_item.vue';
import IssuableAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
@@ -12,6 +12,7 @@ const createComponent = ({ issuableSymbol = '#', issuable = mockIssuable, slots
issuableSymbol,
issuable,
enableLabelPermalinks: true,
+ showDiscussions: true,
showCheckbox: false,
},
slots,
@@ -142,6 +143,31 @@ describe('IssuableItem', () => {
expect(wrapper.vm.updatedAt).toContain('ago');
});
});
+
+ describe('showDiscussions', () => {
+ it.each`
+ userDiscussionsCount | returnValue
+ ${0} | ${true}
+ ${1} | ${true}
+ ${undefined} | ${false}
+ ${null} | ${false}
+ `(
+ 'returns $returnValue when issuable.userDiscussionsCount is $userDiscussionsCount',
+ ({ userDiscussionsCount, returnValue }) => {
+ const wrapperWithDiscussions = createComponent({
+ issuableSymbol: '#',
+ issuable: {
+ ...mockIssuable,
+ userDiscussionsCount,
+ },
+ });
+
+ expect(wrapperWithDiscussions.vm.showDiscussions).toBe(returnValue);
+
+ wrapperWithDiscussions.destroy();
+ },
+ );
+ });
});
describe('methods', () => {
@@ -299,6 +325,24 @@ describe('IssuableItem', () => {
wrapperWithAuthorSlot.destroy();
});
+ it('renders timeframe via slot', () => {
+ const wrapperWithTimeframeSlot = createComponent({
+ issuableSymbol: '#',
+ issuable: mockIssuable,
+ slots: {
+ timeframe: `
+ <b class="js-timeframe">Jan 1, 2020 - Mar 31, 2020</b>
+ `,
+ },
+ });
+ const timeframeEl = wrapperWithTimeframeSlot.find('.js-timeframe');
+
+ expect(timeframeEl.exists()).toBe(true);
+ expect(timeframeEl.text()).toBe('Jan 1, 2020 - Mar 31, 2020');
+
+ wrapperWithTimeframeSlot.destroy();
+ });
+
it('renders gl-label component for each label present within `issuable` prop', () => {
const labelsEl = wrapper.findAll(GlLabel);
@@ -332,6 +376,18 @@ describe('IssuableItem', () => {
wrapperWithStatusSlot.destroy();
});
+ it('renders discussions count', () => {
+ const discussionsEl = wrapper.find('[data-testid="issuable-discussions"]');
+
+ expect(discussionsEl.exists()).toBe(true);
+ expect(discussionsEl.find(GlLink).attributes()).toMatchObject({
+ title: 'Comments',
+ href: `${mockIssuable.webUrl}#notes`,
+ });
+ expect(discussionsEl.find(GlIcon).props('name')).toBe('comments');
+ expect(discussionsEl.find(GlLink).text()).toContain('2');
+ });
+
it('renders issuable-assignees component', () => {
const assigneesEl = wrapper.find(IssuableAssignees);
diff --git a/spec/frontend/issuable_list/mock_data.js b/spec/frontend/issuable_list/mock_data.js
index b18e49e2102..e19a337473a 100644
--- a/spec/frontend/issuable_list/mock_data.js
+++ b/spec/frontend/issuable_list/mock_data.js
@@ -52,6 +52,7 @@ export const mockIssuable = {
nodes: mockLabels,
},
assignees: [mockAuthor],
+ userDiscussionsCount: 2,
};
export const mockIssuables = [
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
index 72840ce381f..3fd1d8b7f42 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
@@ -45,6 +45,7 @@ function createComponent(options = {}) {
provide: {
portalName: 'fake target',
alignSuggestions: function fakeAlignSuggestions() {},
+ suggestionsListClass: 'custom-class',
},
stubs,
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js
index 12b7fd58670..5b7f7d242e9 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js
@@ -45,6 +45,7 @@ function createComponent(options = {}) {
provide: {
portalName: 'fake target',
alignSuggestions: function fakeAlignSuggestions() {},
+ suggestionsListClass: 'custom-class',
},
stubs,
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js
index 3feb05bab35..74172db81c2 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js
@@ -50,6 +50,7 @@ function createComponent(options = {}) {
provide: {
portalName: 'fake target',
alignSuggestions: function fakeAlignSuggestions() {},
+ suggestionsListClass: 'custom-class',
},
stubs,
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js
index 5d91eafbabf..67f9a9c70cc 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js
@@ -48,6 +48,7 @@ function createComponent(options = {}) {
provide: {
portalName: 'fake target',
alignSuggestions: function fakeAlignSuggestions() {},
+ suggestionsListClass: 'custom-class',
},
stubs,
});
diff --git a/spec/models/ci/build_trace_chunk_spec.rb b/spec/models/ci/build_trace_chunk_spec.rb
index 23f5a8d929e..dce7b1d30ca 100644
--- a/spec/models/ci/build_trace_chunk_spec.rb
+++ b/spec/models/ci/build_trace_chunk_spec.rb
@@ -135,30 +135,14 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
context 'when data_store is fog' do
let(:data_store) { :fog }
- context 'when legacy Fog is enabled' do
- before do
- stub_feature_flags(ci_trace_new_fog_store: false)
- build_trace_chunk.send(:unsafe_set_data!, +'Sample data in fog')
- end
-
- it { is_expected.to eq('Sample data in fog') }
-
- it 'returns a LegacyFog store' do
- expect(described_class.get_store_class(data_store)).to be_a(Ci::BuildTraceChunks::LegacyFog)
- end
+ before do
+ build_trace_chunk.send(:unsafe_set_data!, +'Sample data in fog')
end
- context 'when new Fog is enabled' do
- before do
- stub_feature_flags(ci_trace_new_fog_store: true)
- build_trace_chunk.send(:unsafe_set_data!, +'Sample data in fog')
- end
+ it { is_expected.to eq('Sample data in fog') }
- it { is_expected.to eq('Sample data in fog') }
-
- it 'returns a new Fog store' do
- expect(described_class.get_store_class(data_store)).to be_a(Ci::BuildTraceChunks::Fog)
- end
+ it 'returns a new Fog store' do
+ expect(described_class.get_store_class(data_store)).to be_a(Ci::BuildTraceChunks::Fog)
end
end
end
diff --git a/spec/models/ci/build_trace_chunks/legacy_fog_spec.rb b/spec/models/ci/build_trace_chunks/legacy_fog_spec.rb
deleted file mode 100644
index ca4b414b992..00000000000
--- a/spec/models/ci/build_trace_chunks/legacy_fog_spec.rb
+++ /dev/null
@@ -1,164 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Ci::BuildTraceChunks::LegacyFog do
- let(:data_store) { described_class.new }
-
- before do
- stub_artifacts_object_storage
- end
-
- describe '#available?' do
- subject { data_store.available? }
-
- context 'when object storage is enabled' do
- it { is_expected.to be_truthy }
- end
-
- context 'when object storage is disabled' do
- before do
- stub_artifacts_object_storage(enabled: false)
- end
-
- it { is_expected.to be_falsy }
- end
- end
-
- describe '#data' do
- subject { data_store.data(model) }
-
- context 'when data exists' do
- let(:model) { create(:ci_build_trace_chunk, :fog_with_data, initial_data: 'sample data in fog') }
-
- it 'returns the data' do
- is_expected.to eq('sample data in fog')
- end
- end
-
- context 'when data does not exist' do
- let(:model) { create(:ci_build_trace_chunk, :fog_without_data) }
-
- it 'returns nil' do
- expect(data_store.data(model)).to be_nil
- end
- end
- end
-
- describe '#set_data' do
- let(:new_data) { 'abc123' }
-
- context 'when data exists' do
- let(:model) { create(:ci_build_trace_chunk, :fog_with_data, initial_data: 'sample data in fog') }
-
- it 'overwrites data' do
- expect(data_store.data(model)).to eq('sample data in fog')
-
- data_store.set_data(model, new_data)
-
- expect(data_store.data(model)).to eq new_data
- end
- end
-
- context 'when data does not exist' do
- let(:model) { create(:ci_build_trace_chunk, :fog_without_data) }
-
- it 'sets new data' do
- expect(data_store.data(model)).to be_nil
-
- data_store.set_data(model, new_data)
-
- expect(data_store.data(model)).to eq new_data
- end
- end
- end
-
- describe '#delete_data' do
- subject { data_store.delete_data(model) }
-
- context 'when data exists' do
- let(:model) { create(:ci_build_trace_chunk, :fog_with_data, initial_data: 'sample data in fog') }
-
- it 'deletes data' do
- expect(data_store.data(model)).to eq('sample data in fog')
-
- subject
-
- expect(data_store.data(model)).to be_nil
- end
- end
-
- context 'when data does not exist' do
- let(:model) { create(:ci_build_trace_chunk, :fog_without_data) }
-
- it 'does nothing' do
- expect(data_store.data(model)).to be_nil
-
- subject
-
- expect(data_store.data(model)).to be_nil
- end
- end
- end
-
- describe '#size' do
- context 'when data exists' do
- let(:model) { create(:ci_build_trace_chunk, :fog_with_data, initial_data: 'üabcd') }
-
- it 'returns data bytesize correctly' do
- expect(data_store.size(model)).to eq 6
- end
- end
-
- context 'when data does not exist' do
- let(:model) { create(:ci_build_trace_chunk, :fog_without_data) }
-
- it 'returns zero' do
- expect(data_store.size(model)).to be_zero
- end
- end
- end
-
- describe '#keys' do
- subject { data_store.keys(relation) }
-
- let(:build) { create(:ci_build) }
- let(:relation) { build.trace_chunks }
-
- before do
- create(:ci_build_trace_chunk, :fog_with_data, chunk_index: 0, build: build)
- create(:ci_build_trace_chunk, :fog_with_data, chunk_index: 1, build: build)
- end
-
- it 'returns keys' do
- is_expected.to eq([[build.id, 0], [build.id, 1]])
- end
- end
-
- describe '#delete_keys' do
- subject { data_store.delete_keys(keys) }
-
- let(:build) { create(:ci_build) }
- let(:relation) { build.trace_chunks }
- let(:keys) { data_store.keys(relation) }
-
- before do
- create(:ci_build_trace_chunk, :fog_with_data, chunk_index: 0, build: build)
- create(:ci_build_trace_chunk, :fog_with_data, chunk_index: 1, build: build)
- end
-
- it 'deletes multiple data' do
- ::Fog::Storage.new(JobArtifactUploader.object_store_credentials).tap do |connection|
- expect(connection.get_object('artifacts', "tmp/builds/#{build.id}/chunks/0.log")[:body]).to be_present
- expect(connection.get_object('artifacts', "tmp/builds/#{build.id}/chunks/1.log")[:body]).to be_present
- end
-
- subject
-
- ::Fog::Storage.new(JobArtifactUploader.object_store_credentials).tap do |connection|
- expect { connection.get_object('artifacts', "tmp/builds/#{build.id}/chunks/0.log")[:body] }.to raise_error(Excon::Error::NotFound)
- expect { connection.get_object('artifacts', "tmp/builds/#{build.id}/chunks/1.log")[:body] }.to raise_error(Excon::Error::NotFound)
- end
- end
- end
-end
diff --git a/yarn.lock b/yarn.lock
index d3861c0d69b..a18b1f9beaf 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -866,10 +866,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.175.0.tgz#734f341784af1cd1d62d160a17bcdfb61ff7b04d"
integrity sha512-gXpc87TGSXIzfAr4QER1Qw1v3P47pBO6BXkma52blgwXVmcFNe3nhQzqsqt66wKNzrIrk3lAcB4GUyPHbPVXpg==
-"@gitlab/ui@23.6.1":
- version "23.6.1"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-23.6.1.tgz#3b94945166c756a26c9598501ebef0997a3961e7"
- integrity sha512-jOEhJUTQmdsV4XEHqY+ray+GHAMa35CsddPFtKjiD8y1YiJFzXES7tVqQr/hXzSAWbBWfxSO1Rvp55+UnCGz5g==
+"@gitlab/ui@23.8.0":
+ version "23.8.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-23.8.0.tgz#fe1807877c191e9e38b476d2cdfc4261facbb36b"
+ integrity sha512-5CF2jU/d5EX5a1qLHzJujYOTaCze1ZvE9ovK1TbhJ7Va1O0SKB/N53XT8iPOb4MwOzj/zBWDOdsIs+xXxCeOcg==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"