Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-09-01 15:11:56 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-09-01 15:11:56 +0300
commita53033814ddff597cd05244f378915bacdcb5aea (patch)
treec72cddf8268e72cd46e3a1b0f04298aa6a04533b
parentf60abc43151ae4589e96824c3c8674e76cb0cb9c (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop_todo/layout/hash_alignment.yml31
-rw-r--r--app/assets/stylesheets/startup/startup-dark.scss4
-rw-r--r--app/assets/stylesheets/themes/dark_mode_overrides.scss8
-rw-r--r--app/assets/stylesheets/themes/theme_blue.scss1
-rw-r--r--app/assets/stylesheets/themes/theme_gray.scss1
-rw-r--r--app/assets/stylesheets/themes/theme_green.scss1
-rw-r--r--app/assets/stylesheets/themes/theme_helper.scss66
-rw-r--r--app/assets/stylesheets/themes/theme_indigo.scss1
-rw-r--r--app/assets/stylesheets/themes/theme_light_blue.scss1
-rw-r--r--app/assets/stylesheets/themes/theme_light_gray.scss1
-rw-r--r--app/assets/stylesheets/themes/theme_light_green.scss1
-rw-r--r--app/assets/stylesheets/themes/theme_light_indigo.scss1
-rw-r--r--app/assets/stylesheets/themes/theme_light_red.scss1
-rw-r--r--app/assets/stylesheets/themes/theme_red.scss1
-rw-r--r--app/components/pajamas/badge_component.html.haml6
-rw-r--r--app/components/pajamas/badge_component.rb72
-rw-r--r--app/helpers/badges_helper.rb66
-rw-r--r--app/models/users/credit_card_validation.rb4
-rw-r--r--config/metrics/counts_28d/20210216184937_user_packages_total_unique_counts_monthly.yml4
-rw-r--r--config/metrics/counts_7d/20210216184935_user_packages_total_unique_counts_weekly.yml4
-rw-r--r--db/migrate/20220829183356_replace_index_on_credit_card_validations.rb20
-rw-r--r--db/schema_migrations/202208291833561
-rw-r--r--db/structure.sql2
-rw-r--r--doc/administration/external_pipeline_validation.md12
-rw-r--r--doc/api/merge_request_approvals.md5
-rw-r--r--doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md150
-rw-r--r--lib/banzai/filter/kroki_filter.rb11
-rw-r--r--lib/banzai/pipeline/markup_pipeline.rb4
-rw-r--r--lib/gitlab/ci/pipeline/chain/validate/external.rb4
-rw-r--r--lib/gitlab/usage_data_counters/hll_redis_counter.rb2
-rw-r--r--locale/gitlab.pot21
-rw-r--r--rubocop/cop/gitlab/mark_used_feature_flags.rb3
-rw-r--r--spec/components/pajamas/badge_component_spec.rb148
-rw-r--r--spec/components/previews/pajamas/badge_component_preview.rb61
-rw-r--r--spec/controllers/projects/pipeline_schedules_controller_spec.rb5
-rw-r--r--spec/controllers/projects/service_desk_controller_spec.rb5
-rw-r--r--spec/fixtures/api/schemas/external_validation.json12
-rw-r--r--spec/helpers/tab_helper_spec.rb2
-rw-r--r--spec/lib/banzai/filter/kroki_filter_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb64
-rw-r--r--spec/models/users/credit_card_validation_spec.rb11
-rw-r--r--spec/services/ci/create_downstream_pipeline_service_spec.rb5
-rw-r--r--spec/services/ci/create_pipeline_service/logger_spec.rb6
-rw-r--r--spec/services/ci/create_pipeline_service/tags_spec.rb2
-rw-r--r--spec/services/ci/job_artifacts/create_service_spec.rb5
-rw-r--r--spec/services/ci/retry_job_service_spec.rb27
-rw-r--r--spec/services/deployments/link_merge_requests_service_spec.rb4
-rw-r--r--spec/services/discussions/capture_diff_note_positions_service_spec.rb4
-rw-r--r--spec/services/environments/stop_service_spec.rb7
-rw-r--r--spec/services/event_create_service_spec.rb12
-rw-r--r--spec/services/groups/import_export/import_service_spec.rb28
-rw-r--r--spec/services/issuable/bulk_update_service_spec.rb2
-rw-r--r--spec/services/issues/create_service_spec.rb2
-rw-r--r--spec/services/merge_requests/build_service_spec.rb24
-rw-r--r--spec/services/merge_requests/create_service_spec.rb2
-rw-r--r--spec/services/merge_requests/update_service_spec.rb6
-rw-r--r--spec/services/metrics/dashboard/clone_dashboard_service_spec.rb2
-rw-r--r--spec/services/notes/create_service_spec.rb6
-rw-r--r--spec/services/notes/destroy_service_spec.rb11
-rw-r--r--spec/services/packages/debian/parse_debian822_service_spec.rb2
-rw-r--r--spec/services/projects/destroy_service_spec.rb4
-rw-r--r--spec/services/service_ping/submit_service_ping_service_spec.rb16
-rw-r--r--spec/services/suggestions/apply_service_spec.rb53
-rw-r--r--spec/services/work_items/widgets/description_service/update_service_spec.rb2
-rw-r--r--spec/tooling/danger/datateam_spec.rb2
-rw-r--r--spec/views/projects/tags/index.html.haml_spec.rb4
-rw-r--r--spec/workers/emails_on_push_worker_spec.rb2
-rw-r--r--spec/workers/pages_domain_ssl_renewal_cron_worker_spec.rb4
68 files changed, 755 insertions, 315 deletions
diff --git a/.rubocop_todo/layout/hash_alignment.yml b/.rubocop_todo/layout/hash_alignment.yml
index 3e5694d0811..eafd3d58c65 100644
--- a/.rubocop_todo/layout/hash_alignment.yml
+++ b/.rubocop_todo/layout/hash_alignment.yml
@@ -36,7 +36,6 @@ Layout/HashAlignment:
- 'spec/lib/gitlab/error_tracking/stack_trace_highlight_decorator_spec.rb'
- 'spec/lib/gitlab/etag_caching/middleware_spec.rb'
- 'spec/lib/gitlab/etag_caching/router/graphql_spec.rb'
- - 'spec/lib/gitlab/git/repository_spec.rb'
- 'spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb'
- 'spec/lib/gitlab/import_export/attributes_finder_spec.rb'
- 'spec/lib/gitlab/import_export/group/object_builder_spec.rb'
@@ -55,10 +54,8 @@ Layout/HashAlignment:
- 'spec/lib/gitlab/metrics/subscribers/active_record_spec.rb'
- 'spec/lib/gitlab/metrics/subscribers/load_balancing_spec.rb'
- 'spec/models/ci/build_spec.rb'
- - 'spec/models/ci/pipeline_spec.rb'
- 'spec/models/ci/processable_spec.rb'
- 'spec/models/clusters/platforms/kubernetes_spec.rb'
- - 'spec/models/commit_status_spec.rb'
- 'spec/models/container_registry/event_spec.rb'
- 'spec/models/deployment_spec.rb'
- 'spec/models/design_management/version_spec.rb'
@@ -72,7 +69,6 @@ Layout/HashAlignment:
- 'spec/models/remote_mirror_spec.rb'
- 'spec/models/repository_spec.rb'
- 'spec/models/user_spec.rb'
- - 'spec/presenters/clusters/cluster_presenter_spec.rb'
- 'spec/presenters/project_presenter_spec.rb'
- 'spec/routing/project_routing_spec.rb'
- 'spec/serializers/ci/lint/job_entity_spec.rb'
@@ -80,30 +76,3 @@ Layout/HashAlignment:
- 'spec/serializers/deployment_entity_spec.rb'
- 'spec/serializers/environment_serializer_spec.rb'
- 'spec/serializers/merge_request_metrics_helper_spec.rb'
- - 'spec/services/ci/create_downstream_pipeline_service_spec.rb'
- - 'spec/services/ci/create_pipeline_service/logger_spec.rb'
- - 'spec/services/ci/create_pipeline_service/tags_spec.rb'
- - 'spec/services/ci/job_artifacts/create_service_spec.rb'
- - 'spec/services/ci/retry_job_service_spec.rb'
- - 'spec/services/deployments/link_merge_requests_service_spec.rb'
- - 'spec/services/discussions/capture_diff_note_positions_service_spec.rb'
- - 'spec/services/environments/stop_service_spec.rb'
- - 'spec/services/event_create_service_spec.rb'
- - 'spec/services/groups/import_export/import_service_spec.rb'
- - 'spec/services/issuable/bulk_update_service_spec.rb'
- - 'spec/services/issues/create_service_spec.rb'
- - 'spec/services/merge_requests/build_service_spec.rb'
- - 'spec/services/merge_requests/create_service_spec.rb'
- - 'spec/services/merge_requests/update_service_spec.rb'
- - 'spec/services/metrics/dashboard/clone_dashboard_service_spec.rb'
- - 'spec/services/notes/create_service_spec.rb'
- - 'spec/services/notes/destroy_service_spec.rb'
- - 'spec/services/packages/debian/parse_debian822_service_spec.rb'
- - 'spec/services/projects/destroy_service_spec.rb'
- - 'spec/services/service_ping/submit_service_ping_service_spec.rb'
- - 'spec/services/suggestions/apply_service_spec.rb'
- - 'spec/services/work_items/widgets/description_service/update_service_spec.rb'
- - 'spec/tooling/danger/datateam_spec.rb'
- - 'spec/views/projects/tags/index.html.haml_spec.rb'
- - 'spec/workers/emails_on_push_worker_spec.rb'
- - 'spec/workers/pages_domain_ssl_renewal_cron_worker_spec.rb'
diff --git a/app/assets/stylesheets/startup/startup-dark.scss b/app/assets/stylesheets/startup/startup-dark.scss
index 71c99883297..9f2b249e714 100644
--- a/app/assets/stylesheets/startup/startup-dark.scss
+++ b/app/assets/stylesheets/startup/startup-dark.scss
@@ -10,7 +10,6 @@ body.gl-dark {
--gray-50: #303030;
--gray-100: #404040;
--gray-200: #525252;
- --gray-600: #bfbfbf;
--gray-700: #dbdbdb;
--gray-900: #fafafa;
--green-100: #0d532a;
@@ -1791,9 +1790,6 @@ body.gl-dark {
.avatar {
background: rgba(255, 255, 255, 0.04);
}
-.nav-sidebar li a {
- color: var(--gray-600);
-}
body.gl-dark {
--gl-theme-accent: #868686;
}
diff --git a/app/assets/stylesheets/themes/dark_mode_overrides.scss b/app/assets/stylesheets/themes/dark_mode_overrides.scss
index 9348216c2ac..e1ba2a69420 100644
--- a/app/assets/stylesheets/themes/dark_mode_overrides.scss
+++ b/app/assets/stylesheets/themes/dark_mode_overrides.scss
@@ -60,12 +60,6 @@
}
.nav-sidebar {
- li {
- a {
- color: var(--gray-600);
- }
- }
-
.sidebar-sub-level-items.fly-out-list {
box-shadow: none;
border: 1px solid $border-color;
@@ -78,7 +72,7 @@ aside.right-sidebar:not(.right-sidebar-merge-requests) {
}
body.gl-dark {
- @include gitlab-theme($gray-900, $gray-400, $gray-500, $gray-900, $gray-900, $white);
+ @include gitlab-theme($gray-900, $gray-400, $gray-500, $gray-900, $white);
.terms {
.logo-text {
diff --git a/app/assets/stylesheets/themes/theme_blue.scss b/app/assets/stylesheets/themes/theme_blue.scss
index 817557f37cd..90122cec31f 100644
--- a/app/assets/stylesheets/themes/theme_blue.scss
+++ b/app/assets/stylesheets/themes/theme_blue.scss
@@ -6,7 +6,6 @@ body {
$theme-blue-200,
$theme-blue-500,
$theme-blue-700,
- $gray-900,
$theme-blue-900,
$white
);
diff --git a/app/assets/stylesheets/themes/theme_gray.scss b/app/assets/stylesheets/themes/theme_gray.scss
index 75b111f90c7..a6cdfb36a7c 100644
--- a/app/assets/stylesheets/themes/theme_gray.scss
+++ b/app/assets/stylesheets/themes/theme_gray.scss
@@ -7,7 +7,6 @@ body {
$gray-300,
$gray-500,
$gray-900,
- $gray-900,
$white
);
}
diff --git a/app/assets/stylesheets/themes/theme_green.scss b/app/assets/stylesheets/themes/theme_green.scss
index 7e387e97452..0300f261d64 100644
--- a/app/assets/stylesheets/themes/theme_green.scss
+++ b/app/assets/stylesheets/themes/theme_green.scss
@@ -6,7 +6,6 @@ body {
$theme-green-200,
$theme-green-500,
$theme-green-700,
- $gray-900,
$theme-green-900,
$white
);
diff --git a/app/assets/stylesheets/themes/theme_helper.scss b/app/assets/stylesheets/themes/theme_helper.scss
index 042e21cebd6..d644d8acc98 100644
--- a/app/assets/stylesheets/themes/theme_helper.scss
+++ b/app/assets/stylesheets/themes/theme_helper.scss
@@ -6,18 +6,22 @@
$search-and-nav-links,
$accent,
$border-and-box-shadow,
- $sidebar-text,
- $nav-svg-color,
- $color-alternate
+ $navbar-theme-color,
+ $navbar-theme-contrast-color
) {
// Set custom properties
--gl-theme-accent: #{$accent};
+ $search-and-nav-links-a20: rgba($search-and-nav-links, 0.2);
+ $search-and-nav-links-a30: rgba($search-and-nav-links, 0.3);
+ $search-and-nav-links-a40: rgba($search-and-nav-links, 0.4);
+ $search-and-nav-links-a80: rgba($search-and-nav-links, 0.8);
+
// Header
.navbar-gitlab {
- background-color: $nav-svg-color;
+ background-color: $navbar-theme-color;
.navbar-collapse {
color: $search-and-nav-links;
@@ -37,7 +41,7 @@
> button {
&:hover,
&:focus {
- background-color: rgba($search-and-nav-links, 0.2);
+ background-color: $search-and-nav-links-a20;
}
}
@@ -45,13 +49,13 @@
&.dropdown.show {
> a,
> button {
- color: $nav-svg-color;
- background-color: $color-alternate;
+ color: $navbar-theme-color;
+ background-color: $navbar-theme-contrast-color;
}
}
&.line-separator {
- border-left: 1px solid rgba($search-and-nav-links, 0.2);
+ border-left: 1px solid $search-and-nav-links-a20;
}
}
}
@@ -65,12 +69,12 @@
color: $search-and-nav-links;
&.header-search-new {
- color: $sidebar-text;
+ color: $gray-900;
}
> a {
.notification-dot {
- border: 2px solid $nav-svg-color;
+ border: 2px solid $navbar-theme-color;
}
&.header-help-dropdown-toggle {
@@ -88,7 +92,7 @@
&:hover,
&:focus {
@include media-breakpoint-up(sm) {
- background-color: rgba($search-and-nav-links, 0.2);
+ background-color: $search-and-nav-links-a20;
}
svg {
@@ -97,7 +101,7 @@
.notification-dot {
will-change: border-color, background-color;
- border-color: adjust-color($nav-svg-color, $red: 33, $green: 33, $blue: 33);
+ border-color: adjust-color($navbar-theme-color, $red: 33, $green: 33, $blue: 33);
}
&.header-help-dropdown-toggle .notification-dot {
@@ -108,12 +112,12 @@
&.active > a,
&.dropdown.show > a {
- color: $nav-svg-color;
- background-color: $color-alternate;
+ color: $navbar-theme-color;
+ background-color: $navbar-theme-contrast-color;
&:hover {
svg {
- fill: $nav-svg-color;
+ fill: $navbar-theme-color;
}
}
@@ -123,7 +127,7 @@
&.header-help-dropdown-toggle {
.notification-dot {
- background-color: $nav-svg-color;
+ background-color: $navbar-theme-color;
}
}
}
@@ -131,7 +135,7 @@
.impersonated-user,
.impersonated-user:hover {
svg {
- fill: $nav-svg-color;
+ fill: $navbar-theme-color;
}
}
}
@@ -142,30 +146,30 @@
> a {
&:hover,
&:focus {
- background-color: rgba($search-and-nav-links, 0.2);
+ background-color: $search-and-nav-links-a20;
}
}
}
.header-search {
- background-color: rgba($search-and-nav-links, 0.2) !important;
+ background-color: $search-and-nav-links-a20 !important;
border-radius: $border-radius-default;
&:hover {
- background-color: rgba($search-and-nav-links, 0.3) !important;
+ background-color: $search-and-nav-links-a30 !important;
}
svg.gl-search-box-by-type-search-icon {
- color: rgba($search-and-nav-links, 0.8);
+ color: $search-and-nav-links-a80;
}
input {
background-color: transparent;
- color: rgba($search-and-nav-links, 0.8);
- box-shadow: inset 0 0 0 1px rgba($search-and-nav-links, 0.4);
+ color: $search-and-nav-links-a80;
+ box-shadow: inset 0 0 0 1px $search-and-nav-links-a40;
&::placeholder {
- color: rgba($search-and-nav-links, 0.8);
+ color: $search-and-nav-links-a80;
}
&:focus,
@@ -178,27 +182,27 @@
.keyboard-shortcut-helper {
color: $search-and-nav-links;
- background-color: rgba($search-and-nav-links, 0.2);
+ background-color: $search-and-nav-links-a20;
}
}
.search {
form {
- background-color: rgba($search-and-nav-links, 0.2);
+ background-color: $search-and-nav-links-a20;
&:hover {
- background-color: rgba($search-and-nav-links, 0.3);
+ background-color: $search-and-nav-links-a30;
}
}
.search-input::placeholder {
- color: rgba($search-and-nav-links, 0.8);
+ color: $search-and-nav-links-a80;
}
.search-input-wrap {
.search-icon,
.clear-icon {
- fill: rgba($search-and-nav-links, 0.8);
+ fill: $search-and-nav-links-a80;
}
}
@@ -209,7 +213,7 @@
.search-input-wrap {
.search-icon {
- fill: rgba($search-and-nav-links, 0.8);
+ fill: $search-and-nav-links-a80;
}
}
}
@@ -217,7 +221,7 @@
// Sidebar
.nav-sidebar li.active > a {
- color: $sidebar-text;
+ color: $gray-900;
}
.nav-sidebar {
diff --git a/app/assets/stylesheets/themes/theme_indigo.scss b/app/assets/stylesheets/themes/theme_indigo.scss
index 3bf6cfea650..5a27a9cfdc5 100644
--- a/app/assets/stylesheets/themes/theme_indigo.scss
+++ b/app/assets/stylesheets/themes/theme_indigo.scss
@@ -6,7 +6,6 @@ body {
$indigo-200,
$indigo-500,
$indigo-700,
- $gray-900,
$indigo-900,
$white
);
diff --git a/app/assets/stylesheets/themes/theme_light_blue.scss b/app/assets/stylesheets/themes/theme_light_blue.scss
index 771a84911b3..7cb0d98802e 100644
--- a/app/assets/stylesheets/themes/theme_light_blue.scss
+++ b/app/assets/stylesheets/themes/theme_light_blue.scss
@@ -6,7 +6,6 @@ body {
$theme-light-blue-200,
$theme-light-blue-500,
$theme-light-blue-500,
- $gray-900,
$theme-light-blue-700,
$white
);
diff --git a/app/assets/stylesheets/themes/theme_light_gray.scss b/app/assets/stylesheets/themes/theme_light_gray.scss
index ad19438d79a..a0cbec9a92b 100644
--- a/app/assets/stylesheets/themes/theme_light_gray.scss
+++ b/app/assets/stylesheets/themes/theme_light_gray.scss
@@ -6,7 +6,6 @@ body {
$gray-500,
$gray-700,
$gray-500,
- $gray-900,
$gray-50,
$gray-500
);
diff --git a/app/assets/stylesheets/themes/theme_light_green.scss b/app/assets/stylesheets/themes/theme_light_green.scss
index 8c991a7bfb3..797279cc37b 100644
--- a/app/assets/stylesheets/themes/theme_light_green.scss
+++ b/app/assets/stylesheets/themes/theme_light_green.scss
@@ -6,7 +6,6 @@ body {
$theme-green-200,
$theme-green-500,
$theme-green-500,
- $gray-900,
$theme-light-green-700,
$white
);
diff --git a/app/assets/stylesheets/themes/theme_light_indigo.scss b/app/assets/stylesheets/themes/theme_light_indigo.scss
index 6c220e0459a..3632c5ad45a 100644
--- a/app/assets/stylesheets/themes/theme_light_indigo.scss
+++ b/app/assets/stylesheets/themes/theme_light_indigo.scss
@@ -6,7 +6,6 @@ body {
$indigo-200,
$indigo-500,
$indigo-500,
- $gray-900,
$indigo-700,
$white
);
diff --git a/app/assets/stylesheets/themes/theme_light_red.scss b/app/assets/stylesheets/themes/theme_light_red.scss
index e1a715293b4..6c10d9178f1 100644
--- a/app/assets/stylesheets/themes/theme_light_red.scss
+++ b/app/assets/stylesheets/themes/theme_light_red.scss
@@ -6,7 +6,6 @@ body {
$theme-light-red-200,
$theme-light-red-500,
$theme-light-red-500,
- $gray-900,
$theme-light-red-700,
$white
);
diff --git a/app/assets/stylesheets/themes/theme_red.scss b/app/assets/stylesheets/themes/theme_red.scss
index 19fd150727d..140e27de6e2 100644
--- a/app/assets/stylesheets/themes/theme_red.scss
+++ b/app/assets/stylesheets/themes/theme_red.scss
@@ -6,7 +6,6 @@ body {
$theme-red-200,
$theme-red-500,
$theme-red-700,
- $gray-900,
$theme-red-900,
$white
);
diff --git a/app/components/pajamas/badge_component.html.haml b/app/components/pajamas/badge_component.html.haml
new file mode 100644
index 00000000000..eaadc681f0e
--- /dev/null
+++ b/app/components/pajamas/badge_component.html.haml
@@ -0,0 +1,6 @@
+- if link?
+ %a{ href: @href, **html_options }><
+ = badge_content
+- else
+ %span{ **html_options }><
+ = badge_content
diff --git a/app/components/pajamas/badge_component.rb b/app/components/pajamas/badge_component.rb
new file mode 100644
index 00000000000..244064b0e1e
--- /dev/null
+++ b/app/components/pajamas/badge_component.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module Pajamas
+ class BadgeComponent < Pajamas::Component
+ def initialize(
+ text = nil,
+ icon: nil,
+ icon_classes: [],
+ icon_only: false,
+ href: nil,
+ size: :md,
+ variant: :muted,
+ **html_options
+ )
+ @text = text.presence
+ @icon = icon.to_s.presence
+ @icon_classes = Array.wrap(icon_classes)
+ @icon_only = @icon && icon_only
+ @href = href.presence
+ @size = filter_attribute(size.to_sym, SIZE_OPTIONS, default: :md)
+ @variant = filter_attribute(variant.to_sym, VARIANT_OPTIONS, default: :muted)
+ @html_options = html_options
+ end
+
+ private
+
+ SIZE_OPTIONS = [:sm, :md, :lg].freeze
+ VARIANT_OPTIONS = [:muted, :neutral, :info, :success, :warning, :danger].freeze
+
+ delegate :sprite_icon, to: :helpers
+
+ def badge_classes
+ ["gl-badge", "badge", "badge-pill", "badge-#{@variant}", @size.to_s]
+ end
+
+ def icon_classes
+ classes = %w[gl-icon gl-badge-icon] + @icon_classes
+ classes.push("gl-mr-2") unless icon_only?
+ classes.join(" ")
+ end
+
+ def icon_only?
+ @icon_only
+ end
+
+ def link?
+ @href.present?
+ end
+
+ # Determines the rendered text content.
+ # The content slot takes presedence over the text param.
+ def text
+ content || @text
+ end
+
+ def badge_content
+ if icon_only?
+ sprite_icon(@icon, css_class: icon_classes)
+ elsif @icon.present?
+ sprite_icon(@icon, css_class: icon_classes) + text
+ else
+ text
+ end
+ end
+
+ def html_options
+ options = format_options(options: @html_options, css_classes: badge_classes)
+ options.merge!({ aria: { label: text }, role: "img" }) if icon_only?
+ options
+ end
+ end
+end
diff --git a/app/helpers/badges_helper.rb b/app/helpers/badges_helper.rb
index d48eae26a90..069c15433a5 100644
--- a/app/helpers/badges_helper.rb
+++ b/app/helpers/badges_helper.rb
@@ -1,25 +1,6 @@
# frozen_string_literal: true
module BadgesHelper
- VARIANT_CLASSES = {
- muted: "badge-muted",
- neutral: "badge-neutral",
- info: "badge-info",
- success: "badge-success",
- warning: "badge-warning",
- danger: "badge-danger"
- }.tap { |hash| hash.default = hash.fetch(:muted) }.freeze
-
- SIZE_CLASSES = {
- sm: "sm",
- md: "md",
- lg: "lg"
- }.tap { |hash| hash.default = hash.fetch(:md) }.freeze
-
- GL_BADGE_CLASSES = %w[gl-badge badge badge-pill].freeze
-
- GL_ICON_CLASSES = %w[gl-icon gl-badge-icon].freeze
-
# Creates a GitLab UI badge.
#
# Examples:
@@ -53,47 +34,16 @@ module BadgesHelper
#
# See also https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/base-badge--default.
def gl_badge_tag(*args, &block)
+ # Merge the options and html_options hashes if both are present,
+ # because the badge component wants a flat list of keyword args.
+ args.compact!
+ hashes, params = args.partition { |a| a.is_a? Hash }
+ options_hash = hashes.reduce({}, :merge)
+
if block
- build_gl_badge_tag(capture(&block), *args)
+ render Pajamas::BadgeComponent.new(**options_hash), &block
else
- build_gl_badge_tag(*args)
+ render Pajamas::BadgeComponent.new(*params, **options_hash)
end
end
-
- private
-
- def build_gl_badge_tag(content, options = nil, html_options = nil)
- options ||= {}
- html_options ||= {}
-
- icon_only = options[:icon_only]
- variant_class = VARIANT_CLASSES[options.fetch(:variant, :muted)]
- size_class = SIZE_CLASSES[options.fetch(:size, :md)]
- icon_classes = GL_ICON_CLASSES.dup << options.fetch(:icon_classes, nil)
-
- html_options = html_options.merge(
- class: [
- *GL_BADGE_CLASSES,
- variant_class,
- size_class,
- *html_options[:class]
- ]
- )
-
- if icon_only
- html_options['aria-label'] = content
- html_options['role'] = 'img'
- end
-
- if options[:icon]
- icon_classes << "gl-mr-2" unless icon_only
- icon = sprite_icon(options[:icon], css_class: icon_classes.join(' '))
-
- content = icon_only ? icon : icon + content
- end
-
- tag = html_options[:href].nil? ? :span : :a
-
- content_tag(tag, content, html_options)
- end
end
diff --git a/app/models/users/credit_card_validation.rb b/app/models/users/credit_card_validation.rb
index 998a5deb0fd..6f1cadb4344 100644
--- a/app/models/users/credit_card_validation.rb
+++ b/app/models/users/credit_card_validation.rb
@@ -21,5 +21,9 @@ module Users
network: network
).order(credit_card_validated_at: :desc).includes(:user)
end
+
+ def similar_holder_names_count
+ self.class.where('lower(holder_name) = :value', value: holder_name.downcase).count
+ end
end
end
diff --git a/config/metrics/counts_28d/20210216184937_user_packages_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184937_user_packages_total_unique_counts_monthly.yml
index 52e2eec71c5..e758f06bea9 100644
--- a/config/metrics/counts_28d/20210216184937_user_packages_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184937_user_packages_total_unique_counts_monthly.yml
@@ -15,17 +15,13 @@ options:
events:
- i_package_composer_user
- i_package_conan_user
- - i_package_container_user
- - i_package_debian_user
- i_package_generic_user
- - i_package_golang_user
- i_package_helm_user
- i_package_maven_user
- i_package_npm_user
- i_package_nuget_user
- i_package_pypi_user
- i_package_rubygems_user
- - i_package_tag_user
- i_package_terraform_module_user
distribution:
- ee
diff --git a/config/metrics/counts_7d/20210216184935_user_packages_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184935_user_packages_total_unique_counts_weekly.yml
index 81181baa4ee..e7465b79667 100644
--- a/config/metrics/counts_7d/20210216184935_user_packages_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210216184935_user_packages_total_unique_counts_weekly.yml
@@ -15,17 +15,13 @@ options:
events:
- i_package_composer_user
- i_package_conan_user
- - i_package_container_user
- - i_package_debian_user
- i_package_generic_user
- - i_package_golang_user
- i_package_helm_user
- i_package_maven_user
- i_package_npm_user
- i_package_nuget_user
- i_package_pypi_user
- i_package_rubygems_user
- - i_package_tag_user
- i_package_terraform_module_user
distribution:
- ee
diff --git a/db/migrate/20220829183356_replace_index_on_credit_card_validations.rb b/db/migrate/20220829183356_replace_index_on_credit_card_validations.rb
new file mode 100644
index 00000000000..05fa7f75feb
--- /dev/null
+++ b/db/migrate/20220829183356_replace_index_on_credit_card_validations.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class ReplaceIndexOnCreditCardValidations < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ OLD_INDEX_NAME = 'index_user_credit_card_validations_meta_data_full_match'
+ NEW_INDEX_NAME = 'index_user_credit_card_validations_meta_data_full_match_lower'
+ OLD_FIELDS = [:holder_name, :expiration_date, :last_digits, :credit_card_validated_at]
+ NEW_FIELDS = 'lower(holder_name), expiration_date, last_digits, credit_card_validated_at'
+
+ def up
+ add_concurrent_index :user_credit_card_validations, NEW_FIELDS, name: NEW_INDEX_NAME
+ remove_concurrent_index :user_credit_card_validations, OLD_FIELDS, name: OLD_INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :user_credit_card_validations, OLD_FIELDS, name: OLD_INDEX_NAME
+ remove_concurrent_index :user_credit_card_validations, NEW_FIELDS, name: NEW_INDEX_NAME
+ end
+end
diff --git a/db/schema_migrations/20220829183356 b/db/schema_migrations/20220829183356
new file mode 100644
index 00000000000..087a8a8ab6b
--- /dev/null
+++ b/db/schema_migrations/20220829183356
@@ -0,0 +1 @@
+4d8be5080046eff9c3736cd2494c02b2d2cb1eeea2753479617cb344bc5b1cbb \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index a5f072d7c84..9a2b9805046 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -30341,7 +30341,7 @@ CREATE UNIQUE INDEX index_user_canonical_emails_on_user_id ON user_canonical_ema
CREATE UNIQUE INDEX index_user_canonical_emails_on_user_id_and_canonical_email ON user_canonical_emails USING btree (user_id, canonical_email);
-CREATE INDEX index_user_credit_card_validations_meta_data_full_match ON user_credit_card_validations USING btree (holder_name, expiration_date, last_digits, credit_card_validated_at);
+CREATE INDEX index_user_credit_card_validations_meta_data_full_match_lower ON user_credit_card_validations USING btree (lower(holder_name), expiration_date, last_digits, credit_card_validated_at);
CREATE INDEX index_user_credit_card_validations_meta_data_partial_match ON user_credit_card_validations USING btree (expiration_date, last_digits, network, credit_card_validated_at);
diff --git a/doc/administration/external_pipeline_validation.md b/doc/administration/external_pipeline_validation.md
index 99876cdf503..b9bf0cfdc50 100644
--- a/doc/administration/external_pipeline_validation.md
+++ b/doc/administration/external_pipeline_validation.md
@@ -44,6 +44,7 @@ required number of seconds.
"required" : [
"project",
"user",
+ "credit_card",
"pipeline",
"builds",
"total_builds_count",
@@ -85,6 +86,17 @@ required number of seconds.
"sign_in_count": { "type": "integer" }
}
},
+ "credit_card": {
+ "type": "object",
+ "required": [
+ "similar_cards_count",
+ "similar_holder_names_count"
+ ],
+ "properties": {
+ "similar_cards_count": { "type": "integer" },
+ "similar_holder_names_count": { "type": "integer" }
+ }
+ },
"pipeline": {
"type": "object",
"required": [
diff --git a/doc/api/merge_request_approvals.md b/doc/api/merge_request_approvals.md
index 1d99c323946..f32a5eebaeb 100644
--- a/doc/api/merge_request_approvals.md
+++ b/doc/api/merge_request_approvals.md
@@ -33,6 +33,7 @@ GET /projects/:id/approvals
{
"approvals_before_merge": 2,
"reset_approvals_on_push": true,
+ "selective_code_owner_removals": false,
"disable_overriding_approvers_per_merge_request": false,
"merge_requests_author_approval": true,
"merge_requests_disable_committers_approval": false,
@@ -57,16 +58,18 @@ POST /projects/:id/approvals
| ------------------------------------------------ | ------- | -------- | --------------------------------------------------------------------------------------------------- |
| `id` | integer or string | yes | The ID or [URL-encoded path of a project](index.md#namespaced-path-encoding) |
| `approvals_before_merge` | integer | no | How many approvals are required before an MR can be merged. Deprecated in 12.0 in favor of Approval Rules API. |
-| `reset_approvals_on_push` | boolean | no | Reset approvals on a new push |
| `disable_overriding_approvers_per_merge_request` | boolean | no | Allow or prevent overriding approvers per MR |
| `merge_requests_author_approval` | boolean | no | Allow or prevent authors from self approving merge requests; `true` means authors can self approve |
| `merge_requests_disable_committers_approval` | boolean | no | Allow or prevent committers from self approving merge requests |
| `require_password_to_approve` | boolean | no | Require approver to enter a password to authenticate before adding the approval |
+| `reset_approvals_on_push` | boolean | no | Reset approvals on a new push. |
+| `selective_code_owner_removals` | boolean | no | Reset approvals from Code Owners if their files changed. Can be enabled only if `reset_approvals_on_push` is disabled. |
```json
{
"approvals_before_merge": 2,
"reset_approvals_on_push": true,
+ "selective_code_owner_removals": false,
"disable_overriding_approvers_per_merge_request": false,
"merge_requests_author_approval": false,
"merge_requests_disable_committers_approval": false,
diff --git a/doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md b/doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md
index 097c6743042..d46eef0b9fc 100644
--- a/doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md
+++ b/doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md
@@ -159,21 +159,32 @@ and artifacts, will share the same value. We want to add the `partition_id`
column into all 6 problematic tables because we can avoid backfilling this data
when we decide it is time to start partitioning them.
-We want to partition CI/CD data iteratively, so we will start with the
-pipelines table, and create at least one, but likely two, partitions. The
-pipelines table will be partitioned using the `LIST` partitioning strategy. It
-is possible that, after some time, `p_ci_pipelines` will store data in two
-partitions with IDs of `100` and `101`. Then we will try partitioning
-`ci_builds`. Therefore we might want to use `RANGE` partitioning in
-`p_ci_builds` with IDs `100` and `101`, because builds for the two logical
-partitions used will still be stored in a single table.
+We want to partition CI/CD data iteratively. We plan to start with the
+`ci_builds_metadata` table, because this is the fastest growing table in the CI
+database and want to contain this rapid growth. This table has also the most
+simple access patterns - a row from it is being read when a build is exposed to
+a runner, and other access patterns are relatively simple too. Starting with
+`p_ci_builds_metadata` will allow us to achieve tangible and quantifiable
+results earlier, and will become a new pattern that makes partitioning the
+largest table possible. We will partition builds metadata using the `LIST`
+partitioning strategy.
+
+Once we have many partitions attached to `p_ci_builds_metadata`, with many
+`partition_ids` we will choose another CI table to partition next. In that case
+we might want to use `RANGE` partitioning in for that next table because
+`p_ci_builds_metadata` will already have many physical partitions, and
+therefore many logical `partition_ids` will be used at that time. For example,
+if we choose `ci_builds` as the next partitioning candidate, after having
+partitioned `p_ci_builds_metadata`, it will have many different values stored
+in `ci_builds.partition_id`. Using `RANGE` partitioning in that case might be
+easier.
Physical partitioning and logical partitioning will be separated, and a
-strategy will be determined when we implement partitioning for the respective
-database tables. Using `RANGE` partitioning works similarly to using `LIST`
-partitioning in database tables other than `ci_pipelines`, but because we can
-guarantee continuity of `partition_id` values, using `RANGE` partitioning might
-be a better strategy.
+strategy will be determined when we implement physical partitioning for the
+respective database tables. Using `RANGE` partitioning works similarly to using
+`LIST` partitioning in database tables, but because we can guarantee continuity
+of `partition_id` values, using `RANGE` partitioning might be a better
+strategy.
## Why do we want to use explicit logical partition ids?
@@ -335,9 +346,116 @@ scope block takes an argument). Preloading instance dependent scopes is not
supported.
```
-We also need to build a proof of concept for removing data on the PostgreSQL
-side (using foreign keys with `ON DELETE CASCADE`) and removing data through
-Rails associations, as this might be an important area of uncertainty.
+### Foreign keys
+
+Foreign keys must reference columns that either are a primary key or form a
+unique constraint. We can define them using these strategies:
+
+#### Between routing tables sharing partition ID
+
+For relations that are part of the same pipeline hierarchy it is possible to
+share the `partition_id` column to define the foreign key constraint:
+
+```plaintext
+p_ci_pipelines:
+ - id
+ - partition_id
+
+p_ci_builds:
+ - id
+ - partition_id
+ - pipeline_id
+```
+
+In this case, `p_ci_builds.partition_id` indicates the partition for the build
+and also for the pipeline. We can add a FK on the routing table using:
+
+```sql
+ALTER TABLE ONLY p_ci_builds
+ ADD CONSTRAINT fk_on_pipeline_and_partition
+ FOREIGN KEY (pipeline_id, partition_id)
+ REFERENCES p_ci_pipelines(id, partition_id) ON DELETE CASCADE;
+```
+
+#### Between routing tables with different partition IDs
+
+It's not possible to reuse the `partition_id` for all relations in the CI domain,
+so in this case we'll need to store the value as a different attribute. For
+example, when canceling redundant pipelines we store on the old pipeline row
+the ID of the new pipeline that cancelled it as `auto_canceled_by_id`:
+
+```plaintext
+p_ci_pipelines:
+ - id
+ - partition_id
+ - auto_canceled_by_id
+ - auto_canceled_by_partition_id
+```
+
+In this case we can't ensure that the canceling pipeline is part of the same
+hierarchy as the canceled pipelines, so we need an extra attribute to store its
+partition, `auto_canceled_by_partition_id`, and the FK becomes:
+
+```sql
+ALTER TABLE ONLY p_ci_pipelines
+ ADD CONSTRAINT fk_cancel_redundant_pieplines
+ FOREIGN KEY (auto_canceled_by_id, auto_canceled_by_partition_id)
+ REFERENCES p_ci_pipelines(id, partition_id) ON DELETE SET NULL;
+```
+
+#### Between routing tables and regular tables
+
+Not all of the tables in the CI domain will be partitioned, so we'll have routing
+tables that will reference non-partitioned tables, for example we reference
+`external_pull_requests` from `ci_pipelines`:
+
+```sql
+FOREIGN KEY (external_pull_request_id)
+REFERENCES external_pull_requests(id)
+ON DELETE SET NULL
+```
+
+In this case we only need to move the FK definition from the partition level
+to the routing table so that new pipeline partitions may use it:
+
+```sql
+ALTER TABLE p_ci_pipelines
+ ADD CONSTRAINT fk_external_request
+ FOREIGN KEY (external_pull_request_id)
+ REFERENCES external_pull_requests(id) ON DELETE SET NULL;
+```
+
+#### Between regular tables and routing tables
+
+Most of the tables from the CI domain reference at least one table that will be
+turned into a routing tables, for example `ci_pipeline_messages` references
+`ci_pipelines`. These definitions will need to be updated to use the routing
+tables and for this they will need a `partition_id` column:
+
+```plaintext
+p_ci_pipelines:
+ - id
+ - partition_id
+
+ci_pipeline_messages:
+ - id
+ - pipeline_id
+ - pipeline_partition_id
+```
+
+The foreign key can be defined by using:
+
+```sql
+ALTER TABLE ci_pipeline_messages ADD CONSTRAINT fk_pipeline_partitioned
+ FOREIGN KEY (pipeline_id, pipeline_partition_id)
+ REFERENCES p_ci_pipelines(id, partition_id) ON DELETE CASCADE;
+```
+
+The old FK definition will need to be removed, otherwise new inserts in the
+`ci_pipeline_messages` with pipeline IDs from non-zero partition will fail with
+reference errors.
+
+### Indexes
We [learned](https://gitlab.com/gitlab-org/gitlab/-/issues/360148) that `PostgreSQL`
does not allow to create a single index (unique or otherwise) across all partitions of a table.
diff --git a/lib/banzai/filter/kroki_filter.rb b/lib/banzai/filter/kroki_filter.rb
index 845c7f2bc0a..713ff2439fc 100644
--- a/lib/banzai/filter/kroki_filter.rb
+++ b/lib/banzai/filter/kroki_filter.rb
@@ -14,7 +14,10 @@ module Banzai
return doc unless settings.kroki_enabled
diagram_selectors = ::Gitlab::Kroki.formats(settings)
- .map { |diagram_type| %(pre[lang="#{diagram_type}"] > code) }
+ .map do |diagram_type|
+ %(pre[lang="#{diagram_type}"] > code,
+ pre > code[lang="#{diagram_type}"])
+ end
.join(', ')
xpath = Gitlab::Utils::Nokogiri.css_to_xpath(diagram_selectors)
@@ -22,7 +25,7 @@ module Banzai
diagram_format = "svg"
doc.xpath(xpath).each do |node|
- diagram_type = node.parent['lang']
+ diagram_type = node.parent['lang'] || node['lang']
diagram_src = node.content
image_src = create_image_src(diagram_type, diagram_format, diagram_src)
img_tag = Nokogiri::HTML::DocumentFragment.parse(%(<img src="#{image_src}" />))
@@ -33,8 +36,8 @@ module Banzai
img_tag.set_attribute('hidden', '') if lazy_load
img_tag.set_attribute('class', 'js-render-kroki')
- img_tag.set_attribute('data-diagram', node.parent['lang'])
- img_tag.set_attribute('data-diagram-src', "data:text/plain;base64,#{Base64.strict_encode64(node.content)}")
+ img_tag.set_attribute('data-diagram', diagram_type)
+ img_tag.set_attribute('data-diagram-src', "data:text/plain;base64,#{Base64.strict_encode64(diagram_src)}")
node.parent.replace(img_tag)
end
diff --git a/lib/banzai/pipeline/markup_pipeline.rb b/lib/banzai/pipeline/markup_pipeline.rb
index 17a73f29afb..330914f7238 100644
--- a/lib/banzai/pipeline/markup_pipeline.rb
+++ b/lib/banzai/pipeline/markup_pipeline.rb
@@ -9,8 +9,8 @@ module Banzai
Filter::AssetProxyFilter,
Filter::ExternalLinkFilter,
Filter::PlantumlFilter,
- Filter::SyntaxHighlightFilter,
- Filter::KrokiFilter
+ Filter::KrokiFilter,
+ Filter::SyntaxHighlightFilter
]
end
diff --git a/lib/gitlab/ci/pipeline/chain/validate/external.rb b/lib/gitlab/ci/pipeline/chain/validate/external.rb
index ba6de77d57d..f4fa9e5fe2a 100644
--- a/lib/gitlab/ci/pipeline/chain/validate/external.rb
+++ b/lib/gitlab/ci/pipeline/chain/validate/external.rb
@@ -97,6 +97,10 @@ module Gitlab
last_sign_in_ip: current_user.last_sign_in_ip,
sign_in_count: current_user.sign_in_count
},
+ credit_card: {
+ similar_cards_count: current_user.credit_card_validation&.similar_records&.count.to_i,
+ similar_holder_names_count: current_user.credit_card_validation&.similar_holder_names_count.to_i
+ },
pipeline: {
sha: pipeline.sha,
ref: pipeline.ref,
diff --git a/lib/gitlab/usage_data_counters/hll_redis_counter.rb b/lib/gitlab/usage_data_counters/hll_redis_counter.rb
index 51dc3689dfd..d85e9beea39 100644
--- a/lib/gitlab/usage_data_counters/hll_redis_counter.rb
+++ b/lib/gitlab/usage_data_counters/hll_redis_counter.rb
@@ -31,7 +31,6 @@ module Gitlab
issues_edit
pipeline_authoring
quickactions
- user_packages
].freeze
CATEGORIES_COLLECTED_FROM_METRICS_DEFINITIONS = %w[
@@ -49,6 +48,7 @@ module Gitlab
source_code
terraform
testing
+ user_packages
work_items
].freeze
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index ab1356dd35c..e46cf759410 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -11894,15 +11894,6 @@ msgstr ""
msgid "DastProfiles|Delete profile"
msgstr ""
-msgid "DastProfiles|Do you want to discard this scanner profile?"
-msgstr ""
-
-msgid "DastProfiles|Do you want to discard this site profile?"
-msgstr ""
-
-msgid "DastProfiles|Do you want to discard your changes?"
-msgstr ""
-
msgid "DastProfiles|Edit profile"
msgstr ""
@@ -27282,6 +27273,12 @@ msgstr ""
msgid "OnDemandScans|Description (optional)"
msgstr ""
+msgid "OnDemandScans|Discard changes"
+msgstr ""
+
+msgid "OnDemandScans|Do you want to discard the changes or keep editing this profile? Unsaved changes will be lost."
+msgstr ""
+
msgid "OnDemandScans|Dynamic Application Security Testing (DAST)"
msgstr ""
@@ -27303,6 +27300,9 @@ msgstr ""
msgid "OnDemandScans|For example: Tests the login page for SQL injections"
msgstr ""
+msgid "OnDemandScans|Keep editing"
+msgstr ""
+
msgid "OnDemandScans|Manage scanner profiles"
msgstr ""
@@ -27426,6 +27426,9 @@ msgstr ""
msgid "OnDemandScans|View results"
msgstr ""
+msgid "OnDemandScans|You have unsaved changes"
+msgstr ""
+
msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
diff --git a/rubocop/cop/gitlab/mark_used_feature_flags.rb b/rubocop/cop/gitlab/mark_used_feature_flags.rb
index df524c8b0d2..8fbcc56b906 100644
--- a/rubocop/cop/gitlab/mark_used_feature_flags.rb
+++ b/rubocop/cop/gitlab/mark_used_feature_flags.rb
@@ -37,7 +37,8 @@ module RuboCop
USAGE_DATA_COUNTERS_EVENTS_YAML_GLOBS = [
File.expand_path("../../../config/metrics/aggregates/*.yml", __dir__),
- File.expand_path("../../../lib/gitlab/usage_data_counters/known_events/*.yml", __dir__)
+ File.expand_path("../../../lib/gitlab/usage_data_counters/known_events/*.yml", __dir__),
+ File.expand_path("../../../ee/lib/ee/gitlab/usage_data_counters/known_events/*.yml", __dir__)
].freeze
class << self
diff --git a/spec/components/pajamas/badge_component_spec.rb b/spec/components/pajamas/badge_component_spec.rb
new file mode 100644
index 00000000000..4c564121ba2
--- /dev/null
+++ b/spec/components/pajamas/badge_component_spec.rb
@@ -0,0 +1,148 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe Pajamas::BadgeComponent, type: :component do
+ let(:text) { "Hello" }
+ let(:options) { {} }
+ let(:html_options) { {} }
+
+ before do
+ render_inline(described_class.new(text, **options, **html_options))
+ end
+
+ describe "text param" do
+ it "is shown inside the badge" do
+ expect(page).to have_css ".gl-badge", text: text
+ end
+ end
+
+ describe "content slot" do
+ it "can be used instead of the text param" do
+ render_inline(described_class.new) do
+ "Slot content"
+ end
+ expect(page).to have_css ".gl-badge", text: "Slot content"
+ end
+
+ it "takes presendence over the text param" do
+ render_inline(described_class.new(text)) do
+ "Slot wins."
+ end
+ expect(page).to have_css ".gl-badge", text: "Slot wins."
+ end
+ end
+
+ describe "options" do
+ describe "icon" do
+ let(:options) { { icon: :tanuki } }
+
+ it "adds the correct icon and margin" do
+ expect(page).to have_css ".gl-icon.gl-badge-icon.gl-mr-2[data-testid='tanuki-icon']"
+ end
+ end
+
+ describe "icon_classes" do
+ let(:options) { { icon: :tanuki, icon_classes: icon_classes } }
+
+ context "as string" do
+ let(:icon_classes) { "js-special-badge-icon js-extra-special" }
+
+ it "combines custom classes and component classes" do
+ expect(page).to have_css \
+ ".gl-icon.gl-badge-icon.gl-mr-2.js-special-badge-icon.js-extra-special[data-testid='tanuki-icon']"
+ end
+ end
+
+ context "as array" do
+ let(:icon_classes) { %w[js-special-badge-icon js-extra-special] }
+
+ it "combines custom classes and component classes" do
+ expect(page).to have_css \
+ ".gl-icon.gl-badge-icon.gl-mr-2.js-special-badge-icon.js-extra-special[data-testid='tanuki-icon']"
+ end
+ end
+ end
+
+ describe "icon_only" do
+ let(:options) { { icon: :tanuki, icon_only: true } }
+
+ it "adds no extra margin to the icon" do
+ expect(page).not_to have_css ".gl-icon.gl-mr-2"
+ end
+
+ it "adds the text as ARIA label" do
+ expect(page).to have_css ".gl-badge[aria-label='#{text}'][role='img']"
+ end
+ end
+
+ describe "href" do
+ let(:options) { { href: "/foo" } }
+
+ it "makes the a badge a link" do
+ expect(page).to have_link text, class: "gl-badge", href: "/foo"
+ end
+ end
+
+ describe "size" do
+ where(:size) { [:sm, :md, :lg] }
+
+ with_them do
+ let(:options) { { size: size } }
+
+ it "adds size class" do
+ expect(page).to have_css ".gl-badge.#{size}"
+ end
+ end
+
+ context "with unknown size" do
+ let(:options) { { size: :xxl } }
+
+ it "adds the default size class" do
+ expect(page).to have_css ".gl-badge.md"
+ end
+ end
+ end
+
+ describe "variant" do
+ where(:variant) { [:muted, :neutral, :info, :success, :warning, :danger] }
+
+ with_them do
+ let(:options) { { variant: variant } }
+
+ it "adds variant class" do
+ expect(page).to have_css ".gl-badge.badge-#{variant}"
+ end
+ end
+
+ context "with unknown variant" do
+ let(:options) { { variant: :foo } }
+
+ it "adds the default variant class" do
+ expect(page).to have_css ".gl-badge.badge-muted"
+ end
+ end
+ end
+ end
+
+ describe "HTML options" do
+ let(:html_options) { { id: "badge-33", data: { foo: "bar" } } }
+
+ it "get added as HTML attributes" do
+ expect(page).to have_css ".gl-badge#badge-33[data-foo='bar']"
+ end
+
+ it "can be combined with component options in no particular order" do
+ render_inline(described_class.new(text, id: "badge-34", variant: :success, data: { foo: "baz" }, size: :sm))
+ expect(page).to have_css ".gl-badge.badge-success.sm#badge-34[data-foo='baz']"
+ end
+
+ context "with custom CSS classes" do
+ let(:html_options) { { id: "badge-35", class: "js-special-badge" } }
+
+ it "combines custom classes and component classes" do
+ expect(page).to have_css ".gl-badge.js-special-badge#badge-35"
+ end
+ end
+ end
+end
diff --git a/spec/components/previews/pajamas/badge_component_preview.rb b/spec/components/previews/pajamas/badge_component_preview.rb
new file mode 100644
index 00000000000..e740a4a38aa
--- /dev/null
+++ b/spec/components/previews/pajamas/badge_component_preview.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module Pajamas
+ class BadgeComponentPreview < ViewComponent::Preview
+ # Badge
+ # ---
+ #
+ # See its design reference [here](https://design.gitlab.com/components/badge).
+ #
+ # @param icon select [~, star-o, issue-closed, tanuki]
+ # @param icon_only toggle
+ # @param href url
+ # @param size select [sm, md, lg]
+ # @param text text
+ # @param variant select [muted, neutral, info, success, warning, danger]
+ def default(icon: :tanuki, icon_only: false, href: nil, size: :md, text: "Tanuki", variant: :muted)
+ render Pajamas::BadgeComponent.new(
+ text,
+ icon: icon,
+ icon_only: icon_only,
+ href: href,
+ size: size,
+ variant: variant
+ )
+ end
+
+ # Using the content slot
+ # ---
+ #
+ # Use the content slot instead of the `text` param when things get more complicated than a plain string.
+ # All other options (`icon`, `size`, etc.) work as usual.
+ def slot
+ render Pajamas::BadgeComponent.new(size: :lg, variant: :info) do
+ "!ereht olleh".reverse.capitalize
+ end
+ end
+
+ # Custom HTML attributes and icon classes
+ # ---
+ #
+ # Any extra options passed into the component are treated as HTML attributes.
+ # This makes adding data or an id easy.
+ #
+ # CSS classes provided with the `class:` option are combined with the component classes.
+ #
+ # It is also possible to set custom `icon_classes:`.
+ #
+ # The order in which you provide these keywords doesn't matter.
+ def custom
+ render Pajamas::BadgeComponent.new(
+ "I'm special.",
+ class: "js-special-badge",
+ data: { count: 1 },
+ icon: :tanuki,
+ icon_classes: ["js-special-badge-icon"],
+ id: "special-badge-22",
+ variant: :success
+ )
+ end
+ end
+end
diff --git a/spec/controllers/projects/pipeline_schedules_controller_spec.rb b/spec/controllers/projects/pipeline_schedules_controller_spec.rb
index fa90a0d9abc..5bcfae4227c 100644
--- a/spec/controllers/projects/pipeline_schedules_controller_spec.rb
+++ b/spec/controllers/projects/pipeline_schedules_controller_spec.rb
@@ -354,13 +354,14 @@ RSpec.describe Projects::PipelineSchedulesController do
end
def go
- put :update, params: {
+ put :update,
+ params: {
namespace_id: project.namespace.to_param,
project_id: project,
id: pipeline_schedule,
schedule: schedule
},
- as: :html
+ as: :html
end
end
diff --git a/spec/controllers/projects/service_desk_controller_spec.rb b/spec/controllers/projects/service_desk_controller_spec.rb
index bc507a033dc..e078bf9461e 100644
--- a/spec/controllers/projects/service_desk_controller_spec.rb
+++ b/spec/controllers/projects/service_desk_controller_spec.rb
@@ -4,8 +4,9 @@ require 'spec_helper'
RSpec.describe Projects::ServiceDeskController do
let_it_be(:project) do
- create(:project, :private, :custom_repo, service_desk_enabled: true,
- files: { '.gitlab/issue_templates/service_desk.md' => 'template' })
+ create(:project, :private, :custom_repo,
+ service_desk_enabled: true,
+ files: { '.gitlab/issue_templates/service_desk.md' => 'template' })
end
let_it_be(:user) { create(:user) }
diff --git a/spec/fixtures/api/schemas/external_validation.json b/spec/fixtures/api/schemas/external_validation.json
index 4a2538a020e..411c2ed591b 100644
--- a/spec/fixtures/api/schemas/external_validation.json
+++ b/spec/fixtures/api/schemas/external_validation.json
@@ -3,6 +3,7 @@
"required" : [
"project",
"user",
+ "credit_card",
"pipeline",
"builds",
"total_builds_count"
@@ -43,6 +44,17 @@
"sign_in_count": { "type": "integer" }
}
},
+ "credit_card": {
+ "type": "object",
+ "required": [
+ "similar_cards_count",
+ "similar_holder_names_count"
+ ],
+ "properties": {
+ "similar_cards_count": { "type": "integer" },
+ "similar_holder_names_count": { "type": "integer" }
+ }
+ },
"pipeline": {
"type": "object",
"required": [
diff --git a/spec/helpers/tab_helper_spec.rb b/spec/helpers/tab_helper_spec.rb
index dd5707e2aff..80a1224abbb 100644
--- a/spec/helpers/tab_helper_spec.rb
+++ b/spec/helpers/tab_helper_spec.rb
@@ -182,7 +182,7 @@ RSpec.describe TabHelper do
context 'with data attributes' do
it 'creates a tab counter badge with the data attributes' do
expect(helper.gl_tab_counter_badge(1, { data: { some_attribute: 'foo' } })).to eq(
- '<span data-some-attribute="foo" class="gl-badge badge badge-pill badge-muted sm gl-tab-counter-badge">1</span>'
+ '<span class="gl-badge badge badge-pill badge-muted sm gl-tab-counter-badge" data-some-attribute="foo">1</span>'
)
end
end
diff --git a/spec/lib/banzai/filter/kroki_filter_spec.rb b/spec/lib/banzai/filter/kroki_filter_spec.rb
index 1fb61ad1991..3f4f3aafdd6 100644
--- a/spec/lib/banzai/filter/kroki_filter_spec.rb
+++ b/spec/lib/banzai/filter/kroki_filter_spec.rb
@@ -46,4 +46,12 @@ RSpec.describe Banzai::Filter::KrokiFilter do
expect(doc.to_s).to start_with '<img src="http://localhost:8000/nomnoml/svg/eNqLDsgsSixJrUmtTHXOL80rsVLwzCupKUrMTNHQtC7IzMlJTE_V0KyJyVNQiE5KTSxKidXVjS5ILCrKL4lFFrSyi07LL81RyM0vLckAysRGjxo8avCowaMGjxo8avCowaMGU8lgAE7mIdc=" hidden="" class="js-render-kroki" data-diagram="nomnoml" data-diagram-src="data:text/plain;base64,W1BpcmF0ZXxleWVDb3VudDog'
end
+
+ it 'allows the lang attribute on the code tag to support RST files processed by gitlab-markup gem' do
+ stub_application_setting(kroki_enabled: true, kroki_url: "http://localhost:8000")
+ text = '[Pirate|eyeCount: Int|raid();pillage()|\n [beard]--[parrot]\n [beard]-:>[foul mouth]\n]' * 25
+ doc = filter("<pre><code lang='nomnoml'>#{text}</code></pre>")
+
+ expect(doc.to_s).to start_with '<img src="http://localhost:8000/nomnoml/svg/eNqLDsgsSixJrUmtTHXOL80rsVLwzCupKUrMTNHQtC7IzMlJTE_V0KyJyVNQiE5KTSxKidXVjS5ILCrKL4lFFrSyi07LL81RyM0vLckAysRGjxo8avCowaMGjxo8avCowaMGU8lgAE7mIdc=" hidden="" class="js-render-kroki" data-diagram="nomnoml" data-diagram-src="data:text/plain;base64,W1BpcmF0ZXxleWVDb3VudDog'
+ end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
index fb1a360a4b7..52a00e0d501 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
@@ -179,6 +179,70 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
perform!
end
end
+
+ describe 'credit_card' do
+ context 'with no registered credit_card' do
+ it 'returns the expected credit card counts' do
+ expect(::Gitlab::HTTP).to receive(:post) do |_url, params|
+ payload = Gitlab::Json.parse(params[:body])
+
+ expect(payload['credit_card']['similar_cards_count']).to eq(0)
+ expect(payload['credit_card']['similar_holder_names_count']).to eq(0)
+ end
+
+ perform!
+ end
+ end
+
+ context 'with a registered credit card' do
+ let!(:credit_card) { create(:credit_card_validation, last_digits: 10, holder_name: 'Alice', user: user) }
+
+ it 'returns the expected credit card counts' do
+ expect(::Gitlab::HTTP).to receive(:post) do |_url, params|
+ payload = Gitlab::Json.parse(params[:body])
+
+ expect(payload['credit_card']['similar_cards_count']).to eq(1)
+ expect(payload['credit_card']['similar_holder_names_count']).to eq(1)
+ end
+
+ perform!
+ end
+
+ context 'with similar credit cards registered by other users' do
+ before do
+ create(:credit_card_validation, last_digits: 10, holder_name: 'Bob')
+ end
+
+ it 'returns the expected credit card counts' do
+ expect(::Gitlab::HTTP).to receive(:post) do |_url, params|
+ payload = Gitlab::Json.parse(params[:body])
+
+ expect(payload['credit_card']['similar_cards_count']).to eq(2)
+ expect(payload['credit_card']['similar_holder_names_count']).to eq(1)
+ end
+
+ perform!
+ end
+ end
+
+ context 'with similar holder names registered by other users' do
+ before do
+ create(:credit_card_validation, last_digits: 11, holder_name: 'Alice')
+ end
+
+ it 'returns the expected credit card counts' do
+ expect(::Gitlab::HTTP).to receive(:post) do |_url, params|
+ payload = Gitlab::Json.parse(params[:body])
+
+ expect(payload['credit_card']['similar_cards_count']).to eq(1)
+ expect(payload['credit_card']['similar_holder_names_count']).to eq(2)
+ end
+
+ perform!
+ end
+ end
+ end
+ end
end
context 'when EXTERNAL_VALIDATION_SERVICE_TOKEN is set' do
diff --git a/spec/models/users/credit_card_validation_spec.rb b/spec/models/users/credit_card_validation_spec.rb
index 34cfd500c26..c003e004d29 100644
--- a/spec/models/users/credit_card_validation_spec.rb
+++ b/spec/models/users/credit_card_validation_spec.rb
@@ -28,4 +28,15 @@ RSpec.describe Users::CreditCardValidation do
expect(subject.similar_records).to eq([match2, match1, subject])
end
end
+
+ describe '.similar_holder_names_count' do
+ subject!(:credit_card_validation) { create(:credit_card_validation, holder_name: 'ALICE M SMITH') }
+
+ let!(:match) { create(:credit_card_validation, holder_name: 'Alice M Smith') }
+ let!(:non_match) { create(:credit_card_validation, holder_name: 'Bob B Brown') }
+
+ it 'returns the count of cards with similar case insensitive holder names' do
+ expect(subject.similar_holder_names_count).to eq(2)
+ end
+ end
end
diff --git a/spec/services/ci/create_downstream_pipeline_service_spec.rb b/spec/services/ci/create_downstream_pipeline_service_spec.rb
index 11fb564b843..c990d195e51 100644
--- a/spec/services/ci/create_downstream_pipeline_service_spec.rb
+++ b/spec/services/ci/create_downstream_pipeline_service_spec.rb
@@ -440,10 +440,7 @@ RSpec.describe Ci::CreateDownstreamPipelineService, '#execute' do
let!(:trigger_project_bridge) do
create(
- :ci_bridge, status: :pending,
- user: user,
- options: trigger_downstream_project,
- pipeline: child_pipeline
+ :ci_bridge, status: :pending, user: user, options: trigger_downstream_project, pipeline: child_pipeline
)
end
diff --git a/spec/services/ci/create_pipeline_service/logger_spec.rb b/spec/services/ci/create_pipeline_service/logger_spec.rb
index c4063751fa8..2be23802757 100644
--- a/spec/services/ci/create_pipeline_service/logger_spec.rb
+++ b/spec/services/ci/create_pipeline_service/logger_spec.rb
@@ -19,9 +19,9 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
let(:counters) do
{
'count' => a_kind_of(Numeric),
- 'avg' => a_kind_of(Numeric),
- 'max' => a_kind_of(Numeric),
- 'min' => a_kind_of(Numeric)
+ 'avg' => a_kind_of(Numeric),
+ 'max' => a_kind_of(Numeric),
+ 'min' => a_kind_of(Numeric)
}
end
diff --git a/spec/services/ci/create_pipeline_service/tags_spec.rb b/spec/services/ci/create_pipeline_service/tags_spec.rb
index 7eb9acfb422..7450df11eac 100644
--- a/spec/services/ci/create_pipeline_service/tags_spec.rb
+++ b/spec/services/ci/create_pipeline_service/tags_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
context 'tags persistence' do
let(:config) do
{
- build: {
+ build: {
script: 'ls',
stage: 'build',
tags: build_tag_list(label: 'build')
diff --git a/spec/services/ci/job_artifacts/create_service_spec.rb b/spec/services/ci/job_artifacts/create_service_spec.rb
index 7b3f67b192f..6809b694b22 100644
--- a/spec/services/ci/job_artifacts/create_service_spec.rb
+++ b/spec/services/ci/job_artifacts/create_service_spec.rb
@@ -151,9 +151,8 @@ RSpec.describe Ci::JobArtifacts::CreateService do
expect { subject }.not_to change { Ci::JobArtifact.count }
expect(subject).to match(
- a_hash_including(http_status: :bad_request,
- message: 'another artifact of the same type already exists',
- status: :error))
+ a_hash_including(
+ http_status: :bad_request, message: 'another artifact of the same type already exists', status: :error))
end
end
end
diff --git a/spec/services/ci/retry_job_service_spec.rb b/spec/services/ci/retry_job_service_spec.rb
index b14e4187c7a..5914e0fc4c1 100644
--- a/spec/services/ci/retry_job_service_spec.rb
+++ b/spec/services/ci/retry_job_service_spec.rb
@@ -7,14 +7,13 @@ RSpec.describe Ci::RetryJobService do
let_it_be(:developer) { create(:user) }
let_it_be(:project) { create(:project, :repository) }
let_it_be(:pipeline) do
- create(:ci_pipeline, project: project,
- sha: 'b83d6e391c22777fca1ed3012fce84f633d7fed0')
+ create(:ci_pipeline, project: project, sha: 'b83d6e391c22777fca1ed3012fce84f633d7fed0')
end
let_it_be(:stage) do
create(:ci_stage, project: project,
- pipeline: pipeline,
- name: 'test')
+ pipeline: pipeline,
+ name: 'test')
end
let(:job_variables_attributes) { [{ key: 'MANUAL_VAR', value: 'manual test var' }] }
@@ -31,9 +30,8 @@ RSpec.describe Ci::RetryJobService do
let_it_be(:downstream_project) { create(:project, :repository) }
let_it_be_with_refind(:job) do
- create(
- :ci_bridge, :success, pipeline: pipeline, downstream: downstream_project,
- description: 'a trigger job', stage_id: stage.id
+ create(:ci_bridge, :success,
+ pipeline: pipeline, downstream: downstream_project, description: 'a trigger job', stage_id: stage.id
)
end
@@ -133,9 +131,7 @@ RSpec.describe Ci::RetryJobService do
end
let!(:subsequent_bridge) do
- create(:ci_bridge, :skipped, stage_idx: 2,
- pipeline: pipeline,
- stage: 'deploy')
+ create(:ci_bridge, :skipped, stage_idx: 2, pipeline: pipeline, stage: 'deploy')
end
it 'resumes pipeline processing in the subsequent stage' do
@@ -245,10 +241,13 @@ RSpec.describe Ci::RetryJobService do
let(:environment_name) { 'review/$CI_COMMIT_REF_SLUG-$GITLAB_USER_ID' }
let!(:job) do
- create(:ci_build, :with_deployment, environment: environment_name,
- options: { environment: { name: environment_name } },
- pipeline: pipeline, stage_id: stage.id, project: project,
- user: other_developer)
+ create(:ci_build, :with_deployment,
+ environment: environment_name,
+ options: { environment: { name: environment_name } },
+ pipeline: pipeline,
+ stage_id: stage.id,
+ project: project,
+ user: other_developer)
end
it 'creates a new deployment' do
diff --git a/spec/services/deployments/link_merge_requests_service_spec.rb b/spec/services/deployments/link_merge_requests_service_spec.rb
index 62adc834733..a653cd2b48b 100644
--- a/spec/services/deployments/link_merge_requests_service_spec.rb
+++ b/spec/services/deployments/link_merge_requests_service_spec.rb
@@ -159,10 +159,10 @@ RSpec.describe Deployments::LinkMergeRequestsService do
it "doesn't link the same merge_request twice" do
create(:merge_request, :merged, merge_commit_sha: mr1_merge_commit_sha,
- source_project: project)
+ source_project: project)
picked_mr = create(:merge_request, :merged, merge_commit_sha: '123abc',
- source_project: project)
+ source_project: project)
# the first MR includes c1c67abba which is a cherry-pick of the fake picked_mr merge request
create(:track_mr_picking_note, noteable: picked_mr, project: project, commit_id: 'c1c67abbaf91f624347bb3ae96eabe3a1b742478')
diff --git a/spec/services/discussions/capture_diff_note_positions_service_spec.rb b/spec/services/discussions/capture_diff_note_positions_service_spec.rb
index 25e5f549bee..8ba54495d4c 100644
--- a/spec/services/discussions/capture_diff_note_positions_service_spec.rb
+++ b/spec/services/discussions/capture_diff_note_positions_service_spec.rb
@@ -18,8 +18,8 @@ RSpec.describe Discussions::CaptureDiffNotePositionsService do
def build_position(diff_refs, new_line: nil, old_line: nil)
path = 'files/markdown/ruby-style-guide.md'
- Gitlab::Diff::Position.new(old_path: path, new_path: path,
- new_line: new_line, old_line: old_line, diff_refs: diff_refs)
+ Gitlab::Diff::Position.new(
+ old_path: path, new_path: path, new_line: new_line, old_line: old_line, diff_refs: diff_refs)
end
def note_for(new_line: nil, old_line: nil)
diff --git a/spec/services/environments/stop_service_spec.rb b/spec/services/environments/stop_service_spec.rb
index 3ed8a0b1da0..b0c9826b137 100644
--- a/spec/services/environments/stop_service_spec.rb
+++ b/spec/services/environments/stop_service_spec.rb
@@ -208,8 +208,11 @@ RSpec.describe Environments::StopService do
context 'when pipeline is a branch pipeline for merge request' do
let(:pipeline) do
- create(:ci_pipeline, source: :push, project: project, sha: merge_request.diff_head_sha,
- merge_requests_as_head_pipeline: [merge_request])
+ create(:ci_pipeline,
+ source: :push,
+ project: project,
+ sha: merge_request.diff_head_sha,
+ merge_requests_as_head_pipeline: [merge_request])
end
it 'does not stop the active environment' do
diff --git a/spec/services/event_create_service_spec.rb b/spec/services/event_create_service_spec.rb
index e66b413a5c9..06f0eb1efbc 100644
--- a/spec/services/event_create_service_spec.rb
+++ b/spec/services/event_create_service_spec.rb
@@ -420,9 +420,9 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
service.save_designs(author, create: [design])
expect_snowplow_event(
- category: Gitlab::UsageDataCounters::TrackUniqueEvents::DESIGN_ACTION.to_s,
+ category: Gitlab::UsageDataCounters::TrackUniqueEvents::DESIGN_ACTION.to_s,
action: 'create',
- namespace: design.project.namespace,
+ namespace: design.project.namespace,
user: author,
project: design.project,
label: 'design_users'
@@ -433,9 +433,9 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
service.save_designs(author, update: [design])
expect_snowplow_event(
- category: Gitlab::UsageDataCounters::TrackUniqueEvents::DESIGN_ACTION.to_s,
+ category: Gitlab::UsageDataCounters::TrackUniqueEvents::DESIGN_ACTION.to_s,
action: 'update',
- namespace: design.project.namespace,
+ namespace: design.project.namespace,
user: author,
project: design.project,
label: 'design_users'
@@ -481,9 +481,9 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
service.destroy_designs([design], author)
expect_snowplow_event(
- category: Gitlab::UsageDataCounters::TrackUniqueEvents::DESIGN_ACTION.to_s,
+ category: Gitlab::UsageDataCounters::TrackUniqueEvents::DESIGN_ACTION.to_s,
action: 'destroy',
- namespace: design.project.namespace,
+ namespace: design.project.namespace,
user: author,
project: design.project,
label: 'design_users'
diff --git a/spec/services/groups/import_export/import_service_spec.rb b/spec/services/groups/import_export/import_service_spec.rb
index 292f2e2b86b..a4dfec4723a 100644
--- a/spec/services/groups/import_export/import_service_spec.rb
+++ b/spec/services/groups/import_export/import_service_spec.rb
@@ -149,9 +149,9 @@ RSpec.describe Groups::ImportExport::ImportService do
it 'logs the import success' do
expect(import_logger).to receive(:info).with(
- group_id: group.id,
+ group_id: group.id,
group_name: group.name,
- message: 'Group Import/Export: Import succeeded'
+ message: 'Group Import/Export: Import succeeded'
).once
subject
@@ -161,9 +161,9 @@ RSpec.describe Groups::ImportExport::ImportService do
context 'when user does not have correct permissions' do
it 'logs the error and raises an exception' do
expect(import_logger).to receive(:error).with(
- group_id: group.id,
+ group_id: group.id,
group_name: group.name,
- message: a_string_including('Errors occurred')
+ message: a_string_including('Errors occurred')
)
expect { subject }.to raise_error(Gitlab::ImportExport::Error)
@@ -186,9 +186,9 @@ RSpec.describe Groups::ImportExport::ImportService do
it 'logs the error and raises an exception' do
expect(import_logger).to receive(:error).with(
- group_id: group.id,
+ group_id: group.id,
group_name: group.name,
- message: a_string_including('Errors occurred')
+ message: a_string_including('Errors occurred')
).once
expect { subject }.to raise_error(Gitlab::ImportExport::Error)
@@ -267,9 +267,9 @@ RSpec.describe Groups::ImportExport::ImportService do
it 'logs the import success' do
expect(import_logger).to receive(:info).with(
- group_id: group.id,
+ group_id: group.id,
group_name: group.name,
- message: 'Group Import/Export: Import succeeded'
+ message: 'Group Import/Export: Import succeeded'
).once
subject
@@ -279,9 +279,9 @@ RSpec.describe Groups::ImportExport::ImportService do
context 'when user does not have correct permissions' do
it 'logs the error and raises an exception' do
expect(import_logger).to receive(:error).with(
- group_id: group.id,
+ group_id: group.id,
group_name: group.name,
- message: a_string_including('Errors occurred')
+ message: a_string_including('Errors occurred')
)
expect { subject }.to raise_error(Gitlab::ImportExport::Error)
@@ -304,9 +304,9 @@ RSpec.describe Groups::ImportExport::ImportService do
it 'logs the error and raises an exception' do
expect(import_logger).to receive(:error).with(
- group_id: group.id,
+ group_id: group.id,
group_name: group.name,
- message: a_string_including('Errors occurred')
+ message: a_string_including('Errors occurred')
).once
expect { subject }.to raise_error(Gitlab::ImportExport::Error)
@@ -328,9 +328,9 @@ RSpec.describe Groups::ImportExport::ImportService do
allow(Gitlab::Import::Logger).to receive(:build).and_return(import_logger)
expect(import_logger).to receive(:info).with(
- group_id: group.id,
+ group_id: group.id,
group_name: group.name,
- message: 'Group Import/Export: Import succeeded'
+ message: 'Group Import/Export: Import succeeded'
)
subject
diff --git a/spec/services/issuable/bulk_update_service_spec.rb b/spec/services/issuable/bulk_update_service_spec.rb
index 55e0e799c19..dc72cf04776 100644
--- a/spec/services/issuable/bulk_update_service_spec.rb
+++ b/spec/services/issuable/bulk_update_service_spec.rb
@@ -47,7 +47,7 @@ RSpec.describe Issuable::BulkUpdateService do
let(:bulk_update_params) do
{
- add_label_ids: add_labels.map(&:id),
+ add_label_ids: add_labels.map(&:id),
remove_label_ids: remove_labels.map(&:id)
}
end
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index efff967614d..4a84862b9d5 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -416,7 +416,7 @@ RSpec.describe Issues::CreateService do
context "when issuable feature is private" do
before do
project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE,
- merge_requests_access_level: ProjectFeature::PRIVATE)
+ merge_requests_access_level: ProjectFeature::PRIVATE)
end
levels = [Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PUBLIC]
diff --git a/spec/services/merge_requests/build_service_spec.rb b/spec/services/merge_requests/build_service_spec.rb
index 3c9d2271ddc..6a6f01e6a95 100644
--- a/spec/services/merge_requests/build_service_spec.rb
+++ b/spec/services/merge_requests/build_service_spec.rb
@@ -20,18 +20,30 @@ RSpec.describe MergeRequests::BuildService do
let(:merge_request) { service.execute }
let(:compare) { double(:compare, commits: commits) }
let(:commit_1) do
- double(:commit_1, sha: 'f00ba6', safe_message: 'Initial commit',
- gitaly_commit?: false, id: 'f00ba6', parent_ids: ['f00ba5'])
+ double(:commit_1,
+ sha: 'f00ba6',
+ safe_message: 'Initial commit',
+ gitaly_commit?: false,
+ id: 'f00ba6',
+ parent_ids: ['f00ba5'])
end
let(:commit_2) do
- double(:commit_2, sha: 'f00ba7', safe_message: "Closes #1234 Second commit\n\nCreate the app",
- gitaly_commit?: false, id: 'f00ba7', parent_ids: ['f00ba6'])
+ double(:commit_2,
+ sha: 'f00ba7',
+ safe_message: "Closes #1234 Second commit\n\nCreate the app",
+ gitaly_commit?: false,
+ id: 'f00ba7',
+ parent_ids: ['f00ba6'])
end
let(:commit_3) do
- double(:commit_3, sha: 'f00ba8', safe_message: 'This is a bad commit message!',
- gitaly_commit?: false, id: 'f00ba8', parent_ids: ['f00ba7'])
+ double(:commit_3,
+ sha: 'f00ba8',
+ safe_message: 'This is a bad commit message!',
+ gitaly_commit?: false,
+ id: 'f00ba8',
+ parent_ids: ['f00ba7'])
end
let(:commits) { nil }
diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb
index 9c9bcb79990..4102cdc101e 100644
--- a/spec/services/merge_requests/create_service_spec.rb
+++ b/spec/services/merge_requests/create_service_spec.rb
@@ -434,7 +434,7 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
context "when issuable feature is private" do
before do
project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE,
- merge_requests_access_level: ProjectFeature::PRIVATE)
+ merge_requests_access_level: ProjectFeature::PRIVATE)
end
levels = [Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PUBLIC]
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index 606fd066f1c..64145a85b62 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -510,9 +510,9 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
before do
create(:ci_pipeline,
project: project,
- ref: merge_request.source_branch,
- sha: merge_request.diff_head_sha,
- status: :success)
+ ref: merge_request.source_branch,
+ sha: merge_request.diff_head_sha,
+ status: :success)
perform_enqueued_jobs do
@merge_request = service.execute(merge_request)
diff --git a/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb b/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb
index b326fc1726d..47e5557105b 100644
--- a/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb
+++ b/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb
@@ -62,7 +62,7 @@ RSpec.describe Metrics::Dashboard::CloneDashboardService, :use_clean_rails_memor
start_branch: project.default_branch,
encoding: 'text',
file_path: ".gitlab/dashboards/custom_dashboard.yml",
- file_content: file_content_hash.to_yaml
+ file_content: file_content_hash.to_yaml
}
end
diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb
index 37318d76586..74684bc05ce 100644
--- a/spec/services/notes/create_service_spec.rb
+++ b/spec/services/notes/create_service_spec.rb
@@ -134,8 +134,7 @@ RSpec.describe Notes::CreateService do
context 'in a merge request' do
let_it_be(:project_with_repo) { create(:project, :repository) }
let_it_be(:merge_request) do
- create(:merge_request, source_project: project_with_repo,
- target_project: project_with_repo)
+ create(:merge_request, source_project: project_with_repo, target_project: project_with_repo)
end
context 'noteable highlight cache clearing' do
@@ -181,8 +180,7 @@ RSpec.describe Notes::CreateService do
it 'does not clear cache when note is not the first of the discussion' do
prev_note =
- create(:diff_note_on_merge_request, noteable: merge_request,
- project: project_with_repo)
+ create(:diff_note_on_merge_request, noteable: merge_request, project: project_with_repo)
reply_opts =
opts.merge(in_reply_to_discussion_id: prev_note.discussion_id,
type: 'DiffNote',
diff --git a/spec/services/notes/destroy_service_spec.rb b/spec/services/notes/destroy_service_spec.rb
index be95a4bb181..82caec52aee 100644
--- a/spec/services/notes/destroy_service_spec.rb
+++ b/spec/services/notes/destroy_service_spec.rb
@@ -57,13 +57,11 @@ RSpec.describe Notes::DestroyService do
context 'in a merge request' do
let_it_be(:repo_project) { create(:project, :repository) }
let_it_be(:merge_request) do
- create(:merge_request, source_project: repo_project,
- target_project: repo_project)
+ create(:merge_request, source_project: repo_project, target_project: repo_project)
end
let_it_be(:note) do
- create(:diff_note_on_merge_request, project: repo_project,
- noteable: merge_request)
+ create(:diff_note_on_merge_request, project: repo_project, noteable: merge_request)
end
it 'does not track issue comment removal usage data' do
@@ -84,9 +82,8 @@ RSpec.describe Notes::DestroyService do
end
it 'does not clear cache when note is not the first of the discussion' do
- reply_note = create(:diff_note_on_merge_request, in_reply_to: note,
- project: repo_project,
- noteable: merge_request)
+ reply_note = create(:diff_note_on_merge_request,
+ in_reply_to: note, project: repo_project, noteable: merge_request)
expect(merge_request).not_to receive(:diffs)
diff --git a/spec/services/packages/debian/parse_debian822_service_spec.rb b/spec/services/packages/debian/parse_debian822_service_spec.rb
index ff146fda250..a2731816459 100644
--- a/spec/services/packages/debian/parse_debian822_service_spec.rb
+++ b/spec/services/packages/debian/parse_debian822_service_spec.rb
@@ -77,7 +77,7 @@ RSpec.describe Packages::Debian::ParseDebian822Service do
'Depends' => '${shlibs:Depends}, ${misc:Depends}',
'Description' => "Some mostly empty lib\nUsed in GitLab tests.\n\nTesting another paragraph."
},
- 'Package: sample-udeb' => {
+ 'Package: sample-udeb' => {
'Package' => 'sample-udeb',
'Package-Type' => 'udeb',
'Architecture' => 'any',
diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb
index e4ccd83e3ef..94320320407 100644
--- a/spec/services/projects/destroy_service_spec.rb
+++ b/spec/services/projects/destroy_service_spec.rb
@@ -312,7 +312,7 @@ RSpec.describe Projects::DestroyService, :aggregate_failures, :event_store_publi
before do
stub_container_registry_tags(repository: project.full_path + '/image',
- tags: ['tag'])
+ tags: ['tag'])
project.container_repositories << container_repository
end
@@ -350,7 +350,7 @@ RSpec.describe Projects::DestroyService, :aggregate_failures, :event_store_publi
context 'when there are tags for legacy root repository' do
before do
stub_container_registry_tags(repository: project.full_path,
- tags: ['tag'])
+ tags: ['tag'])
end
context 'when image repository tags deletion succeeds' do
diff --git a/spec/services/service_ping/submit_service_ping_service_spec.rb b/spec/services/service_ping/submit_service_ping_service_spec.rb
index b863b2a46b0..70de02723cd 100644
--- a/spec/services/service_ping/submit_service_ping_service_spec.rb
+++ b/spec/services/service_ping/submit_service_ping_service_spec.rb
@@ -386,12 +386,12 @@ RSpec.describe ServicePing::SubmitService do
let(:payload) do
{
uuid: 'uuid',
- metric_a: metric_double,
- metric_group: {
+ metric_a: metric_double,
+ metric_group: {
metric_b: metric_double
},
- metric_without_timing: "value",
- recorded_at: Time.current
+ metric_without_timing: "value",
+ recorded_at: Time.current
}
end
@@ -399,10 +399,10 @@ RSpec.describe ServicePing::SubmitService do
{
metadata: {
uuid: 'uuid',
- metrics: [
- { name: 'metric_a', time_elapsed: 123 },
- { name: 'metric_group.metric_b', time_elapsed: 123 }
- ]
+ metrics: [
+ { name: 'metric_a', time_elapsed: 123 },
+ { name: 'metric_group.metric_b', time_elapsed: 123 }
+ ]
}
}
end
diff --git a/spec/services/suggestions/apply_service_spec.rb b/spec/services/suggestions/apply_service_spec.rb
index e34324d5fe2..41ccd8523fa 100644
--- a/spec/services/suggestions/apply_service_spec.rb
+++ b/spec/services/suggestions/apply_service_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe Suggestions::ApplyService do
def apply(suggestions, custom_message = nil)
result = apply_service.new(user, *suggestions, message: custom_message).execute
- suggestions.map { |suggestion| suggestion.reload }
+ suggestions.map(&:reload)
expect(result[:status]).to eq(:success)
end
@@ -136,21 +136,20 @@ RSpec.describe Suggestions::ApplyService do
end
let(:merge_request) do
- create(:merge_request, source_project: project,
- target_project: project,
- source_branch: 'master')
+ create(:merge_request,
+ source_project: project, target_project: project, source_branch: 'master')
end
let(:position) { build_position }
let(:diff_note) do
- create(:diff_note_on_merge_request, noteable: merge_request,
- position: position, project: project)
+ create(:diff_note_on_merge_request,
+ noteable: merge_request, position: position, project: project)
end
let(:suggestion) do
- create(:suggestion, :content_from_repo, note: diff_note,
- to_content: " raise RuntimeError, 'Explosion'\n # explosion?\n")
+ create(:suggestion, :content_from_repo,
+ note: diff_note, to_content: " raise RuntimeError, 'Explosion'\n # explosion?\n")
end
let(:suggestion2) do
@@ -311,9 +310,9 @@ RSpec.describe Suggestions::ApplyService do
context 'when HEAD from position is different from source branch HEAD on repo' do
it 'returns error message' do
- allow(suggestion).to receive(:appliable?) { true }
- allow(suggestion.position).to receive(:head_sha) { 'old-sha' }
- allow(suggestion.noteable).to receive(:source_branch_sha) { 'new-sha' }
+ allow(suggestion).to receive(:appliable?).and_return(true)
+ allow(suggestion.position).to receive(:head_sha).and_return('old-sha')
+ allow(suggestion.noteable).to receive(:source_branch_sha).and_return('new-sha')
result = apply_service.new(user, suggestion).execute
@@ -430,7 +429,6 @@ RSpec.describe Suggestions::ApplyService do
suggestion1_diff = fetch_raw_diff(suggestion1)
suggestion2_diff = fetch_raw_diff(suggestion2)
- # rubocop: disable Layout/TrailingWhitespace
expected_suggestion1_diff = <<-CONTENT.strip_heredoc
@@ -10,7 +10,7 @@ module Popen
end
@@ -442,9 +440,6 @@ RSpec.describe Suggestions::ApplyService do
"PWD" => path
}
CONTENT
- # rubocop: enable Layout/TrailingWhitespace
-
- # rubocop: disable Layout/TrailingWhitespace
expected_suggestion2_diff = <<-CONTENT.strip_heredoc
@@ -28,7 +28,7 @@ module Popen
@@ -455,8 +450,6 @@ RSpec.describe Suggestions::ApplyService do
@cmd_status = wait_thr.value.exitstatus
end
CONTENT
- # rubocop: enable Layout/TrailingWhitespace
-
expect(suggestion1_diff.strip).to eq(expected_suggestion1_diff.strip)
expect(suggestion2_diff.strip).to eq(expected_suggestion2_diff.strip)
end
@@ -508,10 +501,8 @@ RSpec.describe Suggestions::ApplyService do
end
let(:suggestion) do
- create(:suggestion, :content_from_repo, note: diff_note,
- lines_above: 2,
- lines_below: 3,
- to_content: "# multi\n# line\n")
+ create(:suggestion, :content_from_repo,
+ note: diff_note, lines_above: 2, lines_below: 3, to_content: "# multi\n# line\n")
end
let(:suggestions) { [suggestion] }
@@ -568,7 +559,7 @@ RSpec.describe Suggestions::ApplyService do
end
let(:suggestion) do
- create_suggestion( to_content: "", new_line: 13)
+ create_suggestion(to_content: "", new_line: 13)
end
let(:suggestions) { [suggestion] }
@@ -616,14 +607,12 @@ RSpec.describe Suggestions::ApplyService do
context 'no permission' do
let(:merge_request) do
- create(:merge_request, source_project: project,
- target_project: project)
+ create(:merge_request, source_project: project, target_project: project)
end
let(:diff_note) do
- create(:diff_note_on_merge_request, noteable: merge_request,
- position: position,
- project: project)
+ create(:diff_note_on_merge_request,
+ noteable: merge_request, position: position, project: project)
end
context 'user cannot write in project repo' do
@@ -642,14 +631,12 @@ RSpec.describe Suggestions::ApplyService do
context 'patch is not appliable' do
let(:merge_request) do
- create(:merge_request, source_project: project,
- target_project: project)
+ create(:merge_request, source_project: project, target_project: project)
end
let(:diff_note) do
- create(:diff_note_on_merge_request, noteable: merge_request,
- position: position,
- project: project)
+ create(:diff_note_on_merge_request,
+ noteable: merge_request, position: position, project: project)
end
before do
@@ -669,7 +656,7 @@ RSpec.describe Suggestions::ApplyService do
let(:result) { apply_service.new(user, suggestion).execute }
before do
- expect(suggestion.note).to receive(:latest_diff_file) { nil }
+ expect(suggestion.note).to receive(:latest_diff_file).and_return(nil)
end
it 'returns error message' do
diff --git a/spec/services/work_items/widgets/description_service/update_service_spec.rb b/spec/services/work_items/widgets/description_service/update_service_spec.rb
index 582d9dc85f7..4275950e720 100644
--- a/spec/services/work_items/widgets/description_service/update_service_spec.rb
+++ b/spec/services/work_items/widgets/description_service/update_service_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe WorkItems::Widgets::DescriptionService::UpdateService do
let(:current_user) { author }
let(:work_item) do
create(:work_item, author: author, project: project, description: 'old description',
- last_edited_at: Date.yesterday, last_edited_by: random_user
+ last_edited_at: Date.yesterday, last_edited_by: random_user
)
end
diff --git a/spec/tooling/danger/datateam_spec.rb b/spec/tooling/danger/datateam_spec.rb
index e4ab3a6f4b1..de8a93baa27 100644
--- a/spec/tooling/danger/datateam_spec.rb
+++ b/spec/tooling/danger/datateam_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe Tooling::Danger::Datateam do
impacted: true,
impacted_files: %w(db/structure.sql)
},
- 'with structure.sql changes and Data Warehouse::Impact Check label' => {
+ 'with structure.sql changes and Data Warehouse::Impact Check label' => {
modified_files: %w(db/structure.sql),
changed_lines: ['+group_id bigint NOT NULL)'],
mr_labels: ['Data Warehouse::Impact Check'],
diff --git a/spec/views/projects/tags/index.html.haml_spec.rb b/spec/views/projects/tags/index.html.haml_spec.rb
index aff233b697f..99db5d9e2a8 100644
--- a/spec/views/projects/tags/index.html.haml_spec.rb
+++ b/spec/views/projects/tags/index.html.haml_spec.rb
@@ -7,8 +7,8 @@ RSpec.describe 'projects/tags/index.html.haml' do
let_it_be(:git_tag) { project.repository.tags.last }
let_it_be(:release) do
create(:release, project: project,
- sha: git_tag.target_commit.sha,
- tag: 'v1.1.0')
+ sha: git_tag.target_commit.sha,
+ tag: 'v1.1.0')
end
let(:pipeline) { create(:ci_pipeline, :success, project: project, ref: git_tag.name, sha: release.sha) }
diff --git a/spec/workers/emails_on_push_worker_spec.rb b/spec/workers/emails_on_push_worker_spec.rb
index 3e313610054..7d11957e2df 100644
--- a/spec/workers/emails_on_push_worker_spec.rb
+++ b/spec/workers/emails_on_push_worker_spec.rb
@@ -51,7 +51,7 @@ RSpec.describe EmailsOnPushWorker, :mailer do
context "when push is a force push to delete commits" do
before do
data_force_push = data.stringify_keys.merge(
- "after" => data[:before],
+ "after" => data[:before],
"before" => data[:after]
)
diff --git a/spec/workers/pages_domain_ssl_renewal_cron_worker_spec.rb b/spec/workers/pages_domain_ssl_renewal_cron_worker_spec.rb
index 563bbdef1be..70ffef5342e 100644
--- a/spec/workers/pages_domain_ssl_renewal_cron_worker_spec.rb
+++ b/spec/workers/pages_domain_ssl_renewal_cron_worker_spec.rb
@@ -25,8 +25,8 @@ RSpec.describe PagesDomainSslRenewalCronWorker do
end
let!(:domain_with_failed_auto_ssl) do
- create(:pages_domain, :without_certificate, :without_key, project: project,
- auto_ssl_enabled: true, auto_ssl_failed: true)
+ create(:pages_domain, :without_certificate, :without_key,
+ project: project, auto_ssl_enabled: true, auto_ssl_failed: true)
end
let!(:domain_with_expired_auto_ssl) do