Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-08-16 15:10:05 +00:00
parent 09dff3eec7
commit d872c89ce4
36 changed files with 226 additions and 113 deletions

View File

@ -490,7 +490,7 @@ gem 'flipper', '~> 0.21.0'
gem 'flipper-active_record', '~> 0.21.0'
gem 'flipper-active_support_cache_store', '~> 0.21.0'
gem 'unleash', '~> 3.2.2'
gem 'gitlab-experiment', '~> 0.6.3'
gem 'gitlab-experiment', '~> 0.6.4'
# Structured logging
gem 'lograge', '~> 0.5'

View File

@ -464,7 +464,7 @@ GEM
gitlab-dangerfiles (2.3.0)
danger (>= 8.3.1)
danger-gitlab (>= 8.0.0)
gitlab-experiment (0.6.3)
gitlab-experiment (0.6.4)
activesupport (>= 3.0)
request_store (>= 1.0)
scientist (~> 1.6, >= 1.6.0)
@ -1475,7 +1475,7 @@ DEPENDENCIES
github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5)
gitlab-dangerfiles (~> 2.3.0)
gitlab-experiment (~> 0.6.3)
gitlab-experiment (~> 0.6.4)
gitlab-fog-azure-rm (~> 1.1.1)
gitlab-labkit (~> 0.21.0)
gitlab-license (~> 2.0)

View File

