Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
09dff3eec7
commit
d872c89ce4
2
Gemfile
2
Gemfile
|
@ -490,7 +490,7 @@ gem 'flipper', '~> 0.21.0'
|
||||||
gem 'flipper-active_record', '~> 0.21.0'
|
gem 'flipper-active_record', '~> 0.21.0'
|
||||||
gem 'flipper-active_support_cache_store', '~> 0.21.0'
|
gem 'flipper-active_support_cache_store', '~> 0.21.0'
|
||||||
gem 'unleash', '~> 3.2.2'
|
gem 'unleash', '~> 3.2.2'
|
||||||
gem 'gitlab-experiment', '~> 0.6.3'
|
gem 'gitlab-experiment', '~> 0.6.4'
|
||||||
|
|
||||||
# Structured logging
|
# Structured logging
|
||||||
gem 'lograge', '~> 0.5'
|
gem 'lograge', '~> 0.5'
|
||||||
|
|
|
@ -464,7 +464,7 @@ GEM
|
||||||
gitlab-dangerfiles (2.3.0)
|
gitlab-dangerfiles (2.3.0)
|
||||||
danger (>= 8.3.1)
|
danger (>= 8.3.1)
|
||||||
danger-gitlab (>= 8.0.0)
|
danger-gitlab (>= 8.0.0)
|
||||||
gitlab-experiment (0.6.3)
|
gitlab-experiment (0.6.4)
|
||||||
activesupport (>= 3.0)
|
activesupport (>= 3.0)
|
||||||
request_store (>= 1.0)
|
request_store (>= 1.0)
|
||||||
scientist (~> 1.6, >= 1.6.0)
|
scientist (~> 1.6, >= 1.6.0)
|
||||||
|
@ -1475,7 +1475,7 @@ DEPENDENCIES
|
||||||
github-markup (~> 1.7.0)
|
github-markup (~> 1.7.0)
|
||||||
gitlab-chronic (~> 0.10.5)
|
gitlab-chronic (~> 0.10.5)
|
||||||
gitlab-dangerfiles (~> 2.3.0)
|
gitlab-dangerfiles (~> 2.3.0)
|
||||||
gitlab-experiment (~> 0.6.3)
|
gitlab-experiment (~> 0.6.4)
|
||||||
gitlab-fog-azure-rm (~> 1.1.1)
|
gitlab-fog-azure-rm (~> 1.1.1)
|
||||||
gitlab-labkit (~> 0.21.0)
|
gitlab-labkit (~> 0.21.0)
|
||||||
gitlab-license (~> 2.0)
|
gitlab-license (~> 2.0)
|
||||||
|
|
|
@ -205,7 +205,7 @@ export default {
|
||||||
>{{ issuableSymbol }}{{ issuable.iid }}</span
|
>{{ issuableSymbol }}{{ issuable.iid }}</span
|
||||||
>
|
>
|
||||||
<span class="issuable-authored gl-display-none gl-sm-display-inline-block! gl-mr-3">
|
<span class="issuable-authored gl-display-none gl-sm-display-inline-block! gl-mr-3">
|
||||||
·
|
<span aria-hidden="true">·</span>
|
||||||
<span
|
<span
|
||||||
v-gl-tooltip:tooltipcontainer.bottom
|
v-gl-tooltip:tooltipcontainer.bottom
|
||||||
data-testid="issuable-created-at"
|
data-testid="issuable-created-at"
|
||||||
|
@ -229,17 +229,19 @@ export default {
|
||||||
</span>
|
</span>
|
||||||
<slot name="timeframe"></slot>
|
<slot name="timeframe"></slot>
|
||||||
|
|
||||||
<gl-label
|
<span v-if="labels.length" role="group" :aria-label="__('Labels')">
|
||||||
v-for="(label, index) in labels"
|
<gl-label
|
||||||
:key="index"
|
v-for="(label, index) in labels"
|
||||||
:background-color="label.color"
|
:key="index"
|
||||||
:title="labelTitle(label)"
|
:background-color="label.color"
|
||||||
:description="label.description"
|
:title="labelTitle(label)"
|
||||||
:scoped="scopedLabel(label)"
|
:description="label.description"
|
||||||
:target="labelTarget(label)"
|
:scoped="scopedLabel(label)"
|
||||||
:class="{ 'gl-ml-2': index }"
|
:target="labelTarget(label)"
|
||||||
size="sm"
|
:class="{ 'gl-ml-2': index }"
|
||||||
/>
|
size="sm"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="issuable-meta">
|
<div class="issuable-meta">
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {
|
||||||
GlTooltipDirective,
|
GlTooltipDirective,
|
||||||
} from '@gitlab/ui';
|
} from '@gitlab/ui';
|
||||||
import fuzzaldrinPlus from 'fuzzaldrin-plus';
|
import fuzzaldrinPlus from 'fuzzaldrin-plus';
|
||||||
|
import { cloneDeep } from 'lodash';
|
||||||
import getIssuesQuery from 'ee_else_ce/issues_list/queries/get_issues.query.graphql';
|
import getIssuesQuery from 'ee_else_ce/issues_list/queries/get_issues.query.graphql';
|
||||||
import createFlash from '~/flash';
|
import createFlash from '~/flash';
|
||||||
import { TYPE_USER } from '~/graphql_shared/constants';
|
import { TYPE_USER } from '~/graphql_shared/constants';
|
||||||
|
@ -163,14 +164,17 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
const filterTokens = getFilterTokens(window.location.search);
|
||||||
const state = getParameterByName(PARAM_STATE);
|
const state = getParameterByName(PARAM_STATE);
|
||||||
const sortKey = getSortKey(getParameterByName(PARAM_SORT));
|
const sortKey = getSortKey(getParameterByName(PARAM_SORT));
|
||||||
const defaultSortKey = state === IssuableStates.Closed ? UPDATED_DESC : CREATED_DESC;
|
const defaultSortKey = state === IssuableStates.Closed ? UPDATED_DESC : CREATED_DESC;
|
||||||
|
|
||||||
|
this.initialFilterTokens = cloneDeep(filterTokens);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dueDateFilter: getDueDateValue(getParameterByName(PARAM_DUE_DATE)),
|
dueDateFilter: getDueDateValue(getParameterByName(PARAM_DUE_DATE)),
|
||||||
exportCsvPathWithQuery: this.getExportCsvPathWithQuery(),
|
exportCsvPathWithQuery: this.getExportCsvPathWithQuery(),
|
||||||
filterTokens: getFilterTokens(window.location.search),
|
filterTokens,
|
||||||
issues: [],
|
issues: [],
|
||||||
pageInfo: {},
|
pageInfo: {},
|
||||||
pageParams: getInitialPageParams(sortKey),
|
pageParams: getInitialPageParams(sortKey),
|
||||||
|
@ -609,7 +613,7 @@ export default {
|
||||||
recent-searches-storage-key="issues"
|
recent-searches-storage-key="issues"
|
||||||
:search-input-placeholder="$options.i18n.searchPlaceholder"
|
:search-input-placeholder="$options.i18n.searchPlaceholder"
|
||||||
:search-tokens="searchTokens"
|
:search-tokens="searchTokens"
|
||||||
:initial-filter-value="filterTokens"
|
:initial-filter-value="initialFilterTokens"
|
||||||
:sort-options="sortOptions"
|
:sort-options="sortOptions"
|
||||||
:initial-sort-by="sortKey"
|
:initial-sort-by="sortKey"
|
||||||
:issuables="issues"
|
:issuables="issues"
|
||||||
|
|
|
@ -99,7 +99,7 @@ export default {
|
||||||
// We don't have any information about selected token except for its
|
// We don't have any information about selected token except for its
|
||||||
// group path and iid joined by separator, so we need to manually
|
// group path and iid joined by separator, so we need to manually
|
||||||
// compose epic path from it.
|
// 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);
|
const [groupPath, epicIid] = data.split(this.$options.separator);
|
||||||
epicPath = `/groups/${groupPath}/-/epics/${epicIid}`;
|
epicPath = `/groups/${groupPath}/-/epics/${epicIid}`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ module SpammableActions::CaptchaCheck::HtmlFormatActionsSupport
|
||||||
private
|
private
|
||||||
|
|
||||||
def with_captcha_check_html_format(&block)
|
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)
|
with_captcha_check_common(captcha_render_lambda: captcha_render_lambda, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -207,7 +207,7 @@ module IssuesHelper
|
||||||
initial_email: project.new_issuable_address(current_user, 'issue'),
|
initial_email: project.new_issuable_address(current_user, 'issue'),
|
||||||
is_signed_in: current_user.present?.to_s,
|
is_signed_in: current_user.present?.to_s,
|
||||||
issues_path: project_issues_path(project),
|
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'),
|
markdown_help_path: help_page_path('user/markdown'),
|
||||||
max_attachment_size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes),
|
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) }),
|
new_issue_path: new_project_issue_path(project, issue: { milestone_id: finder.milestones.first.try(:id) }),
|
||||||
|
|
|
@ -57,6 +57,10 @@ module Ci
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def use_denormalized_minutes_data?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def running_builds_for_shared_runners
|
def running_builds_for_shared_runners
|
||||||
|
|
|
@ -40,6 +40,10 @@ module Ci
|
||||||
::Feature.enabled?(:ci_queueing_denormalize_shared_runners_information, runner, type: :development, default_enabled: :yaml)
|
::Feature.enabled?(:ci_queueing_denormalize_shared_runners_information, runner, type: :development, default_enabled: :yaml)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def use_denormalized_minutes_data?
|
||||||
|
::Feature.enabled?(:ci_queueing_denormalize_ci_minutes_information, runner, type: :development, default_enabled: :yaml)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def builds_available_for_shared_runners
|
def builds_available_for_shared_runners
|
||||||
|
@ -83,3 +87,5 @@ module Ci
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Ci::Queue::PendingBuildsStrategy.prepend_mod_with('Ci::Queue::PendingBuildsStrategy')
|
||||||
|
|
|
@ -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
|
|
|
@ -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])
|
|
@ -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])
|
|
|
@ -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'
|
|
@ -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'
|
|
|
@ -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
|
|
@ -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
|
|
@ -1,19 +1,20 @@
|
||||||
---
|
---
|
||||||
data_category: optional
|
data_category: optional
|
||||||
key_path: usage_activity_by_stage_monthly.plan.service_desk_enabled_projects
|
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_section: dev
|
||||||
product_stage:
|
product_stage: plan
|
||||||
product_group: group::plan
|
product_group: group::plan
|
||||||
product_category:
|
product_category: service_desk
|
||||||
value_type: number
|
value_type: number
|
||||||
status: data_available
|
status: data_available
|
||||||
time_frame: 28d
|
time_frame: 28d
|
||||||
data_source:
|
data_source: database
|
||||||
distribution:
|
distribution:
|
||||||
- ce
|
- ce
|
||||||
- ee
|
- ee
|
||||||
tier:
|
tier:
|
||||||
- free
|
- free
|
||||||
skip_validation: true
|
- premium
|
||||||
|
- ultimate
|
||||||
performance_indicator_type: []
|
performance_indicator_type: []
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
---
|
---
|
||||||
data_category: operational
|
data_category: operational
|
||||||
key_path: usage_activity_by_stage_monthly.plan.service_desk_issues
|
key_path: usage_activity_by_stage_monthly.plan.service_desk_issues
|
||||||
description:
|
description: Count of service desk issues
|
||||||
product_section: dev
|
product_section: dev
|
||||||
product_stage:
|
product_stage: plan
|
||||||
product_group: group::plan
|
product_group: group::plan
|
||||||
product_category:
|
product_category:
|
||||||
value_type: number
|
value_type: number
|
||||||
status: data_available
|
status: data_available
|
||||||
time_frame: 28d
|
time_frame: 28d
|
||||||
data_source:
|
data_source: database
|
||||||
distribution:
|
distribution:
|
||||||
- ce
|
- ce
|
||||||
- ee
|
- ee
|
||||||
tier:
|
tier:
|
||||||
- free
|
- free
|
||||||
skip_validation: true
|
- premium
|
||||||
|
- ultimate
|
||||||
performance_indicator_type: []
|
performance_indicator_type: []
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
---
|
---
|
||||||
data_category: optional
|
data_category: optional
|
||||||
key_path: usage_activity_by_stage.plan.service_desk_enabled_projects
|
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_section: dev
|
||||||
product_stage:
|
product_stage: plan
|
||||||
product_group: group::plan
|
product_group: group::plan
|
||||||
product_category:
|
product_category: service_desk
|
||||||
value_type: number
|
value_type: number
|
||||||
status: data_available
|
status: data_available
|
||||||
time_frame: all
|
time_frame: all
|
||||||
data_source:
|
data_source: database
|
||||||
distribution:
|
distribution:
|
||||||
- ce
|
- ce
|
||||||
- ee
|
- ee
|
||||||
tier:
|
tier:
|
||||||
- free
|
- free
|
||||||
skip_validation: true
|
- premium
|
||||||
|
- ultimate
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
---
|
---
|
||||||
data_category: optional
|
data_category: optional
|
||||||
key_path: usage_activity_by_stage.plan.service_desk_issues
|
key_path: usage_activity_by_stage.plan.service_desk_issues
|
||||||
description:
|
description: Count of service desk issues
|
||||||
product_section: dev
|
product_section: dev
|
||||||
product_stage:
|
product_stage: plan
|
||||||
product_group: group::plan
|
product_group: group::plan
|
||||||
product_category:
|
product_category: service_desk
|
||||||
value_type: number
|
value_type: number
|
||||||
status: data_available
|
status: data_available
|
||||||
time_frame: all
|
time_frame: all
|
||||||
data_source:
|
data_source: database
|
||||||
distribution:
|
distribution:
|
||||||
- ce
|
- ce
|
||||||
- ee
|
- ee
|
||||||
tier:
|
tier:
|
||||||
- free
|
- free
|
||||||
skip_validation: true
|
- premium
|
||||||
|
- ultimate
|
||||||
|
|
|
@ -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.
|
> - [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.
|
> - 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.
|
> - `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
|
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:
|
The last log entry reports the number of objects fetched and imported:
|
||||||
|
|
||||||
|
|
|
@ -128,11 +128,19 @@ To deprecate a metric:
|
||||||
|
|
||||||
## Remove 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.
|
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)
|
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
|
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)
|
errors in [Version App](https://gitlab.com/gitlab-services/version-gitlab-com)
|
||||||
|
|
|
@ -88,13 +88,15 @@ at the project level or the [group level](../user/group/index.md#group-push-rule
|
||||||
To create global push rules:
|
To create global push rules:
|
||||||
|
|
||||||
1. On the top bar, select **Menu >** **{admin}** **Admin**.
|
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:
|
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. 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:
|
The following options are available:
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ module Gitlab
|
||||||
|
|
||||||
with_options allow_nil: true do
|
with_options allow_nil: true do
|
||||||
validates :extends, array_of_strings_or_string: true
|
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
|
validates :resource_group, type: String
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,7 +13,7 @@ module Gitlab
|
||||||
end
|
end
|
||||||
|
|
||||||
def value
|
def value
|
||||||
@config
|
[@config].flatten
|
||||||
end
|
end
|
||||||
|
|
||||||
def composable_class
|
def composable_class
|
||||||
|
|
|
@ -78,10 +78,26 @@ module Gitlab
|
||||||
include LegacyValidationHelpers
|
include LegacyValidationHelpers
|
||||||
|
|
||||||
def validate_each(record, attribute, value)
|
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')
|
record.errors.add(attribute, 'should be an array of hashes')
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
||||||
class ArrayOrStringValidator < ActiveModel::EachValidator
|
class ArrayOrStringValidator < ActiveModel::EachValidator
|
||||||
|
|
|
@ -44,7 +44,7 @@ module Gitlab
|
||||||
|
|
||||||
def log_and_increment_counter(value, operation)
|
def log_and_increment_counter(value, operation)
|
||||||
Gitlab::Import::Logger.info(
|
Gitlab::Import::Logger.info(
|
||||||
import_source: :github,
|
import_type: :github,
|
||||||
project_id: project.id,
|
project_id: project.id,
|
||||||
importer: self.class.name,
|
importer: self.class.name,
|
||||||
message: "#{value} #{object_type.to_s.pluralize} #{operation}"
|
message: "#{value} #{object_type.to_s.pluralize} #{operation}"
|
||||||
|
|
|
@ -4,7 +4,7 @@ module Gitlab
|
||||||
module GithubImport
|
module GithubImport
|
||||||
class Logger < ::Gitlab::Import::Logger
|
class Logger < ::Gitlab::Import::Logger
|
||||||
def default_attributes
|
def default_attributes
|
||||||
super.merge(import_source: :github)
|
super.merge(import_type: :github)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -122,6 +122,7 @@ module Gitlab
|
||||||
|
|
||||||
return unless attribute
|
return unless attribute
|
||||||
return unless tie_breaker_attribute
|
return unless tie_breaker_attribute
|
||||||
|
return unless attribute.respond_to?(:name)
|
||||||
|
|
||||||
model_class.column_names.include?(attribute.name.to_s) &&
|
model_class.column_names.include?(attribute.name.to_s) &&
|
||||||
arel_table[primary_key].to_s == tie_breaker_attribute.to_s
|
arel_table[primary_key].to_s == tie_breaker_attribute.to_s
|
||||||
|
|
|
@ -30,7 +30,10 @@ module QA
|
||||||
builder.response(:logger, logger, headers: false, bodies: false)
|
builder.response(:logger, logger, headers: false, bodies: false)
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
let(:gh_branches) { github_client.branches(github_repo).map(&:name) }
|
let(:gh_branches) { github_client.branches(github_repo).map(&:name) }
|
||||||
|
|
|
@ -54,8 +54,8 @@ RSpec.describe SpammableActions::CaptchaCheck::HtmlFormatActionsSupport do
|
||||||
context 'when spammable.render_recaptcha? is true' do
|
context 'when spammable.render_recaptcha? is true' do
|
||||||
let(:render_recaptcha) { true }
|
let(:render_recaptcha) { true }
|
||||||
|
|
||||||
it 'renders :verify' do
|
it 'renders :captcha_check' do
|
||||||
expect(controller).to receive(:render).with(:verify)
|
expect(controller).to receive(:render).with(:captcha_check)
|
||||||
|
|
||||||
subject
|
subject
|
||||||
end
|
end
|
||||||
|
|
|
@ -319,7 +319,7 @@ RSpec.describe IssuesHelper do
|
||||||
initial_email: project.new_issuable_address(current_user, 'issue'),
|
initial_email: project.new_issuable_address(current_user, 'issue'),
|
||||||
is_signed_in: current_user.present?.to_s,
|
is_signed_in: current_user.present?.to_s,
|
||||||
issues_path: project_issues_path(project),
|
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'),
|
markdown_help_path: help_page_path('user/markdown'),
|
||||||
max_attachment_size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes),
|
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 }),
|
new_issue_path: new_project_issue_path(project, issue: { milestone_id: finder.milestones.first.id }),
|
||||||
|
|
|
@ -17,6 +17,10 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules do
|
||||||
describe '.new' do
|
describe '.new' do
|
||||||
subject { entry }
|
subject { entry }
|
||||||
|
|
||||||
|
before do
|
||||||
|
subject.compose!
|
||||||
|
end
|
||||||
|
|
||||||
context 'with a list of rule rule' do
|
context 'with a list of rule rule' do
|
||||||
let(:config) do
|
let(:config) do
|
||||||
[{ if: '$THIS == "that"', when: 'never' }]
|
[{ 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_a(described_class) }
|
||||||
it { is_expected.to be_valid }
|
it { is_expected.to be_valid }
|
||||||
|
|
||||||
context 'when composed' do
|
|
||||||
before do
|
|
||||||
subject.compose!
|
|
||||||
end
|
|
||||||
|
|
||||||
it { is_expected.to be_valid }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with a list of two rules' do
|
context 'with a list of two rules' do
|
||||||
|
@ -42,16 +38,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules do
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
it { is_expected.to be_a(described_class) }
|
|
||||||
it { is_expected.to be_valid }
|
it { is_expected.to be_valid }
|
||||||
|
|
||||||
context 'when composed' do
|
|
||||||
before do
|
|
||||||
subject.compose!
|
|
||||||
end
|
|
||||||
|
|
||||||
it { is_expected.to be_valid }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with a single rule object' do
|
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 }
|
it { is_expected.not_to be_valid }
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
describe '#value' do
|
describe '#value' do
|
||||||
|
@ -90,7 +99,36 @@ RSpec.describe Gitlab::Ci::Config::Entry::Rules do
|
||||||
{ if: '$SKIP', when: 'never' }
|
{ if: '$SKIP', when: 'never' }
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2781,7 +2781,7 @@ module Gitlab
|
||||||
expect(subject.valid?).to eq(false)
|
expect(subject.valid?).to eq(false)
|
||||||
expect(subject.errors).to contain_exactly(
|
expect(subject.errors).to contain_exactly(
|
||||||
'jobs:rspec config contains unknown keys: bad_tags',
|
'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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ RSpec.describe Gitlab::GithubImport::BulkImporting do
|
||||||
expect(Gitlab::Import::Logger)
|
expect(Gitlab::Import::Logger)
|
||||||
.to receive(:info)
|
.to receive(:info)
|
||||||
.with(
|
.with(
|
||||||
import_source: :github,
|
import_type: :github,
|
||||||
project_id: 1,
|
project_id: 1,
|
||||||
importer: 'MyImporter',
|
importer: 'MyImporter',
|
||||||
message: '1 object_types fetched'
|
message: '1 object_types fetched'
|
||||||
|
@ -70,7 +70,7 @@ RSpec.describe Gitlab::GithubImport::BulkImporting do
|
||||||
expect(Gitlab::Import::Logger)
|
expect(Gitlab::Import::Logger)
|
||||||
.to receive(:info)
|
.to receive(:info)
|
||||||
.with(
|
.with(
|
||||||
import_source: :github,
|
import_type: :github,
|
||||||
project_id: 1,
|
project_id: 1,
|
||||||
importer: 'MyImporter',
|
importer: 'MyImporter',
|
||||||
message: '0 object_types fetched'
|
message: '0 object_types fetched'
|
||||||
|
@ -100,7 +100,7 @@ RSpec.describe Gitlab::GithubImport::BulkImporting do
|
||||||
.to receive(:info)
|
.to receive(:info)
|
||||||
.twice
|
.twice
|
||||||
.with(
|
.with(
|
||||||
import_source: :github,
|
import_type: :github,
|
||||||
project_id: 1,
|
project_id: 1,
|
||||||
importer: 'MyImporter',
|
importer: 'MyImporter',
|
||||||
message: '5 object_types imported'
|
message: '5 object_types imported'
|
||||||
|
|
|
@ -21,7 +21,7 @@ RSpec.describe Gitlab::GithubImport::Logger do
|
||||||
'message' => 'Hello world',
|
'message' => 'Hello world',
|
||||||
'correlation_id' => 'new-correlation-id',
|
'correlation_id' => 'new-correlation-id',
|
||||||
'feature_category' => 'importers',
|
'feature_category' => 'importers',
|
||||||
'import_source' => 'github'
|
'import_type' => 'github'
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ RSpec.describe Gitlab::GithubImport::Logger do
|
||||||
'hello' => 1,
|
'hello' => 1,
|
||||||
'correlation_id' => 'new-correlation-id',
|
'correlation_id' => 'new-correlation-id',
|
||||||
'feature_category' => 'importers',
|
'feature_category' => 'importers',
|
||||||
'import_source' => 'github'
|
'import_type' => 'github'
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue