Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-10-06 15:11:48 +00:00
parent 0d1b0d5d03
commit 47d926e838
72 changed files with 762 additions and 265 deletions

View File

@ -18,6 +18,7 @@ import cancelJobMutation from '../graphql/mutations/job_cancel.mutation.graphql'
import playJobMutation from '../graphql/mutations/job_play.mutation.graphql';
import retryJobMutation from '../graphql/mutations/job_retry.mutation.graphql';
import unscheduleJobMutation from '../graphql/mutations/job_unschedule.mutation.graphql';
import { reportMessageToSentry } from '../../../utils';
export default {
ACTIONS_DOWNLOAD_ARTIFACTS,
@ -34,6 +35,7 @@ export default {
jobPlay: 'jobPlay',
jobUnschedule: 'jobUnschedule',
playJobModalId: 'play-job-modal',
name: 'JobActionsCell',
components: {
GlButton,
GlButtonGroup,
@ -99,15 +101,17 @@ export default {
variables: { id: this.job.id },
});
if (errors.length > 0) {
this.reportFailure();
reportMessageToSentry(this.$options.name, errors.join(', '), {});
this.showToastMessage();
} else {
eventHub.$emit('jobActionPerformed');
}
} catch {
this.reportFailure();
} catch (failure) {
reportMessageToSentry(this.$options.name, failure, {});
this.showToastMessage();
}
},
reportFailure() {
showToastMessage() {
const toastProps = {
text: this.$options.GENERIC_ERROR,
variant: 'danger',

View File

@ -19,3 +19,12 @@ export const reportToSentry = (component, failureType) => {
Sentry.captureException(failureType);
});
};
export const reportMessageToSentry = (component, message, context) => {
Sentry.withScope((scope) => {
// eslint-disable-next-line @gitlab/require-i18n-strings
scope.setContext('Vue data', context);
scope.setTag('component', component);
Sentry.captureMessage(message);
});
};

View File

@ -0,0 +1,68 @@
<script>
import { GlButton, GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { sprintf, __ } from '~/locale';
export default {
components: {
GlButton,
GlDropdown,
GlDropdownItem,
},
props: {
widget: {
type: String,
required: true,
},
tertiaryButtons: {
type: Array,
required: false,
default: () => [],
},
},
computed: {
dropdownLabel() {
return sprintf(__('%{widget} options'), { widget: this.widget });
},
},
};
</script>
<template>
<div>
<gl-dropdown
:text="dropdownLabel"
icon="ellipsis_v"
no-caret
category="tertiary"
right
lazy
text-sr-only
size="small"
class="gl-display-block gl-md-display-none!"
>
<gl-dropdown-item
v-for="(btn, index) in tertiaryButtons"
:key="index"
:href="btn.href"
:target="btn.target"
>
{{ btn.text }}
</gl-dropdown-item>
</gl-dropdown>
<template v-if="tertiaryButtons.length">
<gl-button
v-for="(btn, index) in tertiaryButtons"
:key="index"
:href="btn.href"
:target="btn.target"
:class="{ 'gl-mr-3': index > 1 }"
category="tertiary"
variant="confirm"
size="small"
class="gl-display-none gl-md-display-block"
>
{{ btn.text }}
</gl-button>
</template>
</div>
</template>

View File

@ -11,6 +11,7 @@ import { sprintf, s__ } from '~/locale';
import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
import { EXTENSION_ICON_CLASS } from '../../constants';
import StatusIcon from './status_icon.vue';
import Actions from './actions.vue';
export const LOADING_STATES = {
collapsedLoading: 'collapsedLoading',
@ -26,6 +27,7 @@ export default {
GlBadge,
SmartVirtualList,
StatusIcon,
Actions,
},
directives: {
SafeHtml: GlSafeHtmlDirective,
@ -66,6 +68,9 @@ export default {
return this.statusIcon(this.collapsedData);
},
tertiaryActionsButtons() {
return this.tertiaryButtons ? this.tertiaryButtons() : undefined;
},
},
watch: {
isCollapsed(newVal) {
@ -119,13 +124,16 @@ export default {
:is-loading="isLoadingSummary"
:icon-name="statusIconName"
/>
<div class="media-body gl-display-flex gl-align-self-center gl-align-items-center">
<div class="code-text">
<div
class="media-body gl-display-flex gl-align-self-center gl-align-items-center gl-flex-direction-row!"
>
<div class="gl-flex-grow-1">
<template v-if="isLoadingSummary">
{{ __('Loading...') }}
</template>
<div v-else v-safe-html="summary(collapsedData)"></div>
</div>
<actions :widget="$options.name" :tertiary-buttons="tertiaryActionsButtons" />
<div
class="gl-float-right gl-align-self-center gl-border-l-1 gl-border-l-solid gl-border-gray-100 gl-ml-3 gl-pl-3"
>
@ -138,6 +146,7 @@ export default {
:icon="isCollapsed ? 'chevron-lg-down' : 'chevron-lg-up'"
category="tertiary"
data-testid="toggle-button"
size="small"
@click="toggleCollapsed"
/>
</div>

View File

@ -9,7 +9,7 @@ export default {
name: 'Issues',
// Add an array of props
// These then get mapped to values stored in the MR Widget store
props: ['targetProjectFullPath'],
props: ['targetProjectFullPath', 'conflictsDocsPath'],
// Add any extra computed props in here
computed: {
// Small summary text to be displayed in the collapsed state
@ -22,6 +22,11 @@ export default {
statusIcon(count) {
return EXTENSION_ICONS.warning;
},
// Tertiary action buttons that will take the user elsewhere
// in the GitLab app
tertiaryButtons() {
return [{ text: 'Full report', href: this.conflictsDocsPath, target: '_blank' }];
},
},
methods: {
// Fetches the collapsed data

View File

@ -5,6 +5,8 @@ module Ci
class PipelinesForMergeRequestFinder
include Gitlab::Utils::StrongMemoize
COMMITS_LIMIT = 100
def initialize(merge_request, current_user)
@merge_request = merge_request
@current_user = current_user
@ -12,7 +14,7 @@ module Ci
attr_reader :merge_request, :current_user
delegate :commit_shas, :target_project, :source_project, :source_branch, to: :merge_request
delegate :recent_diff_head_shas, :commit_shas, :target_project, :source_project, :source_branch, to: :merge_request
# Fetch all pipelines that the user can read.
def execute
@ -35,7 +37,7 @@ module Ci
pipelines =
if merge_request.persisted?
pipelines_using_cte
all_pipelines_for_merge_request
else
triggered_for_branch.for_sha(commit_shas)
end
@ -79,6 +81,17 @@ module Ci
pipelines.joins(shas_table) # rubocop: disable CodeReuse/ActiveRecord
end
def all_pipelines_for_merge_request
if Feature.enabled?(:decomposed_ci_query_in_pipelines_for_merge_request_finder, target_project, default_enabled: :yaml)
pipelines_for_merge_request = triggered_by_merge_request
pipelines_for_branch = triggered_for_branch.for_sha(recent_diff_head_shas(COMMITS_LIMIT))
Ci::Pipeline.from_union([pipelines_for_merge_request, pipelines_for_branch])
else
pipelines_using_cte
end
end
# NOTE: this method returns only parent merge request pipelines.
# Child merge request pipelines have a different source.
def triggered_by_merge_request

View File

@ -14,6 +14,8 @@ module Clusters
validates :cluster, presence: true
validates :enabled, inclusion: { in: [true, false] }
scope :enabled, -> { where(enabled: true) }
def available?
enabled
end

View File

@ -21,6 +21,8 @@ module Clusters
default_value_for(:alert_manager_token) { SecureRandom.hex }
scope :enabled, -> { where(enabled: true) }
after_destroy do
run_after_commit do
deactivate_project_integrations

View File

@ -1658,6 +1658,10 @@ class MergeRequest < ApplicationRecord
service_class.new(project, current_user, id: id, report_type: report_type).execute(comparison_base_pipeline(identifier), actual_head_pipeline)
end
def recent_diff_head_shas(limit = 100)
merge_request_diffs.recent(limit).pluck(:head_commit_sha)
end
def all_commits
MergeRequestDiffCommit
.where(merge_request_diff: merge_request_diffs.recent)

View File

@ -66,7 +66,7 @@ class MergeRequestDiff < ApplicationRecord
joins(:merge_request).where(merge_requests: { target_project_id: project_id })
end
scope :recent, -> { order(id: :desc).limit(100) }
scope :recent, -> (limit = 100) { order(id: :desc).limit(limit) }
scope :files_in_database, -> do
where(stored_externally: [false, nil]).where(arel_table[:files_count].gt(0))

View File

@ -0,0 +1,8 @@
---
name: add_actor_based_user_to_snowplow_tracking
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71353
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338150
milestone: '14.4'
type: development
group: group::product intelligence
default_enabled: false

View File

@ -0,0 +1,8 @@
---
name: decomposed_ci_query_in_pipelines_for_merge_request_finder
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68549
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341341
milestone: '14.4'
type: development
group: group::pipeline execution
default_enabled: false

View File

@ -7,7 +7,7 @@ product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
status: removed
time_frame: 28d
data_source: database
distribution:
@ -20,3 +20,4 @@ tier:
name: 'count_distinct_user_id_from_clusters_applications_cert_managers'
performance_indicator_type: []
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
status: removed
time_frame: 28d
data_source: database
distribution:
@ -20,3 +20,4 @@ tier:
name: 'count_distinct_user_id_from_clusters_applications_helm'
performance_indicator_type: []
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
status: removed
time_frame: 28d
data_source: database
distribution:
@ -20,3 +20,4 @@ tier:
name: 'count_distinct_user_id_from_clusters_applications_ingress'
performance_indicator_type: []
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
status: removed
time_frame: 28d
data_source: database
distribution:
@ -20,3 +20,4 @@ tier:
name: 'count_distinct_user_id_from_clusters_applications_knative'
performance_indicator_type: []
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: monitor
product_group: group::monitor
product_category: metrics
value_type: number
status: active
status: removed
time_frame: 28d
data_source: database
distribution:
@ -19,3 +19,4 @@ tier:
- ultimate
performance_indicator_type: []
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: verify
product_group: group::runner
product_category: runner
value_type: number
status: active
status: removed
time_frame: 28d
data_source: database
distribution:
@ -19,3 +19,4 @@ tier:
- ultimate
performance_indicator_type: []
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -0,0 +1,21 @@
---
data_category: optional
key_path: usage_activity_by_stage_monthly.monitor.clusters_integrations_prometheus
description: Users creating clusters with Prometheus integration enabled in last 28 days.
product_section: ops
product_stage: monitor
product_group: group::monitor
product_category: metrics
value_type: number
status: active
time_frame: 28d
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate
performance_indicator_type: []
milestone: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
status: removed
time_frame: all
data_source: database
distribution:
@ -19,3 +19,4 @@ tier:
- ultimate
performance_indicator_type: []
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
status: removed
time_frame: all
data_source: database
distribution:
@ -19,3 +19,4 @@ tier:
- ultimate
performance_indicator_type: []
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
status: removed
time_frame: all
data_source: database
distribution:
@ -19,3 +19,4 @@ tier:
- ultimate
performance_indicator_type: []
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
status: removed
time_frame: all
data_source: database
distribution:
@ -19,3 +19,4 @@ tier:
- ultimate
performance_indicator_type: []
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
status: removed
time_frame: all
data_source: database
distribution:
@ -19,3 +19,4 @@ tier:
- ultimate
performance_indicator_type: []
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
status: removed
time_frame: all
data_source: database
distribution:
@ -19,3 +19,4 @@ tier:
- ultimate
performance_indicator_type: []
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
status: removed
time_frame: all
data_source: database
distribution:
@ -19,3 +19,4 @@ tier:
- ultimate
performance_indicator_type: []
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
status: removed
time_frame: all
data_source: database
distribution:
@ -19,3 +19,4 @@ tier:
- ultimate
performance_indicator_type: []
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
status: removed
time_frame: all
data_source: database
distribution:
@ -19,3 +19,4 @@ tier:
- ultimate
performance_indicator_type: []
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
status: removed
time_frame: all
data_source: database
distribution:
@ -19,3 +19,4 @@ tier:
- ultimate
performance_indicator_type: []
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
status: removed
time_frame: all
data_source: database
distribution:
@ -18,3 +18,4 @@ tier:
- premium
- ultimate
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
status: removed
time_frame: all
data_source: database
distribution:
@ -18,3 +18,4 @@ tier:
- premium
- ultimate
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
status: removed
time_frame: all
data_source: database
distribution:
@ -18,3 +18,4 @@ tier:
- premium
- ultimate
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
status: removed
time_frame: all
data_source: database
distribution:
@ -18,3 +18,4 @@ tier:
- premium
- ultimate
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: monitor
product_group: group::monitor
product_category: metrics
value_type: number
status: active
status: removed
time_frame: all
data_source: database
distribution:
@ -18,3 +18,4 @@ tier:
- premium
- ultimate
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -7,7 +7,7 @@ product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
status: removed
time_frame: all
data_source: database
distribution:
@ -18,3 +18,4 @@ tier:
- premium
- ultimate
milestone: "<13.9"
milestone_removed: "14.4"

View File

@ -0,0 +1,21 @@
---
data_category: optional
key_path: counts.clusters_integrations_prometheus
description: Total clusters with Clusters::Integrations::Prometheus enabled
product_section: ops
product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate
performance_indicator_type: []
milestone: "14.4"

View File

@ -0,0 +1,21 @@
---
data_category: optional
key_path: counts.clusters_integrations_elastic_stack
description: Total clusters with Clusters::Integrations::ElasticStack enabled
product_section: ops
product_stage: configure
product_group: group::configure
product_category: kubernetes_management
value_type: number
status: active
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate
performance_indicator_type: []
milestone: "14.4"

View File

@ -0,0 +1,21 @@
---
data_category: optional
key_path: usage_activity_by_stage.monitor.clusters_integrations_prometheus
description: Users creating clusters with Prometheus integration enabled in last 28 days.
product_section: ops
product_stage: monitor
product_group: group::monitor
product_category: metrics
value_type: number
status: active
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate
performance_indicator_type: []
milestone: "14.4"

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
class AddIndexOnClustersIntegrationPrometheusEnabled < Gitlab::Database::Migration[1.0]
disable_ddl_transaction!
INDEX_NAME = 'index_clusters_integration_prometheus_enabled'
def up
add_concurrent_index(:clusters_integration_prometheus, [:enabled, :created_at, :cluster_id], name: INDEX_NAME)
end
def down
remove_concurrent_index_by_name(:clusters_integration_prometheus, INDEX_NAME)
end
end

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
class AddIndexOnClustersIntegrationElasticStackEnabled < Gitlab::Database::Migration[1.0]
disable_ddl_transaction!
INDEX_NAME = 'index_clusters_integration_elasticstack_enabled'
def up
add_concurrent_index(:clusters_integration_elasticstack, [:enabled, :created_at, :cluster_id], name: INDEX_NAME)
end
def down
remove_concurrent_index_by_name(:clusters_integration_elasticstack, INDEX_NAME)
end
end

View File

@ -0,0 +1 @@
ffb4e066420e1492550255e5866df6dc9f83d3d6cec9033284c4c3194d53b827

View File

@ -0,0 +1 @@
fc8f86f794d77902fd86acaec6046b65821ff685f841d28158dc05fb55773c16

View File

@ -24767,6 +24767,10 @@ CREATE UNIQUE INDEX index_clusters_applications_runners_on_cluster_id ON cluster
CREATE INDEX index_clusters_applications_runners_on_runner_id ON clusters_applications_runners USING btree (runner_id);
CREATE INDEX index_clusters_integration_elasticstack_enabled ON clusters_integration_elasticstack USING btree (enabled, created_at, cluster_id);
CREATE INDEX index_clusters_integration_prometheus_enabled ON clusters_integration_prometheus USING btree (enabled, created_at, cluster_id);
CREATE INDEX index_clusters_kubernetes_namespaces_on_cluster_id ON clusters_kubernetes_namespaces USING btree (cluster_id);
CREATE INDEX index_clusters_kubernetes_namespaces_on_cluster_project_id ON clusters_kubernetes_namespaces USING btree (cluster_project_id);

View File

@ -407,6 +407,7 @@ listed in the descriptions of the relevant settings.
| `spam_check_endpoint_enabled` | boolean | no | Enables Spam Check via external API endpoint. Default is `false`. |
| `spam_check_endpoint_url` | string | no | URL of the external Spam Check service endpoint. |
| `spam_check_api_key` | string | no | The API key used by GitLab for accessing the Spam Check service endpoint. |
| `suggest_pipeline_enabled` | boolean | no | Enable pipeline suggestion banner. |
| `terminal_max_session_time` | integer | no | Maximum time for web terminal websocket connection (in seconds). Set to `0` for unlimited time. |
| `terms` | text | required by: `enforce_terms` | (**Required by:** `enforce_terms`) Markdown content for the ToS. |
| `throttle_authenticated_api_enabled` | boolean | no | (**If enabled, requires:** `throttle_authenticated_api_period_in_seconds` and `throttle_authenticated_api_requests_per_period`) Enable authenticated API request rate limit. Helps reduce request volume (for example, from crawlers or abusive bots). |

View File

@ -60,6 +60,11 @@ in the handbook when writing about Alpha features.
Instead of **and/or**, use **or** or rewrite the sentence to spell out both options.
## and so on
Do not use **and so on**. Instead, be more specific. For details, see
[the Microsoft style guide](https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/a/and-so-on).
## area
Use [**section**](#section) instead of **area**. The only exception is [the Admin Area](#admin-admin-area).
@ -213,7 +218,8 @@ Use lowercase for **epic board**.
## etc.
Try to avoid **etc.**. Be as specific as you can. Do not use **and so on** as a replacement.
Try to avoid **etc.**. Be as specific as you can. Do not use
[**and so on**](#and-so-on) as a replacement.
- Do: You can update objects, like merge requests and issues.
- Do not: You can update objects, like merge requests, issues, etc.

View File

@ -68,9 +68,9 @@ We use the following terminology to describe the Service Ping components:
Starting with GitLab version 14.1, free self-managed users running [GitLab EE](../ee_features.md) can receive paid features by registering with GitLab and sending us activity data via [Service Ping](#what-is-service-ping). Features introduced here do not remove the feature from its paid tier. Users can continue to access the features in a paid tier without sharing usage data.
The paid feature available in this offering is [Email from GitLab](../../tools/email.md).
Administrators can use this [Premium](https://about.gitlab.com/pricing/premium/) feature to streamline
their workflow by emailing all or some instance users directly from the Admin Area.
##### Features available in 14.1 and later
1. [Email from GitLab](../../tools/email.md).
NOTE:
Registration is not yet required for participation, but will be added in a future milestone.

View File

@ -264,8 +264,6 @@ module API
when 'md5'
''
else
track_package_event('push_package', :maven, user: current_user, project: user_project, namespace: user_project.namespace) if jar_file?(format)
file_params = {
file: params[:file],
size: params['file.size'],
@ -276,6 +274,7 @@ module API
}
::Packages::CreatePackageFileService.new(package, file_params.merge(build: current_authenticated_job)).execute
track_package_event('push_package', :maven, user: current_user, project: user_project, namespace: user_project.namespace) if jar_file?(format)
end
end
end

View File

@ -177,6 +177,7 @@ module API
optional :whats_new_variant, type: String, values: ApplicationSetting.whats_new_variants.keys, desc: "What's new variant, possible values: `all_tiers`, `current_tier`, and `disabled`."
optional :floc_enabled, type: Grape::API::Boolean, desc: 'Enable FloC (Federated Learning of Cohorts)'
optional :user_deactivation_emails_enabled, type: Boolean, desc: 'Send emails to users upon account deactivation'
optional :suggest_pipeline_enabled, type: Boolean, desc: 'Enable pipeline suggestion banner'
ApplicationSetting::SUPPORTED_KEY_TYPES.each do |type|
optional :"#{type}_key_restriction",

View File

@ -44,7 +44,7 @@ module Gitlab
# We want to use AttributesCleaner for these relations instead, in the future this should be removed to make sure
# we are using AttributesPermitter for every imported relation.
DISABLED_RELATION_NAMES = %i[user author ci_cd_settings issuable_sla push_rule].freeze
DISABLED_RELATION_NAMES = %i[user author issuable_sla].freeze
def initialize(config: ImportExport::Config.new.to_h)
@config = config

View File

@ -183,7 +183,7 @@ module Gitlab
def parsed_relation_hash
strong_memoize(:parsed_relation_hash) do
if Feature.enabled?(:permitted_attributes_for_import_export, default_enabled: :yaml) && attributes_permitter.permitted_attributes_defined?(@relation_sym)
if use_attributes_permitter? && attributes_permitter.permitted_attributes_defined?(@relation_sym)
attributes_permitter.permit(@relation_sym, @relation_hash)
else
Gitlab::ImportExport::AttributeCleaner.clean(relation_hash: @relation_hash, relation_class: relation_class)
@ -195,6 +195,10 @@ module Gitlab
@attributes_permitter ||= Gitlab::ImportExport::AttributesPermitter.new
end
def use_attributes_permitter?
Feature.enabled?(:permitted_attributes_for_import_export, default_enabled: :yaml)
end
def existing_or_new_object
# Only find existing records to avoid mapping tables such as milestones
# Otherwise always create the record, skipping the extra SELECT clause.

View File

@ -10,6 +10,7 @@ tree:
- labels:
- :priorities
- boards:
- :milestone
- lists:
- label:
- :priorities

View File

@ -36,6 +36,10 @@ module Gitlab
@relation_hash['group_id'] = @importable.id
end
def use_attributes_permitter?
false
end
end
end
end

View File

@ -131,7 +131,6 @@ included_attributes:
- :link_url
- :name
- :project_id
- :type
- :updated_at
pipeline_schedules:
- :active
@ -155,6 +154,77 @@ included_attributes:
- :enabled
- :project_id
- :updated_at
boards:
- :project_id
- :created_at
- :updated_at
- :group_id
- :weight
- :name
- :hide_backlog_list
- :hide_closed_list
lists:
- :list_type
- :position
- :created_at
- :updated_at
- :user_id
- :max_issue_count
- :max_issue_weight
- :limit_metric
custom_attributes:
- :created_at
- :updated_at
- :project_id
- :key
- :value
label:
- :title
- :color
- :project_id
- :group_id
- :created_at
- :updated_at
- :template
- :description
- :priority
labels:
- :title
- :color
- :project_id
- :group_id
- :created_at
- :updated_at
- :template
- :description
- :priority
priorities:
- :project_id
- :priority
- :created_at
- :updated_at
milestone:
- :iid
- :title
- :project_id
- :group_id
- :description
- :due_date
- :created_at
- :updated_at
- :start_date
- :state
milestones:
- :iid
- :title
- :project_id
- :group_id
- :description
- :due_date
- :created_at
- :updated_at
- :start_date
- :state
# Do not include the following attributes for the models specified.
excluded_attributes:
@ -498,6 +568,10 @@ ee:
- :deploy_access_levels
- :security_setting
- :push_rule
- boards:
- :milestone
- lists:
- :milestone
included_attributes:
issuable_sla:

View File

@ -10,6 +10,7 @@ module Gitlab
@namespace = namespace
@plan = namespace&.actual_plan_name
@project = project
@user = user
@extra = extra
end
@ -35,7 +36,7 @@ module Gitlab
private
attr_accessor :namespace, :project, :extra, :plan
attr_accessor :namespace, :project, :extra, :plan, :user
def to_h
{
@ -44,6 +45,7 @@ module Gitlab
plan: plan,
extra: extra
}.merge(project_and_namespace)
.merge(user_data)
end
def project_and_namespace
@ -58,6 +60,10 @@ module Gitlab
def project_id
project.is_a?(Integer) ? project : project&.id
end
def user_data
::Feature.enabled?(:add_actor_based_user_to_snowplow_tracking, user) ? { user_id: user&.id } : {}
end
end
end
end

View File

@ -123,17 +123,9 @@ module Gitlab
clusters_platforms_eks: count(::Clusters::Cluster.aws_installed.enabled),
clusters_platforms_gke: count(::Clusters::Cluster.gcp_installed.enabled),
clusters_platforms_user: count(::Clusters::Cluster.user_provided.enabled),
clusters_applications_helm: count(::Clusters::Applications::Helm.available),
clusters_applications_ingress: count(::Clusters::Applications::Ingress.available),
clusters_applications_cert_managers: count(::Clusters::Applications::CertManager.available),
clusters_applications_crossplane: count(::Clusters::Applications::Crossplane.available),
clusters_applications_prometheus: count(::Clusters::Applications::Prometheus.available),
clusters_applications_runner: count(::Clusters::Applications::Runner.available),
clusters_applications_knative: count(::Clusters::Applications::Knative.available),
clusters_applications_elastic_stack: count(::Clusters::Applications::ElasticStack.available),
clusters_applications_jupyter: count(::Clusters::Applications::Jupyter.available),
clusters_applications_cilium: count(::Clusters::Applications::Cilium.available),
clusters_management_project: count(::Clusters::Cluster.with_management_project),
clusters_integrations_elastic_stack: count(::Clusters::Integrations::ElasticStack.enabled),
clusters_integrations_prometheus: count(::Clusters::Integrations::Prometheus.enabled),
kubernetes_agents: count(::Clusters::Agent),
kubernetes_agents_with_token: distinct_count(::Clusters::AgentToken, :agent_id),
in_review_folder: count(::Environment.in_review_folder),
@ -523,10 +515,6 @@ module Gitlab
# rubocop: disable UsageData/LargeTable
def usage_activity_by_stage_configure(time_period)
{
clusters_applications_cert_managers: cluster_applications_user_distinct_count(::Clusters::Applications::CertManager, time_period),
clusters_applications_helm: cluster_applications_user_distinct_count(::Clusters::Applications::Helm, time_period),
clusters_applications_ingress: cluster_applications_user_distinct_count(::Clusters::Applications::Ingress, time_period),
clusters_applications_knative: cluster_applications_user_distinct_count(::Clusters::Applications::Knative, time_period),
clusters_management_project: clusters_user_distinct_count(::Clusters::Cluster.with_management_project, time_period),
clusters_disabled: clusters_user_distinct_count(::Clusters::Cluster.disabled, time_period),
clusters_enabled: clusters_user_distinct_count(::Clusters::Cluster.enabled, time_period),
@ -621,7 +609,7 @@ module Gitlab
{
clusters: distinct_count(::Clusters::Cluster.where(time_period), :user_id),
clusters_applications_prometheus: cluster_applications_user_distinct_count(::Clusters::Applications::Prometheus, time_period),
clusters_integrations_prometheus: cluster_integrations_user_distinct_count(::Clusters::Integrations::Prometheus, time_period),
operations_dashboard_default_dashboard: count(::User.active.with_dashboard('operations').where(time_period),
start: minimum_id(User),
finish: maximum_id(User)),
@ -687,8 +675,7 @@ module Gitlab
ci_pipeline_config_repository: distinct_count(::Ci::Pipeline.repository_source.where(time_period), :user_id, start: minimum_id(User), finish: maximum_id(User)),
ci_pipeline_schedules: distinct_count(::Ci::PipelineSchedule.where(time_period), :owner_id),
ci_pipelines: distinct_count(::Ci::Pipeline.where(time_period), :user_id, start: minimum_id(User), finish: maximum_id(User)),
ci_triggers: distinct_count(::Ci::Trigger.where(time_period), :owner_id),
clusters_applications_runner: cluster_applications_user_distinct_count(::Clusters::Applications::Runner, time_period)
ci_triggers: distinct_count(::Ci::Trigger.where(time_period), :owner_id)
}
end
# rubocop: enable CodeReuse/ActiveRecord
@ -873,8 +860,8 @@ module Gitlab
end
# rubocop: disable CodeReuse/ActiveRecord
def cluster_applications_user_distinct_count(applications, time_period)
distinct_count(applications.where(time_period).available.joins(:cluster), 'clusters.user_id')
def cluster_integrations_user_distinct_count(integrations, time_period)
distinct_count(integrations.where(time_period).enabled.joins(:cluster), 'clusters.user_id')
end
def clusters_user_distinct_count(clusters, time_period)

View File

@ -1055,6 +1055,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr ""
msgid "%{widget} options"
msgstr ""
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
@ -5965,9 +5968,6 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
msgid "CI minutes"
msgstr ""
msgid "CI settings"
msgstr ""
@ -6637,6 +6637,9 @@ msgstr ""
msgid "Checkout|CI minute packs are only used after you've used your subscription's monthly quota. The additional minutes will roll over month to month and are valid for one year."
msgstr ""
msgid "Checkout|CI minutes"
msgstr ""
msgid "Checkout|Checkout"
msgstr ""
@ -6784,6 +6787,9 @@ msgstr ""
msgid "Checkout|minutes"
msgstr ""
msgid "Checkout|x %{quantity} %{units} per pack"
msgstr ""
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr ""

View File

@ -81,7 +81,7 @@ module QA
def with_retry_on_too_many_requests
response = nil
Support::Retrier.retry_until do
Support::Retrier.retry_until(log: false) do
response = yield
if response.code == HTTP_STATUS_TOO_MANY_REQUESTS

View File

@ -34,15 +34,29 @@ module QA
result
end
def retry_until(max_attempts: nil, max_duration: nil, reload_page: nil, sleep_interval: 0, raise_on_failure: true, retry_on_exception: false, log: true)
def retry_until(
max_attempts: nil,
max_duration: nil,
reload_page: nil,
sleep_interval: 0,
raise_on_failure: true,
retry_on_exception: false,
log: true
)
# For backwards-compatibility
max_attempts = 3 if max_attempts.nil? && max_duration.nil?
if log
start_msg ||= ["with retry_until:"]
start_msg = ["with retry_until:"]
start_msg << "max_attempts: #{max_attempts};" if max_attempts
start_msg << "max_duration: #{max_duration};" if max_duration
start_msg << "reload_page: #{reload_page}; sleep_interval: #{sleep_interval}; raise_on_failure: #{raise_on_failure}; retry_on_exception: #{retry_on_exception}"
start_msg.push(*[
"reload_page: #{reload_page};",
"sleep_interval: #{sleep_interval};",
"raise_on_failure: #{raise_on_failure};",
"retry_on_exception: #{retry_on_exception}"
])
QA::Runtime::Logger.debug(start_msg.join(' '))
end
@ -58,7 +72,7 @@ module QA
) do
result = yield
end
QA::Runtime::Logger.debug("ended retry_until")
QA::Runtime::Logger.debug("ended retry_until") if log
result
end

View File

@ -88,17 +88,9 @@ FactoryBot.define do
create(:cluster, :group, :disabled)
create(:cluster, :instance, :disabled)
# Applications
create(:clusters_applications_helm, :installed, cluster: gcp_cluster)
create(:clusters_applications_ingress, :installed, cluster: gcp_cluster)
create(:clusters_applications_cert_manager, :installed, cluster: gcp_cluster)
create(:clusters_applications_prometheus, :installed, cluster: gcp_cluster)
create(:clusters_applications_crossplane, :installed, cluster: gcp_cluster)
create(:clusters_applications_runner, :installed, cluster: gcp_cluster)
create(:clusters_applications_knative, :installed, cluster: gcp_cluster)
create(:clusters_applications_elastic_stack, :installed, cluster: gcp_cluster)
create(:clusters_applications_jupyter, :installed, cluster: gcp_cluster)
create(:clusters_applications_cilium, :installed, cluster: gcp_cluster)
# Cluster Integrations
create(:clusters_integrations_prometheus, cluster: gcp_cluster)
create(:clusters_integrations_elastic_stack, cluster: gcp_cluster)
create(:grafana_integration, project: projects[0], enabled: true)
create(:grafana_integration, project: projects[1], enabled: true)

View File

@ -44,7 +44,7 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do
let(:actor) { developer_in_both }
it 'returns all pipelines' do
is_expected.to eq([pipeline_in_fork, pipeline_in_parent])
is_expected.to match_array([pipeline_in_fork, pipeline_in_parent])
end
end
@ -52,7 +52,7 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do
let(:actor) { reporter_in_parent_and_developer_in_fork }
it 'returns all pipelines' do
is_expected.to eq([pipeline_in_fork, pipeline_in_parent])
is_expected.to match_array([pipeline_in_fork, pipeline_in_parent])
end
end
@ -60,7 +60,7 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do
let(:actor) { developer_in_parent }
it 'returns pipelines in parent' do
is_expected.to eq([pipeline_in_parent])
is_expected.to match_array([pipeline_in_parent])
end
end
@ -68,7 +68,7 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do
let(:actor) { developer_in_fork }
it 'returns pipelines in fork' do
is_expected.to eq([pipeline_in_fork])
is_expected.to match_array([pipeline_in_fork])
end
end
@ -97,7 +97,7 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do
shared_examples 'returning pipelines with proper ordering' do
let!(:all_pipelines) do
merge_request.all_commit_shas.map do |sha|
merge_request.recent_diff_head_shas.map do |sha|
create(:ci_empty_pipeline,
project: project, sha: sha, ref: merge_request.source_branch)
end
@ -135,12 +135,92 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do
end
context 'when pipelines exist for the branch and merge request' do
shared_examples 'returns all pipelines for merge request' do
it 'returns merge request pipeline first' do
expect(subject.all).to eq([detached_merge_request_pipeline, branch_pipeline])
end
context 'when there are a branch pipeline and a merge request pipeline' do
let!(:branch_pipeline_2) do
create(:ci_pipeline, source: :push, project: project,
ref: source_ref, sha: shas.first)
end
let!(:detached_merge_request_pipeline_2) do
create(:ci_pipeline, source: :merge_request_event, project: project,
ref: source_ref, sha: shas.first, merge_request: merge_request)
end
it 'returns merge request pipelines first' do
expect(subject.all)
.to eq([detached_merge_request_pipeline_2,
detached_merge_request_pipeline,
branch_pipeline_2,
branch_pipeline])
end
end
context 'when there are multiple merge request pipelines from the same branch' do
let!(:branch_pipeline_2) do
create(:ci_pipeline, source: :push, project: project,
ref: source_ref, sha: shas.first)
end
let!(:branch_pipeline_with_sha_not_belonging_to_merge_request) do
create(:ci_pipeline, source: :push, project: project, ref: source_ref)
end
let!(:detached_merge_request_pipeline_2) do
create(:ci_pipeline, source: :merge_request_event, project: project,
ref: source_ref, sha: shas.first, merge_request: merge_request_2)
end
let(:merge_request_2) do
create(:merge_request, source_project: project, source_branch: source_ref,
target_project: project, target_branch: 'stable')
end
before do
shas.each.with_index do |sha, index|
create(:merge_request_diff_commit,
merge_request_diff: merge_request_2.merge_request_diff,
sha: sha, relative_order: index)
end
end
it 'returns only related merge request pipelines' do
expect(subject.all)
.to eq([detached_merge_request_pipeline,
branch_pipeline_2,
branch_pipeline])
expect(described_class.new(merge_request_2, nil).all)
.to match_array([detached_merge_request_pipeline_2, branch_pipeline_2, branch_pipeline])
end
end
context 'when detached merge request pipeline is run on head ref of the merge request' do
let!(:detached_merge_request_pipeline) do
create(:ci_pipeline, source: :merge_request_event, project: project,
ref: merge_request.ref_path, sha: shas.second, merge_request: merge_request)
end
it 'sets the head ref of the merge request to the pipeline ref' do
expect(detached_merge_request_pipeline.ref).to match(%r{refs/merge-requests/\d+/head})
end
it 'includes the detached merge request pipeline even though the ref is custom path' do
expect(merge_request.all_pipelines).to include(detached_merge_request_pipeline)
end
end
end
let(:source_ref) { 'feature' }
let(:target_ref) { 'master' }
let!(:branch_pipeline) do
create(:ci_pipeline, source: :push, project: project,
ref: source_ref, sha: shas.second)
ref: source_ref, sha: merge_request.merge_request_diff.head_commit_sha)
end
let!(:tag_pipeline) do
@ -149,97 +229,31 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do
let!(:detached_merge_request_pipeline) do
create(:ci_pipeline, source: :merge_request_event, project: project,
ref: source_ref, sha: shas.second, merge_request: merge_request)
ref: source_ref, sha: shas.second, merge_request: merge_request)
end
let(:merge_request) do
create(:merge_request, source_project: project, source_branch: source_ref,
target_project: project, target_branch: target_ref)
target_project: project, target_branch: target_ref)
end
let(:project) { create(:project, :repository) }
let(:shas) { project.repository.commits(source_ref, limit: 2).map(&:id) }
before do
create(:merge_request_diff_commit,
merge_request_diff: merge_request.merge_request_diff,
sha: shas.second, relative_order: 1)
end
it 'returns merge request pipeline first' do
expect(subject.all).to eq([detached_merge_request_pipeline, branch_pipeline])
end
context 'when there are a branch pipeline and a merge request pipeline' do
let!(:branch_pipeline_2) do
create(:ci_pipeline, source: :push, project: project,
ref: source_ref, sha: shas.first)
end
let!(:detached_merge_request_pipeline_2) do
create(:ci_pipeline, source: :merge_request_event, project: project,
ref: source_ref, sha: shas.first, merge_request: merge_request)
end
it 'returns merge request pipelines first' do
expect(subject.all)
.to eq([detached_merge_request_pipeline_2,
detached_merge_request_pipeline,
branch_pipeline_2,
branch_pipeline])
end
end
context 'when there are multiple merge request pipelines from the same branch' do
let!(:branch_pipeline_2) do
create(:ci_pipeline, source: :push, project: project,
ref: source_ref, sha: shas.first)
end
let!(:detached_merge_request_pipeline_2) do
create(:ci_pipeline, source: :merge_request_event, project: project,
ref: source_ref, sha: shas.first, merge_request: merge_request_2)
end
let(:merge_request_2) do
create(:merge_request, source_project: project, source_branch: source_ref,
target_project: project, target_branch: 'stable')
end
context 'when `decomposed_ci_query_in_pipelines_for_merge_request_finder` feature flag enabled' do
before do
shas.each.with_index do |sha, index|
create(:merge_request_diff_commit,
merge_request_diff: merge_request_2.merge_request_diff,
sha: sha, relative_order: index)
end
stub_feature_flags(decomposed_ci_query_in_pipelines_for_merge_request_finder: merge_request.target_project)
end
it 'returns only related merge request pipelines' do
expect(subject.all)
.to eq([detached_merge_request_pipeline,
branch_pipeline_2,
branch_pipeline])
expect(described_class.new(merge_request_2, nil).all)
.to eq([detached_merge_request_pipeline_2,
branch_pipeline_2,
branch_pipeline])
end
it_behaves_like 'returns all pipelines for merge request'
end
context 'when detached merge request pipeline is run on head ref of the merge request' do
let!(:detached_merge_request_pipeline) do
create(:ci_pipeline, source: :merge_request_event, project: project,
ref: merge_request.ref_path, sha: shas.second, merge_request: merge_request)
context 'when `decomposed_ci_query_in_pipelines_for_merge_request_finder` feature flag disabled' do
before do
stub_feature_flags(decomposed_ci_query_in_pipelines_for_merge_request_finder: false)
end
it 'sets the head ref of the merge request to the pipeline ref' do
expect(detached_merge_request_pipeline.ref).to match(%r{refs/merge-requests/\d+/head})
end
it 'includes the detached merge request pipeline even though the ref is custom path' do
expect(merge_request.all_pipelines).to include(detached_merge_request_pipeline)
end
it_behaves_like 'returns all pipelines for merge request'
end
end
end

View File

@ -7759,7 +7759,29 @@
"created_at": "2019-06-06T14:01:06.204Z",
"updated_at": "2019-06-06T14:22:37.045Z",
"name": "TestBoardABC",
"milestone_id": null,
"milestone": {
"id": 1,
"title": "test milestone",
"project_id": 8,
"description": "test milestone",
"due_date": null,
"created_at": "2016-06-14T15:02:04.415Z",
"updated_at": "2016-06-14T15:02:04.415Z",
"state": "active",
"iid": 1,
"events": [
{
"id": 487,
"target_type": "Milestone",
"target_id": 1,
"project_id": 46,
"created_at": "2016-06-14T15:02:04.418Z",
"updated_at": "2016-06-14T15:02:04.418Z",
"action": 1,
"author_id": 18
}
]
},
"group_id": null,
"weight": null,
"lists": [
@ -7772,7 +7794,29 @@
"created_at": "2019-06-06T14:01:06.214Z",
"updated_at": "2019-06-06T14:01:06.214Z",
"user_id": null,
"milestone_id": null
"milestone": {
"id": 1,
"title": "test milestone",
"project_id": 8,
"description": "test milestone",
"due_date": null,
"created_at": "2016-06-14T15:02:04.415Z",
"updated_at": "2016-06-14T15:02:04.415Z",
"state": "active",
"iid": 1,
"events": [
{
"id": 487,
"target_type": "Milestone",
"target_id": 1,
"project_id": 46,
"created_at": "2016-06-14T15:02:04.418Z",
"updated_at": "2016-06-14T15:02:04.418Z",
"action": 1,
"author_id": 18
}
]
}
},
{
"id": 61,
@ -7783,7 +7827,29 @@
"created_at": "2019-06-06T14:01:43.197Z",
"updated_at": "2019-06-06T14:01:43.197Z",
"user_id": null,
"milestone_id": null,
"milestone": {
"id": 1,
"title": "test milestone",
"project_id": 8,
"description": "test milestone",
"due_date": null,
"created_at": "2016-06-14T15:02:04.415Z",
"updated_at": "2016-06-14T15:02:04.415Z",
"state": "active",
"iid": 1,
"events": [
{
"id": 487,
"target_type": "Milestone",
"target_id": 1,
"project_id": 46,
"created_at": "2016-06-14T15:02:04.418Z",
"updated_at": "2016-06-14T15:02:04.418Z",
"action": 1,
"author_id": 18
}
]
},
"label": {
"id": 20,
"title": "testlabel",
@ -7807,7 +7873,29 @@
"created_at": "2019-06-06T14:01:06.221Z",
"updated_at": "2019-06-06T14:01:06.221Z",
"user_id": null,
"milestone_id": null
"milestone": {
"id": 1,
"title": "test milestone",
"project_id": 8,
"description": "test milestone",
"due_date": null,
"created_at": "2016-06-14T15:02:04.415Z",
"updated_at": "2016-06-14T15:02:04.415Z",
"state": "active",
"iid": 1,
"events": [
{
"id": 487,
"target_type": "Milestone",
"target_id": 1,
"project_id": 46,
"created_at": "2016-06-14T15:02:04.418Z",
"updated_at": "2016-06-14T15:02:04.418Z",
"action": 1,
"author_id": 18
}
]
}
}
]
}

View File

@ -1 +1 @@
{"id":29,"project_id":49,"created_at":"2019-06-06T14:01:06.204Z","updated_at":"2019-06-06T14:22:37.045Z","name":"TestBoardABC","milestone_id":null,"group_id":null,"weight":null,"lists":[{"id":59,"board_id":29,"label_id":null,"list_type":"backlog","position":null,"created_at":"2019-06-06T14:01:06.214Z","updated_at":"2019-06-06T14:01:06.214Z","user_id":null,"milestone_id":null},{"id":61,"board_id":29,"label_id":20,"list_type":"label","position":0,"created_at":"2019-06-06T14:01:43.197Z","updated_at":"2019-06-06T14:01:43.197Z","user_id":null,"milestone_id":null,"label":{"id":20,"title":"testlabel","color":"#0033CC","project_id":49,"created_at":"2019-06-06T14:01:19.698Z","updated_at":"2019-06-06T14:01:19.698Z","template":false,"description":null,"group_id":null,"type":"ProjectLabel","priorities":[]}},{"id":60,"board_id":29,"label_id":null,"list_type":"closed","position":null,"created_at":"2019-06-06T14:01:06.221Z","updated_at":"2019-06-06T14:01:06.221Z","user_id":null,"milestone_id":null}]}
{"id":29,"project_id":49,"created_at":"2019-06-06T14:01:06.204Z","updated_at":"2019-06-06T14:22:37.045Z","name":"TestBoardABC","group_id":null,"weight":null,"milestone":{"id":1,"title":"test milestone","project_id":8,"description":"test milestone","due_date":null,"created_at":"2016-06-14T15:02:04.415Z","updated_at":"2016-06-14T15:02:04.415Z","state":"active","iid":1,"events":[{"id":487,"target_type":"Milestone","target_id":1,"project_id":46,"created_at":"2016-06-14T15:02:04.418Z","updated_at":"2016-06-14T15:02:04.418Z","action":1,"author_id":18}]},"lists":[{"id":59,"board_id":29,"label_id":null,"list_type":"backlog","position":null,"created_at":"2019-06-06T14:01:06.214Z","updated_at":"2019-06-06T14:01:06.214Z","user_id":null,"milestone":{"id":1,"title":"test milestone","project_id":8,"description":"test milestone","due_date":null,"created_at":"2016-06-14T15:02:04.415Z","updated_at":"2016-06-14T15:02:04.415Z","state":"active","iid":1,"events":[{"id":487,"target_type":"Milestone","target_id":1,"project_id":46,"created_at":"2016-06-14T15:02:04.418Z","updated_at":"2016-06-14T15:02:04.418Z","action":1,"author_id":18}]}},{"id":61,"board_id":29,"label_id":20,"list_type":"label","position":0,"created_at":"2019-06-06T14:01:43.197Z","updated_at":"2019-06-06T14:01:43.197Z","user_id":null,"milestone":{"id":1,"title":"test milestone","project_id":8,"description":"test milestone","due_date":null,"created_at":"2016-06-14T15:02:04.415Z","updated_at":"2016-06-14T15:02:04.415Z","state":"active","iid":1,"events":[{"id":487,"target_type":"Milestone","target_id":1,"project_id":46,"created_at":"2016-06-14T15:02:04.418Z","updated_at":"2016-06-14T15:02:04.418Z","action":1,"author_id":18}]},"label":{"id":20,"title":"testlabel","color":"#0033CC","project_id":49,"created_at":"2019-06-06T14:01:19.698Z","updated_at":"2019-06-06T14:01:19.698Z","template":false,"description":null,"group_id":null,"type":"ProjectLabel","priorities":[]}},{"id":60,"board_id":29,"label_id":null,"list_type":"closed","position":null,"created_at":"2019-06-06T14:01:06.221Z","updated_at":"2019-06-06T14:01:06.221Z","user_id":null,"milestone":{"id":1,"title":"test milestone","project_id":8,"description":"test milestone","due_date":null,"created_at":"2016-06-14T15:02:04.415Z","updated_at":"2016-06-14T15:02:04.415Z","state":"active","iid":1,"events":[{"id":487,"target_type":"Milestone","target_id":1,"project_id":46,"created_at":"2016-06-14T15:02:04.418Z","updated_at":"2016-06-14T15:02:04.418Z","action":1,"author_id":18}]}}]}

View File

@ -0,0 +1,35 @@
import { GlButton, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Actions from '~/vue_merge_request_widget/components/extensions/actions.vue';
let wrapper;
function factory(propsData = {}) {
wrapper = shallowMount(Actions, {
propsData: { ...propsData, widget: 'test' },
});
}
describe('MR widget extension actions', () => {
afterEach(() => {
wrapper.destroy();
});
describe('tertiaryButtons', () => {
it('renders buttons', () => {
factory({
tertiaryButtons: [{ text: 'hello world', href: 'https://gitlab.com', target: '_blank' }],
});
expect(wrapper.findAllComponents(GlButton)).toHaveLength(1);
});
it('renders tertiary actions in dropdown', () => {
factory({
tertiaryButtons: [{ text: 'hello world', href: 'https://gitlab.com', target: '_blank' }],
});
expect(wrapper.findAllComponents(GlDropdownItem)).toHaveLength(1);
});
});
});

View File

@ -83,14 +83,15 @@ RSpec.describe Gitlab::ImportExport::AttributesPermitter do
where(:relation_name, :permitted_attributes_defined) do
:user | false
:author | false
:ci_cd_settings | false
:issuable_sla | false
:push_rule | false
:ci_cd_settings | true
:metrics_setting | true
:project_badges | true
:pipeline_schedules | true
:error_tracking_setting | true
:auto_devops | true
:boards | true
:custom_attributes | true
:labels | true
end
with_them do
@ -99,47 +100,11 @@ RSpec.describe Gitlab::ImportExport::AttributesPermitter do
end
describe 'included_attributes for Project' do
let(:prohibited_attributes) { %i[remote_url my_attributes my_ids token my_id test] }
subject { described_class.new }
Gitlab::ImportExport::Config.new.to_h[:included_attributes].each do |relation_sym, permitted_attributes|
context "for #{relation_sym}" do
let(:import_export_config) { Gitlab::ImportExport::Config.new.to_h }
let(:project_relation_factory) { Gitlab::ImportExport::Project::RelationFactory }
let(:relation_hash) { (permitted_attributes + prohibited_attributes).map(&:to_s).zip([]).to_h }
let(:relation_name) { project_relation_factory.overrides[relation_sym]&.to_sym || relation_sym }
let(:relation_class) { project_relation_factory.relation_class(relation_name) }
let(:excluded_keys) { import_export_config.dig(:excluded_keys, relation_sym) || [] }
let(:cleaned_hash) do
Gitlab::ImportExport::AttributeCleaner.new(
relation_hash: relation_hash,
relation_class: relation_class,
excluded_keys: excluded_keys
).clean
end
let(:permitted_hash) { subject.permit(relation_sym, relation_hash) }
if described_class.new.permitted_attributes_defined?(relation_sym)
it 'contains only attributes that are defined as permitted in the import/export config' do
expect(permitted_hash.keys).to contain_exactly(*permitted_attributes.map(&:to_s))
end
it 'does not contain attributes that would be cleaned with AttributeCleaner' do
expect(cleaned_hash.keys).to include(*permitted_hash.keys)
end
it 'does not contain prohibited attributes that are not related to given relation' do
expect(permitted_hash.keys).not_to include(*prohibited_attributes.map(&:to_s))
end
else
it 'is disabled' do
expect(subject).not_to be_permitted_attributes_defined(relation_sym)
end
end
it_behaves_like 'a permitted attribute', relation_sym, permitted_attributes
end
end
end

View File

@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Tracking::StandardContext do
let_it_be(:project) { create(:project) }
let_it_be(:namespace) { create(:namespace) }
let_it_be(:user) { create(:user) }
let(:snowplow_context) { subject.to_context }
@ -87,8 +88,8 @@ RSpec.describe Gitlab::Tracking::StandardContext do
end
end
it 'does not contain user id' do
expect(snowplow_context.to_json[:data].keys).not_to include(:user_id)
it 'contains user id' do
expect(snowplow_context.to_json[:data].keys).to include(:user_id)
end
it 'contains namespace and project ids' do
@ -104,8 +105,18 @@ RSpec.describe Gitlab::Tracking::StandardContext do
stub_feature_flags(add_namespace_and_project_to_snowplow_tracking: false)
end
it 'does not contain any ids' do
expect(snowplow_context.to_json[:data].keys).not_to include(:user_id, :project_id, :namespace_id)
it 'does not contain project or namespace ids' do
expect(snowplow_context.to_json[:data].keys).not_to include(:project_id, :namespace_id)
end
end
context 'without add_actor_based_user_to_snowplow_tracking feature' do
before do
stub_feature_flags(add_actor_based_user_to_snowplow_tracking: false)
end
it 'does not contain user_id' do
expect(snowplow_context.to_json[:data].keys).not_to include(:user_id)
end
end
end

View File

@ -48,7 +48,7 @@ RSpec.describe Gitlab::Tracking do
other_context = double(:context)
project = build_stubbed(:project)
user = double(:user)
user = build_stubbed(:user)
expect(Gitlab::Tracking::StandardContext)
.to receive(:new)

View File

@ -101,11 +101,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
it 'includes accurate usage_activity_by_stage data' do
for_defined_days_back do
user = create(:user)
cluster = create(:cluster, user: user)
create(:clusters_applications_cert_manager, :installed, cluster: cluster)
create(:clusters_applications_helm, :installed, cluster: cluster)
create(:clusters_applications_ingress, :installed, cluster: cluster)
create(:clusters_applications_knative, :installed, cluster: cluster)
create(:cluster, user: user)
create(:cluster, :disabled, user: user)
create(:cluster_provider_gcp, :created)
create(:cluster_provider_aws, :created)
@ -118,10 +114,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
expect(described_class.usage_activity_by_stage_configure({})).to include(
clusters_applications_cert_managers: 2,
clusters_applications_helm: 2,
clusters_applications_ingress: 2,
clusters_applications_knative: 2,
clusters_management_project: 2,
clusters_disabled: 4,
clusters_enabled: 12,
@ -136,10 +128,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
project_clusters_enabled: 10
)
expect(described_class.usage_activity_by_stage_configure(described_class.monthly_time_range_db_params)).to include(
clusters_applications_cert_managers: 1,
clusters_applications_helm: 1,
clusters_applications_ingress: 1,
clusters_applications_knative: 1,
clusters_management_project: 1,
clusters_disabled: 2,
clusters_enabled: 6,
@ -392,7 +380,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
user = create(:user, dashboard: 'operations')
cluster = create(:cluster, user: user)
project = create(:project, creator: user)
create(:clusters_applications_prometheus, :installed, cluster: cluster)
create(:clusters_integrations_prometheus, cluster: cluster)
create(:project_tracing_setting)
create(:project_error_tracking_setting)
create(:incident)
@ -402,7 +390,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(described_class.usage_activity_by_stage_monitor({})).to include(
clusters: 2,
clusters_applications_prometheus: 2,
clusters_integrations_prometheus: 2,
operations_dashboard_default_dashboard: 2,
projects_with_tracing_enabled: 2,
projects_with_error_tracking_enabled: 2,
@ -414,7 +402,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
data_28_days = described_class.usage_activity_by_stage_monitor(described_class.monthly_time_range_db_params)
expect(data_28_days).to include(
clusters: 1,
clusters_applications_prometheus: 1,
clusters_integrations_prometheus: 1,
operations_dashboard_default_dashboard: 1,
projects_with_tracing_enabled: 1,
projects_with_error_tracking_enabled: 1,
@ -502,7 +490,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
create(:ci_pipeline, :repository_source, user: user)
create(:ci_pipeline_schedule, owner: user)
create(:ci_trigger, owner: user)
create(:clusters_applications_runner, :installed)
end
expect(described_class.usage_activity_by_stage_verify({})).to include(
@ -513,8 +500,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
ci_pipeline_config_repository: 2,
ci_pipeline_schedules: 2,
ci_pipelines: 2,
ci_triggers: 2,
clusters_applications_runner: 2
ci_triggers: 2
)
expect(described_class.usage_activity_by_stage_verify(described_class.monthly_time_range_db_params)).to include(
ci_builds: 1,
@ -524,8 +510,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
ci_pipeline_config_repository: 1,
ci_pipeline_schedules: 1,
ci_pipelines: 1,
ci_triggers: 1,
clusters_applications_runner: 1
ci_triggers: 1
)
end
end
@ -607,17 +592,9 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(count_data[:clusters_platforms_eks]).to eq(1)
expect(count_data[:clusters_platforms_gke]).to eq(1)
expect(count_data[:clusters_platforms_user]).to eq(1)
expect(count_data[:clusters_applications_helm]).to eq(1)
expect(count_data[:clusters_applications_ingress]).to eq(1)
expect(count_data[:clusters_applications_cert_managers]).to eq(1)
expect(count_data[:clusters_applications_crossplane]).to eq(1)
expect(count_data[:clusters_applications_prometheus]).to eq(1)
expect(count_data[:clusters_applications_runner]).to eq(1)
expect(count_data[:clusters_applications_knative]).to eq(1)
expect(count_data[:clusters_applications_elastic_stack]).to eq(1)
expect(count_data[:clusters_integrations_elastic_stack]).to eq(1)
expect(count_data[:clusters_integrations_prometheus]).to eq(1)
expect(count_data[:grafana_integrated_projects]).to eq(2)
expect(count_data[:clusters_applications_jupyter]).to eq(1)
expect(count_data[:clusters_applications_cilium]).to eq(1)
expect(count_data[:clusters_management_project]).to eq(1)
expect(count_data[:kubernetes_agents]).to eq(2)
expect(count_data[:kubernetes_agents_with_token]).to eq(1)

View File

@ -39,7 +39,7 @@ RSpec.describe 'Query.project.mergeRequests.pipelines' do
before do
merge_requests.each do |mr|
shas = mr.all_commits.limit(2).pluck(:sha)
shas = mr.recent_diff_head_shas
shas.each do |sha|
create(:ci_pipeline, :success, project: project, ref: mr.source_branch, sha: sha)
@ -52,7 +52,7 @@ RSpec.describe 'Query.project.mergeRequests.pipelines' do
p_nodes = graphql_data_at(:project, :merge_requests, :nodes)
expect(p_nodes).to all(match('iid' => be_present, 'pipelines' => match('count' => 2)))
expect(p_nodes).to all(match('iid' => be_present, 'pipelines' => match('count' => 1)))
end
it 'is scalable', :request_store, :use_clean_rails_memory_store_caching do

View File

@ -798,8 +798,6 @@ RSpec.describe API::MavenPackages do
end
describe 'PUT /api/v4/projects/:id/packages/maven/*path/:file_name' do
include_context 'workhorse headers'
let(:send_rewritten_field) { true }
let(:file_upload) { fixture_file_upload('spec/fixtures/packages/maven/my-app-1.0-20180724.124855-1.jar') }
@ -833,6 +831,8 @@ RSpec.describe API::MavenPackages do
context 'when params from workhorse are correct' do
let(:params) { { file: file_upload } }
subject { upload_file_with_token(params: params) }
context 'file size is too large' do
it 'rejects the request' do
allow_next_instance_of(UploadedFile) do |uploaded_file|
@ -851,18 +851,20 @@ RSpec.describe API::MavenPackages do
expect(response).to have_gitlab_http_status(:bad_request)
end
context 'without workhorse header' do
let(:workhorse_headers) { {} }
subject { upload_file_with_token(params: params) }
it_behaves_like 'package workhorse uploads'
end
it_behaves_like 'package workhorse uploads'
context 'event tracking' do
subject { upload_file_with_token(params: params) }
it_behaves_like 'a package tracking event', described_class.name, 'push_package'
context 'when the package file fails to be created' do
before do
allow_next_instance_of(::Packages::CreatePackageFileService) do |create_package_file_service|
allow(create_package_file_service).to receive(:execute).and_raise(StandardError)
end
end
it_behaves_like 'not a package tracking event'
end
end
it 'creates package and stores package file' do

View File

@ -48,6 +48,7 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
expect(json_response['admin_mode']).to be(false)
expect(json_response['whats_new_variant']).to eq('all_tiers')
expect(json_response['user_deactivation_emails_enabled']).to be(true)
expect(json_response['suggest_pipeline_enabled']).to be(true)
end
end
@ -135,7 +136,8 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
wiki_page_max_content_bytes: 12345,
personal_access_token_prefix: "GL-",
user_deactivation_emails_enabled: false,
admin_mode: true
admin_mode: true,
suggest_pipeline_enabled: false
}
expect(response).to have_gitlab_http_status(:ok)
@ -187,6 +189,7 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
expect(json_response['personal_access_token_prefix']).to eq("GL-")
expect(json_response['admin_mode']).to be(true)
expect(json_response['user_deactivation_emails_enabled']).to be(false)
expect(json_response['suggest_pipeline_enabled']).to be(false)
end
end

View File

@ -54,15 +54,8 @@ module UsageDataHelpers
clusters_platforms_eks
clusters_platforms_gke
clusters_platforms_user
clusters_applications_helm
clusters_applications_ingress
clusters_applications_cert_managers
clusters_applications_prometheus
clusters_applications_crossplane
clusters_applications_runner
clusters_applications_knative
clusters_applications_elastic_stack
clusters_applications_jupyter
clusters_integrations_elastic_stack
clusters_integrations_prometheus
clusters_management_project
in_review_folder
grafana_integrated_projects

View File

@ -0,0 +1,40 @@
# frozen_string_literal: true
RSpec.shared_examples 'a permitted attribute' do |relation_sym, permitted_attributes|
let(:prohibited_attributes) { %i[remote_url my_attributes my_ids token my_id test] }
let(:import_export_config) { Gitlab::ImportExport::Config.new.to_h }
let(:project_relation_factory) { Gitlab::ImportExport::Project::RelationFactory }
let(:relation_hash) { (permitted_attributes + prohibited_attributes).map(&:to_s).zip([]).to_h }
let(:relation_name) { project_relation_factory.overrides[relation_sym]&.to_sym || relation_sym }
let(:relation_class) { project_relation_factory.relation_class(relation_name) }
let(:excluded_keys) { import_export_config.dig(:excluded_keys, relation_sym) || [] }
let(:cleaned_hash) do
Gitlab::ImportExport::AttributeCleaner.new(
relation_hash: relation_hash,
relation_class: relation_class,
excluded_keys: excluded_keys
).clean
end
let(:permitted_hash) { subject.permit(relation_sym, relation_hash) }
if described_class.new.permitted_attributes_defined?(relation_sym)
it 'contains only attributes that are defined as permitted in the import/export config' do
expect(permitted_hash.keys).to contain_exactly(*permitted_attributes.map(&:to_s))
end
it 'does not contain attributes that would be cleaned with AttributeCleaner' do
expect(cleaned_hash.keys).to include(*permitted_hash.keys)
end
it 'does not contain prohibited attributes that are not related to given relation' do
expect(permitted_hash.keys).not_to include(*prohibited_attributes.map(&:to_s))
end
else
it 'is disabled' do
expect(subject).not_to be_permitted_attributes_defined(relation_sym)
end
end
end