@ -205,7 +205,7 @@ export default {
>{{ issuableSymbol }}{{ issuable.iid }}</span
>
<span class="issuable-authored gl-display-none gl-sm-display-inline-block! gl-mr-3">
&middot;
<span aria-hidden="true">&middot;</span>
<span
v-gl-tooltip:tooltipcontainer.bottom
data-testid="issuable-created-at"
@ -229,17 +229,19 @@ export default {
</span>
<slot name="timeframe"></slot>
&nbsp;
<gl-label
v-for="(label, index) in labels"
:key="index"
:background-color="label.color"
:title="labelTitle(label)"
:description="label.description"
:scoped="scopedLabel(label)"
:target="labelTarget(label)"
:class="{ 'gl-ml-2': index }"
size="sm"
/>
<span v-if="labels.length" role="group" :aria-label="__('Labels')">
<gl-label
v-for="(label, index) in labels"
:key="index"
:background-color="label.color"
:title="labelTitle(label)"
:description="label.description"
:scoped="scopedLabel(label)"
:target="labelTarget(label)"
:class="{ 'gl-ml-2': index }"
size="sm"
/>
</span>
</div>
</div>
<div class="issuable-meta">

View File

@ -9,6 +9,7 @@ import {
GlTooltipDirective,
} from '@gitlab/ui';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
import { cloneDeep } from 'lodash';
import getIssuesQuery from 'ee_else_ce/issues_list/queries/get_issues.query.graphql';
import createFlash from '~/flash';
import { TYPE_USER } from '~/graphql_shared/constants';
@ -163,14 +164,17 @@ export default {
},
},
data() {
const filterTokens = getFilterTokens(window.location.search);
const state = getParameterByName(PARAM_STATE);
const sortKey = getSortKey(getParameterByName(PARAM_SORT));
const defaultSortKey = state === IssuableStates.Closed ? UPDATED_DESC : CREATED_DESC;
this.initialFilterTokens = cloneDeep(filterTokens);
return {
dueDateFilter: getDueDateValue(getParameterByName(PARAM_DUE_DATE)),
exportCsvPathWithQuery: this.getExportCsvPathWithQuery(),
filterTokens: getFilterTokens(window.location.search),
filterTokens,
issues: [],
pageInfo: {},
pageParams: getInitialPageParams(sortKey),
@ -609,7 +613,7 @@ export default {
recent-searches-storage-key="issues"
:search-input-placeholder="$options.i18n.searchPlaceholder"
:search-tokens="searchTokens"
:initial-filter-value="filterTokens"
:initial-filter-value="initialFilterTokens"
:sort-options="sortOptions"
:initial-sort-by="sortKey"
:issuables="issues"

View File

@ -99,7 +99,7 @@ export default {
// We don't have any information about selected token except for its
// group path and iid joined by separator, so we need to manually
// compose epic path from it.
if (data.includes(this.$options.separator)) {
if (data.includes?.(this.$options.separator)) {
const [groupPath, epicIid] = data.split(this.$options.separator);
epicPath = `/groups/${groupPath}/-/epics/${epicIid}`;
}

View File

@ -18,7 +18,7 @@ module SpammableActions::CaptchaCheck::HtmlFormatActionsSupport
private
def with_captcha_check_html_format(&block)
captcha_render_lambda = -> { render :verify }
captcha_render_lambda = -> { render :captcha_check }
with_captcha_check_common(captcha_render_lambda: captcha_render_lambda, &block)
end

View File

@ -207,7 +207,7 @@ module IssuesHelper
initial_email: project.new_issuable_address(current_user, 'issue'),
is_signed_in: current_user.present?.to_s,
issues_path: project_issues_path(project),
jira_integration_path: help_page_url('integration/jira/', anchor: 'view-jira-issues'),
jira_integration_path: help_page_url('integration/jira/issues', anchor: 'view-jira-issues'),
markdown_help_path: help_page_path('user/markdown'),
max_attachment_size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes),
new_issue_path: new_project_issue_path(project, issue: { milestone_id: finder.milestones.first.try(:id) }),

View File

@ -57,6 +57,10 @@ module Ci
false
end
def use_denormalized_minutes_data?
false
end
private
def running_builds_for_shared_runners

View File

@ -40,6 +40,10 @@ module Ci
::Feature.enabled?(:ci_queueing_denormalize_shared_runners_information, runner, type: :development, default_enabled: :yaml)
end
def use_denormalized_minutes_data?
::Feature.enabled?(:ci_queueing_denormalize_ci_minutes_information, runner, type: :development, default_enabled: :yaml)
end
private
def builds_available_for_shared_runners
@ -83,3 +87,5 @@ module Ci
end
end
end
Ci::Queue::PendingBuildsStrategy.prepend_mod_with('Ci::Queue::PendingBuildsStrategy')

View File

@ -1,10 +0,0 @@
- humanized_resource_name = spammable.class.model_name.human.downcase
%h3.page-title
= _('Anti-spam verification')
%hr
%p
= _("We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed.") % { humanized_resource_name: humanized_resource_name }
= render 'shared/recaptcha_form', spammable: spammable

View File

@ -0,0 +1,7 @@
= render layout: 'shared/captcha_check', locals: { spammable: @issue } do
-# These fields are for values which are passed via URL parameters, and not included in the
-# issue's params, so they must be yielded to the block to be rendered.
-# If these are removed and no longer passed via URL parameters, the support
-# for yielding in the layout can also be removed.
= hidden_field_tag(:merge_request_to_resolve_discussions_of, params[:merge_request_to_resolve_discussions_of])
= hidden_field_tag(:discussion_to_resolve, params[:discussion_to_resolve])

View File

@ -1,3 +0,0 @@
= render layout: 'layouts/recaptcha_verification', locals: { spammable: @issue } do
= hidden_field_tag(:merge_request_to_resolve_discussions_of, params[:merge_request_to_resolve_discussions_of])
= hidden_field_tag(:discussion_to_resolve, params[:discussion_to_resolve])

View File

@ -0,0 +1,37 @@
- resource_name = spammable.class.model_name.singular
- humanized_resource_name = spammable.class.model_name.human.downcase
- script = local_assigns.fetch(:script, true)
- method = params[:action] == 'create' ? :post : :put
%h3.page-title
= _('Anti-spam verification')
%hr
%p
= _("We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed.") % { humanized_resource_name: humanized_resource_name }
= form_for resource_name, method: method, html: { class: 'recaptcha-form js-recaptcha-form' } do |f|
.recaptcha
-# Create a hidden field for each param of the resource
- params[resource_name].each do |field, value|
= hidden_field(resource_name, field, value: value)
-# The reCAPTCHA response value will be returned in the 'g-recaptcha-response' field in non-test environments
= recaptcha_tags script: script, callback: 'recaptchaDialogCallback', nonce: content_security_policy_nonce unless Rails.env.test?
-# Fake the 'g-recaptcha-response' field in the test environment, so that the feature spec
-# can get to the (mocked) SpamVerdictService check.
= hidden_field_tag('g-recaptcha-response', 'abc123') if Rails.env.test?
-# Create a hidden field to pass back the ID of the spam_log record which was previously created
= hidden_field_tag(:spam_log_id, spammable.spam_log.id)
-# Yields a block with given extra params which are not included in `params[resource_name]`.
-# Currently, this is only used for these params which are passed via URL parameters,
-# and can be removed once they are no longer needed to be passed:
-# - merge_request_to_resolve_discussions_of
-# - discussion_to_resolve
= yield
.row-content-block.footer-block
= f.submit _("Create %{humanized_resource_name}") % { humanized_resource_name: humanized_resource_name }, class: 'gl-button btn btn-confirm'

View File

@ -1,23 +0,0 @@
- resource_name = spammable.class.model_name.singular
- humanized_resource_name = spammable.class.model_name.human.downcase
- script = local_assigns.fetch(:script, true)
- method = params[:action] == 'create' ? :post : :put
- has_submit = local_assigns.fetch(:has_submit, true)
= form_for resource_name, method: method, html: { class: 'recaptcha-form js-recaptcha-form' } do |f|
.recaptcha
- params[resource_name].each do |field, value|
= hidden_field(resource_name, field, value: value)
= hidden_field_tag(:spam_log_id, spammable.spam_log.id)
-# The reCAPTCHA response value will be returned in the 'g-recaptcha-response' field
= recaptcha_tags script: script, callback: 'recaptchaDialogCallback', nonce: content_security_policy_nonce unless Rails.env.test?
-# Fake the 'g-recaptcha-response' field in the test environment, so that the feature spec
-# can get to the (mocked) SpamVerdictService check.
= hidden_field_tag('g-recaptcha-response', 'abc123') if Rails.env.test?
-# Yields a block with given extra params.
= yield
- if has_submit
.row-content-block.footer-block
= f.submit _("Create %{humanized_resource_name}") % { humanized_resource_name: humanized_resource_name }, class: 'gl-button btn btn-confirm'

View File

@ -0,0 +1,8 @@
---
name: cache_shared_runners_enabled
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68002
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338267
milestone: '14.2'
type: development
group: group::optimize
default_enabled: false

View File

@ -0,0 +1,8 @@
---
name: ci_queueing_denormalize_ci_minutes_information
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66962
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338290
milestone: '14.2'
type: development
group: 'group::pipeline execution'
default_enabled: false

View File

@ -1,19 +1,20 @@
---
data_category: optional
key_path: usage_activity_by_stage_monthly.plan.service_desk_enabled_projects
description:
description: Count creator ids from projects with service desk enabled
product_section: dev
product_stage:
product_stage: plan
product_group: group::plan
product_category:
product_category: service_desk
value_type: number
status: data_available
time_frame: 28d
data_source:
data_source: database
distribution:
- ce
- ee
tier:
- free
skip_validation: true
- premium
- ultimate
performance_indicator_type: []

View File

@ -1,19 +1,20 @@
---
data_category: operational
key_path: usage_activity_by_stage_monthly.plan.service_desk_issues
description:
description: Count of service desk issues
product_section: dev
product_stage:
product_stage: plan
product_group: group::plan
product_category:
value_type: number
status: data_available
time_frame: 28d
data_source:
data_source: database
distribution:
- ce
- ee
tier:
- free
skip_validation: true
- premium
- ultimate
performance_indicator_type: []

View File

@ -1,18 +1,19 @@
---
data_category: optional
key_path: usage_activity_by_stage.plan.service_desk_enabled_projects
description:
description: Count creator ids from projects with service desk enabled
product_section: dev
product_stage:
product_stage: plan
product_group: group::plan
product_category:
product_category: service_desk
value_type: number
status: data_available
time_frame: all
data_source:
data_source: database
distribution:
- ce
- ee
tier:
- free
skip_validation: true
- premium
- ultimate

View File

@ -1,18 +1,19 @@
---
data_category: optional
key_path: usage_activity_by_stage.plan.service_desk_issues
description:
description: Count of service desk issues
product_section: dev
product_stage:
product_stage: plan
product_group: group::plan
product_category:
product_category: service_desk
value_type: number
status: data_available
time_frame: all
data_source:
data_source: database
distribution:
- ce
- ee
tier:
- free
skip_validation: true
- premium
- ultimate

View File

@ -238,9 +238,10 @@ The code for this resides in:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48512/diffs) in GitLab 13.7.
> - Number of imported objects [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64256) in GitLab 14.1.
> - `Gitlab::GithubImport::Logger` [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65968) in GitLab 14.2.
> - `import_source` [renamed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67726) to `import_type` in GitLab 14.2.
The import progress can be checked in the `logs/importer.log` file. Each relevant import is logged
with `"import_source": "github"` and the `"project_id"`.
with `"import_type": "github"` and the `"project_id"`.
The last log entry reports the number of objects fetched and imported:

View File

@ -128,11 +128,19 @@ To deprecate a metric:
## Remove a metric
### Removal policy
WARNING:
A metric that is not used in Sisense or any other system after 6 months is marked by the
Product Intelligence team as inactive and is assigned to the group owner for review.
We are working on automating this process. See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/338466) for details.
Only deprecated metrics can be removed from Service Ping.
For an example of the metric removal process take a look at this [example issue](https://gitlab.com/gitlab-org/gitlab/-/issues/297029)
To remove a deprecated metric:
### To remove a deprecated metric
1. Verify that removing the metric from the Service Ping payload does not cause
errors in [Version App](https://gitlab.com/gitlab-services/version-gitlab-com)

View File

@ -88,13 +88,15 @@ at the project level or the [group level](../user/group/index.md#group-push-rule
To create global push rules:
1. On the top bar, select **Menu >** **{admin}** **Admin**.
1. In the left sidebar, select **Push rules**.
1. On the left sidebar, select **Push Rules**.
To override global push rules in a project's settings:
1. Navigate to your project's **Settings > Repository** and expand **Push rules**.
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Settings > Repository**.
1. Expand **Push rules**.
1. Set the rule you want.
1. Select **Save Push Rules** for the changes to take effect.
1. Select **Save push rules**.
The following options are available:

View File

@ -31,7 +31,7 @@ module Gitlab
with_options allow_nil: true do
validates :extends, array_of_strings_or_string: true
validates :rules, array_of_hashes: true
validates :rules, nested_array_of_hashes: true
validates :resource_group, type: String
end
end

View File

@ -13,7 +13,7 @@ module Gitlab
end
def value
@config
[@config].flatten
end
def composable_class

View File

@ -78,10 +78,26 @@ module Gitlab
include LegacyValidationHelpers
def validate_each(record, attribute, value)
unless value.is_a?(Array) && value.map { |hsh| hsh.is_a?(Hash) }.all?
unless validate_array_of_hashes(value)
record.errors.add(attribute, 'should be an array of hashes')
end
end
private
def validate_array_of_hashes(value)
value.is_a?(Array) && value.all? { |obj| obj.is_a?(Hash) }
end
end
class NestedArrayOfHashesValidator < ArrayOfHashesValidator
include NestedArrayHelpers
def validate_each(record, attribute, value)
unless validate_nested_array(value, 1, &method(:validate_array_of_hashes))
record.errors.add(attribute, 'should be an array containing hashes and arrays of hashes')
end
end
end
class ArrayOrStringValidator < ActiveModel::EachValidator

View File

@ -44,7 +44,7 @@ module Gitlab
def log_and_increment_counter(value, operation)
Gitlab::Import::Logger.info(
import_source: :github,
import_type: :github,
project_id: project.id,
importer: self.class.name,
message: "#{value} #{object_type.to_s.pluralize} #{operation}"

View File

@ -4,7 +4,7 @@ module Gitlab
module GithubImport
class Logger < ::Gitlab::Import::Logger
def default_attributes
super.merge(import_source: :github)
super.merge(import_type: :github)
end
end
end

View File

@ -122,6 +122,7 @@ module Gitlab
return unless attribute
return unless tie_breaker_attribute
return unless attribute.respond_to?(:name)
model_class.column_names.include?(attribute.name.to_s) &&
arel_table[primary_key].to_s == tie_breaker_attribute.to_s

View File

@ -30,7 +30,10 @@ module QA
builder.response(:logger, logger, headers: false, bodies: false)
end
Octokit::Client.new(access_token: Runtime::Env.github_access_token, auto_paginate: true)
Octokit::Client.new(
access_token: ENV['QA_LARGE_GH_IMPORT_GH_TOKEN'] || Runtime::Env.github_access_token,
auto_paginate: true
)
end
let(:gh_branches) { github_client.branches(github_repo).map(&:name) }

View File

@ -54,8 +54,8 @@ RSpec.describe SpammableActions::CaptchaCheck::HtmlFormatActionsSupport do
context 'when spammable.render_recaptcha? is true' do
let(:render_recaptcha) { true }
it 'renders :verify' do
expect(controller).to receive(:render).with(:verify)
it 'renders :captcha_check' do
expect(controller).to receive(:render).with(:captcha_check)
subject
end

View File

@ -319,7 +319,7 @@ RSpec.describe IssuesHelper do
initial_email: project.new_issuable_address(current_user, 'issue'),
is_signed_in: current_user.present?.to_s,
issues_path: project_issues_path(project),
jira_integration_path: help_page_url('integration/jira/', anchor: 'view-jira-issues'),
jira_integration_path: help_page_url('integration/jira/issues', anchor: 'view-jira-issues'),
markdown_help_path: help_page_path('user/markdown'),
max_attachment_size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes),
new_issue_path: new_project_issue_path(project, issue: { milestone_id: finder.milestones.first.id }),

View File

@ -17,6 +17,10 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules do
describe '.new' do
subject { entry }
before do
subject.compose!
end
context 'with a list of rule rule' do
let(:config) do
[{ if: '$THIS == "that"', when: 'never' }]
@ -24,14 +28,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules do
it { is_expected.to be_a(described_class) }
it { is_expected.to be_valid }
context 'when composed' do
before do
subject.compose!
end
it { is_expected.to be_valid }
end
end
context 'with a list of two rules' do
@ -42,16 +38,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules do
]
end
it { is_expected.to be_a(described_class) }
it { is_expected.to be_valid }
context 'when composed' do
before do
subject.compose!
end
it { is_expected.to be_valid }
end
end
context 'with a single rule object' do
@ -61,6 +48,28 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules do
it { is_expected.not_to be_valid }
end
context 'with nested rules' do
let(:config) do
[
{ if: '$THIS == "that"', when: 'always' },
[{ if: '$SKIP', when: 'never' }]
]
end
it { is_expected.to be_valid }
end
context 'with rules nested more than one level' do
let(:config) do
[
{ if: '$THIS == "that"', when: 'always' },
[{ if: '$SKIP', when: 'never' }, [{ if: '$THIS == "other"', when: 'aways' }]]
]
end
it { is_expected.not_to be_valid }
end
end
describe '#value' do
@ -90,7 +99,36 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules do
{ if: '$SKIP', when: 'never' }
end
it { is_expected.to eq(config) }
it { is_expected.to eq([config]) }
end
context 'with nested rules' do
let(:first_rule) { { if: '$THIS == "that"', when: 'always' } }
let(:second_rule) { { if: '$SKIP', when: 'never' } }
let(:config) do
[
first_rule,
[second_rule]
]
end
it { is_expected.to contain_exactly(first_rule, second_rule) }
end
context 'with rules nested more than one level' do
let(:first_rule) { { if: '$THIS == "that"', when: 'always' } }
let(:second_rule) { { if: '$SKIP', when: 'never' } }
let(:third_rule) { { if: '$THIS == "other"', when: 'aways' } }
let(:config) do
[
first_rule,
[second_rule, [third_rule]]
]
end
it { is_expected.to contain_exactly(first_rule, second_rule, third_rule) }
end
end

View File

@ -2781,7 +2781,7 @@ module Gitlab
expect(subject.valid?).to eq(false)
expect(subject.errors).to contain_exactly(
'jobs:rspec config contains unknown keys: bad_tags',
'jobs:rspec rules should be an array of hashes')
'jobs:rspec rules should be an array containing hashes and arrays of hashes')
end
end

View File

@ -36,7 +36,7 @@ RSpec.describe Gitlab::GithubImport::BulkImporting do
expect(Gitlab::Import::Logger)
.to receive(:info)
.with(
import_source: :github,
import_type: :github,
project_id: 1,
importer: 'MyImporter',
message: '1 object_types fetched'
@ -70,7 +70,7 @@ RSpec.describe Gitlab::GithubImport::BulkImporting do
expect(Gitlab::Import::Logger)
.to receive(:info)
.with(
import_source: :github,
import_type: :github,
project_id: 1,
importer: 'MyImporter',
message: '0 object_types fetched'
@ -100,7 +100,7 @@ RSpec.describe Gitlab::GithubImport::BulkImporting do
.to receive(:info)
.twice
.with(
import_source: :github,
import_type: :github,
project_id: 1,
importer: 'MyImporter',
message: '5 object_types imported'

View File

@ -21,7 +21,7 @@ RSpec.describe Gitlab::GithubImport::Logger do
'message' => 'Hello world',
'correlation_id' => 'new-correlation-id',
'feature_category' => 'importers',
'import_source' => 'github'
'import_type' => 'github'
})
end
@ -34,7 +34,7 @@ RSpec.describe Gitlab::GithubImport::Logger do
'hello' => 1,
'correlation_id' => 'new-correlation-id',
'feature_category' => 'importers',
'import_source' => 'github'
'import_type' => 'github'
})
end
end