diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-09-09 21:10:12 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-09-09 21:10:12 +0000 |
commit | dc22d7faa23a7988be2b70da2bfb956de4df00f0 (patch) | |
tree | cf79ae05494af210a53390fd8bd7ade54d54bad8 | |
parent | 7c0e5472c80f1826b36916a95e6f9d84a7b68fe3 (diff) | |
download | gitlab-ce-dc22d7faa23a7988be2b70da2bfb956de4df00f0.tar.gz |
Add latest changes from gitlab-org/gitlab@master
57 files changed, 785 insertions, 274 deletions
diff --git a/.rubocop_todo/layout/argument_alignment.yml b/.rubocop_todo/layout/argument_alignment.yml index 1977bedd143..bd4cd386153 100644 --- a/.rubocop_todo/layout/argument_alignment.yml +++ b/.rubocop_todo/layout/argument_alignment.yml @@ -391,7 +391,6 @@ Layout/ArgumentAlignment: - 'ee/spec/features/projects/environments/environments_spec.rb' - 'ee/spec/features/projects/merge_requests/user_edits_merge_request_spec.rb' - 'ee/spec/features/projects/pipelines/pipeline_spec.rb' - - 'ee/spec/features/uncompleted_learn_gitlab_link_spec.rb' - 'ee/spec/finders/security/pipeline_vulnerabilities_finder_spec.rb' - 'ee/spec/frontend/fixtures/search.rb' - 'ee/spec/graphql/mutations/requirements_management/export_requirements_spec.rb' diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml index 6d2ea48e48c..bd7bf28a1f3 100644 --- a/.rubocop_todo/layout/line_length.yml +++ b/.rubocop_todo/layout/line_length.yml @@ -1979,7 +1979,6 @@ Layout/LineLength: - 'ee/spec/features/search/elastic/snippet_search_spec.rb' - 'ee/spec/features/subscriptions_spec.rb' - 'ee/spec/features/trial_registrations/company_information_spec.rb' - - 'ee/spec/features/uncompleted_learn_gitlab_link_spec.rb' - 'ee/spec/features/users/login_spec.rb' - 'ee/spec/finders/analytics/devops_adoption/enabled_namespaces_finder_spec.rb' - 'ee/spec/finders/analytics/devops_adoption/snapshots_finder_spec.rb' @@ -5159,7 +5158,6 @@ Layout/LineLength: - 'spec/lib/grafana/validator_spec.rb' - 'spec/lib/kramdown/kramdown_spec.rb' - 'spec/lib/kramdown/parser/atlassian_document_format_spec.rb' - - 'spec/lib/learn_gitlab/project_spec.rb' - 'spec/lib/mattermost/command_spec.rb' - 'spec/lib/microsoft_teams/notifier_spec.rb' - 'spec/lib/object_storage/config_spec.rb' diff --git a/.rubocop_todo/rails/index_with.yml b/.rubocop_todo/rails/index_with.yml index 09339d3fd56..d8ccbd97f7c 100644 --- a/.rubocop_todo/rails/index_with.yml +++ b/.rubocop_todo/rails/index_with.yml @@ -43,7 +43,6 @@ Rails/IndexWith: - 'spec/lib/gitlab/import_export/model_configuration_spec.rb' - 'spec/lib/gitlab/import_export/project/tree_restorer_spec.rb' - 'spec/lib/google_api/cloud_platform/client_spec.rb' - - 'spec/lib/learn_gitlab/onboarding_spec.rb' - 'spec/models/event_spec.rb' - 'spec/presenters/projects/security/configuration_presenter_spec.rb' - 'spec/support/database/multiple_databases.rb' diff --git a/.rubocop_todo/rspec/expect_in_hook.yml b/.rubocop_todo/rspec/expect_in_hook.yml index 8ab50ede1ba..2353c11ce3a 100644 --- a/.rubocop_todo/rspec/expect_in_hook.yml +++ b/.rubocop_todo/rspec/expect_in_hook.yml @@ -311,12 +311,10 @@ RSpec/ExpectInHook: - 'spec/lib/gitlab/verify/uploads_spec.rb' - 'spec/lib/gitlab/zentao/query_spec.rb' - 'spec/lib/gitlab_spec.rb' - - 'spec/lib/learn_gitlab/onboarding_spec.rb' - 'spec/lib/omni_auth/strategies/jwt_spec.rb' - 'spec/lib/prometheus/pid_provider_spec.rb' - 'spec/lib/sidebars/projects/menus/external_issue_tracker_menu_spec.rb' - 'spec/lib/sidebars/projects/menus/external_wiki_menu_spec.rb' - - 'spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb' - 'spec/mailers/emails/service_desk_spec.rb' - 'spec/metrics_server/metrics_server_spec.rb' - 'spec/migrations/20210406144743_backfill_total_tuple_count_for_batched_migrations_spec.rb' diff --git a/.rubocop_todo/style/float_division.yml b/.rubocop_todo/style/float_division.yml index 201f89ac35a..7fd0cda469d 100644 --- a/.rubocop_todo/style/float_division.yml +++ b/.rubocop_todo/style/float_division.yml @@ -3,6 +3,5 @@ Style/FloatDivision: Exclude: - 'ee/app/models/geo_node_status.rb' - 'ee/app/models/namespaces/storage/root_size.rb' - - 'lib/learn_gitlab/onboarding.rb' - 'qa/qa/support/formatters/allure_metadata_formatter.rb' - 'qa/qa/tools/reliable_report.rb' diff --git a/.rubocop_todo/style/hash_as_last_array_item.yml b/.rubocop_todo/style/hash_as_last_array_item.yml index 384d2dc5fce..aa22e9ed82b 100644 --- a/.rubocop_todo/style/hash_as_last_array_item.yml +++ b/.rubocop_todo/style/hash_as_last_array_item.yml @@ -20,7 +20,6 @@ Style/HashAsLastArrayItem: - 'app/graphql/resolvers/concerns/issue_resolver_arguments.rb' - 'app/graphql/types/boards/board_issuable_input_base_type.rb' - 'app/graphql/types/boards/board_issue_input_base_type.rb' - - 'app/helpers/learn_gitlab_helper.rb' - 'app/helpers/namespaces_helper.rb' - 'app/models/customer_relations/contact.rb' - 'app/models/customer_relations/organization.rb' diff --git a/.rubocop_todo/style/symbol_proc.yml b/.rubocop_todo/style/symbol_proc.yml index 75aab7c6116..bfb3867b127 100644 --- a/.rubocop_todo/style/symbol_proc.yml +++ b/.rubocop_todo/style/symbol_proc.yml @@ -239,7 +239,6 @@ Style/SymbolProc: - 'spec/graphql/mutations/releases/create_spec.rb' - 'spec/graphql/types/work_items/widget_type_enum_spec.rb' - 'spec/helpers/instance_configuration_helper_spec.rb' - - 'spec/helpers/learn_gitlab_helper_spec.rb' - 'spec/helpers/members_helper_spec.rb' - 'spec/lib/backup/gitaly_backup_spec.rb' - 'spec/lib/gitlab/database/dynamic_model_helpers_spec.rb' diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index f65c45d6d89..e8f71c8a21c 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -49,7 +49,7 @@ input[type='checkbox']:hover { } &.header-search-is-active { - .navbar-collapse { + .global-search-container { flex-grow: 1; } @@ -59,12 +59,6 @@ input[type='checkbox']:hover { overflow: hidden; } } - - @include media-breakpoint-up(xl) { - .navbar-nav { - padding-left: 1rem; - } - } } } diff --git a/app/assets/stylesheets/startup/startup-dark.scss b/app/assets/stylesheets/startup/startup-dark.scss index e6ed15a86fe..0450b3d9a44 100644 --- a/app/assets/stylesheets/startup/startup-dark.scss +++ b/app/assets/stylesheets/startup/startup-dark.scss @@ -2088,6 +2088,12 @@ body.gl-dark { .gl-pt-0 { padding-top: 0; } +.gl-mr-auto { + margin-right: auto; +} +.gl-mr-3 { + margin-right: 0.5rem; +} .gl-ml-n2 { margin-left: -0.25rem; } diff --git a/app/assets/stylesheets/startup/startup-general.scss b/app/assets/stylesheets/startup/startup-general.scss index 5b8a3e3d5d4..356fb58b4c8 100644 --- a/app/assets/stylesheets/startup/startup-general.scss +++ b/app/assets/stylesheets/startup/startup-general.scss @@ -1739,6 +1739,12 @@ svg.s16 { .gl-pt-0 { padding-top: 0; } +.gl-mr-auto { + margin-right: auto; +} +.gl-mr-3 { + margin-right: 0.5rem; +} .gl-ml-n2 { margin-left: -0.25rem; } diff --git a/app/helpers/learn_gitlab_helper.rb b/app/helpers/learn_gitlab_helper.rb index 6f0db6cfcb6..a07922e451a 100644 --- a/app/helpers/learn_gitlab_helper.rb +++ b/app/helpers/learn_gitlab_helper.rb @@ -22,7 +22,7 @@ module LearnGitlabHelper def learn_gitlab_onboarding_available?(project) Onboarding::Progress.onboarding?(project.namespace) && - LearnGitlab::Project.new(current_user).available? + Onboarding::LearnGitlab.new(current_user).available? end private @@ -33,10 +33,12 @@ module LearnGitlabHelper action_urls(project).to_h do |action, url| [ action, - url: url, - completed: attributes[Onboarding::Progress.column_name(action)].present?, - svg: image_path("learn_gitlab/#{action}.svg"), - enabled: true + { + url: url, + completed: attributes[Onboarding::Progress.column_name(action)].present?, + svg: image_path("learn_gitlab/#{action}.svg"), + enabled: true + } ] end end @@ -70,11 +72,14 @@ module LearnGitlabHelper end def action_issue_urls - LearnGitlab::Onboarding::ACTION_ISSUE_IDS.transform_values { |id| project_issue_url(learn_gitlab_project, id) } + Onboarding::Completion::ACTION_ISSUE_IDS.transform_values do |id| + project_issue_url(learn_gitlab_project, id) + end end def deploy_section_action_urls(project) - experiment(:security_actions_continuous_onboarding, + experiment( + :security_actions_continuous_onboarding, namespace: project.namespace, user: current_user, sticky_to: current_user @@ -91,7 +96,7 @@ module LearnGitlabHelper end def learn_gitlab_project - @learn_gitlab_project ||= LearnGitlab::Project.new(current_user).project + @learn_gitlab_project ||= Onboarding::LearnGitlab.new(current_user).project end def onboarding_progress(project) diff --git a/app/helpers/nav/new_dropdown_helper.rb b/app/helpers/nav/new_dropdown_helper.rb index dc7d8049556..b017c9a81d1 100644 --- a/app/helpers/nav/new_dropdown_helper.rb +++ b/app/helpers/nav/new_dropdown_helper.rb @@ -135,7 +135,7 @@ module Nav id: 'general_new_group', title: _('New group'), href: new_group_path, - data: { track_action: 'click_link_new_group', track_label: 'plus_menu_dropdown' } + data: { track_action: 'click_link_new_group', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_group_link' } ) ) end diff --git a/app/helpers/nav/top_nav_helper.rb b/app/helpers/nav/top_nav_helper.rb index c4135dc086e..32d3f4aebb4 100644 --- a/app/helpers/nav/top_nav_helper.rb +++ b/app/helpers/nav/top_nav_helper.rb @@ -281,52 +281,74 @@ module Nav end def projects_submenu_items(builder:) - # These project links come from `app/views/layouts/nav/projects_dropdown/_show.html.haml` - [ - { id: 'your', title: _('Your projects'), href: dashboard_projects_path }, - { id: 'starred', title: _('Starred projects'), href: starred_dashboard_projects_path }, - { id: 'explore', title: _('Explore projects'), href: explore_root_path }, - { id: 'topics', title: _('Explore topics'), href: topics_explore_projects_path } - ].each do |item| + if Feature.enabled?(:remove_extra_primary_submenu_options) + title = _('View all projects') + builder.add_primary_menu_item( - **item, - data: { qa_selector: 'menu_item_link', qa_title: item[:title], **menu_data_tracking_attrs(item[:title]) } + id: 'your', + title: title, + href: dashboard_projects_path, + data: { qa_selector: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) } ) - end + else + # These project links come from `app/views/layouts/nav/projects_dropdown/_show.html.haml` + [ + { id: 'your', title: _('Your projects'), href: dashboard_projects_path }, + { id: 'starred', title: _('Starred projects'), href: starred_dashboard_projects_path }, + { id: 'explore', title: _('Explore projects'), href: explore_root_path }, + { id: 'topics', title: _('Explore topics'), href: topics_explore_projects_path } + ].each do |item| + builder.add_primary_menu_item( + **item, + data: { qa_selector: 'menu_item_link', qa_title: item[:title], **menu_data_tracking_attrs(item[:title]) } + ) + end - title = _('Create new project') + title = _('Create new project') - builder.add_secondary_menu_item( - id: 'create', - title: title, - href: new_project_path, - data: { qa_selector: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) } - ) + builder.add_secondary_menu_item( + id: 'create', + title: title, + href: new_project_path, + data: { qa_selector: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) } + ) + end end def groups_submenu # These group links come from `app/views/layouts/nav/groups_dropdown/_show.html.haml` builder = ::Gitlab::Nav::TopNavMenuBuilder.new - [ - { id: 'your', title: _('Your groups'), href: dashboard_groups_path }, - { id: 'explore', title: _('Explore groups'), href: explore_groups_path } - ].each do |item| - builder.add_primary_menu_item( - **item, - data: { qa_selector: 'menu_item_link', qa_title: item[:title], **menu_data_tracking_attrs(item[:title]) } - ) - end - - if current_user.can_create_group? - title = _('Create group') + if Feature.enabled?(:remove_extra_primary_submenu_options) + title = _('View all groups') - builder.add_secondary_menu_item( - id: 'create', + builder.add_primary_menu_item( + id: 'your', title: title, - href: new_group_path, + href: dashboard_groups_path, data: { qa_selector: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) } ) + else + [ + { id: 'your', title: _('Your groups'), href: dashboard_groups_path }, + { id: 'explore', title: _('Explore groups'), href: explore_groups_path } + ].each do |item| + builder.add_primary_menu_item( + **item, + data: { qa_selector: 'menu_item_link', qa_title: item[:title], **menu_data_tracking_attrs(item[:title]) } + ) + end + + if current_user.can_create_group? + title = _('Create group') + + builder.add_secondary_menu_item( + id: 'create', + title: title, + href: new_group_path, + data: { qa_selector: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) } + ) + end end builder.build diff --git a/app/models/ci/freeze_period_status.rb b/app/models/ci/freeze_period_status.rb index befa935e750..e810bb3f229 100644 --- a/app/models/ci/freeze_period_status.rb +++ b/app/models/ci/freeze_period_status.rb @@ -13,32 +13,16 @@ module Ci end def within_freeze_period?(period) - # previous_freeze_end, ..., previous_freeze_start, ..., NOW, ..., next_freeze_end, ..., next_freeze_start - # Current time is within a freeze period if - # it falls between a previous freeze start and next freeze end - start_freeze = Gitlab::Ci::CronParser.new(period.freeze_start, period.cron_timezone) - end_freeze = Gitlab::Ci::CronParser.new(period.freeze_end, period.cron_timezone) - - previous_freeze_start = previous_time(start_freeze) - previous_freeze_end = previous_time(end_freeze) - next_freeze_start = next_time(start_freeze) - next_freeze_end = next_time(end_freeze) - - previous_freeze_end < previous_freeze_start && - previous_freeze_start <= time_zone_now && - time_zone_now <= next_freeze_end && - next_freeze_end < next_freeze_start - end + start_freeze_cron = Gitlab::Ci::CronParser.new(period.freeze_start, period.cron_timezone) + end_freeze_cron = Gitlab::Ci::CronParser.new(period.freeze_end, period.cron_timezone) - private + start_freeze = start_freeze_cron.previous_time_from(time_zone_now) + end_freeze = end_freeze_cron.next_time_from(start_freeze) - def previous_time(cron_parser) - cron_parser.previous_time_from(time_zone_now) + start_freeze <= time_zone_now && time_zone_now <= end_freeze end - def next_time(cron_parser) - cron_parser.next_time_from(time_zone_now) - end + private def time_zone_now @time_zone_now ||= Time.zone.now diff --git a/lib/learn_gitlab/onboarding.rb b/app/models/onboarding/completion.rb index 4215221cdf1..49fdb102209 100644 --- a/lib/learn_gitlab/onboarding.rb +++ b/app/models/onboarding/completion.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -module LearnGitlab - class Onboarding +module Onboarding + class Completion include Gitlab::Utils::StrongMemoize include Gitlab::Experiment::Dsl @@ -24,7 +24,7 @@ module LearnGitlab @current_user = current_user end - def completed_percentage + def percentage return 0 unless onboarding_progress attributes = onboarding_progress.attributes.symbolize_keys @@ -32,14 +32,14 @@ module LearnGitlab total_actions = action_columns.count completed_actions = action_columns.count { |column| attributes[column].present? } - (completed_actions.to_f / total_actions.to_f * 100).round + (completed_actions.to_f / total_actions * 100).round end private def onboarding_progress strong_memoize(:onboarding_progress) do - ::Onboarding::Progress.find_by(namespace: namespace) # rubocop: disable CodeReuse/ActiveRecord + ::Onboarding::Progress.find_by(namespace: namespace) end end @@ -54,7 +54,8 @@ module LearnGitlab end def deploy_section_tracked_actions - experiment(:security_actions_continuous_onboarding, + experiment( + :security_actions_continuous_onboarding, namespace: namespace, user: current_user, sticky_to: current_user diff --git a/lib/learn_gitlab/project.rb b/app/models/onboarding/learn_gitlab.rb index 64f91dcf1a8..d7a189ed6e2 100644 --- a/lib/learn_gitlab/project.rb +++ b/app/models/onboarding/learn_gitlab.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -module LearnGitlab - class Project +module Onboarding + class LearnGitlab PROJECT_NAME = 'Learn GitLab' PROJECT_NAME_ULTIMATE_TRIAL = 'Learn GitLab - Ultimate trial' BOARD_NAME = 'GitLab onboarding' diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index 836fd3b4c31..a00c5c186cc 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -5,7 +5,7 @@ %a.gl-sr-only.gl-accessibility{ href: "#content-body" } Skip to content .container-fluid .header-content.js-header-content - .title-container.hide-when-top-nav-responsive-open.gl-transition-medium.gl-display-flex.gl-align-items-stretch.gl-pt-0 + .title-container.hide-when-top-nav-responsive-open.gl-transition-medium.gl-display-flex.gl-align-items-stretch.gl-pt-0.gl-mr-3 .title %span.gl-sr-only GitLab = link_to root_path, title: _('Dashboard'), id: 'logo', class: 'has-tooltip', **tracking_attrs('main_navigation', 'click_gitlab_logo_link', 'navigation') do @@ -28,11 +28,25 @@ .gl-display-none.gl-sm-display-block = render "layouts/nav/top_nav" - .navbar-collapse.gl-transition-medium.collapse + - if top_nav_show_search && Feature.enabled?(:new_navbar_layout) + .navbar-collapse.gl-transition-medium.collapse.gl-mr-auto.global-search-container.hide-when-top-nav-responsive-open + - search_menu_item = top_nav_search_menu_item_attrs + %ul.nav.navbar-nav.gl-w-full.gl-align-items-center + %li.nav-item.header-search-new.gl-display-none.gl-lg-display-block.gl-w-full + - unless current_controller?(:search) + - if Feature.enabled?(:new_header_search) + = render 'layouts/header_search' + - else + = render 'layouts/search' + %li.nav-item{ class: 'd-none d-sm-inline-block d-lg-none' } + = link_to search_menu_item.fetch(:href), title: search_menu_item.fetch(:title), aria: { label: search_menu_item.fetch(:title) }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do + = sprite_icon(search_menu_item.fetch(:icon)) + + .navbar-collapse.gl-transition-medium.collapse{ class: ('global-search-container' unless Feature.enabled?(:new_navbar_layout)) } %ul.nav.navbar-nav.gl-w-full.gl-align-items-center.gl-justify-content-end - if current_user = render 'layouts/header/new_dropdown', class: 'gl-display-none gl-sm-display-block gl-white-space-nowrap gl-text-right' - - if top_nav_show_search + - if top_nav_show_search && Feature.disabled?(:new_navbar_layout) - search_menu_item = top_nav_search_menu_item_attrs %li.nav-item.header-search-new.gl-display-none.gl-lg-display-block.gl-w-full - unless current_controller?(:search) diff --git a/config/feature_flags/development/new_navbar_layout.yml b/config/feature_flags/development/new_navbar_layout.yml index f88fe63567b..2d212922fcc 100644 --- a/config/feature_flags/development/new_navbar_layout.yml +++ b/config/feature_flags/development/new_navbar_layout.yml @@ -1,8 +1,8 @@ --- name: new_navbar_layout introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96853 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366082 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/373078 milestone: '15.4' type: development group: group::foundations -default_enabled: false +default_enabled: true diff --git a/config/feature_flags/development/remove_extra_primary_submenu_options.yml b/config/feature_flags/development/remove_extra_primary_submenu_options.yml new file mode 100644 index 00000000000..dda22c5d57e --- /dev/null +++ b/config/feature_flags/development/remove_extra_primary_submenu_options.yml @@ -0,0 +1,8 @@ +--- +name: remove_extra_primary_submenu_options +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96931 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/373078 +milestone: '15.4' +type: development +group: group::foundations +default_enabled: true diff --git a/config/metrics/counts_28d/20220907080630_i_quickactions_timeline_monthly.yml b/config/metrics/counts_28d/20220907080630_i_quickactions_timeline_monthly.yml new file mode 100644 index 00000000000..f3f9499e9d9 --- /dev/null +++ b/config/metrics/counts_28d/20220907080630_i_quickactions_timeline_monthly.yml @@ -0,0 +1,27 @@ +--- +key_path: redis_hll_counters.quickactions.i_quickactions_timeline_monthly +name: quickactions_timeline_monthly +description: Count of MAU using the `/timeline` quick action +product_section: ops +product_stage: monitor +product_group: respond +product_category: incident_management +value_type: number +status: active +milestone: "15.4" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97020 +time_frame: 28d +data_source: redis_hll +data_category: optional +instrumentation_class: RedisHLLMetric +options: + events: + - i_quickactions_timeline +performance_indicator_type: [] +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/metrics/counts_7d/20220907080626_i_quickactions_timeline_weekly.yml b/config/metrics/counts_7d/20220907080626_i_quickactions_timeline_weekly.yml new file mode 100644 index 00000000000..5b10a9a93d4 --- /dev/null +++ b/config/metrics/counts_7d/20220907080626_i_quickactions_timeline_weekly.yml @@ -0,0 +1,27 @@ +--- +key_path: redis_hll_counters.quickactions.i_quickactions_timeline_weekly +name: quickactions_timeline_weekly +description: Count of WAU using the `/timeline` quick action +product_section: ops +product_stage: monitor +product_group: respond +product_category: incident_management +value_type: number +status: active +milestone: "15.4" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97020 +time_frame: 7d +data_source: redis_hll +data_category: optional +instrumentation_class: RedisHLLMetric +options: + events: + - i_quickactions_timeline +performance_indicator_type: [] +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/db/migrate/20220909091410_add_dismissal_reason_to_vulnerability_state_transitions.rb b/db/migrate/20220909091410_add_dismissal_reason_to_vulnerability_state_transitions.rb new file mode 100644 index 00000000000..01fcb3aa6e1 --- /dev/null +++ b/db/migrate/20220909091410_add_dismissal_reason_to_vulnerability_state_transitions.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddDismissalReasonToVulnerabilityStateTransitions < Gitlab::Database::Migration[2.0] + def change + add_column :vulnerability_state_transitions, :dismissal_reason, :smallint + end +end diff --git a/db/schema_migrations/20220909091410 b/db/schema_migrations/20220909091410 new file mode 100644 index 00000000000..49738ad23af --- /dev/null +++ b/db/schema_migrations/20220909091410 @@ -0,0 +1 @@ +34e485c0c94960fc07a3f529aed749c2bbc1a72bb49d064225a37b85134f70f2
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index aa1548927a3..7cc22d2150b 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -22823,6 +22823,7 @@ CREATE TABLE vulnerability_state_transitions ( updated_at timestamp with time zone NOT NULL, author_id bigint, comment text, + dismissal_reason smallint, CONSTRAINT check_fca4a7ca39 CHECK ((char_length(comment) <= 255)) ); diff --git a/doc/operations/incident_management/incident_timeline_events.md b/doc/operations/incident_management/incident_timeline_events.md index 8ea962da35f..a360cac0d01 100644 --- a/doc/operations/incident_management/incident_timeline_events.md +++ b/doc/operations/incident_management/incident_timeline_events.md @@ -52,6 +52,12 @@ To create a timeline event: 1. Complete the required fields. 1. Select **Save** or **Save and add another event**. +### Using a quick action + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/368721) in GitLab 15.4. + +You can create a timeline event using the `/timeline` [quick action](../../user/project/quick_actions.md). + ### From a comment on the incident > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/344058) in GitLab 15.4. diff --git a/doc/topics/git/cherry_picking.md b/doc/topics/git/cherry_picking.md index 98458133937..d9314c3becc 100644 --- a/doc/topics/git/cherry_picking.md +++ b/doc/topics/git/cherry_picking.md @@ -17,8 +17,8 @@ and apply those changes to another branch. Cherry-picks can help you: You can cherry-pick commits from the command line. In the GitLab user interface, you can also: -- Cherry-pick [all changes from a merge request](../../user/project/merge_requests/cherry_pick_changes.md#cherry-pick-a-merge-request). -- Cherry-pick [a single commit](../../user/project/merge_requests/cherry_pick_changes.md#cherry-pick-a-commit). +- Cherry-pick [all changes from a merge request](../../user/project/merge_requests/cherry_pick_changes.md#cherry-pick-all-changes-from-a-merge-request). +- Cherry-pick [a single commit](../../user/project/merge_requests/cherry_pick_changes.md#cherry-pick-a-single-commit). - Cherry-pick [from a fork to the upstream repository](../../user/project/merge_requests/cherry_pick_changes.md#cherry-pick-into-a-project). ## Cherry-pick from the command line diff --git a/doc/topics/git/index.md b/doc/topics/git/index.md index 54af1e99797..3e78e366e00 100644 --- a/doc/topics/git/index.md +++ b/doc/topics/git/index.md @@ -36,7 +36,7 @@ The following resources can help you get started with Git: - [GitLab Git Cheat Sheet (download)](https://about.gitlab.com/images/press/git-cheat-sheet.pdf) - Commits: - [Revert a commit](../../user/project/merge_requests/revert_changes.md#revert-a-commit) - - [Cherry-picking a commit](../../user/project/merge_requests/cherry_pick_changes.md#cherry-pick-a-commit) + - [Cherry-picking a commit](../../user/project/merge_requests/cherry_pick_changes.md) - [Squashing commits](../gitlab_flow.md#squashing-commits-with-rebase) - [Squash-and-merge](../../user/project/merge_requests/squash_and_merge.md) - [Signing commits](../../user/project/repository/gpg_signed_commits/index.md) diff --git a/doc/topics/git/numerous_undo_possibilities_in_git/index.md b/doc/topics/git/numerous_undo_possibilities_in_git/index.md index 9786d1399f7..0ed7b2b5e03 100644 --- a/doc/topics/git/numerous_undo_possibilities_in_git/index.md +++ b/doc/topics/git/numerous_undo_possibilities_in_git/index.md @@ -209,7 +209,7 @@ To recover from multiple incorrect commits: The commits are now `A-B-C-D-E`. Alternatively, with GitLab, -you can [cherry-pick](../../../user/project/merge_requests/cherry_pick_changes.md#cherry-pick-a-commit) +you can [cherry-pick](../../../user/project/merge_requests/cherry_pick_changes.md#cherry-pick-a-single-commit) that commit into a new merge request. NOTE: diff --git a/doc/user/clusters/migrating_from_gma_to_project_template.md b/doc/user/clusters/migrating_from_gma_to_project_template.md index 9a59d135fa0..ce39e13d928 100644 --- a/doc/user/clusters/migrating_from_gma_to_project_template.md +++ b/doc/user/clusters/migrating_from_gma_to_project_template.md @@ -4,7 +4,7 @@ group: Configure info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- -# Migrate from GitLab Managed Apps to Cluster Management Projects **(FREE)** +# Migrate from GitLab Managed Apps to Cluster Management Projects (DEPRECATED) **(FREE)** The GitLab Managed Apps were deprecated in GitLab 14.0 in favor of user-controlled Cluster Management projects. diff --git a/doc/user/project/merge_requests/cherry_pick_changes.md b/doc/user/project/merge_requests/cherry_pick_changes.md index 14f3979cf34..ade0277efa8 100644 --- a/doc/user/project/merge_requests/cherry_pick_changes.md +++ b/doc/user/project/merge_requests/cherry_pick_changes.md @@ -7,61 +7,79 @@ type: reference, concepts # Cherry-pick changes **(FREE)** -GitLab implements Git's powerful feature to -[cherry-pick any commit](https://git-scm.com/docs/git-cherry-pick "Git cherry-pick documentation") -with a **Cherry-pick** button in merge requests and commit details. +In Git, *cherry-picking* is taking a single commit from one branch and adding it +as the latest commit on another branch. The rest of the commits in the source branch +are not added to the target. You should cherry-pick a commit when you need the +change contained in a single commit, but you can't or don't want to pull the +entire contents of that branch into another. -## Cherry-pick a merge request +You can use the GitLab UI to cherry-pick single commits or entire merge requests. +You can even cherry-pick a commit from [a fork of your project](#cherry-pick-into-a-project). -After the merge request has been merged, a **Cherry-pick** button displays -to cherry-pick the changes introduced by that merge request. +NOTE: +Support for tracking commits cherry-picked from the command line +is tracked [in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/202215). -![Cherry-pick merge request](img/cherry_pick_changes_mr.png) +## Cherry-pick all changes from a merge request -After you select that button, a modal displays a -[branch filter search box](../repository/branches/index.md#branch-filter-search-box) -where you can choose to either: +After a merge request is merged, you can cherry-pick all changes introduced +by the merge request: -- Cherry-pick the changes directly into the selected branch. -- Create a new merge request with the cherry-picked changes. +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select **Merge requests**, and find your merge request. +1. Scroll to the merge request reports section, and find the **Merged by** report. +1. In the top right, select **Cherry-pick**: -### Track a cherry-pick + ![Cherry-pick merge request](img/cherry_pick_v15_4.png) +1. In the modal window, select the project and branch to cherry-pick into. +1. Optional. Select **Start a new merge request with these changes**. +1. Select **Cherry-pick**. -> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2675) in GitLab 12.9. +## Cherry-pick a single commit -When you cherry-pick a merge commit, GitLab displays a system note to the related merge -request thread. It crosslinks the new commit and the existing merge request. +You can cherry-pick a single commit from multiple locations in your GitLab project. -![Cherry-pick tracking in merge request timeline](img/cherry_pick_mr_timeline_v12_9.png) +### From a project's commit list -Each deployment's [list of associated merge requests](../../../api/deployments.md#list-of-merge-requests-associated-with-a-deployment) includes cherry-picked merge commits. - -NOTE: -We only track cherry-pick executed from GitLab (both UI and API). Support for tracking cherry-picked commits through the command line -is tracked [in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/202215). +To cherry-pick a commit from the list of all commits for a project: -## Cherry-pick a commit +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select **Repository > Commits**. +1. Select the title of the commit you want to cherry-pick. +1. In the modal window, select the project and branch to cherry-pick into. +1. Optional. Select **Start a new merge request with these changes**. +1. Select **Cherry-pick**. -You can cherry-pick a commit from the commit details page: +### From a merge request -![Cherry-pick commit](img/cherry_pick_changes_commit.png) +You can cherry-pick commits from any merge request in your project, regardless of +whether the merge request is open or closed. To cherry-pick a commit from the +list of commits included in a merge request: -Similar to cherry-picking a merge request, you can cherry-pick the changes -directly into the target branch or create a new merge request to cherry-pick the -changes. +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select **Merge requests**, and find your merge request. +1. In the merge request's secondary menu, select **Commits** to display the commit details page. +1. Select the title of the commit you want to cherry-pick. +1. In the top right corner, select **Options > Cherry-pick** to show the cherry-pick modal. +1. In the modal window, select the project and branch to cherry-pick into. +1. Optional. Select **Start a new merge request with these changes**. +1. Select **Cherry-pick**. -When cherry-picking merge commits, the mainline is always the -first parent. If you want to use a different mainline, you need to do that -from the command line. +### From the file view of a repository -Here's a quick example to cherry-pick a merge commit using the second parent as the -mainline: +You can cherry-pick from the list of previous commits affecting an individual file +when you view that file in your project's Git repository: -```shell -git cherry-pick -m 2 7a39eb0 -``` +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select **Repository > Files** and go to the file + changed by the commit. +1. Select **History**, then select the title of the commit you want to cherry-pick. +1. In the top right corner, select **Options > Cherry-pick** to show the cherry-pick modal. +1. In the modal window, select the project and branch to cherry-pick into. +1. Optional. Select **Start a new merge request with these changes**. +1. Select **Cherry-pick**. -### Cherry-pick into a project +## Cherry-pick into a project > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21268) in GitLab 13.11 behind a [feature flag](../../feature_flags.md), disabled by default. > - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/324154) in GitLab 14.0. @@ -70,25 +88,38 @@ You can cherry-pick merge requests from the same project, or forks of the same project, from the GitLab user interface: 1. In the merge request's secondary menu, select **Commits** to display the commit details page. -1. Select the **Options** dropdown and select **Cherry-pick** to show the cherry-pick modal. +1. In the top right corner, select **Options > Cherry-pick** to show the cherry-pick modal. 1. In **Pick into project** and **Pick into branch**, select the destination project and branch: ![Cherry-pick commit](img/cherry_pick_into_project_v13_11.png) 1. Optional. Select **Start a new merge request** if you're ready to create a merge request. 1. Select **Cherry-pick**. +## View system notes for cherry-picked commits + +When you cherry-pick a merge commit in the GitLab UI or API, GitLab adds a system note +to the related merge request thread in the format **{cherry-pick-commit}** +`[USER]` **picked the changes into the branch** `[BRANCHNAME]` with commit** `[SHA]` `[DATE]`: + +![Cherry-pick tracking in merge request timeline](img/cherry_pick_mr_timeline_v15_4.png) + +The system note crosslinks the new commit and the existing merge request. +Each deployment's [list of associated merge requests](../../../api/deployments.md#list-of-merge-requests-associated-with-a-deployment) includes cherry-picked merge commits. + ## Related topics -- The [Commits API](../../../api/commits.md) enables you to add custom messages - to changes you cherry-pick through the API. +- Use the [Commits API](../../../api/commits.md) to add custom messages + to changes when you use the API to cherry-pick. -<!-- ## Troubleshooting +## Troubleshooting -Include any troubleshooting steps that you can foresee. If you know beforehand what issues -one might have when setting this up, or when something is changed, or on upgrading, it's -important to describe those, too. Think of things that may go wrong and include them here. -This is important to minimize requests for support, and to avoid doc comments with -questions that you know someone might ask. +### Selecting a different parent commit when cherry-picking -Each scenario can be a third-level heading, e.g. `### Getting error message X`. -If you have none to add when creating a doc, leave this section in place -but commented out to help encourage others to add to it in the future. --> +When you cherry-pick a merge commit in the GitLab UI, the mainline is always the +first parent. Use the command line to cherry-pick with a different mainline. + +Here's a quick example to cherry-pick a merge commit using the second parent as the +mainline: + +```shell +git cherry-pick -m 2 7a39eb0 +``` diff --git a/doc/user/project/merge_requests/img/cherry_pick_changes_commit.png b/doc/user/project/merge_requests/img/cherry_pick_changes_commit.png Binary files differdeleted file mode 100644 index c98821548f8..00000000000 --- a/doc/user/project/merge_requests/img/cherry_pick_changes_commit.png +++ /dev/null diff --git a/doc/user/project/merge_requests/img/cherry_pick_changes_mr.png b/doc/user/project/merge_requests/img/cherry_pick_changes_mr.png Binary files differdeleted file mode 100644 index 8b51503419b..00000000000 --- a/doc/user/project/merge_requests/img/cherry_pick_changes_mr.png +++ /dev/null diff --git a/doc/user/project/merge_requests/img/cherry_pick_mr_timeline_v12_9.png b/doc/user/project/merge_requests/img/cherry_pick_mr_timeline_v12_9.png Binary files differdeleted file mode 100644 index 919b576fcc6..00000000000 --- a/doc/user/project/merge_requests/img/cherry_pick_mr_timeline_v12_9.png +++ /dev/null diff --git a/doc/user/project/merge_requests/img/cherry_pick_mr_timeline_v15_4.png b/doc/user/project/merge_requests/img/cherry_pick_mr_timeline_v15_4.png Binary files differnew file mode 100644 index 00000000000..d18c4aaec20 --- /dev/null +++ b/doc/user/project/merge_requests/img/cherry_pick_mr_timeline_v15_4.png diff --git a/doc/user/project/merge_requests/img/cherry_pick_v15_4.png b/doc/user/project/merge_requests/img/cherry_pick_v15_4.png Binary files differnew file mode 100644 index 00000000000..174bb113961 --- /dev/null +++ b/doc/user/project/merge_requests/img/cherry_pick_v15_4.png diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md index fe2d3cd6cd1..af43d53679b 100644 --- a/doc/user/project/quick_actions.md +++ b/doc/user/project/quick_actions.md @@ -110,6 +110,7 @@ threads. Some quick actions might not be available to all subscription tiers. | `/tableflip <comment>` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Append the comment with `(╯°□°)╯︵ ┻━┻`. | | `/target_branch <local branch name>` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Set target branch. | | `/title <new title>` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Change title. | +| `/timeline <timeline comment> \| <date(YYYY-MM-DD)> <time(HH:MM)>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Add a timeline event to this incident. For example, `/timeline DB load spiked \| 2022-09-07 09:30`. ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/368721) in GitLab 15.4). | | `/todo` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Add a to-do item. | | `/unapprove` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Unapprove the merge request. ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8103) in GitLab 14.3 | | `/unassign @user1 @user2` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Remove specific assignees. | diff --git a/doc/user/project/repository/index.md b/doc/user/project/repository/index.md index 40584541e53..4926cf3812e 100644 --- a/doc/user/project/repository/index.md +++ b/doc/user/project/repository/index.md @@ -49,7 +49,7 @@ to a branch in the repository. When you use the command line, you can commit mul on their respective thread. - **Cherry-pick a commit:** In GitLab, you can - [cherry-pick a commit](../merge_requests/cherry_pick_changes.md#cherry-pick-a-commit) + [cherry-pick a commit](../merge_requests/cherry_pick_changes.md#cherry-pick-a-single-commit) from the UI. - **Revert a commit:** [Revert a commit](../merge_requests/revert_changes.md#revert-a-commit) diff --git a/lib/gitlab/quick_actions/issue_actions.rb b/lib/gitlab/quick_actions/issue_actions.rb index 1d122bb2b6e..4883c649a62 100644 --- a/lib/gitlab/quick_actions/issue_actions.rb +++ b/lib/gitlab/quick_actions/issue_actions.rb @@ -317,6 +317,30 @@ module Gitlab command :remove_contacts do |contact_emails| @updates[:remove_contacts] = contact_emails.split(' ') end + + desc { _('Add a timeline event to incident') } + explanation { _('Adds a timeline event to incident.') } + params '<timeline comment> | <date(YYYY-MM-DD)> <time(HH:MM)>' + types Issue + condition do + quick_action_target.incident? && + current_user.can?(:admin_incident_management_timeline_event, quick_action_target) + end + parse_params do |event_params| + Gitlab::QuickActions::TimelineTextAndDateTimeSeparator.new(event_params).execute + end + command :timeline do |event_text, date_time| + if event_text && date_time + timeline_event = timeline_event_create_service(event_text, date_time).execute + + @execution_message[:timeline] = + if timeline_event.success? + _('Timeline event added successfully.') + else + _('Something went wrong while adding timeline event.') + end + end + end end private @@ -336,6 +360,10 @@ module Gitlab def merge_updates(result, update_hash) update_hash.merge!(result.payload) if result.payload end + + def timeline_event_create_service(event_text, event_date_time) + ::IncidentManagement::TimelineEvents::CreateService.new(quick_action_target, current_user, { note: event_text, occurred_at: event_date_time, editable: true }) + end end end end diff --git a/lib/gitlab/quick_actions/timeline_text_and_date_time_separator.rb b/lib/gitlab/quick_actions/timeline_text_and_date_time_separator.rb new file mode 100644 index 00000000000..e8002656ff5 --- /dev/null +++ b/lib/gitlab/quick_actions/timeline_text_and_date_time_separator.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +module Gitlab + module QuickActions + class TimelineTextAndDateTimeSeparator + DATETIME_REGEX = %r{(\d{2,4}[\-.]\d{1,2}[\-.]\d{1,2} \d{1,2}:\d{2})}.freeze + MIXED_DELIMITER = %r{([/.])}.freeze + TIME_REGEX = %r{(\d{1,2}:\d{2})}.freeze + + def initialize(timeline_event_arg) + @timeline_event_arg = timeline_event_arg + @timeline_text = get_text + @timeline_date_string = get_raw_date_string + end + + def execute + return if @timeline_event_arg.blank? + return if date_contains_mixed_delimiters? + return [@timeline_text, get_current_date_time] unless date_time_present? + return unless valid_date? + + [@timeline_text, get_actual_date_time] + end + + private + + def get_text + @timeline_event_arg.split('|')[0]&.strip + end + + def get_raw_date_string + @timeline_event_arg.split('|')[1]&.strip + end + + def get_current_date_time + DateTime.current.strftime("%Y-%m-%d %H:%M:00 UTC") + end + + def get_actual_date_time + DateTime.parse(@timeline_date_string) + end + + def date_time_present? + DATETIME_REGEX =~ @timeline_date_string || TIME_REGEX =~ @timeline_date_string + end + + def date_contains_mixed_delimiters? + MIXED_DELIMITER =~ @timeline_date_string + end + + def valid_date? + get_actual_date_time + rescue Date::Error + nil + end + end + end +end diff --git a/lib/gitlab/usage_data_counters/known_events/quickactions.yml b/lib/gitlab/usage_data_counters/known_events/quickactions.yml index 007401ecd44..58a0c0695af 100644 --- a/lib/gitlab/usage_data_counters/known_events/quickactions.yml +++ b/lib/gitlab/usage_data_counters/known_events/quickactions.yml @@ -127,6 +127,10 @@ category: quickactions redis_slot: quickactions aggregation: weekly +- name: i_quickactions_timeline + category: quickactions + redis_slot: quickactions + aggregation: weekly - name: i_quickactions_page category: quickactions redis_slot: quickactions diff --git a/lib/sidebars/projects/menus/learn_gitlab_menu.rb b/lib/sidebars/projects/menus/learn_gitlab_menu.rb index d2bc2fa0681..b6fae2af93d 100644 --- a/lib/sidebars/projects/menus/learn_gitlab_menu.rb +++ b/lib/sidebars/projects/menus/learn_gitlab_menu.rb @@ -29,10 +29,10 @@ module Sidebars override :pill_count def pill_count strong_memoize(:pill_count) do - percentage = LearnGitlab::Onboarding.new( + percentage = Onboarding::Completion.new( context.project.namespace, context.current_user - ).completed_percentage + ).percentage "#{percentage}%" end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 2a82ce046a8..e7b02fc8ab4 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -2201,6 +2201,9 @@ msgstr "" msgid "Add a table" msgstr "" +msgid "Add a timeline event to incident" +msgstr "" + msgid "Add a title..." msgstr "" @@ -2471,6 +2474,9 @@ msgstr "" msgid "Adds a Zoom meeting." msgstr "" +msgid "Adds a timeline event to incident." +msgstr "" + msgid "Adds a to do." msgstr "" @@ -37111,6 +37117,9 @@ msgstr "" msgid "Something went wrong when reordering designs. Please try again" msgstr "" +msgid "Something went wrong while adding timeline event." +msgstr "" + msgid "Something went wrong while adding your award. Please try again." msgstr "" @@ -40971,6 +40980,9 @@ msgstr "" msgid "Timeago|right now" msgstr "" +msgid "Timeline event added successfully." +msgstr "" + msgid "Timeline|Turn recent updates view off" msgstr "" @@ -43386,9 +43398,15 @@ msgstr "" msgid "View all environments." msgstr "" +msgid "View all groups" +msgstr "" + msgid "View all issues" msgstr "" +msgid "View all projects" +msgstr "" + msgid "View blame" msgstr "" diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb index 90b419f8cef..aaf10e12e82 100644 --- a/qa/qa/page/main/menu.rb +++ b/qa/qa/page/main/menu.rb @@ -53,28 +53,45 @@ module QA element :search_term_field end + view 'app/views/layouts/header/_new_dropdown.html.haml' do + element :new_menu_toggle + end + + view 'app/helpers/nav/new_dropdown_helper.rb' do + element :global_new_group_link + element :global_new_project_link + end + def go_to_groups within_groups_menu do - click_element(:menu_item_link, title: 'Your groups') + # Remove if statement once :remove_extra_primary_submenu_options ff is enabled by default + if has_element?(:menu_item_link, title: 'Your groups') + click_element(:menu_item_link, title: 'Your groups') + else + click_element(:menu_item_link, title: 'View all groups') + end end end def go_to_create_group - within_groups_menu do - click_element(:menu_item_link, title: 'Create group') - end + click_element(:new_menu_toggle) + click_element(:global_new_group_link) end def go_to_projects within_projects_menu do - click_element(:menu_item_link, title: 'Your projects') + # Remove if statement once :remove_extra_primary_submenu_options ff is enabled by default + if has_element?(:menu_item_link, title: 'Your projects') + click_element(:menu_item_link, title: 'Your projects') + else + click_element(:menu_item_link, title: 'View all projects') + end end end def go_to_create_project - within_projects_menu do - click_element(:menu_item_link, title: 'Create new project') - end + click_element(:new_menu_toggle) + click_element(:global_new_project_link) end def go_to_menu_dropdown_option(option_name) diff --git a/spec/features/admin/admin_mode_spec.rb b/spec/features/admin/admin_mode_spec.rb index 24a10d3677d..33cf0e8c4f8 100644 --- a/spec/features/admin/admin_mode_spec.rb +++ b/spec/features/admin/admin_mode_spec.rb @@ -33,7 +33,7 @@ RSpec.describe 'Admin mode', :js do open_top_nav_projects within_top_nav do - click_link('Your projects') + click_link('View all projects') end expect(page).to have_current_path(dashboard_projects_path) @@ -99,7 +99,7 @@ RSpec.describe 'Admin mode', :js do open_top_nav_projects within_top_nav do - click_link('Your projects') + click_link('View all projects') end expect(page).to have_current_path(dashboard_projects_path) diff --git a/spec/features/incidents/user_uses_quick_actions_spec.rb b/spec/features/incidents/user_uses_quick_actions_spec.rb new file mode 100644 index 00000000000..fce9eadd42f --- /dev/null +++ b/spec/features/incidents/user_uses_quick_actions_spec.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Incidents > User uses quick actions', :js do + include Spec::Support::Helpers::Features::NotesHelpers + + describe 'incident-only commands' do + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project) } + let_it_be(:issue, reload: true) { create(:incident, project: project) } + + before do + project.add_developer(user) + sign_in(user) + visit project_issue_path(project, issue) + wait_for_all_requests + end + + after do + wait_for_requests + end + + it_behaves_like 'timeline quick action' + end +end diff --git a/spec/features/users/show_spec.rb b/spec/features/users/show_spec.rb index 068e1fd4243..bbf5882f89f 100644 --- a/spec/features/users/show_spec.rb +++ b/spec/features/users/show_spec.rb @@ -339,7 +339,7 @@ RSpec.describe 'User page' do subject - page.within '.navbar-nav' do + page.within '.navbar-gitlab' do expect(page).to have_link('Sign in') end end @@ -351,7 +351,7 @@ RSpec.describe 'User page' do subject - page.within '.navbar-nav' do + page.within '.navbar-gitlab' do expect(page).to have_link('Sign in / Register') end end diff --git a/spec/helpers/learn_gitlab_helper_spec.rb b/spec/helpers/learn_gitlab_helper_spec.rb index 68f847e80b0..0d4f1965d92 100644 --- a/spec/helpers/learn_gitlab_helper_spec.rb +++ b/spec/helpers/learn_gitlab_helper_spec.rb @@ -7,11 +7,11 @@ RSpec.describe LearnGitlabHelper do include Devise::Test::ControllerHelpers let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project, name: LearnGitlab::Project::PROJECT_NAME, namespace: user.namespace) } + let_it_be(:project) { create(:project, name: Onboarding::LearnGitlab::PROJECT_NAME, namespace: user.namespace) } let_it_be(:namespace) { project.namespace } before do - allow_next_instance_of(LearnGitlab::Project) do |learn_gitlab| + allow_next_instance_of(Onboarding::LearnGitlab) do |learn_gitlab| allow(learn_gitlab).to receive(:project).and_return(project) end @@ -38,7 +38,7 @@ RSpec.describe LearnGitlabHelper do with_them do before do allow(Onboarding::Progress).to receive(:onboarding?).with(project.namespace).and_return(onboarding) - allow_next(LearnGitlab::Project, user).to receive(:available?).and_return(learn_gitlab_available) + allow_next(Onboarding::LearnGitlab, user).to receive(:available?).and_return(learn_gitlab_available) end context 'when signed in' do @@ -81,7 +81,7 @@ RSpec.describe LearnGitlabHelper do it 'has all section data', :aggregate_failures do expect(onboarding_sections_data.keys).to contain_exactly(:deploy, :plan, :workspace) - expect(onboarding_sections_data.values.map { |section| section.keys }).to match_array([[:svg]] * 3) + expect(onboarding_sections_data.values.map(&:keys)).to match_array([[:svg]] * 3) end it 'has all project data', :aggregate_failures do diff --git a/spec/helpers/nav/new_dropdown_helper_spec.rb b/spec/helpers/nav/new_dropdown_helper_spec.rb index 45664a7e0bd..3a65131aab0 100644 --- a/spec/helpers/nav/new_dropdown_helper_spec.rb +++ b/spec/helpers/nav/new_dropdown_helper_spec.rb @@ -100,7 +100,7 @@ RSpec.describe Nav::NewDropdownHelper do id: 'general_new_group', title: 'New group', href: '/groups/new', - data: { track_action: 'click_link_new_group', track_label: 'plus_menu_dropdown' } + data: { qa_selector: 'global_new_group_link', track_action: 'click_link_new_group', track_label: 'plus_menu_dropdown' } ) ) ) diff --git a/spec/helpers/nav/top_nav_helper_spec.rb b/spec/helpers/nav/top_nav_helper_spec.rb index dc8f062ded8..9c396d6bf25 100644 --- a/spec/helpers/nav/top_nav_helper_spec.rb +++ b/spec/helpers/nav/top_nav_helper_spec.rb @@ -161,61 +161,87 @@ RSpec.describe Nav::TopNavHelper do ::Gitlab::Nav::TopNavMenuItem.build( data: { qa_selector: 'menu_item_link', - qa_title: 'Your projects', - **menu_data_tracking_attrs('your_projects') + qa_title: 'View all projects', + **menu_data_tracking_attrs('view_all_projects') }, href: '/dashboard/projects', id: 'your', - title: 'Your projects' - ), - ::Gitlab::Nav::TopNavMenuItem.build( - data: { - qa_selector: 'menu_item_link', - qa_title: 'Starred projects', - **menu_data_tracking_attrs('starred_projects') - }, - href: '/dashboard/projects/starred', - id: 'starred', - title: 'Starred projects' - ), - ::Gitlab::Nav::TopNavMenuItem.build( - data: { - qa_selector: 'menu_item_link', - qa_title: 'Explore projects', - **menu_data_tracking_attrs('explore_projects') - }, - href: '/explore', - id: 'explore', - title: 'Explore projects' - ), - ::Gitlab::Nav::TopNavMenuItem.build( - data: { - qa_selector: 'menu_item_link', - qa_title: 'Explore topics', - **menu_data_tracking_attrs('explore_topics') - }, - href: '/explore/projects/topics', - id: 'topics', - title: 'Explore topics' + title: 'View all projects' ) ] expect(projects_view[:linksPrimary]).to eq(expected_links_primary) end - it 'has expected :linksSecondary' do - expected_links_secondary = [ - ::Gitlab::Nav::TopNavMenuItem.build( - data: { - qa_selector: 'menu_item_link', - qa_title: 'Create new project', - **menu_data_tracking_attrs('create_new_project') - }, - href: '/projects/new', - id: 'create', - title: 'Create new project' - ) - ] - expect(projects_view[:linksSecondary]).to eq(expected_links_secondary) + it 'does not have any :linksSecondary' do + expect(projects_view[:linksSecondary]).to eq([]) + end + + context 'when extra submenu options are not hidden' do + before do + stub_feature_flags(remove_extra_primary_submenu_options: false) + end + + it 'has expected :linksPrimary' do + expected_links_primary = [ + ::Gitlab::Nav::TopNavMenuItem.build( + data: { + qa_selector: 'menu_item_link', + qa_title: 'Your projects', + **menu_data_tracking_attrs('your_projects') + }, + href: '/dashboard/projects', + id: 'your', + title: 'Your projects' + ), + ::Gitlab::Nav::TopNavMenuItem.build( + data: { + qa_selector: 'menu_item_link', + qa_title: 'Starred projects', + **menu_data_tracking_attrs('starred_projects') + }, + href: '/dashboard/projects/starred', + id: 'starred', + title: 'Starred projects' + ), + ::Gitlab::Nav::TopNavMenuItem.build( + data: { + qa_selector: 'menu_item_link', + qa_title: 'Explore projects', + **menu_data_tracking_attrs('explore_projects') + }, + href: '/explore', + id: 'explore', + title: 'Explore projects' + ), + ::Gitlab::Nav::TopNavMenuItem.build( + data: { + qa_selector: 'menu_item_link', + qa_title: 'Explore topics', + **menu_data_tracking_attrs('explore_topics') + }, + href: '/explore/projects/topics', + id: 'topics', + title: 'Explore topics' + ) + ] + expect(projects_view[:linksPrimary]).to eq(expected_links_primary) + end + + it 'has expected :linksSecondary' do + expected_links_secondary = [ + ::Gitlab::Nav::TopNavMenuItem.build( + data: { + qa_selector: 'menu_item_link', + qa_title: 'Create new project', + **menu_data_tracking_attrs('create_new_project') + }, + href: '/projects/new', + id: 'create', + title: 'Create new project' + ) + ] + expect(projects_view[:linksSecondary]).to eq(expected_links_secondary) + end end context 'with current nav as project' do @@ -300,41 +326,67 @@ RSpec.describe Nav::TopNavHelper do ::Gitlab::Nav::TopNavMenuItem.build( data: { qa_selector: 'menu_item_link', - qa_title: 'Your groups', - **menu_data_tracking_attrs('your_groups') + qa_title: 'View all groups', + **menu_data_tracking_attrs('view_all_groups') }, href: '/dashboard/groups', id: 'your', - title: 'Your groups' - ), - ::Gitlab::Nav::TopNavMenuItem.build( - data: { - qa_selector: 'menu_item_link', - qa_title: 'Explore groups', - **menu_data_tracking_attrs('explore_groups') - }, - href: '/explore/groups', - id: 'explore', - title: 'Explore groups' + title: 'View all groups' ) ] expect(groups_view[:linksPrimary]).to eq(expected_links_primary) end - it 'has expected :linksSecondary' do - expected_links_secondary = [ - ::Gitlab::Nav::TopNavMenuItem.build( - data: { - qa_selector: 'menu_item_link', - qa_title: 'Create group', - **menu_data_tracking_attrs('create_group') - }, - href: '/groups/new', - id: 'create', - title: 'Create group' - ) - ] - expect(groups_view[:linksSecondary]).to eq(expected_links_secondary) + it 'does not have any :linksSecondary' do + expect(groups_view[:linksSecondary]).to eq([]) + end + + context 'when extra submenu options are not hidden' do + before do + stub_feature_flags(remove_extra_primary_submenu_options: false) + end + + it 'has expected :linksPrimary' do + expected_links_primary = [ + ::Gitlab::Nav::TopNavMenuItem.build( + data: { + qa_selector: 'menu_item_link', + qa_title: 'Your groups', + **menu_data_tracking_attrs('your_groups') + }, + href: '/dashboard/groups', + id: 'your', + title: 'Your groups' + ), + ::Gitlab::Nav::TopNavMenuItem.build( + data: { + qa_selector: 'menu_item_link', + qa_title: 'Explore groups', + **menu_data_tracking_attrs('explore_groups') + }, + href: '/explore/groups', + id: 'explore', + title: 'Explore groups' + ) + ] + expect(groups_view[:linksPrimary]).to eq(expected_links_primary) + end + + it 'has expected :linksSecondary' do + expected_links_secondary = [ + ::Gitlab::Nav::TopNavMenuItem.build( + data: { + qa_selector: 'menu_item_link', + qa_title: 'Create group', + **menu_data_tracking_attrs('create_group') + }, + href: '/groups/new', + id: 'create', + title: 'Create group' + ) + ] + expect(groups_view[:linksSecondary]).to eq(expected_links_secondary) + end end context 'with external user' do diff --git a/spec/lib/gitlab/quick_actions/timeline_text_and_date_time_separator_spec.rb b/spec/lib/gitlab/quick_actions/timeline_text_and_date_time_separator_spec.rb new file mode 100644 index 00000000000..89fe19b8f60 --- /dev/null +++ b/spec/lib/gitlab/quick_actions/timeline_text_and_date_time_separator_spec.rb @@ -0,0 +1,94 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::QuickActions::TimelineTextAndDateTimeSeparator do + subject(:timeline_text_and_datetime_separator) { described_class } + + shared_examples 'arg line with invalid parameters' do + it 'returns nil' do + expect(timeline_text_and_datetime_separator.new(invalid_arg).execute).to eq(nil) + end + end + + shared_examples 'arg line with valid parameters' do + it 'returns text and date time array' do + freeze_time do + expect(timeline_text_and_datetime_separator.new(valid_arg).execute).to eq(expected_response) + end + end + end + + describe 'execute' do + context 'with invalid parameters in arg line' do + context 'with empty arg line' do + it_behaves_like 'arg line with invalid parameters' do + let(:invalid_arg) { '' } + end + end + + context 'with invalid date' do + it_behaves_like 'arg line with invalid parameters' do + let(:invalid_arg) { 'timeline comment | 2022-13-13 09:30' } + end + + it_behaves_like 'arg line with invalid parameters' do + let(:invalid_arg) { 'timeline comment | 2022-09/09 09:30' } + end + + it_behaves_like 'arg line with invalid parameters' do + let(:invalid_arg) { 'timeline comment | 2022-09.09 09:30' } + end + end + + context 'with invalid time' do + it_behaves_like 'arg line with invalid parameters' do + let(:invalid_arg) { 'timeline comment | 2022-11-13 29:30' } + end + end + + context 'when date is invalid in arg line' do + let(:invalid_arg) { 'timeline comment | wrong data type' } + + it 'return current date' do + timeline_args = timeline_text_and_datetime_separator.new(invalid_arg).execute + + expect(timeline_args).to be_an_instance_of(Array) + expect(timeline_args.first).to eq('timeline comment') + expect(timeline_args.second).to match(Gitlab::QuickActions::TimelineTextAndDateTimeSeparator::DATETIME_REGEX) + end + end + end + + context 'with valid parameters' do + context 'when only timeline text present in arg line' do + it_behaves_like 'arg line with valid parameters' do + let(:timeline_text) { 'timeline comment' } + let(:valid_arg) { timeline_text } + let(:date) { DateTime.current.strftime("%Y-%m-%d %H:%M:00 UTC") } + let(:expected_response) { [timeline_text, date] } + end + end + + context 'when only timeline text and time present in arg line' do + it_behaves_like 'arg line with valid parameters' do + let(:timeline_text) { 'timeline comment' } + let(:date) { '09:30' } + let(:valid_arg) { "#{timeline_text} | #{date}" } + let(:parsed_date) { DateTime.parse(date) } + let(:expected_response) { [timeline_text, parsed_date] } + end + end + + context 'when timeline text and date is present in arg line' do + it_behaves_like 'arg line with valid parameters' do + let(:timeline_text) { 'timeline comment' } + let(:date) { '2022-06-05 09:30' } + let(:valid_arg) { "#{timeline_text} | #{date}" } + let(:parsed_date) { DateTime.parse(date) } + let(:expected_response) { [timeline_text, parsed_date] } + end + end + end + end +end diff --git a/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb b/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb index 36a76e70a48..4ae29f28f3a 100644 --- a/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb +++ b/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb @@ -68,13 +68,11 @@ RSpec.describe Sidebars::Projects::Menus::LearnGitlabMenu do end describe '#pill_count' do - before do - expect_next_instance_of(LearnGitlab::Onboarding) do |onboarding| - expect(onboarding).to receive(:completed_percentage).and_return(20) + it 'returns pill count' do + expect_next_instance_of(Onboarding::Completion) do |onboarding| + expect(onboarding).to receive(:percentage).and_return(20) end - end - it 'returns pill count' do expect(subject.pill_count).to eq '20%' end end diff --git a/spec/models/ci/freeze_period_status_spec.rb b/spec/models/ci/freeze_period_status_spec.rb index f51381f7a5f..ecbb7af64f7 100644 --- a/spec/models/ci/freeze_period_status_spec.rb +++ b/spec/models/ci/freeze_period_status_spec.rb @@ -59,4 +59,13 @@ RSpec.describe Ci::FreezePeriodStatus do it_behaves_like 'outside freeze period', Time.utc(2020, 4, 13, 8, 1) end + + # https://gitlab.com/gitlab-org/gitlab/-/issues/370472 + context 'when period overlaps with itself' do + let!(:freeze_period) { create(:ci_freeze_period, project: project, freeze_start: '* * * 8 *', freeze_end: '* * * 10 *') } + + it_behaves_like 'within freeze period', Time.utc(2020, 8, 11, 0, 0) + + it_behaves_like 'outside freeze period', Time.utc(2020, 10, 11, 0, 0) + end end diff --git a/spec/lib/learn_gitlab/onboarding_spec.rb b/spec/models/onboarding/completion_spec.rb index 97926f8a612..e1fad4255bc 100644 --- a/spec/lib/learn_gitlab/onboarding_spec.rb +++ b/spec/models/onboarding/completion_spec.rb @@ -2,13 +2,11 @@ require 'spec_helper' -RSpec.describe LearnGitlab::Onboarding do - describe '#completed_percentage' do +RSpec.describe Onboarding::Completion do + describe '#percentage' do let(:completed_actions) { {} } - let(:onboarding_progress) { build(:onboarding_progress, namespace: namespace, **completed_actions) } - let(:namespace) { create(:namespace) } - - let_it_be(:tracked_action_columns) do + let!(:onboarding_progress) { create(:onboarding_progress, namespace: namespace, **completed_actions) } + let(:tracked_action_columns) do [ *described_class::ACTION_ISSUE_IDS.keys, *described_class::ACTION_PATHS, @@ -16,14 +14,12 @@ RSpec.describe LearnGitlab::Onboarding do ].map { |key| ::Onboarding::Progress.column_name(key) } end - before do - expect(::Onboarding::Progress).to receive(:find_by).with(namespace: namespace).and_return(onboarding_progress) - end + let_it_be(:namespace) { create(:namespace) } - subject { described_class.new(namespace).completed_percentage } + subject { described_class.new(namespace).percentage } context 'when no onboarding_progress exists' do - let(:onboarding_progress) { nil } + subject { described_class.new(build(:namespace)).percentage } it { is_expected.to eq(0) } end @@ -34,13 +30,13 @@ RSpec.describe LearnGitlab::Onboarding do context 'when all tracked actions have been completed' do let(:completed_actions) do - tracked_action_columns.to_h { |action| [action, Time.current] } + tracked_action_columns.index_with { Time.current } end it { is_expected.to eq(100) } end - describe 'security_actions_continuous_onboarding experiment' do + context 'with security_actions_continuous_onboarding experiment' do let(:completed_actions) { Hash[tracked_action_columns.first, Time.current] } context 'when control' do diff --git a/spec/lib/learn_gitlab/project_spec.rb b/spec/models/onboarding/learn_gitlab_spec.rb index 23784709817..5e3e1f9c304 100644 --- a/spec/lib/learn_gitlab/project_spec.rb +++ b/spec/models/onboarding/learn_gitlab_spec.rb @@ -2,17 +2,17 @@ require 'spec_helper' -RSpec.describe LearnGitlab::Project do +RSpec.describe Onboarding::LearnGitlab do let_it_be(:current_user) { create(:user) } - let_it_be(:learn_gitlab_project) { create(:project, name: LearnGitlab::Project::PROJECT_NAME) } - let_it_be(:learn_gitlab_board) { create(:board, project: learn_gitlab_project, name: LearnGitlab::Project::BOARD_NAME) } - let_it_be(:learn_gitlab_label) { create(:label, project: learn_gitlab_project, name: LearnGitlab::Project::LABEL_NAME) } + let_it_be(:learn_gitlab_project) { create(:project, name: described_class::PROJECT_NAME) } + let_it_be(:learn_gitlab_board) { create(:board, project: learn_gitlab_project, name: described_class::BOARD_NAME) } + let_it_be(:learn_gitlab_label) { create(:label, project: learn_gitlab_project, name: described_class::LABEL_NAME) } before do learn_gitlab_project.add_developer(current_user) end - describe '.available?' do + describe '#available?' do using RSpec::Parameterized::TableSyntax where(:project, :board, :label, :expected_result) do @@ -41,25 +41,27 @@ RSpec.describe LearnGitlab::Project do end end - describe '.project' do + describe '#project' do subject { described_class.new(current_user).project } it { is_expected.to eq learn_gitlab_project } context 'when it is created during trial signup' do - let_it_be(:learn_gitlab_project) { create(:project, name: LearnGitlab::Project::PROJECT_NAME_ULTIMATE_TRIAL, path: 'learn-gitlab-ultimate-trial') } + let_it_be(:learn_gitlab_project) do + create(:project, name: described_class::PROJECT_NAME_ULTIMATE_TRIAL, path: 'learn-gitlab-ultimate-trial') + end it { is_expected.to eq learn_gitlab_project } end end - describe '.board' do + describe '#board' do subject { described_class.new(current_user).board } it { is_expected.to eq learn_gitlab_board } end - describe '.label' do + describe '#label' do subject { described_class.new(current_user).label } it { is_expected.to eq learn_gitlab_label } diff --git a/spec/support/rspec_order_todo.yml b/spec/support/rspec_order_todo.yml index f297734b4b7..9d54e746d63 100644 --- a/spec/support/rspec_order_todo.yml +++ b/spec/support/rspec_order_todo.yml @@ -537,7 +537,6 @@ - './ee/spec/features/trials/capture_lead_spec.rb' - './ee/spec/features/trials/select_namespace_spec.rb' - './ee/spec/features/trials/show_trial_banner_spec.rb' -- './ee/spec/features/uncompleted_learn_gitlab_link_spec.rb' - './ee/spec/features/users/arkose_labs_csp_spec.rb' - './ee/spec/features/users/login_spec.rb' - './ee/spec/features/users/signup_spec.rb' @@ -5459,7 +5458,6 @@ - './spec/helpers/keyset_helper_spec.rb' - './spec/helpers/labels_helper_spec.rb' - './spec/helpers/lazy_image_tag_helper_spec.rb' -- './spec/helpers/learn_gitlab_helper_spec.rb' - './spec/helpers/listbox_helper_spec.rb' - './spec/helpers/markup_helper_spec.rb' - './spec/helpers/members_helper_spec.rb' @@ -7756,8 +7754,6 @@ - './spec/lib/json_web_token/token_spec.rb' - './spec/lib/kramdown/kramdown_spec.rb' - './spec/lib/kramdown/parser/atlassian_document_format_spec.rb' -- './spec/lib/learn_gitlab/onboarding_spec.rb' -- './spec/lib/learn_gitlab/project_spec.rb' - './spec/lib/marginalia_spec.rb' - './spec/lib/mattermost/client_spec.rb' - './spec/lib/mattermost/command_spec.rb' @@ -7824,7 +7820,6 @@ - './spec/lib/sidebars/projects/menus/infrastructure_menu_spec.rb' - './spec/lib/sidebars/projects/menus/invite_team_members_menu_spec.rb' - './spec/lib/sidebars/projects/menus/issues_menu_spec.rb' -- './spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb' - './spec/lib/sidebars/projects/menus/merge_requests_menu_spec.rb' - './spec/lib/sidebars/projects/menus/monitor_menu_spec.rb' - './spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb' diff --git a/spec/support/shared_examples/quick_actions/incident/timeline_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/incident/timeline_quick_action_shared_examples.rb new file mode 100644 index 00000000000..ae7e511a739 --- /dev/null +++ b/spec/support/shared_examples/quick_actions/incident/timeline_quick_action_shared_examples.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'timeline quick action' do + describe '/timeline' do + context 'with valid args' do + where(:timeline_text, :date_time_arg) do + [ + ['timeline comment', '2022-09-09 09:30'], + ['new timeline comment', '09:30'], + ['another timeline comment', ' 2022-09-09 09:15'] + ] + end + + with_them do + it 'adds a timeline event' do + add_note("/timeline #{timeline_text} | #{date_time_arg}") + + expect(page).to have_content('Timeline event added successfully.') + expect(issue.incident_management_timeline_events.first.note).to eq(timeline_text) + expect(issue.incident_management_timeline_events.first.occurred_at).to eq(DateTime.parse(date_time_arg)) + end + end + + it 'adds a timeline event when no date is passed' do + freeze_time do + add_note('/timeline timeline event with not date') + + expect(page).to have_content('Timeline event added successfully.') + expect(issue.incident_management_timeline_events.first.note).to eq('timeline event with not date') + expect(issue.incident_management_timeline_events.first.occurred_at).to eq(DateTime + .current.strftime("%Y-%m-%d %H:%M:00 UTC")) + end + end + + it 'adds a timeline event when only date is passed' do + freeze_time do + add_note('/timeline timeline event with not date | 2022-10-11') + + expect(page).to have_content('Timeline event added successfully.') + expect(issue.incident_management_timeline_events.first.note).to eq('timeline event with not date') + expect(issue.incident_management_timeline_events.first.occurred_at).to eq(DateTime + .current.strftime("%Y-%m-%d %H:%M:00 UTC")) + end + end + end + + context 'with invalid args' do + where(:timeline_text, :date_time_arg) do + [ + ['timeline comment', '2022-13-13 09:30'], + ['timeline comment 2', '2022-09-06 24:30'] + ] + end + + with_them do + it 'does not add a timeline event' do + add_note("/timeline #{timeline_text} | #{date_time_arg}") + + expect(page).to have_content('Failed to apply commands.') + expect(issue.incident_management_timeline_events.length).to eq(0) + end + end + end + + context 'when create service fails' do + before do + allow_next_instance_of(::IncidentManagement::TimelineEvents::CreateService) do |service| + allow(service).to receive(:execute).and_return( + ServiceResponse.error(payload: { timeline_event: nil }, message: 'Some error') + ) + end + end + + it 'does not add a timeline event' do + add_note('/timeline text | 2022-09-10 09:30') + + expect(page).to have_content('Something went wrong while adding timeline event.') + expect(issue.incident_management_timeline_events.length).to eq(0) + end + end + end +end diff --git a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb index f5cd5679270..e7d9a8a4708 100644 --- a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb +++ b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb @@ -70,8 +70,8 @@ RSpec.describe 'layouts/nav/sidebar/_project' do describe 'Learn GitLab' do it 'has a link to the learn GitLab' do allow(view).to receive(:learn_gitlab_enabled?).and_return(true) - allow_next_instance_of(LearnGitlab::Onboarding) do |onboarding| - expect(onboarding).to receive(:completed_percentage).and_return(20) + allow_next_instance_of(Onboarding::Completion) do |onboarding| + expect(onboarding).to receive(:percentage).and_return(20) end render |