diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-10-06 18:11:48 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-10-06 18:11:48 +0300 |
commit | 47d926e838b670f5bfeebab36ddd524f5397c5ca (patch) | |
tree | f0438f24c1ac4acf89009a441761339842ec3b27 | |
parent | 0d1b0d5d03389eea2a4435eea47ec0a37cce9b26 (diff) |
Add latest changes from gitlab-org/gitlab@master
72 files changed, 762 insertions, 265 deletions
diff --git a/app/assets/javascripts/jobs/components/table/cells/actions_cell.vue b/app/assets/javascripts/jobs/components/table/cells/actions_cell.vue index 6ef507126ec..51251c0cacc 100644 --- a/app/assets/javascripts/jobs/components/table/cells/actions_cell.vue +++ b/app/assets/javascripts/jobs/components/table/cells/actions_cell.vue @@ -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', diff --git a/app/assets/javascripts/jobs/utils.js b/app/assets/javascripts/jobs/utils.js index bb27658369f..a4e695518f1 100644 --- a/app/assets/javascripts/jobs/utils.js +++ b/app/assets/javascripts/jobs/utils.js @@ -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); + }); +}; diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/actions.vue b/app/assets/javascripts/vue_merge_request_widget/components/extensions/actions.vue new file mode 100644 index 00000000000..fb883af330e --- /dev/null +++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/actions.vue @@ -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> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue index 1347586c738..7ea24171aa8 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue @@ -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> diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js index 3a07bd0c0fb..0b96b2844c2 100644 --- a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js +++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js @@ -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 diff --git a/app/finders/ci/pipelines_for_merge_request_finder.rb b/app/finders/ci/pipelines_for_merge_request_finder.rb index 5d794c0903a..9476c30f525 100644 --- a/app/finders/ci/pipelines_for_merge_request_finder.rb +++ b/app/finders/ci/pipelines_for_merge_request_finder.rb @@ -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 diff --git a/app/models/clusters/integrations/elastic_stack.rb b/app/models/clusters/integrations/elastic_stack.rb index 565d268259a..97d73d252b9 100644 --- a/app/models/clusters/integrations/elastic_stack.rb +++ b/app/models/clusters/integrations/elastic_stack.rb @@ -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 diff --git a/app/models/clusters/integrations/prometheus.rb b/app/models/clusters/integrations/prometheus.rb index 3f2c47d48e6..d745a49afc1 100644 --- a/app/models/clusters/integrations/prometheus.rb +++ b/app/models/clusters/integrations/prometheus.rb @@ -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 diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index a24bb0b6bf9..7b890a630cc 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -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) diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index d2b3ca753b1..bd94c0ad30e 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -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)) diff --git a/config/feature_flags/development/add_actor_based_user_to_snowplow_tracking.yml b/config/feature_flags/development/add_actor_based_user_to_snowplow_tracking.yml new file mode 100644 index 00000000000..9dc20148d56 --- /dev/null +++ b/config/feature_flags/development/add_actor_based_user_to_snowplow_tracking.yml @@ -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 diff --git a/config/feature_flags/development/decomposed_ci_query_in_pipelines_for_merge_request_finder.yml b/config/feature_flags/development/decomposed_ci_query_in_pipelines_for_merge_request_finder.yml new file mode 100644 index 00000000000..235b37dfb1d --- /dev/null +++ b/config/feature_flags/development/decomposed_ci_query_in_pipelines_for_merge_request_finder.yml @@ -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 diff --git a/config/metrics/counts_28d/20210216175405_clusters_applications_cert_managers.yml b/config/metrics/counts_28d/20210216175405_clusters_applications_cert_managers.yml index a34c679e919..76627a91d0f 100644 --- a/config/metrics/counts_28d/20210216175405_clusters_applications_cert_managers.yml +++ b/config/metrics/counts_28d/20210216175405_clusters_applications_cert_managers.yml @@ -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" diff --git a/config/metrics/counts_28d/20210216175407_clusters_applications_helm.yml b/config/metrics/counts_28d/20210216175407_clusters_applications_helm.yml index 2cc0e937d92..ced2b454844 100644 --- a/config/metrics/counts_28d/20210216175407_clusters_applications_helm.yml +++ b/config/metrics/counts_28d/20210216175407_clusters_applications_helm.yml @@ -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" diff --git a/config/metrics/counts_28d/20210216175409_clusters_applications_ingress.yml b/config/metrics/counts_28d/20210216175409_clusters_applications_ingress.yml index 2cdd680eaee..eee58397947 100644 --- a/config/metrics/counts_28d/20210216175409_clusters_applications_ingress.yml +++ b/config/metrics/counts_28d/20210216175409_clusters_applications_ingress.yml @@ -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" diff --git a/config/metrics/counts_28d/20210216175411_clusters_applications_knative.yml b/config/metrics/counts_28d/20210216175411_clusters_applications_knative.yml index 23114b91d1f..f12fe191220 100644 --- a/config/metrics/counts_28d/20210216175411_clusters_applications_knative.yml +++ b/config/metrics/counts_28d/20210216175411_clusters_applications_knative.yml @@ -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" diff --git a/config/metrics/counts_28d/20210216180958_clusters_applications_prometheus.yml b/config/metrics/counts_28d/20210216180958_clusters_applications_prometheus.yml index b947a6ff7ea..895746f5121 100644 --- a/config/metrics/counts_28d/20210216180958_clusters_applications_prometheus.yml +++ b/config/metrics/counts_28d/20210216180958_clusters_applications_prometheus.yml @@ -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" diff --git a/config/metrics/counts_28d/20210216181951_clusters_applications_runner.yml b/config/metrics/counts_28d/20210216181951_clusters_applications_runner.yml index 22702146bc5..4d676e436b2 100644 --- a/config/metrics/counts_28d/20210216181951_clusters_applications_runner.yml +++ b/config/metrics/counts_28d/20210216181951_clusters_applications_runner.yml @@ -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" diff --git a/config/metrics/counts_28d/20210916201533_clusters_integrations_prometheus.yml b/config/metrics/counts_28d/20210916201533_clusters_integrations_prometheus.yml new file mode 100644 index 00000000000..6ecc98dcad1 --- /dev/null +++ b/config/metrics/counts_28d/20210916201533_clusters_integrations_prometheus.yml @@ -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" diff --git a/config/metrics/counts_all/20210216175255_clusters_applications_helm.yml b/config/metrics/counts_all/20210216175255_clusters_applications_helm.yml index 661d809ae65..e772f669513 100644 --- a/config/metrics/counts_all/20210216175255_clusters_applications_helm.yml +++ b/config/metrics/counts_all/20210216175255_clusters_applications_helm.yml @@ -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" diff --git a/config/metrics/counts_all/20210216175257_clusters_applications_ingress.yml b/config/metrics/counts_all/20210216175257_clusters_applications_ingress.yml index 889e701a8d7..1e31c28f543 100644 --- a/config/metrics/counts_all/20210216175257_clusters_applications_ingress.yml +++ b/config/metrics/counts_all/20210216175257_clusters_applications_ingress.yml @@ -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" diff --git a/config/metrics/counts_all/20210216175259_clusters_applications_cert_managers.yml b/config/metrics/counts_all/20210216175259_clusters_applications_cert_managers.yml index a22cf9dd848..bc16040f143 100644 --- a/config/metrics/counts_all/20210216175259_clusters_applications_cert_managers.yml +++ b/config/metrics/counts_all/20210216175259_clusters_applications_cert_managers.yml @@ -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" diff --git a/config/metrics/counts_all/20210216175301_clusters_applications_crossplane.yml b/config/metrics/counts_all/20210216175301_clusters_applications_crossplane.yml index 1fc50c89bdc..2856a0e25ac 100644 --- a/config/metrics/counts_all/20210216175301_clusters_applications_crossplane.yml +++ b/config/metrics/counts_all/20210216175301_clusters_applications_crossplane.yml @@ -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" diff --git a/config/metrics/counts_all/20210216175303_clusters_applications_prometheus.yml b/config/metrics/counts_all/20210216175303_clusters_applications_prometheus.yml index b883f9cdd1b..961c9adfdb7 100644 --- a/config/metrics/counts_all/20210216175303_clusters_applications_prometheus.yml +++ b/config/metrics/counts_all/20210216175303_clusters_applications_prometheus.yml @@ -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" diff --git a/config/metrics/counts_all/20210216175305_clusters_applications_runner.yml b/config/metrics/counts_all/20210216175305_clusters_applications_runner.yml index 5f9c9a9c0d0..33f8d045d2b 100644 --- a/config/metrics/counts_all/20210216175305_clusters_applications_runner.yml +++ b/config/metrics/counts_all/20210216175305_clusters_applications_runner.yml @@ -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" diff --git a/config/metrics/counts_all/20210216175307_clusters_applications_knative.yml b/config/metrics/counts_all/20210216175307_clusters_applications_knative.yml index 8b5f50c6c7f..e5a80ca6385 100644 --- a/config/metrics/counts_all/20210216175307_clusters_applications_knative.yml +++ b/config/metrics/counts_all/20210216175307_clusters_applications_knative.yml @@ -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" diff --git a/config/metrics/counts_all/20210216175309_clusters_applications_elastic_stack.yml b/config/metrics/counts_all/20210216175309_clusters_applications_elastic_stack.yml index fafbf8a7d47..4d5dbcd198f 100644 --- a/config/metrics/counts_all/20210216175309_clusters_applications_elastic_stack.yml +++ b/config/metrics/counts_all/20210216175309_clusters_applications_elastic_stack.yml @@ -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" diff --git a/config/metrics/counts_all/20210216175310_clusters_applications_jupyter.yml b/config/metrics/counts_all/20210216175310_clusters_applications_jupyter.yml index 89c8116f0d8..85d62985fa8 100644 --- a/config/metrics/counts_all/20210216175310_clusters_applications_jupyter.yml +++ b/config/metrics/counts_all/20210216175310_clusters_applications_jupyter.yml @@ -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" diff --git a/config/metrics/counts_all/20210216175312_clusters_applications_cilium.yml b/config/metrics/counts_all/20210216175312_clusters_applications_cilium.yml index faf7f486d32..33a8a53a8ab 100644 --- a/config/metrics/counts_all/20210216175312_clusters_applications_cilium.yml +++ b/config/metrics/counts_all/20210216175312_clusters_applications_cilium.yml @@ -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" diff --git a/config/metrics/counts_all/20210216175329_clusters_applications_cert_managers.yml b/config/metrics/counts_all/20210216175329_clusters_applications_cert_managers.yml index 185ab921fd6..f97816e18c1 100644 --- a/config/metrics/counts_all/20210216175329_clusters_applications_cert_managers.yml +++ b/config/metrics/counts_all/20210216175329_clusters_applications_cert_managers.yml @@ -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" diff --git a/config/metrics/counts_all/20210216175331_clusters_applications_helm.yml b/config/metrics/counts_all/20210216175331_clusters_applications_helm.yml index 4561338a3cb..28c58e11854 100644 --- a/config/metrics/counts_all/20210216175331_clusters_applications_helm.yml +++ b/config/metrics/counts_all/20210216175331_clusters_applications_helm.yml @@ -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" diff --git a/config/metrics/counts_all/20210216175333_clusters_applications_ingress.yml b/config/metrics/counts_all/20210216175333_clusters_applications_ingress.yml index 8336b6a4048..b93198b92a4 100644 --- a/config/metrics/counts_all/20210216175333_clusters_applications_ingress.yml +++ b/config/metrics/counts_all/20210216175333_clusters_applications_ingress.yml @@ -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" diff --git a/config/metrics/counts_all/20210216175335_clusters_applications_knative.yml b/config/metrics/counts_all/20210216175335_clusters_applications_knative.yml index c5979093a18..735f3ea8e04 100644 --- a/config/metrics/counts_all/20210216175335_clusters_applications_knative.yml +++ b/config/metrics/counts_all/20210216175335_clusters_applications_knative.yml @@ -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" diff --git a/config/metrics/counts_all/20210216180947_clusters_applications_prometheus.yml b/config/metrics/counts_all/20210216180947_clusters_applications_prometheus.yml index a43dc103f9c..bf567337380 100644 --- a/config/metrics/counts_all/20210216180947_clusters_applications_prometheus.yml +++ b/config/metrics/counts_all/20210216180947_clusters_applications_prometheus.yml @@ -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" diff --git a/config/metrics/counts_all/20210216181949_clusters_applications_runner.yml b/config/metrics/counts_all/20210216181949_clusters_applications_runner.yml index 96f16043e65..3c3fc600698 100644 --- a/config/metrics/counts_all/20210216181949_clusters_applications_runner.yml +++ b/config/metrics/counts_all/20210216181949_clusters_applications_runner.yml @@ -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" diff --git a/config/metrics/counts_all/20210916200930_clusters_integrations_prometheus.yml b/config/metrics/counts_all/20210916200930_clusters_integrations_prometheus.yml new file mode 100644 index 00000000000..2e17c5d261b --- /dev/null +++ b/config/metrics/counts_all/20210916200930_clusters_integrations_prometheus.yml @@ -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" diff --git a/config/metrics/counts_all/20210916200931_clusters_integrations_elastic_stack.yml b/config/metrics/counts_all/20210916200931_clusters_integrations_elastic_stack.yml new file mode 100644 index 00000000000..54437cfbf36 --- /dev/null +++ b/config/metrics/counts_all/20210916200931_clusters_integrations_elastic_stack.yml @@ -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" diff --git a/config/metrics/counts_all/20210916202342_clusters_integrations_prometheus.yml b/config/metrics/counts_all/20210916202342_clusters_integrations_prometheus.yml new file mode 100644 index 00000000000..d0baa4d0751 --- /dev/null +++ b/config/metrics/counts_all/20210916202342_clusters_integrations_prometheus.yml @@ -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" diff --git a/db/migrate/20210915000453_add_index_on_clusters_integration_prometheus_enabled.rb b/db/migrate/20210915000453_add_index_on_clusters_integration_prometheus_enabled.rb new file mode 100644 index 00000000000..35cd18c1da9 --- /dev/null +++ b/db/migrate/20210915000453_add_index_on_clusters_integration_prometheus_enabled.rb @@ -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 diff --git a/db/migrate/20210915001242_add_index_on_clusters_integration_elastic_stack_enabled.rb b/db/migrate/20210915001242_add_index_on_clusters_integration_elastic_stack_enabled.rb new file mode 100644 index 00000000000..bdaa84f27fe --- /dev/null +++ b/db/migrate/20210915001242_add_index_on_clusters_integration_elastic_stack_enabled.rb @@ -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 diff --git a/db/schema_migrations/20210915000453 b/db/schema_migrations/20210915000453 new file mode 100644 index 00000000000..611af2b1310 --- /dev/null +++ b/db/schema_migrations/20210915000453 @@ -0,0 +1 @@ +ffb4e066420e1492550255e5866df6dc9f83d3d6cec9033284c4c3194d53b827
\ No newline at end of file diff --git a/db/schema_migrations/20210915001242 b/db/schema_migrations/20210915001242 new file mode 100644 index 00000000000..7aa9b5c5787 --- /dev/null +++ b/db/schema_migrations/20210915001242 @@ -0,0 +1 @@ +fc8f86f794d77902fd86acaec6046b65821ff685f841d28158dc05fb55773c16
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index f1c78f64d93..b8b94d53e00 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -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); diff --git a/doc/api/settings.md b/doc/api/settings.md index 2ebcf833d19..7b8778973f2 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -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). | diff --git a/doc/development/documentation/styleguide/word_list.md b/doc/development/documentation/styleguide/word_list.md index d68b68613d8..c8091656643 100644 --- a/doc/development/documentation/styleguide/word_list.md +++ b/doc/development/documentation/styleguide/word_list.md @@ -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. diff --git a/doc/development/service_ping/index.md b/doc/development/service_ping/index.md index 791013db88e..19bf7446da9 100644 --- a/doc/development/service_ping/index.md +++ b/doc/development/service_ping/index.md @@ -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. diff --git a/lib/api/maven_packages.rb b/lib/api/maven_packages.rb index 9e5705abe88..5245cd10564 100644 --- a/lib/api/maven_packages.rb +++ b/lib/api/maven_packages.rb @@ -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 diff --git a/lib/api/settings.rb b/lib/api/settings.rb index 36f816ae638..12e1d21a00d 100644 --- a/lib/api/settings.rb +++ b/lib/api/settings.rb @@ -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", diff --git a/lib/gitlab/import_export/attributes_permitter.rb b/lib/gitlab/import_export/attributes_permitter.rb index acd03d9ec20..2d8e25a9f70 100644 --- a/lib/gitlab/import_export/attributes_permitter.rb +++ b/lib/gitlab/import_export/attributes_permitter.rb @@ -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 diff --git a/lib/gitlab/import_export/base/relation_factory.rb b/lib/gitlab/import_export/base/relation_factory.rb index a84efd1d240..6749ef4e276 100644 --- a/lib/gitlab/import_export/base/relation_factory.rb +++ b/lib/gitlab/import_export/base/relation_factory.rb @@ -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. diff --git a/lib/gitlab/import_export/group/import_export.yml b/lib/gitlab/import_export/group/import_export.yml index f7ab1677001..c2a1c60e927 100644 --- a/lib/gitlab/import_export/group/import_export.yml +++ b/lib/gitlab/import_export/group/import_export.yml @@ -10,6 +10,7 @@ tree: - labels: - :priorities - boards: + - :milestone - lists: - label: - :priorities diff --git a/lib/gitlab/import_export/group/relation_factory.rb b/lib/gitlab/import_export/group/relation_factory.rb index 91637161377..adbbd37ce10 100644 --- a/lib/gitlab/import_export/group/relation_factory.rb +++ b/lib/gitlab/import_export/group/relation_factory.rb @@ -36,6 +36,10 @@ module Gitlab @relation_hash['group_id'] = @importable.id end + + def use_attributes_permitter? + false + end end end end diff --git a/lib/gitlab/import_export/project/import_export.yml b/lib/gitlab/import_export/project/import_export.yml index 8046fedc4f3..d6bb7738ea6 100644 --- a/lib/gitlab/import_export/project/import_export.yml +++ b/lib/gitlab/import_export/project/import_export.yml @@ -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: diff --git a/lib/gitlab/tracking/standard_context.rb b/lib/gitlab/tracking/standard_context.rb index fe5669be014..02f4efcad81 100644 --- a/lib/gitlab/tracking/standard_context.rb +++ b/lib/gitlab/tracking/standard_context.rb @@ -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 diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb index 87ba1f72428..306b903a837 100644 --- a/lib/gitlab/usage_data.rb +++ b/lib/gitlab/usage_data.rb @@ -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) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 6b62fe35b3d..6cfc0a343f9 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -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 "" diff --git a/qa/qa/support/api.rb b/qa/qa/support/api.rb index 302527f4029..663761805ee 100644 --- a/qa/qa/support/api.rb +++ b/qa/qa/support/api.rb @@ -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 diff --git a/qa/qa/support/retrier.rb b/qa/qa/support/retrier.rb index fde8ac263ca..aa568d633fc 100644 --- a/qa/qa/support/retrier.rb +++ b/qa/qa/support/retrier.rb @@ -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 diff --git a/spec/factories/usage_data.rb b/spec/factories/usage_data.rb index c02bcfc2169..fc1f5d71f39 100644 --- a/spec/factories/usage_data.rb +++ b/spec/factories/usage_data.rb @@ -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) diff --git a/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb b/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb index 65f6dc0ba74..8a802e9660b 100644 --- a/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb +++ b/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb @@ -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) - 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}) + 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 '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 diff --git a/spec/fixtures/lib/gitlab/import_export/complex/project.json b/spec/fixtures/lib/gitlab/import_export/complex/project.json index 1072e63b20b..fd4c2d55124 100644 --- a/spec/fixtures/lib/gitlab/import_export/complex/project.json +++ b/spec/fixtures/lib/gitlab/import_export/complex/project.json @@ -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 + } + ] + } } ] } diff --git a/spec/fixtures/lib/gitlab/import_export/complex/tree/project/boards.ndjson b/spec/fixtures/lib/gitlab/import_export/complex/tree/project/boards.ndjson index ef18af69c9b..a63b583f087 100644 --- a/spec/fixtures/lib/gitlab/import_export/complex/tree/project/boards.ndjson +++ b/spec/fixtures/lib/gitlab/import_export/complex/tree/project/boards.ndjson @@ -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}]}}]} diff --git a/spec/frontend/vue_mr_widget/components/extensions/actions_spec.js b/spec/frontend/vue_mr_widget/components/extensions/actions_spec.js new file mode 100644 index 00000000000..d5d779d7a34 --- /dev/null +++ b/spec/frontend/vue_mr_widget/components/extensions/actions_spec.js @@ -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); + }); + }); +}); diff --git a/spec/lib/gitlab/import_export/attributes_permitter_spec.rb b/spec/lib/gitlab/import_export/attributes_permitter_spec.rb index 36a831a785c..61f09758328 100644 --- a/spec/lib/gitlab/import_export/attributes_permitter_spec.rb +++ b/spec/lib/gitlab/import_export/attributes_permitter_spec.rb @@ -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 diff --git a/spec/lib/gitlab/tracking/standard_context_spec.rb b/spec/lib/gitlab/tracking/standard_context_spec.rb index ca7a6b6b1c3..8ded80dd191 100644 --- a/spec/lib/gitlab/tracking/standard_context_spec.rb +++ b/spec/lib/gitlab/tracking/standard_context_spec.rb @@ -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 diff --git a/spec/lib/gitlab/tracking_spec.rb b/spec/lib/gitlab/tracking_spec.rb index 02e66458f46..dacaae55676 100644 --- a/spec/lib/gitlab/tracking_spec.rb +++ b/spec/lib/gitlab/tracking_spec.rb @@ -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) diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb index 38382590828..756c728f998 100644 --- a/spec/lib/gitlab/usage_data_spec.rb +++ b/spec/lib/gitlab/usage_data_spec.rb @@ -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) diff --git a/spec/requests/api/graphql/project/merge_request/pipelines_spec.rb b/spec/requests/api/graphql/project/merge_request/pipelines_spec.rb index 70c5bda35e1..820a5d818c7 100644 --- a/spec/requests/api/graphql/project/merge_request/pipelines_spec.rb +++ b/spec/requests/api/graphql/project/merge_request/pipelines_spec.rb @@ -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 diff --git a/spec/requests/api/maven_packages_spec.rb b/spec/requests/api/maven_packages_spec.rb index 07111dd1d62..5a682ee8532 100644 --- a/spec/requests/api/maven_packages_spec.rb +++ b/spec/requests/api/maven_packages_spec.rb @@ -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 diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb index f5d261ba4c6..423e19c3971 100644 --- a/spec/requests/api/settings_spec.rb +++ b/spec/requests/api/settings_spec.rb @@ -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 diff --git a/spec/support/helpers/usage_data_helpers.rb b/spec/support/helpers/usage_data_helpers.rb index e772fd237fa..5ead1813439 100644 --- a/spec/support/helpers/usage_data_helpers.rb +++ b/spec/support/helpers/usage_data_helpers.rb @@ -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 diff --git a/spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb new file mode 100644 index 00000000000..5ce698c4701 --- /dev/null +++ b/spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb @@ -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 |