Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-08-24 21:09:59 +00:00
parent e9322e019b
commit 8a0ba60290
34 changed files with 76 additions and 252 deletions

View File

@ -44,8 +44,8 @@ const KNOWN_TYPES = [
];
export function isTextFile({ name, raw, binary, content, mimeType = '' }) {
// some file objects already have a `binary` property set on them. If true, return false
if (binary) return false;
// some file objects already have a `binary` property set on them. If so, use it first
if (typeof binary === 'boolean') return !binary;
const knownType = KNOWN_TYPES.find((type) => type.isMatch(mimeType, name));
if (knownType) return knownType.isText;

View File

@ -1,5 +1,4 @@
import initVariableList from '~/ci_variable_list';
import projectSelect from '~/project_select';
import initSearchSettings from '~/search_settings';
import selfMonitor from '~/self_monitor';
import initSettingsPanels from '~/settings_panels';
@ -8,5 +7,4 @@ initVariableList('js-instance-variables');
selfMonitor();
// Initialize expandable settings panels
initSettingsPanels();
projectSelect();
initSearchSettings();

View File

@ -2,7 +2,6 @@ import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered
import initManualOrdering from '~/manual_ordering';
import { FILTERED_SEARCH } from '~/pages/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import projectSelect from '~/project_select';
initFilteredSearch({
page: FILTERED_SEARCH.ISSUES,
@ -10,5 +9,4 @@ initFilteredSearch({
useDefaultState: true,
});
projectSelect();
initManualOrdering();

View File

@ -2,7 +2,6 @@ import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
import { FILTERED_SEARCH } from '~/pages/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import projectSelect from '~/project_select';
addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys, true);
@ -11,5 +10,3 @@ initFilteredSearch({
filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
useDefaultState: true,
});
projectSelect();

View File

@ -1,3 +0,0 @@
import projectSelect from '~/project_select';
projectSelect();

View File

@ -4,7 +4,6 @@ import { mountIssuablesListApp } from '~/issues_list';
import initManualOrdering from '~/manual_ordering';
import { FILTERED_SEARCH } from '~/pages/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import projectSelect from '~/project_select';
const ISSUE_BULK_UPDATE_PREFIX = 'issue_';
@ -18,7 +17,6 @@ initFilteredSearch({
useDefaultState: true,
filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
});
projectSelect();
initManualOrdering();
if (gon.features?.vueIssuablesList) {

View File

@ -3,7 +3,6 @@ import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered
import issuableInitBulkUpdateSidebar from '~/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar';
import { FILTERED_SEARCH } from '~/pages/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import projectSelect from '~/project_select';
const ISSUABLE_BULK_UPDATE_PREFIX = 'merge_request_';
@ -16,4 +15,3 @@ initFilteredSearch({
useDefaultState: true,
filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
});
projectSelect();

View File

@ -160,39 +160,6 @@ module CacheMarkdownField
# We can only store mentions if the mentionable is a database object
return unless self.is_a?(ApplicationRecord)
return store_mentions_without_subtransaction! if Feature.enabled?(:store_mentions_without_subtransaction, default_enabled: :yaml)
refs = all_references(self.author)
references = {}
references[:mentioned_users_ids] = refs.mentioned_user_ids.presence
references[:mentioned_groups_ids] = refs.mentioned_group_ids.presence
references[:mentioned_projects_ids] = refs.mentioned_project_ids.presence
# One retry is enough as next time `model_user_mention` should return the existing mention record,
# that threw the `ActiveRecord::RecordNotUnique` exception in first place.
self.class.safe_ensure_unique(retries: 1) do # rubocop:disable Performance/ActiveRecordSubtransactionMethods
user_mention = model_user_mention
# this may happen due to notes polymorphism, so noteable_id may point to a record
# that no longer exists as we cannot have FK on noteable_id
break if user_mention.blank?
user_mention.mentioned_users_ids = references[:mentioned_users_ids]
user_mention.mentioned_groups_ids = references[:mentioned_groups_ids]
user_mention.mentioned_projects_ids = references[:mentioned_projects_ids]
if user_mention.has_mentions?
user_mention.save!
else
user_mention.destroy!
end
end
true
end
def store_mentions_without_subtransaction!
identifier = user_mention_identifier
# this may happen due to notes polymorphism, so noteable_id may point to a record

View File

@ -217,17 +217,6 @@ module Mentionable
def user_mention_association
association(:user_mentions).reflection
end
# User mention that is parsed from model description rather then its related notes.
# Models that have a description attribute like Issue, MergeRequest, Epic, Snippet may have such a user mention.
# Other mentionable models like Commit, DesignManagement::Design, will never have such record as those do not have
# a description attribute.
#
# Using this method followed by a call to *save* may result in *ActiveRecord::RecordNotUnique* exception
# in a multi-threaded environment. Make sure to use it within a *safe_ensure_unique* block.
def model_user_mention
user_mentions.where(note_id: nil).first_or_initialize
end
end
Mentionable.prepend_mod_with('Mentionable')

View File

@ -606,14 +606,6 @@ class Note < ApplicationRecord
private
# Using this method followed by a call to *save* may result in *ActiveRecord::RecordNotUnique* exception
# in a multi-threaded environment. Make sure to use it within a *safe_ensure_unique* block.
def model_user_mention
return if user_mentions.is_a?(ActiveRecord::NullRelation)
user_mentions.first_or_initialize
end
def system_note_viewable_by?(user)
return true unless system_note_metadata

View File

@ -9,10 +9,6 @@
.page-title-holder.d-flex.align-items-center
%h1.page-title= _('Issues')
- if current_user
.page-title-controls
= render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues', type: :issues
.top-area
= render 'shared/issuable/nav', type: :issues, display_count: !@no_filters_set
.nav-controls

View File

@ -7,10 +7,6 @@
.page-title-holder.d-flex.align-items-start.flex-column.flex-sm-row.align-items-sm-center
%h1.page-title= _('Merge requests')
- if current_user
.page-title-controls.ml-0.mb-3.ml-sm-auto.mb-sm-0
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests', type: :merge_requests
.top-area
= render 'shared/issuable/nav', type: :merge_requests, display_count: !@no_filters_set

View File

@ -6,12 +6,6 @@
.page-title-holder.d-flex.align-items-center
%h1.page-title= _('Milestones')
- if current_user
.page-title-controls
= render 'shared/new_project_item_select',
path: '-/milestones/new', label: 'New milestone',
include_groups: true, type: :milestones
.top-area
= render 'shared/milestones_filter', counts: @milestone_states
.nav-controls

View File

@ -13,8 +13,6 @@
- if @can_bulk_update
= render_if_exists 'shared/issuable/bulk_update_button', type: :issues
= render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", type: :issues, with_feature_enabled: 'issues', with_shared: false, include_projects_in_subgroups: true
= render 'shared/issuable/search_bar', type: :issues
- if @can_bulk_update

View File

@ -12,8 +12,6 @@
- if @can_bulk_update
= render_if_exists 'shared/issuable/bulk_update_button', type: :merge_requests
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", type: :merge_requests, with_feature_enabled: 'merge_requests', with_shared: false, include_projects_in_subgroups: true
= render 'shared/issuable/search_bar', type: :merge_requests
- if @can_bulk_update

View File

@ -1,7 +1,7 @@
- form = local_assigns.fetch(:form)
.form-group
= form.label :notification_email, class: "label-bold"
= form.select :notification_email, @user.public_verified_emails, { include_blank: false }, class: "select2", disabled: local_assigns.fetch(:email_change_disabled, nil)
= form.select :notification_email, @user.public_verified_emails, { include_blank: _('Use primary email (%{email})') % { email: @user.email }, selected: @user.read_attribute(:notification_email) }, class: "select2", disabled: local_assigns.fetch(:email_change_disabled, nil)
.help-block
= local_assigns.fetch(:help_text, nil)
.form-group

View File

@ -1,8 +0,0 @@
---
name: store_mentions_without_subtransaction
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68433
rollout_issue_url:
milestone: '14.3'
type: development
group: group::project management
default_enabled: false

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
class RemoveSeatLinkEnabledFromApplicationSettings < ActiveRecord::Migration[6.1]
def up
remove_column :application_settings, :seat_link_enabled
end
def down
add_column :application_settings, :seat_link_enabled, :boolean, null: false, default: true
end
end

View File

@ -0,0 +1 @@
483ef6f8ef379f39ecff32853c777c12c59d2858f061879c375ff6d429396167

View File

@ -9542,7 +9542,6 @@ CREATE TABLE application_settings (
email_restrictions_enabled boolean DEFAULT false NOT NULL,
email_restrictions text,
npm_package_requests_forwarding boolean DEFAULT true NOT NULL,
seat_link_enabled boolean DEFAULT true NOT NULL,
container_expiration_policies_enable_historic_entries boolean DEFAULT false NOT NULL,
issues_create_limit integer DEFAULT 0 NOT NULL,
push_rule_id bigint,

View File

@ -25,6 +25,12 @@ If you just want to delete everything and start over with an empty DB (approxima
bundle exec rake db:reset RAILS_ENV=development
```
If you want to seed the empty DB with sample data (approximately 4 minutes):
```shell
bundle exec rake dev:setup
```
If you just want to delete everything and start over with sample data (approximately 4 minutes). This
also does `db:reset` and runs DB-specific migrations:

View File

@ -70,6 +70,7 @@ Your **Global notification settings** are the default settings unless you select
different values for a project or a group.
- **Notification email**: the email address your notifications are sent to.
Defaults to your primary email address.
- **Receive product marketing emails**: select this checkbox to receive
[periodic emails](#product-marketing-emails) about GitLab features.
- **Global notification level**: the default [notification level](#notification-levels)

View File

@ -97,7 +97,9 @@ module Gitlab
def observe_queue_size(size_proc, runner_type)
return unless Feature.enabled?(:gitlab_ci_builds_queuing_metrics, default_enabled: false)
self.class.queue_size_total.observe({ runner_type: runner_type }, size_proc.call.to_f)
size = size_proc.call.to_f
self.class.queue_size_total.observe({ runner_type: runner_type }, size)
self.class.current_queue_size.set({ runner_type: runner_type }, size)
end
def observe_queue_time(metric, runner_type)
@ -199,6 +201,15 @@ module Gitlab
end
end
def self.current_queue_size
strong_memoize(:current_queue_size) do
name = :gitlab_ci_current_queue_size
comment = 'Current size of initialized CI/CD builds queue'
Gitlab::Metrics.gauge(name, comment)
end
end
def self.queue_iteration_duration_seconds
strong_memoize(:queue_iteration_duration_seconds) do
name = :gitlab_ci_queue_iteration_duration_seconds

View File

@ -153,6 +153,10 @@ module Gitlab
method_visibility = method_visibility_for(target, name)
# We silence warnings to avoid such warnings:
# `Skipping set of ruby2_keywords flag for <...>
# (method accepts keywords or method does not accept argument splat)`
# as we apply ruby2_keywords 'blindly' for every instrumented method.
proxy_module.class_eval <<-EOF, __FILE__, __LINE__ + 1
def #{name}(#{args_signature})
if trans = Gitlab::Metrics::Instrumentation.transaction
@ -162,6 +166,7 @@ module Gitlab
super
end
end
silence_warnings { ruby2_keywords(:#{name}) if respond_to?(:ruby2_keywords, true) }
#{method_visibility} :#{name}
EOF

View File

@ -36265,6 +36265,9 @@ msgstr ""
msgid "Use one line per URI"
msgstr ""
msgid "Use primary email (%{email})"
msgstr ""
msgid "Use shortcuts"
msgstr ""

View File

@ -46,38 +46,4 @@ RSpec.describe 'Dashboard Issues' do
it_behaves_like "it has an RSS button with current_user's feed token"
it_behaves_like "an autodiscoverable RSS feed with current_user's feed token"
end
describe 'new issue dropdown' do
it 'shows projects only with issues feature enabled', :js do
find('.new-project-item-select-button').click
page.within('.select2-results') do
expect(page).to have_content(project.full_name)
expect(page).not_to have_content(project_with_issues_disabled.full_name)
end
end
it 'shows the new issue page', :js do
find('.new-project-item-select-button').click
wait_for_requests
project_path = "/#{project.full_path}"
project_json = { name: project.full_name, url: project_path }.to_json
# simulate selection, and prevent overlap by dropdown menu
first('.project-item-select', visible: false)
execute_script("$('.project-item-select').val('#{project_json}').trigger('change');")
find('#select2-drop-mask', visible: false)
execute_script("$('#select2-drop-mask').remove();")
find('.new-project-item-link').click
expect(page).to have_current_path("#{project_path}/-/issues/new")
page.within('#content-body') do
expect(page).to have_selector('.issue-form')
end
end
end
end

View File

@ -25,24 +25,6 @@ RSpec.describe 'Dashboard Merge Requests' do
expect(page).not_to have_selector('#js-dropdown-target-branch', visible: false)
end
context 'new merge request dropdown' do
let(:project_with_disabled_merge_requests) { create(:project, :merge_requests_disabled) }
before do
project_with_disabled_merge_requests.add_maintainer(current_user)
visit merge_requests_dashboard_path
end
it 'shows projects only with merge requests feature enabled', :js do
find('.new-project-item-select-button').click
page.within('.select2-results') do
expect(page).to have_content(project.full_name)
expect(page).not_to have_content(project_with_disabled_merge_requests.full_name)
end
end
end
context 'no merge requests exist' do
it 'shows an empty state' do
visit merge_requests_dashboard_path(assignee_username: current_user.username)

View File

@ -32,20 +32,6 @@ RSpec.describe 'Dashboard > Milestones' do
expect(page).to have_content(group.name)
expect(first('.milestone')).to have_content('Merge requests')
end
describe 'new milestones dropdown', :js do
it 'takes user to a new milestone page', :js do
find('.new-project-item-select-button').click
page.within('.select2-results') do
first('.select2-result-label').click
end
find('.new-project-item-link').click
expect(current_path).to eq(new_group_milestone_path(group))
end
end
end
describe 'with merge requests disabled' do

View File

@ -92,20 +92,6 @@ RSpec.describe 'Group empty states' do
it 'displays an empty state' do
expect(page).to have_selector('.empty-state')
end
it "shows a new #{issuable_name} button" do
within '.empty-state' do
expect(page).to have_content("create #{issuable_name}")
end
end
it "the new #{issuable_name} button opens a project dropdown" do
within '.empty-state' do
find('.new-project-item-select-button').click
end
expect(page).to have_selector('.ajax-project-dropdown')
end
end
end

View File

@ -96,28 +96,6 @@ RSpec.describe 'Group issues page' do
end
end
context 'projects with issues disabled' do
describe 'issue dropdown' do
let(:user_in_group) { create(:group_member, :maintainer, user: create(:user), group: group ).user }
before do
[project, project_with_issues_disabled].each { |project| project.add_maintainer(user_in_group) }
sign_in(user_in_group)
visit issues_group_path(group)
end
it 'shows projects only with issues feature enabled', :js do
find('.empty-state .js-lazy-loaded')
find('.empty-state .new-project-item-link').click
page.within('.select2-results') do
expect(page).to have_content(project.full_name)
expect(page).not_to have_content(project_with_issues_disabled.full_name)
end
end
end
end
context 'manual ordering', :js do
let(:user_in_group) { create(:group_member, :maintainer, user: create(:user), group: group ).user }

View File

@ -59,23 +59,6 @@ RSpec.describe 'Group merge requests page' do
end
end
describe 'new merge request dropdown' do
let(:project_with_merge_requests_disabled) { create(:project, :merge_requests_disabled, group: group) }
before do
visit path
end
it 'shows projects only with merge requests feature enabled', :js do
find('.new-project-item-link').click
page.within('.select2-results') do
expect(page).to have_content(project.name_with_namespace)
expect(page).not_to have_content(project_with_merge_requests_disabled.name_with_namespace)
end
end
end
context 'empty state with no merge requests' do
before do
MergeRequest.delete_all
@ -85,7 +68,6 @@ RSpec.describe 'Group merge requests page' do
visit path
expect(page).to have_selector('.empty-state')
expect(page).to have_link('Select project to create merge request')
expect(page).not_to have_selector('.issues-filters')
end
@ -95,7 +77,6 @@ RSpec.describe 'Group merge requests page' do
visit path
expect(page).to have_selector('.empty-state')
expect(page).to have_link('Select project to create merge request')
expect(page).to have_selector('.issues-filters')
end
end

View File

@ -90,6 +90,9 @@ describe('WebIDE utils', () => {
it('returns true if there is a `binary` property already set on the file object', () => {
expect(isTextFile({ name: 'abc.txt', content: '' })).toBe(true);
expect(isTextFile({ name: 'abc.txt', content: '', binary: true })).toBe(false);
expect(isTextFile({ name: 'abc.tex', content: 'éêė' })).toBe(false);
expect(isTextFile({ name: 'abc.tex', content: 'éêė', binary: false })).toBe(true);
});
});

View File

@ -207,7 +207,7 @@ RSpec.shared_examples 'an editable mentionable' do
end
RSpec.shared_examples 'mentions in description' do |mentionable_type|
shared_examples 'when storing user mentions' do
context 'when storing user mentions' do
before do
mentionable.store_mentions!
end
@ -238,26 +238,10 @@ RSpec.shared_examples 'mentions in description' do |mentionable_type|
end
end
end
context 'when store_mentions_without_subtransaction is enabled' do
before do
stub_feature_flags(store_mentions_without_subtransaction: true)
end
it_behaves_like 'when storing user mentions'
end
context 'when store_mentions_without_subtransaction is disabled' do
before do
stub_feature_flags(store_mentions_without_subtransaction: false)
end
it_behaves_like 'when storing user mentions'
end
end
RSpec.shared_examples 'mentions in notes' do |mentionable_type|
shared_examples 'when mentionable notes contain mentions' do
context 'when mentionable notes contain mentions' do
let(:user) { create(:user) }
let(:user2) { create(:user) }
let(:group) { create(:group) }
@ -277,22 +261,6 @@ RSpec.shared_examples 'mentions in notes' do |mentionable_type|
expect(mentionable.referenced_groups(user)).to eq [group]
end
end
context 'when store_mentions_without_subtransaction is enabled' do
before do
stub_feature_flags(store_mentions_without_subtransaction: true)
end
it_behaves_like 'when mentionable notes contain mentions'
end
context 'when store_mentions_without_subtransaction is disabled' do
before do
stub_feature_flags(store_mentions_without_subtransaction: false)
end
it_behaves_like 'when mentionable notes contain mentions'
end
end
RSpec.shared_examples 'load mentions from DB' do |mentionable_type|

View File

@ -0,0 +1,29 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'profiles/notifications/show' do
let(:groups) { GroupsFinder.new(user).execute.page(1) }
let(:user) { create(:user) }
before do
assign(:group_notifications, [])
assign(:project_notifications, [])
assign(:user, user)
assign(:user_groups, groups)
allow(controller).to receive(:current_user).and_return(user)
allow(view).to receive(:experiment_enabled?)
end
context 'when there is no database value for User#notification_email' do
let(:option_default) { _('Use primary email (%{email})') % { email: user.email } }
let(:option_primary_email) { user.email }
let(:options) { [option_default, option_primary_email] }
it 'displays the correct elements' do
render
expect(rendered).to have_select('user_notification_email', options: options, selected: nil)
end
end
end