summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-09-09 21:10:12 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-09-09 21:10:12 +0000
commitdc22d7faa23a7988be2b70da2bfb956de4df00f0 (patch)
treecf79ae05494af210a53390fd8bd7ade54d54bad8
parent7c0e5472c80f1826b36916a95e6f9d84a7b68fe3 (diff)
downloadgitlab-ce-dc22d7faa23a7988be2b70da2bfb956de4df00f0.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop_todo/layout/argument_alignment.yml1
-rw-r--r--.rubocop_todo/layout/line_length.yml2
-rw-r--r--.rubocop_todo/rails/index_with.yml1
-rw-r--r--.rubocop_todo/rspec/expect_in_hook.yml2
-rw-r--r--.rubocop_todo/style/float_division.yml1
-rw-r--r--.rubocop_todo/style/hash_as_last_array_item.yml1
-rw-r--r--.rubocop_todo/style/symbol_proc.yml1
-rw-r--r--app/assets/stylesheets/pages/search.scss8
-rw-r--r--app/assets/stylesheets/startup/startup-dark.scss6
-rw-r--r--app/assets/stylesheets/startup/startup-general.scss6
-rw-r--r--app/helpers/learn_gitlab_helper.rb21
-rw-r--r--app/helpers/nav/new_dropdown_helper.rb2
-rw-r--r--app/helpers/nav/top_nav_helper.rb86
-rw-r--r--app/models/ci/freeze_period_status.rb28
-rw-r--r--app/models/onboarding/completion.rb (renamed from lib/learn_gitlab/onboarding.rb)13
-rw-r--r--app/models/onboarding/learn_gitlab.rb (renamed from lib/learn_gitlab/project.rb)4
-rw-r--r--app/views/layouts/header/_default.html.haml20
-rw-r--r--config/feature_flags/development/new_navbar_layout.yml4
-rw-r--r--config/feature_flags/development/remove_extra_primary_submenu_options.yml8
-rw-r--r--config/metrics/counts_28d/20220907080630_i_quickactions_timeline_monthly.yml27
-rw-r--r--config/metrics/counts_7d/20220907080626_i_quickactions_timeline_weekly.yml27
-rw-r--r--db/migrate/20220909091410_add_dismissal_reason_to_vulnerability_state_transitions.rb7
-rw-r--r--db/schema_migrations/202209090914101
-rw-r--r--db/structure.sql1
-rw-r--r--doc/operations/incident_management/incident_timeline_events.md6
-rw-r--r--doc/topics/git/cherry_picking.md4
-rw-r--r--doc/topics/git/index.md2
-rw-r--r--doc/topics/git/numerous_undo_possibilities_in_git/index.md2
-rw-r--r--doc/user/clusters/migrating_from_gma_to_project_template.md2
-rw-r--r--doc/user/project/merge_requests/cherry_pick_changes.md129
-rw-r--r--doc/user/project/merge_requests/img/cherry_pick_changes_commit.pngbin13568 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/cherry_pick_changes_mr.pngbin7214 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/cherry_pick_mr_timeline_v12_9.pngbin29557 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/img/cherry_pick_mr_timeline_v15_4.pngbin0 -> 7678 bytes
-rw-r--r--doc/user/project/merge_requests/img/cherry_pick_v15_4.pngbin0 -> 10187 bytes
-rw-r--r--doc/user/project/quick_actions.md1
-rw-r--r--doc/user/project/repository/index.md2
-rw-r--r--lib/gitlab/quick_actions/issue_actions.rb28
-rw-r--r--lib/gitlab/quick_actions/timeline_text_and_date_time_separator.rb58
-rw-r--r--lib/gitlab/usage_data_counters/known_events/quickactions.yml4
-rw-r--r--lib/sidebars/projects/menus/learn_gitlab_menu.rb4
-rw-r--r--locale/gitlab.pot18
-rw-r--r--qa/qa/page/main/menu.rb33
-rw-r--r--spec/features/admin/admin_mode_spec.rb4
-rw-r--r--spec/features/incidents/user_uses_quick_actions_spec.rb26
-rw-r--r--spec/features/users/show_spec.rb4
-rw-r--r--spec/helpers/learn_gitlab_helper_spec.rb8
-rw-r--r--spec/helpers/nav/new_dropdown_helper_spec.rb2
-rw-r--r--spec/helpers/nav/top_nav_helper_spec.rb200
-rw-r--r--spec/lib/gitlab/quick_actions/timeline_text_and_date_time_separator_spec.rb94
-rw-r--r--spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb8
-rw-r--r--spec/models/ci/freeze_period_status_spec.rb9
-rw-r--r--spec/models/onboarding/completion_spec.rb (renamed from spec/lib/learn_gitlab/onboarding_spec.rb)22
-rw-r--r--spec/models/onboarding/learn_gitlab_spec.rb (renamed from spec/lib/learn_gitlab/project_spec.rb)20
-rw-r--r--spec/support/rspec_order_todo.yml5
-rw-r--r--spec/support/shared_examples/quick_actions/incident/timeline_quick_action_shared_examples.rb82
-rw-r--r--spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb4
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
deleted file mode 100644
index c98821548f8..00000000000
--- a/doc/user/project/merge_requests/img/cherry_pick_changes_commit.png
+++ /dev/null
Binary files differ
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
deleted file mode 100644
index 8b51503419b..00000000000
--- a/doc/user/project/merge_requests/img/cherry_pick_changes_mr.png
+++ /dev/null
Binary files differ
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
deleted file mode 100644
index 919b576fcc6..00000000000
--- a/doc/user/project/merge_requests/img/cherry_pick_mr_timeline_v12_9.png
+++ /dev/null
Binary files differ
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
new file mode 100644
index 00000000000..d18c4aaec20
--- /dev/null
+++ b/doc/user/project/merge_requests/img/cherry_pick_mr_timeline_v15_4.png
Binary files differ
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
new file mode 100644
index 00000000000..174bb113961
--- /dev/null
+++ b/doc/user/project/merge_requests/img/cherry_pick_v15_4.png
Binary files differ
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