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:
-rw-r--r--.gitlab/CODEOWNERS16
-rw-r--r--app/assets/stylesheets/framework/blocks.scss83
-rw-r--r--app/assets/stylesheets/framework/calendar.scss39
-rw-r--r--app/assets/stylesheets/page_bundles/profile.scss212
-rw-r--r--app/assets/stylesheets/pages/profile.scss94
-rw-r--r--app/components/pajamas/checkbox_component.rb9
-rw-r--r--app/components/pajamas/checkbox_tag_component.html.haml6
-rw-r--r--app/components/pajamas/checkbox_tag_component.rb44
-rw-r--r--app/components/pajamas/concerns/checkbox_radio_label_with_help_text.rb4
-rw-r--r--app/components/pajamas/radio_component.rb4
-rw-r--r--app/services/ci/runners/process_runner_version_update_service.rb2
-rw-r--r--app/services/ci/runners/reconcile_existing_runner_versions_service.rb2
-rw-r--r--app/services/merge_requests/approval_service.rb2
-rw-r--r--app/views/projects/_new_project_fields.html.haml18
-rw-r--r--app/views/projects/compare/show.html.haml2
-rw-r--r--app/views/users/show.html.haml1
-rw-r--r--config/application.rb1
-rw-r--r--config/feature_flags/development/incremental_repository_backup.yml8
-rw-r--r--config/sidekiq_queues.yml2
-rw-r--r--doc/development/fe_guide/view_component.md33
-rw-r--r--doc/development/single_table_inheritance.md11
-rw-r--r--doc/development/testing_guide/contract/index.md10
-rw-r--r--lib/backup/gitaly_backup.rb11
-rw-r--r--lib/backup/manager.rb6
-rw-r--r--lib/gitlab/ci/runner_releases.rb2
-rw-r--r--lib/gitlab/ci/runner_upgrade_check.rb19
-rw-r--r--lib/tasks/contracts/merge_requests.rake4
-rw-r--r--lib/tasks/contracts/pipeline_schedules.rake34
-rw-r--r--lib/tasks/contracts/pipelines.rake2
-rw-r--r--spec/components/pajamas/checkbox_component_spec.rb6
-rw-r--r--spec/components/pajamas/checkbox_tag_component_spec.rb59
-rw-r--r--spec/components/pajamas/concerns/checkbox_radio_label_with_help_text_spec.rb77
-rw-r--r--spec/contracts/consumer/fixtures/project/pipeline_schedule/update_pipeline_schedule.fixture.js48
-rw-r--r--spec/contracts/consumer/helpers/common_regex_patterns.js2
-rw-r--r--spec/contracts/consumer/resources/api/pipeline_schedules.js26
-rw-r--r--spec/contracts/consumer/specs/project/pipeline_schedule/edit.spec.js45
-rw-r--r--spec/contracts/contracts/project/pipeline_schedule/edit/pipelineschedules#edit-put_edit_a_pipeline_schedule.json48
-rw-r--r--spec/contracts/provider/pact_helpers/project/pipeline_schedule/update_pipeline_schedule_helper.rb16
-rw-r--r--spec/contracts/provider/states/project/pipeline_schedule/edit_state.rb15
-rw-r--r--spec/frontend/fixtures/runner.rb7
-rw-r--r--spec/lib/backup/gitaly_backup_spec.rb70
-rw-r--r--spec/lib/gitlab/ci/runner_releases_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/runner_upgrade_check_spec.rb23
-rw-r--r--spec/requests/api/graphql/ci/runners_spec.rb4
-rw-r--r--spec/services/ci/runners/reconcile_existing_runner_versions_service_spec.rb34
-rw-r--r--spec/support/helpers/runner_releases_helper.rb22
-rw-r--r--spec/support/shared_examples/components/pajamas_shared_examples.rb6
47 files changed, 778 insertions, 415 deletions
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index 04ed04b1f9d..7810021a883 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -493,7 +493,6 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/ci/unit_test_reports.md @marcel.amirault
/doc/ci/variables/ @marcel.amirault
/doc/ci/yaml/ @marcel.amirault
-/doc/development/adding_database_indexes.md @aqualls
/doc/development/application_limits.md @axil
/doc/development/approval_rules.md @aqualls
/doc/development/audit_event_guide/index.md @eread
@@ -512,12 +511,8 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/code_intelligence/index.md @aqualls
/doc/development/contributing/ @sselhorn
/doc/development/contributing/merge_request_workflow.md @aqualls
-/doc/development/creating_enums.md @aqualls
-/doc/development/database_debugging.md @aqualls
-/doc/development/database_query_comments.md @aqualls
/doc/development/database_review.md @aqualls
/doc/development/database/ @aqualls
-/doc/development/db_dump.md @aqualls
/doc/development/developing_with_solargraph.md @aqualls
/doc/development/diffs.md @aqualls
/doc/development/distributed_tracing.md @msedlakjakubowski
@@ -538,7 +533,6 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/feature_flags/controls.md @sselhorn
/doc/development/feature_flags/index.md @sselhorn
/doc/development/filtering_by_label.md @msedlakjakubowski
-/doc/development/foreign_keys.md @aqualls
/doc/development/geo.md @axil
/doc/development/geo/framework.md @axil
/doc/development/git_object_deduplication.md @eread
@@ -552,7 +546,6 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/image_scaling.md @sselhorn
/doc/development/import_export.md @eread
/doc/development/index.md @sselhorn
-/doc/development/insert_into_tables_in_batches.md @aqualls
/doc/development/integrations/ @kpaizee
/doc/development/integrations/codesandbox.md @sselhorn
/doc/development/integrations/secure_partner_integration.md @rdickenson
@@ -561,7 +554,6 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/internal_users.md @sselhorn
/doc/development/issuable-like-models.md @msedlakjakubowski
/doc/development/issue_types.md @msedlakjakubowski
-/doc/development/iterating_tables_in_batches.md @aqualls
/doc/development/kubernetes.md @sselhorn
/doc/development/lfs.md @aqualls
/doc/development/ee_features.md @fneill
@@ -570,30 +562,22 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/new_fe_guide/modules/widget_extensions.md @aqualls
/doc/development/new_fe_guide/tips.md @sselhorn
/doc/development/omnibus.md @axil
-/doc/development/ordering_table_columns.md @aqualls
/doc/development/packages/ @claytoncornell
/doc/development/permissions.md @eread
/doc/development/policies.md @eread
/doc/development/product_qualified_lead_guide/index.md @kpaizee
/doc/development/project_templates.md @fneill
/doc/development/prometheus_metrics.md @msedlakjakubowski
-/doc/development/query_performance.md @aqualls
-/doc/development/query_recorder.md @aqualls
/doc/development/real_time.md @msedlakjakubowski
/doc/development/secure_coding_guidelines.md @sselhorn
-/doc/development/serializing_data.md @aqualls
/doc/development/service_ping/ @claytoncornell
-/doc/development/single_table_inheritance.md @aqualls
/doc/development/snowplow/ @claytoncornell
/doc/development/spam_protection_and_captcha/ @eread
/doc/development/sql.md @aqualls
-/doc/development/swapping_tables.md @aqualls
/doc/development/testing_guide/best_practices.md @sselhorn
/doc/development/testing_guide/end_to_end/best_practices.md @sselhorn
-/doc/development/understanding_explain_plans.md @aqualls
/doc/development/value_stream_analytics.md @fneill
/doc/development/value_stream_analytics/value_stream_analytics_aggregated_backend.md @fneill
-/doc/development/verifying_database_capabilities.md @aqualls
/doc/development/wikis.md @aqualls
/doc/development/work_items_widgets.md @msedlakjakubowski
/doc/development/work_items.md @msedlakjakubowski
diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss
index 549289450a4..f947042ba51 100644
--- a/app/assets/stylesheets/framework/blocks.scss
+++ b/app/assets/stylesheets/framework/blocks.scss
@@ -84,89 +84,6 @@
border-bottom: 1px solid $white-dark;
padding: 11px 0;
margin-bottom: 11px;
-
- &.no-bottom-space {
- border-bottom: 0;
- margin-bottom: 0;
- }
-}
-
-.cover-block {
- text-align: center;
- background: $gray-light;
- padding-top: 44px;
- position: relative;
-
- .avatar-holder {
- .avatar,
- .identicon {
- margin: 0 auto;
- float: none;
- }
-
- .identicon {
- border-radius: 50%;
- }
- }
-
- .cover-title {
- color: $gl-text-color;
- font-size: 23px;
-
- h1 {
- color: $gl-text-color;
- margin-bottom: 6px;
- font-size: 23px;
- }
-
- .visibility-icon {
- display: inline-block;
- margin-left: 5px;
- font-size: 18px;
- color: color('gray');
- }
-
- p {
- padding: 0 $gl-padding;
- color: $gl-text-color;
- }
- }
-
- .cover-controls {
- @include media-breakpoint-up(sm) {
- position: absolute;
- top: 1rem;
- right: 1.25rem;
- }
-
- &.left {
- @include media-breakpoint-up(sm) {
- left: 1.25rem;
- right: auto;
- }
- }
- }
-
- &.user-cover-block {
- padding: 24px 0 0;
-
- .nav-links {
- width: 100%;
- float: none;
-
- &.scrolling-tabs {
- float: none;
- }
- }
-
- li:first-child {
- margin-left: auto;
- }
-
- li:last-child {
- margin-right: auto;
- }
- }
}
.content-block {
diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss
index 1fa03d66f32..b1e5ca50a8b 100644
--- a/app/assets/stylesheets/framework/calendar.scss
+++ b/app/assets/stylesheets/framework/calendar.scss
@@ -1,30 +1,3 @@
-.calendar-block {
- padding-left: 0;
- padding-right: 0;
- border-top: 0;
-
- @media (min-width: map-get($grid-breakpoints, sm)) and (max-width: map-get($grid-breakpoints, sm)) {
- overflow-x: auto;
- }
-}
-
-.user-calendar-activities {
- direction: ltr;
-
- .str-truncated {
- max-width: 70%;
- }
-}
-
-.user-calendar {
- text-align: center;
- min-height: 172px;
-
- .calendar {
- display: inline-block;
- }
-}
-
.user-contrib-cell {
&:hover {
cursor: pointer;
@@ -42,18 +15,6 @@
}
}
-.user-contrib-text {
- font-size: 12px;
- fill: $calendar-user-contrib-text;
-}
-
-.calendar-hint {
- font-size: 12px;
- direction: ltr;
- margin-top: -23px;
- float: right;
-}
-
.pika-single.gitlab-theme {
.pika-label {
color: $gl-text-color-secondary;
diff --git a/app/assets/stylesheets/page_bundles/profile.scss b/app/assets/stylesheets/page_bundles/profile.scss
new file mode 100644
index 00000000000..59b8823c113
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/profile.scss
@@ -0,0 +1,212 @@
+@import 'mixins_and_variables_and_functions';
+
+.calendar-block {
+ padding-left: 0;
+ padding-right: 0;
+ border-top: 0;
+
+ @media (min-width: map-get($grid-breakpoints, sm)) and (max-width: map-get($grid-breakpoints, sm)) {
+ overflow-x: auto;
+ }
+}
+
+.calendar-hint {
+ font-size: 12px;
+ direction: ltr;
+ margin-top: -23px;
+ float: right;
+}
+
+.cover-block {
+ text-align: center;
+ background: var(--gray-50, $gray-light);
+ padding-top: 44px;
+ position: relative;
+
+ .avatar-holder {
+ .avatar,
+ .identicon {
+ margin: 0 auto;
+ float: none;
+ }
+
+ .identicon {
+ border-radius: 50%;
+ }
+ }
+
+ .cover-title {
+ color: var(--gl-text-color, $gl-text-color);
+ font-size: 23px;
+
+ h1 {
+ color: var(--gl-text-color, $gl-text-color);
+ margin-bottom: 6px;
+ font-size: 23px;
+ }
+
+ .visibility-icon {
+ display: inline-block;
+ margin-left: 5px;
+ font-size: 18px;
+ color: color('gray');
+ }
+
+ p {
+ padding: 0 $gl-padding;
+ color: var(--gl-text-color, $gl-text-color);
+ }
+ }
+
+ .cover-controls {
+ @include media-breakpoint-up(sm) {
+ position: absolute;
+ top: 1rem;
+ right: 1.25rem;
+ }
+
+ &.left {
+ @include media-breakpoint-up(sm) {
+ left: 1.25rem;
+ right: auto;
+ }
+ }
+ }
+
+ &.user-cover-block {
+ padding: 24px 0 0;
+
+ .nav-links {
+ width: 100%;
+ float: none;
+
+ &.scrolling-tabs {
+ float: none;
+ }
+ }
+
+ li:first-child {
+ margin-left: auto;
+ }
+
+ li:last-child {
+ margin-right: auto;
+ }
+ }
+}
+
+// Middle dot divider between each element in a list of items.
+.middle-dot-divider {
+ @include middle-dot-divider;
+}
+
+.middle-dot-divider-sm {
+ @include media-breakpoint-up(sm) {
+ @include middle-dot-divider;
+ }
+}
+
+.profile-user-bio {
+ // Limits the width of the user bio for readability.
+ max-width: 600px;
+ margin: 10px auto;
+}
+
+.user-calendar {
+ text-align: center;
+ min-height: 172px;
+
+ .calendar {
+ display: inline-block;
+ }
+}
+
+.user-calendar-activities {
+ direction: ltr;
+
+ .str-truncated {
+ max-width: 70%;
+ }
+}
+
+.user-contrib-text {
+ font-size: 12px;
+ fill: $calendar-user-contrib-text;
+}
+
+.user-profile {
+ .profile-header {
+ margin: 0 $gl-padding;
+
+ &.with-no-profile-tabs {
+ margin-bottom: $gl-padding-24;
+ }
+
+ .avatar-holder {
+ width: 90px;
+ margin: 0 auto 10px;
+ }
+ }
+
+ .user-profile-nav {
+ font-size: 0;
+ }
+
+ .fade-right {
+ right: 0;
+ }
+
+ .fade-left {
+ left: 0;
+ }
+
+ .activities-block {
+ .event-item {
+ padding-left: 40px;
+ }
+
+ .gl-label-scoped {
+ --label-inset-border: inset 0 0 0 1px currentColor;
+ }
+
+ @include media-breakpoint-up(lg) {
+ margin-right: 5px;
+ }
+ }
+
+ .projects-block {
+ @include media-breakpoint-up(lg) {
+ margin-left: 5px;
+ }
+ }
+
+ @include media-breakpoint-down(xs) {
+ .cover-block {
+ padding-top: 20px;
+ }
+
+ .user-profile-nav {
+ a {
+ margin-right: 0;
+ }
+ }
+
+ .activities-block {
+ .event-item {
+ padding-left: 0;
+ }
+ }
+ }
+}
+
+.linkedin-icon {
+ color: $linkedin;
+}
+
+.skype-icon {
+ color: $skype;
+}
+
+.twitter-icon {
+ color: $twitter;
+}
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index 812cc6ab4e6..951e31ef768 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -29,23 +29,6 @@
}
}
-// Middle dot divider between each element in a list of items.
-.middle-dot-divider {
- @include middle-dot-divider;
-}
-
-.middle-dot-divider-sm {
- @include media-breakpoint-up(sm) {
- @include middle-dot-divider;
- }
-}
-
-.profile-user-bio {
- // Limits the width of the user bio for readability.
- max-width: 600px;
- margin: 10px auto;
-}
-
.user-avatar-button {
.file-name {
display: inline-block;
@@ -156,71 +139,6 @@
}
}
-.user-profile {
- .profile-header {
- margin: 0 $gl-padding;
-
- &.with-no-profile-tabs {
- margin-bottom: $gl-padding-24;
- }
-
- .avatar-holder {
- width: 90px;
- margin: 0 auto 10px;
- }
- }
-
- .user-profile-nav {
- font-size: 0;
- }
-
- .fade-right {
- right: 0;
- }
-
- .fade-left {
- left: 0;
- }
-
- .activities-block {
- .event-item {
- padding-left: 40px;
- }
-
- .gl-label-scoped {
- --label-inset-border: inset 0 0 0 1px currentColor;
- }
-
- @include media-breakpoint-up(lg) {
- margin-right: 5px;
- }
- }
-
- .projects-block {
- @include media-breakpoint-up(lg) {
- margin-left: 5px;
- }
- }
-
- @include media-breakpoint-down(xs) {
- .cover-block {
- padding-top: 20px;
- }
-
- .user-profile-nav {
- a {
- margin-right: 0;
- }
- }
-
- .activities-block {
- .event-item {
- padding-left: 0;
- }
- }
- }
-}
-
table.u2f-registrations {
th:not(:last-child),
td:not(:last-child) {
@@ -366,15 +284,3 @@ table.u2f-registrations {
.gitlab-slack-slack-logo {
transform: scale(200%); // Slack logo SVG is scaled down 50% and has empty space around it
}
-
-.skype-icon {
- color: $skype;
-}
-
-.linkedin-icon {
- color: $linkedin;
-}
-
-.twitter-icon {
- color: $twitter;
-}
diff --git a/app/components/pajamas/checkbox_component.rb b/app/components/pajamas/checkbox_component.rb
index ae78d0453f8..d9987b7653c 100644
--- a/app/components/pajamas/checkbox_component.rb
+++ b/app/components/pajamas/checkbox_component.rb
@@ -1,7 +1,10 @@
# frozen_string_literal: true
# Renders a Pajamas compliant checkbox element
-# Must be used in an instance of `ActionView::Helpers::FormBuilder`
+# An instance of `ActionView::Helpers::FormBuilder` must be passed as the `form` argument.
+# The easiest way to use this component is by using the `gitlab_ui_checkbox_component` helper.
+# See https://docs.gitlab.com/ee/development/fe_guide/haml.html#gitlab_ui_checkbox_component
+# To use a checkbox without an instance of `ActionView::Helpers::FormBuilder` use `CheckboxTagComponent`.
module Pajamas
class CheckboxComponent < Pajamas::Component
include Pajamas::Concerns::CheckboxRadioLabelWithHelpText
@@ -31,6 +34,8 @@ module Pajamas
@value = checked_value if checkbox_options[:multiple]
end
+ private
+
attr_reader(
:form,
:method,
@@ -43,8 +48,6 @@ module Pajamas
:value
)
- private
-
def label_content
label? ? label : label_argument
end
diff --git a/app/components/pajamas/checkbox_tag_component.html.haml b/app/components/pajamas/checkbox_tag_component.html.haml
new file mode 100644
index 00000000000..ad02c966fad
--- /dev/null
+++ b/app/components/pajamas/checkbox_tag_component.html.haml
@@ -0,0 +1,6 @@
+.gl-form-checkbox.custom-control.custom-checkbox
+ = check_box_tag(name,
+ value,
+ checked,
+ formatted_input_options)
+ = render_label_tag_with_help_text
diff --git a/app/components/pajamas/checkbox_tag_component.rb b/app/components/pajamas/checkbox_tag_component.rb
new file mode 100644
index 00000000000..45e88588059
--- /dev/null
+++ b/app/components/pajamas/checkbox_tag_component.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+# Renders a Pajamas compliant checkbox element
+module Pajamas
+ class CheckboxTagComponent < Pajamas::Component
+ include Pajamas::Concerns::CheckboxRadioLabelWithHelpText
+ include Pajamas::Concerns::CheckboxRadioOptions
+
+ renders_one :label
+ renders_one :help_text
+
+ def initialize(
+ name:,
+ label_options: {},
+ checkbox_options: {},
+ value: '1',
+ checked: false
+ )
+ @name = name
+ @label_options = label_options
+ @input_options = checkbox_options
+ @value = value
+ @checked = checked
+ end
+
+ private
+
+ attr_reader(
+ :name,
+ :label_options,
+ :input_options,
+ :value,
+ :checked
+ )
+
+ def label_content
+ label
+ end
+
+ def help_text_content
+ help_text
+ end
+ end
+end
diff --git a/app/components/pajamas/concerns/checkbox_radio_label_with_help_text.rb b/app/components/pajamas/concerns/checkbox_radio_label_with_help_text.rb
index 4ece904fb85..298ed200101 100644
--- a/app/components/pajamas/concerns/checkbox_radio_label_with_help_text.rb
+++ b/app/components/pajamas/concerns/checkbox_radio_label_with_help_text.rb
@@ -7,6 +7,10 @@ module Pajamas
form.label(method, formatted_label_options) { label_entry }
end
+ def render_label_tag_with_help_text
+ label_tag(name, formatted_label_options) { label_entry }
+ end
+
private
def label_entry
diff --git a/app/components/pajamas/radio_component.rb b/app/components/pajamas/radio_component.rb
index 52a761b9d7d..7a3d95c8565 100644
--- a/app/components/pajamas/radio_component.rb
+++ b/app/components/pajamas/radio_component.rb
@@ -28,6 +28,8 @@ module Pajamas
@value = value
end
+ private
+
attr_reader(
:form,
:method,
@@ -38,8 +40,6 @@ module Pajamas
:value
)
- private
-
def label_content
label? ? label : label_argument
end
diff --git a/app/services/ci/runners/process_runner_version_update_service.rb b/app/services/ci/runners/process_runner_version_update_service.rb
index ed591a9ab3e..c8a5e42ccab 100644
--- a/app/services/ci/runners/process_runner_version_update_service.rb
+++ b/app/services/ci/runners/process_runner_version_update_service.rb
@@ -20,7 +20,7 @@ module Ci
private
def upgrade_check_service
- Gitlab::Ci::RunnerUpgradeCheck.instance
+ @runner_upgrade_check ||= Gitlab::Ci::RunnerUpgradeCheck.new(::Gitlab::VERSION)
end
end
end
diff --git a/app/services/ci/runners/reconcile_existing_runner_versions_service.rb b/app/services/ci/runners/reconcile_existing_runner_versions_service.rb
index 18b959513a8..da9be7d7207 100644
--- a/app/services/ci/runners/reconcile_existing_runner_versions_service.rb
+++ b/app/services/ci/runners/reconcile_existing_runner_versions_service.rb
@@ -22,7 +22,7 @@ module Ci
private
def upgrade_check
- Gitlab::Ci::RunnerUpgradeCheck.instance
+ @runner_upgrade_check ||= Gitlab::Ci::RunnerUpgradeCheck.new(::Gitlab::VERSION)
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/services/merge_requests/approval_service.rb b/app/services/merge_requests/approval_service.rb
index f2651370305..be6ab9050d9 100644
--- a/app/services/merge_requests/approval_service.rb
+++ b/app/services/merge_requests/approval_service.rb
@@ -25,9 +25,9 @@ module MergeRequests
)
else
create_event(merge_request)
+ stream_audit_event(merge_request)
end
- stream_audit_event(merge_request)
create_approval_note(merge_request)
mark_pending_todos_as_done(merge_request)
execute_approval_hooks(merge_request, current_user)
diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml
index 992b46c1f7b..3c7d358bde9 100644
--- a/app/views/projects/_new_project_fields.html.haml
+++ b/app/views/projects/_new_project_fields.html.haml
@@ -63,18 +63,20 @@
= s_('ProjectsNew|Project Configuration')
.form-group
- .form-check.gl-mb-3
- = check_box_tag 'project[initialize_with_readme]', '1', true, class: 'form-check-input', data: { qa_selector: 'initialize_with_readme_checkbox', track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_readme' }
- = label_tag 'project[initialize_with_readme]', s_('ProjectsNew|Initialize repository with a README'), class: 'form-check-label'
- .form-text.text-muted
+ = render Pajamas::CheckboxTagComponent.new(name: 'project[initialize_with_readme]',
+ checked: true,
+ checkbox_options: { data: { qa_selector: 'initialize_with_readme_checkbox', track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_readme' } }) do |c|
+ = c.label do
+ = s_('ProjectsNew|Initialize repository with a README')
+ = c.help_text do
= s_('ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository.')
.form-group
- .form-check.gl-mb-3
- = check_box_tag 'project[initialize_with_sast]', '1', false, class: 'form-check-input', data: { qa_selector: 'initialize_with_sast_checkbox', track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' }
- = label_tag 'project[initialize_with_sast]', class: 'form-check-label' do
+ = render Pajamas::CheckboxTagComponent.new(name: 'project[initialize_with_sast]',
+ checkbox_options: { data: { qa_selector: 'initialize_with_sast_checkbox', track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' } }) do |c|
+ = c.label do
= s_('ProjectsNew|Enable Static Application Security Testing (SAST)')
- .form-text.text-muted
+ = c.help_text do
= s_('ProjectsNew|Analyze your source code for known security vulnerabilities.')
= link_to _('Learn more.'), help_page_path('user/application_security/sast/index'), target: '_blank', rel: 'noopener noreferrer', data: { track_action: 'followed' }
diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml
index adb5cceb5d6..95186b85838 100644
--- a/app/views/projects/compare/show.html.haml
+++ b/app/views/projects/compare/show.html.haml
@@ -1,7 +1,7 @@
- add_to_breadcrumbs _("Compare Revisions"), project_compare_index_path(@project)
- page_title "#{params[:from]}...#{params[:to]}"
-.sub-header-block.no-bottom-space
+.sub-header-block.gl-border-b-0.gl-mb-0
.js-signature-container{ data: { 'signatures-path' => signatures_namespace_project_compare_index_path } }
#js-compare-selector{ data: project_compare_selector_data(@project, @merge_request, params) }
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 0eb243137b6..25070138128 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -4,6 +4,7 @@
- page_title user_display_name(@user)
- page_description @user.bio unless @user.blocked? || !@user.confirmed?
- page_itemtype 'http://schema.org/Person'
+- add_page_specific_style 'page_bundles/profile'
- link_classes = "flex-grow-1 mx-1 "
= content_for :meta_tags do
diff --git a/config/application.rb b/config/application.rb
index d5e7cd69b37..d28967f2966 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -290,6 +290,7 @@ module Gitlab
config.assets.precompile << "page_bundles/pipelines.css"
config.assets.precompile << "page_bundles/pipeline_editor.css"
config.assets.precompile << "page_bundles/productivity_analytics.css"
+ config.assets.precompile << "page_bundles/profile.css"
config.assets.precompile << "page_bundles/profile_two_factor_auth.css"
config.assets.precompile << "page_bundles/project.css"
config.assets.precompile << "page_bundles/projects_edit.css"
diff --git a/config/feature_flags/development/incremental_repository_backup.yml b/config/feature_flags/development/incremental_repository_backup.yml
deleted file mode 100644
index 2b980abd403..00000000000
--- a/config/feature_flags/development/incremental_repository_backup.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: incremental_repository_backup
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79589
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/355945
-milestone: '14.9'
-type: development
-group: group::gitaly
-default_enabled: true
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 6d27b9de54c..80a452eec44 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -287,6 +287,8 @@
- 1
- - merge_requests_resolve_todos
- 1
+- - merge_requests_stream_approval_audit_event
+ - 1
- - merge_requests_sync_code_owner_approval_rules
- 1
- - merge_requests_update_head_pipeline
diff --git a/doc/development/fe_guide/view_component.md b/doc/development/fe_guide/view_component.md
index 35df9db2452..2e373e6933b 100644
--- a/doc/development/fe_guide/view_component.md
+++ b/doc/development/fe_guide/view_component.md
@@ -153,6 +153,39 @@ If you want to add custom attributes to any of these or the card itself, use the
For the full list of options, see its
[source](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/components/pajamas/card_component.rb).
+#### Checkbox tag
+
+The `Pajamas::CheckboxTagComponent` follows the [Pajamas Checkbox](https://design.gitlab.com/components/checkbox) specification.
+
+The `name` argument and `label` slot are required.
+
+For example:
+
+```haml
+= render Pajamas::CheckboxTagComponent.new(name: 'project[initialize_with_sast]',
+ checkbox_options: { data: { qa_selector: 'initialize_with_sast_checkbox', track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' } }) do |c|
+ = c.label do
+ = s_('ProjectsNew|Enable Static Application Security Testing (SAST)')
+ = c.help_text do
+ = s_('ProjectsNew|Analyze your source code for known security vulnerabilities.')
+ = link_to _('Learn more.'), help_page_path('user/application_security/sast/index'), target: '_blank', rel: 'noopener noreferrer', data: { track_action: 'followed' }
+```
+
+For the full list of options, see its
+[source](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/components/pajamas/checkbox_tag_component.rb).
+
+#### Checkbox
+
+The `Pajamas::CheckboxComponent` follows the [Pajamas Checkbox](https://design.gitlab.com/components/checkbox) specification.
+
+NOTE:
+`Pajamas::CheckboxComponent` is used internally by the [GitLab UI form builder](haml.md#use-the-gitlab-ui-form-builder) and requires an instance of [ActionView::Helpers::FormBuilder](https://api.rubyonrails.org/v6.1.0/classes/ActionView/Helpers/FormBuilder.html) to be passed as the `form` argument.
+It is preferred to use the [gitlab_ui_checkbox_component](haml.md#gitlab_ui_checkbox_component) method to render this ViewComponent.
+To use a checkbox without an instance of [ActionView::Helpers::FormBuilder](https://api.rubyonrails.org/v6.1.0/classes/ActionView/Helpers/FormBuilder.html) use [CheckboxTagComponent](#checkbox-tag).
+
+For the full list of options, see its
+[source](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/components/pajamas/checkbox_component.rb).
+
#### Toggle
The `Pajamas::ToggleComponent` follows the [Pajamas Toggle](https://design.gitlab.com/components/toggle) specification.
diff --git a/doc/development/single_table_inheritance.md b/doc/development/single_table_inheritance.md
new file mode 100644
index 00000000000..da8d48f2a42
--- /dev/null
+++ b/doc/development/single_table_inheritance.md
@@ -0,0 +1,11 @@
+---
+redirect_to: 'database/single_table_inheritance.md'
+remove_date: '2022-11-06'
+---
+
+This document was moved to [another location](database/single_table_inheritance.md).
+
+<!-- This redirect file can be deleted after <2022-11-06>. -->
+<!-- Redirects that point to other docs in the same project expire in three months. -->
+<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/development/testing_guide/contract/index.md b/doc/development/testing_guide/contract/index.md
index 8e12eea2874..f61f842e167 100644
--- a/doc/development/testing_guide/contract/index.md
+++ b/doc/development/testing_guide/contract/index.md
@@ -28,14 +28,14 @@ Before running the consumer tests, go to `spec/contracts/consumer` and run `npm
### Run the provider tests
-Before running the provider tests, make sure your GDK (GitLab Development Kit) is fully set up and running. You can follow the setup instructions detailed in the [GDK repository](https://gitlab.com/gitlab-org/gitlab-development-kit/-/tree/main). To run the provider tests, you use Rake tasks that are defined in [`./lib/tasks/contracts.rake`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/tasks/contracts.rake). To get a list of all the Rake tasks related to the provider tests, run `bundle exec rake -T contracts`. For example:
+Before running the provider tests, make sure your GDK (GitLab Development Kit) is fully set up and running. You can follow the setup instructions detailed in the [GDK repository](https://gitlab.com/gitlab-org/gitlab-development-kit/-/tree/main). To run the provider tests, you use Rake tasks that can be found in [`./lib/tasks/contracts`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/tasks/contracts). To get a list of all the Rake tasks related to the provider tests, run `bundle exec rake -T contracts`. For example:
```shell
$ bundle exec rake -T contracts
-rake contracts:mr:pact:verify:diffs # Verify provider against the consumer pacts for diffs
-rake contracts:mr:pact:verify:discussions # Verify provider against the consumer pacts for discussions
-rake contracts:mr:pact:verify:metadata # Verify provider against the consumer pacts for metadata
-rake contracts:mr:test:merge_request[contract_mr] # Run all merge request contract tests
+rake contracts:merge_requests:pact:verify:diffs_batch # Verify provider against the consumer pacts for diffs_batch
+rake contracts:merge_requests:pact:verify:diffs_metadata # Verify provider against the consumer pacts for diffs_metadata
+rake contracts:merge_requests:pact:verify:discussions # Verify provider against the consumer pacts for discussions
+rake contracts:merge_requests:test:merge_requests[contract_merge_requests] # Run all merge request contract tests
```
## Test suite folder structure and naming conventions
diff --git a/lib/backup/gitaly_backup.rb b/lib/backup/gitaly_backup.rb
index a995f308c2b..b777b581ae1 100644
--- a/lib/backup/gitaly_backup.rb
+++ b/lib/backup/gitaly_backup.rb
@@ -32,15 +32,12 @@ module Backup
raise Error, "unknown backup type: #{type}"
end
- args = []
+ args = ['-layout', 'pointer']
args += ['-parallel', @max_parallelism.to_s] if @max_parallelism
args += ['-parallel-storage', @storage_parallelism.to_s] if @storage_parallelism
- if Feature.enabled?(:incremental_repository_backup)
- args += ['-layout', 'pointer']
- if type == :create
- args += ['-incremental'] if incremental?
- args += ['-id', backup_id] if backup_id
- end
+ if type == :create
+ args += ['-incremental'] if incremental?
+ args += ['-id', backup_id] if backup_id
end
@input_stream, stdout, @thread = Open3.popen2(build_env, bin_path, command, '-path', backup_repos_path, *args)
diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb
index 18d9124fbd2..a95311e0ecc 100644
--- a/lib/backup/manager.rb
+++ b/lib/backup/manager.rb
@@ -34,11 +34,7 @@ module Backup
def initialize(progress, definitions: nil)
@progress = progress
-
- @incremental = Feature.feature_flags_available? &&
- Feature.enabled?(:incremental_repository_backup) &&
- Gitlab::Utils.to_boolean(ENV['INCREMENTAL'], default: false)
-
+ @incremental = Gitlab::Utils.to_boolean(ENV['INCREMENTAL'], default: false)
@definitions = definitions
end
diff --git a/lib/gitlab/ci/runner_releases.rb b/lib/gitlab/ci/runner_releases.rb
index 8773ecbf09e..31a537f1b61 100644
--- a/lib/gitlab/ci/runner_releases.rb
+++ b/lib/gitlab/ci/runner_releases.rb
@@ -74,7 +74,7 @@ module Gitlab
releases = response.parsed_response
.map { |release| parse_runner_release(release) }
.select(&:valid?)
- .sort!
+ .sort
return if releases.empty? && response.parsed_response.present?
diff --git a/lib/gitlab/ci/runner_upgrade_check.rb b/lib/gitlab/ci/runner_upgrade_check.rb
index 646d1420ffb..03130addd6a 100644
--- a/lib/gitlab/ci/runner_upgrade_check.rb
+++ b/lib/gitlab/ci/runner_upgrade_check.rb
@@ -3,7 +3,10 @@
module Gitlab
module Ci
class RunnerUpgradeCheck
- include Singleton
+ def initialize(gitlab_version, runner_releases_store = nil)
+ @gitlab_version = ::Gitlab::VersionInfo.parse(gitlab_version, parse_suffix: true)
+ @releases_store = runner_releases_store
+ end
def check_runner_upgrade_suggestion(runner_version)
check_runner_upgrade_suggestions(runner_version).first
@@ -11,12 +14,8 @@ module Gitlab
private
- def gitlab_version
- @gitlab_version ||= ::Gitlab::VersionInfo.parse(::Gitlab::VERSION, parse_suffix: true)
- end
-
def runner_releases_store
- RunnerReleases.instance
+ @releases_store ||= RunnerReleases.instance
end
def add_suggestion(suggestions, runner_version, version, status)
@@ -54,12 +53,12 @@ module Gitlab
# Consider the edge case of pre-release runner versions that get registered, but are never published.
# In this case, suggest the latest compatible runner version
- latest_release = runner_releases_store.releases_by_minor.values.select { |v| v < gitlab_version }.max
+ latest_release = runner_releases_store.releases_by_minor.values.select { |v| v < @gitlab_version }.max
add_suggestion(suggestions, runner_version, latest_release, :recommended)
end
def add_available_runner_release(runner_version, suggestions)
- available_version = runner_releases_store.releases_by_minor[gitlab_version.without_patch]
+ available_version = runner_releases_store.releases_by_minor[@gitlab_version.without_patch]
unless suggestions.include?(available_version)
add_suggestion(suggestions, runner_version, available_version, :available)
end
@@ -76,12 +75,12 @@ module Gitlab
outside_window = minor_releases_with_index.count - runner_minor_version_index > 3
if outside_window
- recommended_version = runner_releases_store.releases_by_minor[gitlab_version.without_patch]
+ recommended_version = runner_releases_store.releases_by_minor[@gitlab_version.without_patch]
return add_suggestion(suggestions, runner_version, recommended_version, :recommended)
end
else
# If unknown runner version, then recommend the latest version for the GitLab instance
- return add_recommended_runner_release_update(gitlab_version, suggestions)
+ return add_recommended_runner_release_update(@gitlab_version, suggestions)
end
false
diff --git a/lib/tasks/contracts/merge_requests.rake b/lib/tasks/contracts/merge_requests.rake
index 05ed9c30495..2fdd2beb4ee 100644
--- a/lib/tasks/contracts/merge_requests.rake
+++ b/lib/tasks/contracts/merge_requests.rake
@@ -33,9 +33,9 @@ namespace :contracts do
end
desc 'Run all merge request contract tests'
- task 'test:merge_requests', :contract_mr do |_t, arg|
+ task 'test:merge_requests', :contract_merge_requests do |_t, arg|
errors = %w[diffs_batch diffs_metadata discussions].each_with_object([]) do |task, err|
- Rake::Task["contracts:mr:pact:verify:#{task}"].execute
+ Rake::Task["contracts:merge_requests:pact:verify:#{task}"].execute
rescue StandardError, SystemExit
err << "contracts:merge_requests:pact:verify:#{task}"
end
diff --git a/lib/tasks/contracts/pipeline_schedules.rake b/lib/tasks/contracts/pipeline_schedules.rake
new file mode 100644
index 00000000000..b6d331448e2
--- /dev/null
+++ b/lib/tasks/contracts/pipeline_schedules.rake
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+return if Rails.env.production?
+
+require 'pact/tasks/verification_task'
+
+contracts = File.expand_path('../../../spec/contracts/contracts/project/pipeline_schedule', __dir__)
+provider = File.expand_path('../../../provider', contracts)
+
+# rubocop:disable Rails/RakeEnvironment
+namespace :contracts do
+ namespace :pipeline_schedules do
+ Pact::VerificationTask.new(:update_pipeline_schedule) do |pact|
+ pact.uri(
+ "#{contracts}/edit/pipelineschedules#edit-put_edit_a_pipeline_schedule.json",
+ pact_helper: "#{provider}/pact_helpers/project/pipeline_schedule/update_pipeline_schedule_helper.rb"
+ )
+ end
+
+ desc 'Run all pipeline schedule contract tests'
+ task 'test:pipeline_schedules', :contract_pipeline_schedules do |_t, arg|
+ errors = %w[
+ update_pipeline_schedule
+ ].each_with_object([]) do |task, err|
+ Rake::Task["contracts:pipeline_schedules:pact:verify:#{task}"].execute
+ rescue StandardError, SystemExit
+ err << "contracts:pipeline_schedule:pact:verify:#{task}"
+ end
+
+ raise StandardError, "Errors in tasks #{errors.join(', ')}" unless errors.empty?
+ end
+ end
+end
+# rubocop:enable Rails/RakeEnvironment
diff --git a/lib/tasks/contracts/pipelines.rake b/lib/tasks/contracts/pipelines.rake
index 522e1f0399e..75955822242 100644
--- a/lib/tasks/contracts/pipelines.rake
+++ b/lib/tasks/contracts/pipelines.rake
@@ -39,7 +39,7 @@ namespace :contracts do
end
desc 'Run all pipeline contract tests'
- task 'test:pipelines', :contract_mr do |_t, arg|
+ task 'test:pipelines', :contract_pipelines do |_t, arg|
errors = %w[
create_a_new_pipeline
get_list_project_pipelines
diff --git a/spec/components/pajamas/checkbox_component_spec.rb b/spec/components/pajamas/checkbox_component_spec.rb
index d79c537a30e..3d50509ef10 100644
--- a/spec/components/pajamas/checkbox_component_spec.rb
+++ b/spec/components/pajamas/checkbox_component_spec.rb
@@ -8,12 +8,6 @@ RSpec.describe Pajamas::CheckboxComponent, :aggregate_failures, type: :component
let_it_be(:label) { "Show one file at a time on merge request's Changes tab" }
let_it_be(:help_text) { 'Instead of all the files changed, show only one file at a time.' }
- RSpec.shared_examples 'it renders unchecked checkbox with value of `1`' do
- it 'renders unchecked checkbox with value of `1`' do
- expect(page).to have_unchecked_field(label, with: '1')
- end
- end
-
context 'with default options' do
before do
fake_form_for do |form|
diff --git a/spec/components/pajamas/checkbox_tag_component_spec.rb b/spec/components/pajamas/checkbox_tag_component_spec.rb
new file mode 100644
index 00000000000..bca7a6005d5
--- /dev/null
+++ b/spec/components/pajamas/checkbox_tag_component_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+require "spec_helper"
+
+RSpec.describe Pajamas::CheckboxTagComponent, :aggregate_failures, type: :component do
+ let_it_be(:name) { :view_diffs_file_by_file }
+ let_it_be(:label) { "Show one file at a time on merge request's Changes tab" }
+ let_it_be(:help_text) { 'Instead of all the files changed, show only one file at a time.' }
+
+ context 'with default options' do
+ before do
+ render_inline(described_class.new(name: name)) do |c|
+ c.label { label }
+ end
+ end
+
+ include_examples 'it renders unchecked checkbox with value of `1`'
+ include_examples 'it does not render help text'
+ end
+
+ context 'with custom options' do
+ let_it_be(:value) { 'yes' }
+ let_it_be(:checkbox_options) { { class: 'checkbox-foo-bar', checked: true } }
+ let_it_be(:label_options) { { class: 'label-foo-bar' } }
+
+ before do
+ render_inline(
+ described_class.new(
+ name: name,
+ value: value,
+ checked: true,
+ checkbox_options: checkbox_options,
+ label_options: label_options
+ )
+ ) do |c|
+ c.label { label }
+ end
+ end
+
+ it 'renders checked checkbox with value of `yes`' do
+ expect(page).to have_checked_field(label, with: value, class: checkbox_options[:class])
+ end
+
+ it 'adds CSS class to label' do
+ expect(page).to have_selector('label.label-foo-bar')
+ end
+ end
+
+ context 'with `help_text` slot' do
+ before do
+ render_inline(described_class.new(name: name)) do |c|
+ c.label { label }
+ c.help_text { help_text }
+ end
+ end
+
+ include_examples 'it renders unchecked checkbox with value of `1`'
+ include_examples 'it renders help text'
+ end
+end
diff --git a/spec/components/pajamas/concerns/checkbox_radio_label_with_help_text_spec.rb b/spec/components/pajamas/concerns/checkbox_radio_label_with_help_text_spec.rb
index 7a792592b3c..4994abcfb93 100644
--- a/spec/components/pajamas/concerns/checkbox_radio_label_with_help_text_spec.rb
+++ b/spec/components/pajamas/concerns/checkbox_radio_label_with_help_text_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe Pajamas::Concerns::CheckboxRadioLabelWithHelpText do
attr_reader(
:form,
:method,
+ :name,
:label_argument,
:help_text_argument,
:label_options,
@@ -16,8 +17,9 @@ RSpec.describe Pajamas::Concerns::CheckboxRadioLabelWithHelpText do
)
def initialize(
- form:,
- method:,
+ form: nil,
+ method: nil,
+ name: nil,
label: nil,
help_text: nil,
label_options: {},
@@ -26,6 +28,7 @@ RSpec.describe Pajamas::Concerns::CheckboxRadioLabelWithHelpText do
)
@form = form
@method = method
+ @name = name
@label_argument = label
@help_text_argument = help_text
@label_options = label_options
@@ -46,19 +49,25 @@ RSpec.describe Pajamas::Concerns::CheckboxRadioLabelWithHelpText do
end
include Pajamas::Concerns::CheckboxRadioLabelWithHelpText
+ include ActionView::Context
include ActionView::Helpers::TagHelper
+ include ActionView::Helpers::FormTagHelper
end
end
- let_it_be(:method) { 'username' }
+ let_it_be(:method_or_name) { 'username' }
let_it_be(:label_options) { { class: 'foo-bar' } }
let_it_be(:value) { 'Foo bar' }
+ let_it_be(:expected_label_entry) { '<span>Label argument</span>' }
+ let_it_be(:expected_label_with_help_text_entry) do
+ '<span>Label argument</span><p class="help-text" data-testid="pajamas-component-help-text">Help text argument</p>'
+ end
describe '#render_label_with_help_text' do
it 'calls `#format_options` with correct arguments' do
allow(form).to receive(:label)
- component = component_class.new(form: form, method: method, label_options: label_options, value: value)
+ component = component_class.new(form: form, method: method_or_name, label_options: label_options, value: value)
expect(component).to receive(:format_options).with(
options: label_options,
@@ -73,16 +82,13 @@ RSpec.describe Pajamas::Concerns::CheckboxRadioLabelWithHelpText do
it 'calls `form.label` with `label` and `help_text` arguments used in the block' do
component = component_class.new(
form: form,
- method: method,
+ method: method_or_name,
label: 'Label argument',
help_text: 'Help text argument'
)
- expected_label_entry = '<span>Label argument</span><p class="help-text"' \
- ' data-testid="pajamas-component-help-text">Help text argument</p>'
-
- expect(form).to receive(:label).with(method, {}) do |&block|
- expect(block.call).to eq(expected_label_entry)
+ expect(form).to receive(:label).with(method_or_name, {}) do |&block|
+ expect(block.call).to eq(expected_label_with_help_text_entry)
end
component.render_label_with_help_text
@@ -93,13 +99,11 @@ RSpec.describe Pajamas::Concerns::CheckboxRadioLabelWithHelpText do
it 'calls `form.label` with `label` argument used in the block' do
component = component_class.new(
form: form,
- method: method,
+ method: method_or_name,
label: 'Label argument'
)
- expected_label_entry = '<span>Label argument</span>'
-
- expect(form).to receive(:label).with(method, {}) do |&block|
+ expect(form).to receive(:label).with(method_or_name, {}) do |&block|
expect(block.call).to eq(expected_label_entry)
end
@@ -107,4 +111,49 @@ RSpec.describe Pajamas::Concerns::CheckboxRadioLabelWithHelpText do
end
end
end
+
+ describe '#render_label_tag_with_help_text' do
+ it 'calls `#format_options` with correct arguments' do
+ component = component_class.new(name: method_or_name, label_options: label_options, value: value)
+
+ expect(component).to receive(:format_options).with(
+ options: label_options,
+ css_classes: ['custom-control-label'],
+ additional_options: { value: value }
+ )
+
+ component.render_label_tag_with_help_text
+ end
+
+ context 'when `help_text` argument is passed' do
+ it 'calls `label_tag` with `label` and `help_text` arguments used in the block' do
+ component = component_class.new(
+ name: method_or_name,
+ label: 'Label argument',
+ help_text: 'Help text argument'
+ )
+
+ expect(component).to receive(:label_tag).with(method_or_name, {}) do |&block|
+ expect(block.call).to eq(expected_label_with_help_text_entry)
+ end
+
+ component.render_label_tag_with_help_text
+ end
+ end
+
+ context 'when `help_text` argument is not passed' do
+ it 'calls `label_tag` with `label` argument used in the block' do
+ component = component_class.new(
+ name: method_or_name,
+ label: 'Label argument'
+ )
+
+ expect(component).to receive(:label_tag).with(method_or_name, {}) do |&block|
+ expect(block.call).to eq(expected_label_entry)
+ end
+
+ component.render_label_tag_with_help_text
+ end
+ end
+ end
end
diff --git a/spec/contracts/consumer/fixtures/project/pipeline_schedule/update_pipeline_schedule.fixture.js b/spec/contracts/consumer/fixtures/project/pipeline_schedule/update_pipeline_schedule.fixture.js
new file mode 100644
index 00000000000..acdc94d5c6e
--- /dev/null
+++ b/spec/contracts/consumer/fixtures/project/pipeline_schedule/update_pipeline_schedule.fixture.js
@@ -0,0 +1,48 @@
+/* eslint-disable @gitlab/require-i18n-strings */
+
+import { Matchers } from '@pact-foundation/pact';
+import { REDIRECT_HTML } from '../../../helpers/common_regex_patterns';
+
+const body = Matchers.term({
+ matcher: REDIRECT_HTML,
+ generate:
+ '<html><body>You are being <a href="http://example.org/gitlab-org/gitlab-qa/-/pipelines/5">redirected</a>.</body></html>',
+});
+
+const UpdatePipelineSchedule = {
+ success: {
+ status: 302,
+ headers: {
+ 'Content-Type': 'text/html; charset=utf-8',
+ },
+ body,
+ },
+
+ scenario: {
+ state: 'a project with a pipeline schedule exists',
+ uponReceiving: 'a request to edit a pipeline schedule',
+ },
+
+ request: {
+ withRequest: {
+ method: 'PUT',
+ path: '/gitlab-org/gitlab-qa/-/pipeline_schedules/25',
+ headers: {
+ Accept: '*/*',
+ 'Content-Type': 'application/json; charset=utf-8',
+ },
+ body: {
+ schedule: {
+ description: 'bar',
+ cron: '0 1 * * *',
+ cron_timezone: 'UTC',
+ active: true,
+ },
+ },
+ },
+ },
+};
+
+export { UpdatePipelineSchedule };
+
+/* eslint-enable @gitlab/require-i18n-strings */
diff --git a/spec/contracts/consumer/helpers/common_regex_patterns.js b/spec/contracts/consumer/helpers/common_regex_patterns.js
index 2fbb4ea49f8..78dfeb7748f 100644
--- a/spec/contracts/consumer/helpers/common_regex_patterns.js
+++ b/spec/contracts/consumer/helpers/common_regex_patterns.js
@@ -3,7 +3,7 @@
*/
export const URL = '^(http|https)://[a-z0-9]+([-.]{1}[a-z0-9]+)*.[a-z]{2,5}(:[0-9]{1,5})?(/.*)?$';
export const URL_PATH = '^/[a-zA-Z0-9#-=?_]+$';
-export const REDIRECT_HTML = 'You are being <a href=\\"(.)+/pipelines/[0-9]+\\">redirected</a>.';
+export const REDIRECT_HTML = 'You are being <a href=\\"(.)+\\">redirected</a>.';
// Pipelines
export const PIPELINE_GROUPS =
diff --git a/spec/contracts/consumer/resources/api/pipeline_schedules.js b/spec/contracts/consumer/resources/api/pipeline_schedules.js
new file mode 100644
index 00000000000..ad04e59b9cd
--- /dev/null
+++ b/spec/contracts/consumer/resources/api/pipeline_schedules.js
@@ -0,0 +1,26 @@
+import axios from 'axios';
+
+export async function updatePipelineSchedule(endpoint) {
+ const { url } = endpoint;
+
+ return axios({
+ method: 'PUT',
+ baseURL: url,
+ url: '/gitlab-org/gitlab-qa/-/pipeline_schedules/25',
+ headers: {
+ Accept: '*/*',
+ 'Content-Type': 'application/json; charset=utf-8',
+ },
+ data: {
+ schedule: {
+ description: 'bar',
+ cron: '0 1 * * *',
+ cron_timezone: 'UTC',
+ active: true,
+ },
+ },
+ validateStatus: (status) => {
+ return status === 302;
+ },
+ });
+}
diff --git a/spec/contracts/consumer/specs/project/pipeline_schedule/edit.spec.js b/spec/contracts/consumer/specs/project/pipeline_schedule/edit.spec.js
new file mode 100644
index 00000000000..7d89825bcd4
--- /dev/null
+++ b/spec/contracts/consumer/specs/project/pipeline_schedule/edit.spec.js
@@ -0,0 +1,45 @@
+/* eslint-disable @gitlab/require-i18n-strings */
+
+import { pactWith } from 'jest-pact';
+
+import { UpdatePipelineSchedule } from '../../../fixtures/project/pipeline_schedule/update_pipeline_schedule.fixture';
+import { updatePipelineSchedule } from '../../../resources/api/pipeline_schedules';
+
+const CONSUMER_NAME = 'PipelineSchedules#edit';
+const CONSUMER_LOG = '../logs/consumer.log';
+const CONTRACT_DIR = '../contracts/project/pipeline_schedule/edit';
+const PROVIDER_NAME = 'PUT Edit a pipeline schedule';
+
+// API endpoint: /pipelines.json
+pactWith(
+ {
+ consumer: CONSUMER_NAME,
+ provider: PROVIDER_NAME,
+ log: CONSUMER_LOG,
+ dir: CONTRACT_DIR,
+ },
+
+ (provider) => {
+ describe(PROVIDER_NAME, () => {
+ beforeEach(() => {
+ const interaction = {
+ ...UpdatePipelineSchedule.scenario,
+ ...UpdatePipelineSchedule.request,
+ willRespondWith: UpdatePipelineSchedule.success,
+ };
+
+ provider.addInteraction(interaction);
+ });
+
+ it('returns a successful body', async () => {
+ const pipelineSchedule = await updatePipelineSchedule({
+ url: provider.mockService.baseUrl,
+ });
+
+ expect(pipelineSchedule.status).toEqual(UpdatePipelineSchedule.success.status);
+ });
+ });
+ },
+);
+
+/* eslint-enable @gitlab/require-i18n-strings */
diff --git a/spec/contracts/contracts/project/pipeline_schedule/edit/pipelineschedules#edit-put_edit_a_pipeline_schedule.json b/spec/contracts/contracts/project/pipeline_schedule/edit/pipelineschedules#edit-put_edit_a_pipeline_schedule.json
new file mode 100644
index 00000000000..e0dd68dc230
--- /dev/null
+++ b/spec/contracts/contracts/project/pipeline_schedule/edit/pipelineschedules#edit-put_edit_a_pipeline_schedule.json
@@ -0,0 +1,48 @@
+{
+ "consumer": {
+ "name": "PipelineSchedules#edit"
+ },
+ "provider": {
+ "name": "PUT Edit a pipeline schedule"
+ },
+ "interactions": [
+ {
+ "description": "a request to edit a pipeline schedule",
+ "providerState": "a project with a pipeline schedule exists",
+ "request": {
+ "method": "PUT",
+ "path": "/gitlab-org/gitlab-qa/-/pipeline_schedules/25",
+ "headers": {
+ "Accept": "*/*",
+ "Content-Type": "application/json; charset=utf-8"
+ },
+ "body": {
+ "schedule": {
+ "description": "bar",
+ "cron": "0 1 * * *",
+ "cron_timezone": "UTC",
+ "active": true
+ }
+ }
+ },
+ "response": {
+ "status": 302,
+ "headers": {
+ "Content-Type": "text/html; charset=utf-8"
+ },
+ "body": "<html><body>You are being <a href=\"http://example.org/gitlab-org/gitlab-qa/-/pipelines/5\">redirected</a>.</body></html>",
+ "matchingRules": {
+ "$.body": {
+ "match": "regex",
+ "regex": "You are being <a href=\\\"(.)+\\\">redirected<\\/a>."
+ }
+ }
+ }
+ }
+ ],
+ "metadata": {
+ "pactSpecification": {
+ "version": "2.0.0"
+ }
+ }
+} \ No newline at end of file
diff --git a/spec/contracts/provider/pact_helpers/project/pipeline_schedule/update_pipeline_schedule_helper.rb b/spec/contracts/provider/pact_helpers/project/pipeline_schedule/update_pipeline_schedule_helper.rb
new file mode 100644
index 00000000000..a83aa9524dc
--- /dev/null
+++ b/spec/contracts/provider/pact_helpers/project/pipeline_schedule/update_pipeline_schedule_helper.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require_relative '../../../spec_helper'
+require_relative '../../../states/project/pipeline_schedule/edit_state'
+
+module Provider
+ module CreateNewPipelineHelper
+ Pact.service_provider "PUT Edit a pipeline schedule" do
+ app { Environments::Test.app }
+
+ honours_pact_with 'PipelineSchedule#edit' do
+ pact_uri '../contracts/project/pipeline_schedule/edit/pipelineschedules#edit-put_edit_a_pipeline_schedule.json'
+ end
+ end
+ end
+end
diff --git a/spec/contracts/provider/states/project/pipeline_schedule/edit_state.rb b/spec/contracts/provider/states/project/pipeline_schedule/edit_state.rb
new file mode 100644
index 00000000000..4ee714f15f3
--- /dev/null
+++ b/spec/contracts/provider/states/project/pipeline_schedule/edit_state.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+Pact.provider_states_for "PipelineSchedules#edit" do
+ provider_state "a project with a pipeline schedule exists" do
+ set_up do
+ user = User.find_by(name: Provider::UsersHelper::CONTRACT_USER_NAME)
+ namespace = create(:namespace, name: 'gitlab-org')
+ project = create(:project, :repository, name: 'gitlab-qa', namespace: namespace, creator: user)
+
+ project.add_maintainer(user)
+
+ create(:ci_pipeline_schedule, id: 25, project: project, owner: user)
+ end
+ end
+end
diff --git a/spec/frontend/fixtures/runner.rb b/spec/frontend/fixtures/runner.rb
index 1df0e4bef54..b523650dda5 100644
--- a/spec/frontend/fixtures/runner.rb
+++ b/spec/frontend/fixtures/runner.rb
@@ -28,9 +28,10 @@ RSpec.describe 'Runner (JavaScript fixtures)' do
end
before do
- allow(Gitlab::Ci::RunnerUpgradeCheck.instance)
- .to receive(:check_runner_upgrade_suggestion)
- .and_return([nil, :not_available])
+ allow_next_instance_of(::Gitlab::Ci::RunnerUpgradeCheck) do |instance|
+ allow(instance).to receive(:check_runner_upgrade_suggestion)
+ .and_return([nil, :not_available])
+ end
end
describe 'as admin', GraphQL::Query do
diff --git a/spec/lib/backup/gitaly_backup_spec.rb b/spec/lib/backup/gitaly_backup_spec.rb
index 3a9c4dfe3fb..d427e41026e 100644
--- a/spec/lib/backup/gitaly_backup_spec.rb
+++ b/spec/lib/backup/gitaly_backup_spec.rb
@@ -73,7 +73,7 @@ RSpec.describe Backup::GitalyBackup do
let(:max_parallelism) { 3 }
it 'passes parallel option through' do
- expect(Open3).to receive(:popen2).with(expected_env, anything, 'create', '-path', anything, '-parallel', '3', '-layout', 'pointer', '-id', backup_id).and_call_original
+ expect(Open3).to receive(:popen2).with(expected_env, anything, 'create', '-path', anything, '-layout', 'pointer', '-parallel', '3', '-id', backup_id).and_call_original
subject.start(:create, destination, backup_id: backup_id)
subject.finish!
@@ -84,7 +84,7 @@ RSpec.describe Backup::GitalyBackup do
let(:storage_parallelism) { 3 }
it 'passes parallel option through' do
- expect(Open3).to receive(:popen2).with(expected_env, anything, 'create', '-path', anything, '-parallel-storage', '3', '-layout', 'pointer', '-id', backup_id).and_call_original
+ expect(Open3).to receive(:popen2).with(expected_env, anything, 'create', '-path', anything, '-layout', 'pointer', '-parallel-storage', '3', '-id', backup_id).and_call_original
subject.start(:create, destination, backup_id: backup_id)
subject.finish!
@@ -103,36 +103,6 @@ RSpec.describe Backup::GitalyBackup do
expect { subject.start(:create, destination, backup_id: backup_id) }.to raise_error(::Backup::Error, 'gitaly-backup binary not found and gitaly_backup_path is not configured')
end
-
- context 'feature flag incremental_repository_backup disabled' do
- before do
- stub_feature_flags(incremental_repository_backup: false)
- end
-
- it 'creates repository bundles', :aggregate_failures do
- # Add data to the wiki, design repositories, and snippets, so they will be included in the dump.
- create(:wiki_page, container: project)
- create(:design, :with_file, issue: create(:issue, project: project))
- project_snippet = create(:project_snippet, :repository, project: project)
- personal_snippet = create(:personal_snippet, :repository, author: project.first_owner)
-
- expect(Open3).to receive(:popen2).with(expected_env, anything, 'create', '-path', anything).and_call_original
-
- subject.start(:create, destination, backup_id: backup_id)
- subject.enqueue(project, Gitlab::GlRepository::PROJECT)
- subject.enqueue(project, Gitlab::GlRepository::WIKI)
- subject.enqueue(project, Gitlab::GlRepository::DESIGN)
- subject.enqueue(personal_snippet, Gitlab::GlRepository::SNIPPET)
- subject.enqueue(project_snippet, Gitlab::GlRepository::SNIPPET)
- subject.finish!
-
- expect(File).to exist(File.join(destination, project.disk_path + '.bundle'))
- expect(File).to exist(File.join(destination, project.disk_path + '.wiki.bundle'))
- expect(File).to exist(File.join(destination, project.disk_path + '.design.bundle'))
- expect(File).to exist(File.join(destination, personal_snippet.disk_path + '.bundle'))
- expect(File).to exist(File.join(destination, project_snippet.disk_path + '.bundle'))
- end
- end
end
context 'hashed storage' do
@@ -208,7 +178,7 @@ RSpec.describe Backup::GitalyBackup do
let(:max_parallelism) { 3 }
it 'passes parallel option through' do
- expect(Open3).to receive(:popen2).with(expected_env, anything, 'restore', '-path', anything, '-parallel', '3', '-layout', 'pointer').and_call_original
+ expect(Open3).to receive(:popen2).with(expected_env, anything, 'restore', '-path', anything, '-layout', 'pointer', '-parallel', '3').and_call_original
subject.start(:restore, destination, backup_id: backup_id)
subject.finish!
@@ -219,45 +189,13 @@ RSpec.describe Backup::GitalyBackup do
let(:storage_parallelism) { 3 }
it 'passes parallel option through' do
- expect(Open3).to receive(:popen2).with(expected_env, anything, 'restore', '-path', anything, '-parallel-storage', '3', '-layout', 'pointer').and_call_original
+ expect(Open3).to receive(:popen2).with(expected_env, anything, 'restore', '-path', anything, '-layout', 'pointer', '-parallel-storage', '3').and_call_original
subject.start(:restore, destination, backup_id: backup_id)
subject.finish!
end
end
- context 'feature flag incremental_repository_backup disabled' do
- before do
- stub_feature_flags(incremental_repository_backup: false)
- end
-
- it 'restores from repository bundles', :aggregate_failures do
- copy_bundle_to_backup_path('project_repo.bundle', project.disk_path + '.bundle')
- copy_bundle_to_backup_path('wiki_repo.bundle', project.disk_path + '.wiki.bundle')
- copy_bundle_to_backup_path('design_repo.bundle', project.disk_path + '.design.bundle')
- copy_bundle_to_backup_path('personal_snippet_repo.bundle', personal_snippet.disk_path + '.bundle')
- copy_bundle_to_backup_path('project_snippet_repo.bundle', project_snippet.disk_path + '.bundle')
-
- expect(Open3).to receive(:popen2).with(expected_env, anything, 'restore', '-path', anything).and_call_original
-
- subject.start(:restore, destination, backup_id: backup_id)
- subject.enqueue(project, Gitlab::GlRepository::PROJECT)
- subject.enqueue(project, Gitlab::GlRepository::WIKI)
- subject.enqueue(project, Gitlab::GlRepository::DESIGN)
- subject.enqueue(personal_snippet, Gitlab::GlRepository::SNIPPET)
- subject.enqueue(project_snippet, Gitlab::GlRepository::SNIPPET)
- subject.finish!
-
- collect_commit_shas = -> (repo) { repo.commits('master', limit: 10).map(&:sha) }
-
- expect(collect_commit_shas.call(project.repository)).to match_array(['393a7d860a5a4c3cc736d7eb00604e3472bb95ec'])
- expect(collect_commit_shas.call(project.wiki.repository)).to match_array(['c74b9948d0088d703ee1fafeddd9ed9add2901ea'])
- expect(collect_commit_shas.call(project.design_repository)).to match_array(['c3cd4d7bd73a51a0f22045c3a4c871c435dc959d'])
- expect(collect_commit_shas.call(personal_snippet.repository)).to match_array(['3b3c067a3bc1d1b695b51e2be30c0f8cf698a06e'])
- expect(collect_commit_shas.call(project_snippet.repository)).to match_array(['6e44ba56a4748be361a841e759c20e421a1651a1'])
- end
- end
-
it 'raises when the exit code not zero' do
expect(subject).to receive(:bin_path).and_return(Gitlab::Utils.which('false'))
diff --git a/spec/lib/gitlab/ci/runner_releases_spec.rb b/spec/lib/gitlab/ci/runner_releases_spec.rb
index 1cc582cf972..b47e94400c5 100644
--- a/spec/lib/gitlab/ci/runner_releases_spec.rb
+++ b/spec/lib/gitlab/ci/runner_releases_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::RunnerReleases do
subject { described_class.instance }
- let(:runner_releases_url) { 'the release API URL' }
+ let(:runner_releases_url) { 'http://testurl.com/runner_public_releases' }
def releases
subject.releases
@@ -18,7 +18,7 @@ RSpec.describe Gitlab::Ci::RunnerReleases do
before do
subject.reset_backoff!
- stub_application_setting(public_runner_releases_url: runner_releases_url)
+ allow(subject).to receive(:runner_releases_url).and_return(runner_releases_url)
end
describe 'caching behavior', :use_clean_rails_memory_store_caching do
diff --git a/spec/lib/gitlab/ci/runner_upgrade_check_spec.rb b/spec/lib/gitlab/ci/runner_upgrade_check_spec.rb
index 191579607b1..55c3834bfa7 100644
--- a/spec/lib/gitlab/ci/runner_upgrade_check_spec.rb
+++ b/spec/lib/gitlab/ci/runner_upgrade_check_spec.rb
@@ -5,24 +5,20 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::RunnerUpgradeCheck do
using RSpec::Parameterized::TableSyntax
+ subject(:instance) { described_class.new(gitlab_version, runner_releases) }
+
describe '#check_runner_upgrade_suggestion' do
- subject(:result) { described_class.instance.check_runner_upgrade_suggestion(runner_version) }
+ subject(:result) { instance.check_runner_upgrade_suggestion(runner_version) }
let(:gitlab_version) { '14.1.1' }
let(:parsed_runner_version) { ::Gitlab::VersionInfo.parse(runner_version, parse_suffix: true) }
-
- before do
- allow(described_class.instance).to receive(:gitlab_version)
- .and_return(::Gitlab::VersionInfo.parse(gitlab_version))
- end
+ let(:runner_releases) { instance_double(Gitlab::Ci::RunnerReleases) }
context 'with failing Gitlab::Ci::RunnerReleases request' do
let(:runner_version) { '14.1.123' }
- let(:runner_releases_double) { instance_double(Gitlab::Ci::RunnerReleases) }
before do
- allow(Gitlab::Ci::RunnerReleases).to receive(:instance).and_return(runner_releases_double)
- allow(runner_releases_double).to receive(:releases).and_return(nil)
+ allow(runner_releases).to receive(:releases).and_return(nil)
end
it 'returns :error' do
@@ -31,10 +27,13 @@ RSpec.describe Gitlab::Ci::RunnerUpgradeCheck do
end
context 'with available_runner_releases configured' do
- before do
- url = ::Gitlab::CurrentSettings.current_application_settings.public_runner_releases_url
+ let(:runner_releases) { Gitlab::Ci::RunnerReleases.instance }
+ let(:runner_releases_url) do
+ ::Gitlab::CurrentSettings.current_application_settings.public_runner_releases_url
+ end
- WebMock.stub_request(:get, url).to_return(
+ before do
+ WebMock.stub_request(:get, runner_releases_url).to_return(
body: available_runner_releases.map { |v| { name: v } }.to_json,
status: 200,
headers: { 'Content-Type' => 'application/json' }
diff --git a/spec/requests/api/graphql/ci/runners_spec.rb b/spec/requests/api/graphql/ci/runners_spec.rb
index 65492876489..749f6839cb5 100644
--- a/spec/requests/api/graphql/ci/runners_spec.rb
+++ b/spec/requests/api/graphql/ci/runners_spec.rb
@@ -37,7 +37,9 @@ RSpec.describe 'Query.runners' do
end
before do
- allow(Gitlab::Ci::RunnerUpgradeCheck.instance).to receive(:check_runner_upgrade_suggestion)
+ allow_next_instance_of(::Gitlab::Ci::RunnerUpgradeCheck) do |instance|
+ allow(instance).to receive(:check_runner_upgrade_suggestion)
+ end
post_graphql(query, current_user: current_user)
end
diff --git a/spec/services/ci/runners/reconcile_existing_runner_versions_service_spec.rb b/spec/services/ci/runners/reconcile_existing_runner_versions_service_spec.rb
index 64b735b2153..47a7ae4af4d 100644
--- a/spec/services/ci/runners/reconcile_existing_runner_versions_service_spec.rb
+++ b/spec/services/ci/runners/reconcile_existing_runner_versions_service_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe ::Ci::Runners::ReconcileExistingRunnerVersionsService, '#execute' do
+ include RunnerReleasesHelper
+
subject(:execute) { described_class.new.execute }
let_it_be(:runner_14_0_1) { create(:ci_runner, version: '14.0.1') }
@@ -11,12 +13,12 @@ RSpec.describe ::Ci::Runners::ReconcileExistingRunnerVersionsService, '#execute'
end
context 'with RunnerUpgradeCheck recommending 14.0.2' do
+ let(:upgrade_check) { instance_double(::Gitlab::Ci::RunnerUpgradeCheck) }
+
before do
stub_const('Ci::Runners::ReconcileExistingRunnerVersionsService::VERSION_BATCH_SIZE', 1)
- allow(::Gitlab::Ci::RunnerUpgradeCheck.instance)
- .to receive(:check_runner_upgrade_suggestion)
- .and_return([::Gitlab::VersionInfo.new(14, 0, 2), :recommended])
+ allow(::Gitlab::Ci::RunnerUpgradeCheck).to receive(:new).and_return(upgrade_check).once
end
context 'with runner with new version' do
@@ -25,8 +27,9 @@ RSpec.describe ::Ci::Runners::ReconcileExistingRunnerVersionsService, '#execute'
let!(:runner_14_0_0) { create(:ci_runner, version: '14.0.0') }
before do
- allow(::Gitlab::Ci::RunnerUpgradeCheck.instance)
- .to receive(:check_runner_upgrade_suggestion)
+ allow(upgrade_check).to receive(:check_runner_upgrade_suggestion)
+ .and_return([::Gitlab::VersionInfo.new(14, 0, 2), :recommended])
+ allow(upgrade_check).to receive(:check_runner_upgrade_suggestion)
.with('14.0.2')
.and_return([::Gitlab::VersionInfo.new(14, 0, 2), :not_available])
.once
@@ -58,8 +61,7 @@ RSpec.describe ::Ci::Runners::ReconcileExistingRunnerVersionsService, '#execute'
let!(:runner_version_14_0_2) { create(:ci_runner_version, version: '14.0.2', status: :not_available) }
before do
- allow(::Gitlab::Ci::RunnerUpgradeCheck.instance)
- .to receive(:check_runner_upgrade_suggestion)
+ allow(upgrade_check).to receive(:check_runner_upgrade_suggestion)
.and_return([::Gitlab::VersionInfo.new(14, 0, 2), :not_available])
end
@@ -80,8 +82,7 @@ RSpec.describe ::Ci::Runners::ReconcileExistingRunnerVersionsService, '#execute'
context 'with no runner version changes' do
before do
- allow(::Gitlab::Ci::RunnerUpgradeCheck.instance)
- .to receive(:check_runner_upgrade_suggestion)
+ allow(upgrade_check).to receive(:check_runner_upgrade_suggestion)
.and_return([::Gitlab::VersionInfo.new(14, 0, 1), :not_available])
end
@@ -100,8 +101,7 @@ RSpec.describe ::Ci::Runners::ReconcileExistingRunnerVersionsService, '#execute'
context 'with failing version check' do
before do
- allow(::Gitlab::Ci::RunnerUpgradeCheck.instance)
- .to receive(:check_runner_upgrade_suggestion)
+ allow(upgrade_check).to receive(:check_runner_upgrade_suggestion)
.and_return([::Gitlab::VersionInfo.new(14, 0, 1), :error])
end
@@ -120,18 +120,8 @@ RSpec.describe ::Ci::Runners::ReconcileExistingRunnerVersionsService, '#execute'
end
context 'integration testing with Gitlab::Ci::RunnerUpgradeCheck' do
- let(:available_runner_releases) do
- %w[14.0.0 14.0.1]
- end
-
before do
- url = ::Gitlab::CurrentSettings.current_application_settings.public_runner_releases_url
-
- WebMock.stub_request(:get, url).to_return(
- body: available_runner_releases.map { |v| { name: v } }.to_json,
- status: 200,
- headers: { 'Content-Type' => 'application/json' }
- )
+ stub_runner_releases(%w[14.0.0 14.0.1])
end
it 'does not modify ci_runner_versions entries', :aggregate_failures do
diff --git a/spec/support/helpers/runner_releases_helper.rb b/spec/support/helpers/runner_releases_helper.rb
new file mode 100644
index 00000000000..ab16a705425
--- /dev/null
+++ b/spec/support/helpers/runner_releases_helper.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module RunnerReleasesHelper
+ def stub_runner_releases(available_runner_releases, gitlab_version: nil)
+ # We stub the behavior of RunnerReleases so that we don't need to rely on flaky global settings
+ available_runner_releases = available_runner_releases
+ .map { |v| ::Gitlab::VersionInfo.parse(v, parse_suffix: true) }
+ .sort
+ releases_by_minor = available_runner_releases
+ .group_by(&:without_patch)
+ .transform_values(&:max)
+
+ runner_releases_double = instance_double(Gitlab::Ci::RunnerReleases)
+ allow(::Gitlab::Ci::RunnerUpgradeCheck).to receive(:new).and_wrap_original do |method, *_original_args|
+ gitlab_version ||= available_runner_releases.max
+ method.call(gitlab_version, runner_releases_double)
+ end
+
+ allow(runner_releases_double).to receive(:releases).and_return(available_runner_releases)
+ allow(runner_releases_double).to receive(:releases_by_minor).and_return(releases_by_minor)
+ end
+end
diff --git a/spec/support/shared_examples/components/pajamas_shared_examples.rb b/spec/support/shared_examples/components/pajamas_shared_examples.rb
index 955b64152ef..bcf7df24fd9 100644
--- a/spec/support/shared_examples/components/pajamas_shared_examples.rb
+++ b/spec/support/shared_examples/components/pajamas_shared_examples.rb
@@ -11,3 +11,9 @@ RSpec.shared_examples 'it does not render help text' do
expect(page).not_to have_css('[data-testid="pajamas-component-help-text"]')
end
end
+
+RSpec.shared_examples 'it renders unchecked checkbox with value of `1`' do
+ it 'renders unchecked checkbox with value of `1`' do
+ expect(page).to have_unchecked_field(label, with: '1')
+ end
+end