Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
087d90af
Commit
087d90af
authored
Apr 30, 2021
by
Francisco Javier López
Committed by
Arturo Herrero
Apr 30, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add `Operations` menu to the new sidebar
parent
08344e29
Changes
17
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
823 additions
and
418 deletions
+823
-418
app/helpers/projects_helper.rb
app/helpers/projects_helper.rb
+0
-42
app/helpers/sidebars_helper.rb
app/helpers/sidebars_helper.rb
+2
-1
app/views/layouts/nav/sidebar/_project_menus.html.haml
app/views/layouts/nav/sidebar/_project_menus.html.haml
+0
-95
app/views/layouts/nav/sidebar/_tracing_link.html.haml
app/views/layouts/nav/sidebar/_tracing_link.html.haml
+0
-7
ee/app/helpers/ee/projects_helper.rb
ee/app/helpers/ee/projects_helper.rb
+0
-7
ee/app/views/projects/sidebar/_oncall_schedules.html.haml
ee/app/views/projects/sidebar/_oncall_schedules.html.haml
+0
-6
ee/lib/ee/sidebars/projects/menus/operations_menu.rb
ee/lib/ee/sidebars/projects/menus/operations_menu.rb
+35
-0
ee/spec/helpers/projects_helper_spec.rb
ee/spec/helpers/projects_helper_spec.rb
+0
-69
ee/spec/lib/ee/sidebars/projects/menus/operations_menu_spec.rb
...ec/lib/ee/sidebars/projects/menus/operations_menu_spec.rb
+25
-0
ee/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
ee/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
+25
-35
lib/sidebars/projects/menus/operations_menu.rb
lib/sidebars/projects/menus/operations_menu.rb
+217
-0
lib/sidebars/projects/panel.rb
lib/sidebars/projects/panel.rb
+1
-0
qa/qa/page/project/sub_menus/operations.rb
qa/qa/page/project/sub_menus/operations.rb
+5
-12
spec/features/operations_sidebar_link_spec.rb
spec/features/operations_sidebar_link_spec.rb
+50
-49
spec/helpers/projects_helper_spec.rb
spec/helpers/projects_helper_spec.rb
+0
-37
spec/lib/sidebars/projects/menus/operations_menu_spec.rb
spec/lib/sidebars/projects/menus/operations_menu_spec.rb
+205
-0
spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
+258
-58
No files found.
app/helpers/projects_helper.rb
View file @
087d90af
...
...
@@ -404,14 +404,6 @@ module ProjectsHelper
nav_tabs
<<
:pipelines
end
if
can_view_operations_tab?
(
current_user
,
project
)
nav_tabs
<<
:operations
end
if
can_view_product_analytics?
(
current_user
,
project
)
nav_tabs
<<
:product_analytics
end
tab_ability_map
.
each
do
|
tab
,
ability
|
if
can?
(
current_user
,
ability
,
project
)
nav_tabs
<<
tab
...
...
@@ -470,32 +462,6 @@ module ProjectsHelper
}
end
def
view_operations_tab_ability
[
:metrics_dashboard
,
:read_alert_management_alert
,
:read_environment
,
:read_issue
,
:read_sentry_issue
,
:read_cluster
,
:read_feature_flag
,
:read_terraform_state
]
end
def
can_view_operations_tab?
(
current_user
,
project
)
return
false
unless
project
.
feature_available?
(
:operations
,
current_user
)
view_operations_tab_ability
.
any?
do
|
ability
|
can?
(
current_user
,
ability
,
project
)
end
end
def
can_view_product_analytics?
(
current_user
,
project
)
Feature
.
enabled?
(
:product_analytics
,
project
)
&&
can?
(
current_user
,
:read_product_analytics
,
project
)
end
def
search_tab_ability_map
@search_tab_ability_map
||=
tab_ability_map
.
merge
(
blobs: :download_code
,
...
...
@@ -563,14 +529,6 @@ module ProjectsHelper
end
end
def
sidebar_operations_link_path
(
project
=
@project
)
if
can?
(
current_user
,
:read_environment
,
project
)
metrics_project_environments_path
(
project
)
else
project_feature_flags_path
(
project
)
end
end
def
project_last_activity
(
project
)
if
project
.
last_activity_at
time_ago_with_tooltip
(
project
.
last_activity_at
,
placement:
'bottom'
,
html_class:
'last_activity_time_ago'
)
...
...
app/helpers/sidebars_helper.rb
View file @
087d90af
...
...
@@ -41,7 +41,8 @@ module SidebarsHelper
learn_gitlab_experiment_enabled:
learn_gitlab_experiment_enabled?
(
project
),
current_ref:
current_ref
,
jira_issues_integration:
project_jira_issues_integration?
,
can_view_pipeline_editor:
can_view_pipeline_editor?
(
project
)
can_view_pipeline_editor:
can_view_pipeline_editor?
(
project
),
show_cluster_hint:
show_gke_cluster_integration_callout?
(
project
)
}
end
end
...
...
app/views/layouts/nav/sidebar/_project_menus.html.haml
View file @
087d90af
-
if
project_nav_tab?
:operations
=
nav_link
(
controller:
sidebar_operations_paths
)
do
=
link_to
sidebar_operations_link_path
,
class:
'shortcuts-operations'
,
data:
{
qa_selector:
'operations_link'
}
do
.nav-icon-container
=
sprite_icon
(
'cloud-gear'
)
%span
.nav-item-name
=
_
(
'Operations'
)
%ul
.sidebar-sub-level-items
=
nav_link
(
controller:
sidebar_operations_paths
,
html_options:
{
class:
"fly-out-top-item"
}
)
do
=
link_to
sidebar_operations_link_path
do
%strong
.fly-out-top-item-name
=
_
(
'Operations'
)
%li
.divider.fly-out-top-item
-
if
project_nav_tab?
:metrics_dashboards
=
nav_link
(
controller: :metrics_dashboard
,
action:
[
:show
])
do
=
link_to
project_metrics_dashboard_path
(
@project
),
title:
_
(
'Metrics'
),
class:
'shortcuts-metrics'
,
data:
{
qa_selector:
'operations_metrics_link'
}
do
%span
=
_
(
'Metrics'
)
-
if
project_nav_tab?
(
:environments
)
&&
can?
(
current_user
,
:read_pod_logs
,
@project
)
=
nav_link
(
controller: :logs
,
action:
[
:index
])
do
=
link_to
project_logs_path
(
@project
),
title:
_
(
'Logs'
)
do
%span
=
_
(
'Logs'
)
-
if
project_nav_tab?
:environments
=
render
"layouts/nav/sidebar/tracing_link"
-
if
project_nav_tab?
(
:error_tracking
)
=
nav_link
(
controller: :error_tracking
)
do
=
link_to
project_error_tracking_index_path
(
@project
),
title:
_
(
'Error Tracking'
)
do
%span
=
_
(
'Error Tracking'
)
-
if
project_nav_tab?
(
:alert_management
)
=
nav_link
(
controller: :alert_management
)
do
=
link_to
project_alert_management_index_path
(
@project
),
title:
_
(
'Alerts'
)
do
%span
=
_
(
'Alerts'
)
-
if
project_nav_tab?
(
:incidents
)
=
nav_link
(
controller: :incidents
)
do
=
link_to
project_incidents_path
(
@project
),
title:
_
(
'Incidents'
),
data:
{
qa_selector:
'operations_incidents_link'
}
do
%span
=
_
(
'Incidents'
)
=
render_if_exists
'projects/sidebar/oncall_schedules'
-
if
project_nav_tab?
:serverless
=
nav_link
(
controller: :functions
)
do
=
link_to
project_serverless_functions_path
(
@project
),
title:
_
(
'Serverless'
)
do
%span
=
_
(
'Serverless'
)
-
if
project_nav_tab?
:terraform
=
nav_link
(
controller: :terraform
)
do
=
link_to
project_terraform_index_path
(
@project
),
title:
_
(
'Terraform'
)
do
%span
=
_
(
'Terraform'
)
-
if
project_nav_tab?
:clusters
-
show_cluster_hint
=
show_gke_cluster_integration_callout?
(
@project
)
=
nav_link
(
controller:
[
:cluster_agents
,
:clusters
])
do
=
link_to
project_clusters_path
(
@project
),
title:
_
(
'Kubernetes'
),
class:
'shortcuts-kubernetes'
do
%span
=
_
(
'Kubernetes'
)
-
if
show_cluster_hint
.js-feature-highlight
{
disabled:
true
,
data:
{
trigger:
'manual'
,
container:
'body'
,
placement:
'right'
,
highlight:
UserCalloutsHelper
::
GKE_CLUSTER_INTEGRATION
,
highlight_priority:
UserCallout
.
feature_names
[
:GKE_CLUSTER_INTEGRATION
],
dismiss_endpoint:
user_callouts_path
,
auto_devops_help_path:
help_page_path
(
'topics/autodevops/index.md'
)
}
}
-
if
project_nav_tab?
:environments
=
nav_link
(
controller: :environments
,
action:
[
:index
,
:folder
,
:show
,
:new
,
:edit
,
:create
,
:update
,
:stop
,
:terminal
])
do
=
link_to
project_environments_path
(
@project
),
title:
_
(
'Environments'
),
class:
'shortcuts-environments qa-operations-environments-link'
do
%span
=
_
(
'Environments'
)
-
if
project_nav_tab?
:feature_flags
=
nav_link
(
controller: :feature_flags
)
do
=
link_to
project_feature_flags_path
(
@project
),
title:
_
(
'Feature Flags'
),
class:
'shortcuts-feature-flags'
do
%span
=
_
(
'Feature Flags'
)
-
if
project_nav_tab?
(
:product_analytics
)
=
nav_link
(
controller: :product_analytics
)
do
=
link_to
project_product_analytics_path
(
@project
),
title:
_
(
'Product Analytics'
)
do
%span
=
_
(
'Product Analytics'
)
=
render_if_exists
'layouts/nav/sidebar/project_packages_link'
-
if
project_nav_tab?
:analytics
...
...
app/views/layouts/nav/sidebar/_tracing_link.html.haml
deleted
100644 → 0
View file @
08344e29
-
return
unless
can?
(
current_user
,
:read_environment
,
@project
)
-
if
project_nav_tab?
:settings
=
nav_link
(
controller: :tracings
,
action:
[
:show
])
do
=
link_to
project_tracing_path
(
@project
),
title:
_
(
'Tracing'
)
do
%span
=
_
(
'Tracing'
)
ee/app/helpers/ee/projects_helper.rb
View file @
087d90af
...
...
@@ -302,12 +302,5 @@ module EE
}
}
end
override
:view_operations_tab_ability
def
view_operations_tab_ability
super
+
[
:read_incident_management_oncall_schedule
]
end
end
end
ee/app/views/projects/sidebar/_oncall_schedules.html.haml
deleted
100644 → 0
View file @
08344e29
-
return
unless
project_nav_tab?
:oncall_schedule
=
nav_link
(
controller: :oncall_schedules
)
do
=
link_to
project_incident_management_oncall_schedules_path
(
@project
),
title:
_
(
'On-call Schedules'
)
do
%span
=
_
(
'On-call Schedules'
)
ee/lib/ee/sidebars/projects/menus/operations_menu.rb
0 → 100644
View file @
087d90af
# frozen_string_literal: true
module
EE
module
Sidebars
module
Projects
module
Menus
module
OperationsMenu
extend
::
Gitlab
::
Utils
::
Override
override
:configure_menu_items
def
configure_menu_items
return
false
unless
super
insert_item_after
(
:incidents
,
on_call_schedules_menu_item
)
true
end
private
def
on_call_schedules_menu_item
return
unless
can?
(
context
.
current_user
,
:read_incident_management_oncall_schedule
,
context
.
project
)
::
Sidebars
::
MenuItem
.
new
(
title:
_
(
'On-call Schedules'
),
link:
project_incident_management_oncall_schedules_path
(
context
.
project
),
active_routes:
{
controller: :oncall_schedules
},
item_id: :on_call_schedules
)
end
end
end
end
end
end
ee/spec/helpers/projects_helper_spec.rb
View file @
087d90af
...
...
@@ -209,41 +209,6 @@ RSpec.describe ProjectsHelper do
end
end
describe
'#get_project_nav_tabs'
do
using
RSpec
::
Parameterized
::
TableSyntax
let_it_be
(
:user
)
{
create
(
:user
)
}
subject
{
helper
.
get_project_nav_tabs
(
project
,
user
)
}
before
do
allow
(
helper
).
to
receive
(
:current_user
).
and_return
(
user
)
allow
(
helper
).
to
receive
(
:can?
).
and_return
(
false
)
allow
(
helper
).
to
receive
(
:can?
).
with
(
user
,
ability
,
project
).
and_return
(
feature_available?
)
end
describe
'tabs'
do
where
(
:ability
,
:nav_tabs
)
do
:read_feature_flag
|
[
:operations
]
:read_incident_management_oncall_schedule
|
[
:oncall_schedule
]
end
with_them
do
context
'when the feature is available'
do
let
(
:feature_available?
)
{
true
}
it
{
is_expected
.
to
include
(
*
nav_tabs
)
}
end
context
'when the feature is not available'
do
let
(
:feature_available?
)
{
false
}
it
{
is_expected
.
not_to
include
(
*
nav_tabs
)
}
end
end
end
end
describe
'#show_discover_project_security?'
do
using
RSpec
::
Parameterized
::
TableSyntax
...
...
@@ -308,40 +273,6 @@ RSpec.describe ProjectsHelper do
end
end
describe
'#can_view_operations_tab?'
do
let_it_be
(
:user
)
{
create
(
:user
)
}
before
do
allow
(
helper
).
to
receive
(
:current_user
).
and_return
(
user
)
allow
(
helper
).
to
receive
(
:can?
).
and_return
(
false
)
end
subject
{
helper
.
send
(
:can_view_operations_tab?
,
user
,
project
)
}
where
(
:ability
)
do
[
:read_incident_management_oncall_schedule
]
end
with_them
do
it
'includes operations tab'
do
allow
(
helper
).
to
receive
(
:can?
).
with
(
user
,
ability
,
project
).
and_return
(
true
)
is_expected
.
to
be
(
true
)
end
context
'when operations feature is disabled'
do
it
'does not include operations tab'
do
allow
(
helper
).
to
receive
(
:can?
).
with
(
user
,
ability
,
project
).
and_return
(
true
)
project
.
project_feature
.
update_attribute
(
:operations_access_level
,
ProjectFeature
::
DISABLED
)
is_expected
.
to
be
(
false
)
end
end
end
end
describe
'#project_permissions_settings'
do
using
RSpec
::
Parameterized
::
TableSyntax
...
...
ee/spec/lib/ee/sidebars/projects/menus/operations_menu_spec.rb
0 → 100644
View file @
087d90af
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Sidebars
::
Projects
::
Menus
::
OperationsMenu
do
let
(
:project
)
{
build
(
:project
)
}
let
(
:user
)
{
project
.
owner
}
let
(
:context
)
{
Sidebars
::
Projects
::
Context
.
new
(
current_user:
user
,
container:
project
,
show_cluster_hint:
true
)
}
describe
'On-call Schedules'
do
subject
{
described_class
.
new
(
context
).
items
.
index
{
|
e
|
e
.
item_id
==
:on_call_schedules
}
}
before
do
stub_licensed_features
(
oncall_schedules:
true
)
end
specify
{
is_expected
.
not_to
be_nil
}
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
specify
{
is_expected
.
to
be_nil
}
end
end
end
ee/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
View file @
087d90af
...
...
@@ -180,41 +180,6 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end
end
describe
'Operations > Pod logs'
do
before
do
allow
(
view
).
to
receive
(
:can?
).
with
(
nil
,
:read_environment
,
project
).
and_return
(
can_read_environment
)
allow
(
view
).
to
receive
(
:can?
).
with
(
nil
,
:read_pod_logs
,
project
).
and_return
(
can_read_pod_logs
)
render
end
describe
'when the user can read environments and logs'
do
let
(
:can_read_environment
)
{
true
}
let
(
:can_read_pod_logs
)
{
true
}
it
'link is visible'
do
expect
(
rendered
).
to
have_link
(
'Logs'
,
href:
project_logs_path
(
project
))
end
end
describe
'when the user cannot read environment or logs'
do
let
(
:can_read_environment
)
{
false
}
let
(
:can_read_pod_logs
)
{
false
}
it
'link is not visible'
do
expect
(
rendered
).
not_to
have_link
'Logs'
end
end
describe
'when the user can read environment but not logs'
do
let
(
:can_read_environment
)
{
true
}
let
(
:can_read_pod_logs
)
{
false
}
it
'link is not visible'
do
expect
(
rendered
).
not_to
have_link
'Logs'
end
end
end
describe
'Security and Compliance'
do
describe
'when user does not have permissions'
do
before
do
...
...
@@ -296,6 +261,31 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end
end
describe
'Operations'
do
describe
'On-call schedules'
do
before
do
allow
(
view
).
to
receive
(
:current_user
).
and_return
(
user
)
stub_licensed_features
(
oncall_schedules:
true
)
end
it
'has a link to the on-call schedules page'
do
render
expect
(
rendered
).
to
have_link
(
'On-call Schedules'
,
href:
project_incident_management_oncall_schedules_path
(
project
))
end
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
it
'does not have a link to the on-call schedules page'
do
render
expect
(
rendered
).
not_to
have_link
(
'On-call Schedules'
)
end
end
end
end
describe
'Settings > Operations'
do
it
'is not visible when no valid license'
do
allow
(
view
).
to
receive
(
:can?
).
and_return
(
true
)
...
...
lib/sidebars/projects/menus/operations_menu.rb
0 → 100644
View file @
087d90af
# frozen_string_literal: true
module
Sidebars
module
Projects
module
Menus
class
OperationsMenu
<
::
Sidebars
::
Menu
override
:configure_menu_items
def
configure_menu_items
return
false
unless
context
.
project
.
feature_available?
(
:operations
,
context
.
current_user
)
add_item
(
metrics_dashboard_menu_item
)
add_item
(
logs_menu_item
)
add_item
(
tracing_menu_item
)
add_item
(
error_tracking_menu_item
)
add_item
(
alert_management_menu_item
)
add_item
(
incidents_menu_item
)
add_item
(
serverless_menu_item
)
add_item
(
terraform_menu_item
)
add_item
(
kubernetes_menu_item
)
add_item
(
environments_menu_item
)
add_item
(
feature_flags_menu_item
)
add_item
(
product_analytics_menu_item
)
true
end
override
:link
def
link
if
can?
(
context
.
current_user
,
:read_environment
,
context
.
project
)
metrics_project_environments_path
(
context
.
project
)
else
project_feature_flags_path
(
context
.
project
)
end
end
override
:extra_container_html_options
def
extra_container_html_options
{
class:
'shortcuts-operations'
}
end
override
:title
def
title
_
(
'Operations'
)
end
override
:sprite_icon
def
sprite_icon
'cloud-gear'
end
override
:active_routes
def
active_routes
{
controller:
[
:user
,
:gcp
]
}
end
private
def
metrics_dashboard_menu_item
return
unless
can?
(
context
.
current_user
,
:metrics_dashboard
,
context
.
project
)
::
Sidebars
::
MenuItem
.
new
(
title:
_
(
'Metrics'
),
link:
project_metrics_dashboard_path
(
context
.
project
),
active_routes:
{
path:
'metrics_dashboard#show'
},
container_html_options:
{
class:
'shortcuts-metrics'
},
item_id: :metrics
)
end
def
logs_menu_item
return
unless
can?
(
context
.
current_user
,
:read_environment
,
context
.
project
)
return
unless
can?
(
context
.
current_user
,
:read_pod_logs
,
context
.
project
)
::
Sidebars
::
MenuItem
.
new
(
title:
_
(
'Logs'
),
link:
project_logs_path
(
context
.
project
),
active_routes:
{
path:
'logs#index'
},
item_id: :logs
)
end
def
tracing_menu_item
return
unless
can?
(
context
.
current_user
,
:read_environment
,
context
.
project
)
return
unless
can?
(
context
.
current_user
,
:admin_project
,
context
.
project
)
::
Sidebars
::
MenuItem
.
new
(
title:
_
(
'Tracing'
),
link:
project_tracing_path
(
context
.
project
),
active_routes:
{
path:
'tracings#show'
},
item_id: :tracing
)
end
def
error_tracking_menu_item
return
unless
can?
(
context
.
current_user
,
:read_sentry_issue
,
context
.
project
)
::
Sidebars
::
MenuItem
.
new
(
title:
_
(
'Error Tracking'
),
link:
project_error_tracking_index_path
(
context
.
project
),
active_routes:
{
controller: :error_tracking
},
item_id: :error_tracking
)
end
def
alert_management_menu_item
return
unless
can?
(
context
.
current_user
,
:read_alert_management_alert
,
context
.
project
)
::
Sidebars
::
MenuItem
.
new
(
title:
_
(
'Alerts'
),
link:
project_alert_management_index_path
(
context
.
project
),
active_routes:
{
controller: :alert_management
},
item_id: :alert_management
)
end
def
incidents_menu_item
return
unless
can?
(
context
.
current_user
,
:read_issue
,
context
.
project
)
::
Sidebars
::
MenuItem
.
new
(
title:
_
(
'Incidents'
),
link:
project_incidents_path
(
context
.
project
),
active_routes:
{
controller:
[
:incidents
,
:incident_management
]
},
item_id: :incidents
)
end
def
serverless_menu_item
return
unless
can?
(
context
.
current_user
,
:read_cluster
,
context
.
project
)
::
Sidebars
::
MenuItem
.
new
(
title:
_
(
'Serverless'
),
link:
project_serverless_functions_path
(
context
.
project
),
active_routes:
{
controller: :functions
},
item_id: :serverless
)
end
def
terraform_menu_item
return
unless
can?
(
context
.
current_user
,
:read_terraform_state
,
context
.
project
)
::
Sidebars
::
MenuItem
.
new
(
title:
_
(
'Terraform'
),
link:
project_terraform_index_path
(
context
.
project
),
active_routes:
{
controller: :terraform
},
item_id: :terraform
)
end
def
kubernetes_menu_item
return
unless
can?
(
context
.
current_user
,
:read_cluster
,
context
.
project
)
::
Sidebars
::
MenuItem
.
new
(
title:
_
(
'Kubernetes'
),
link:
project_clusters_path
(
context
.
project
),
active_routes:
{
controller:
[
:cluster_agents
,
:clusters
]
},
container_html_options:
{
class:
'shortcuts-kubernetes'
},
hint_html_options:
kubernetes_hint_html_options
,
item_id: :kubernetes
)
end
def
kubernetes_hint_html_options
return
{}
unless
context
.
show_cluster_hint
{
disabled:
true
,
data:
{
trigger:
'manual'
,
container:
'body'
,
placement:
'right'
,
highlight:
UserCalloutsHelper
::
GKE_CLUSTER_INTEGRATION
,
highlight_priority:
UserCallout
.
feature_names
[
:GKE_CLUSTER_INTEGRATION
],
dismiss_endpoint:
user_callouts_path
,
auto_devops_help_path:
help_page_path
(
'topics/autodevops/index.md'
)
}
}
end
def
environments_menu_item
return
unless
can?
(
context
.
current_user
,
:read_environment
,
context
.
project
)
::
Sidebars
::
MenuItem
.
new
(
title:
_
(
'Environments'
),
link:
project_environments_path
(
context
.
project
),
active_routes:
{
controller: :environments
},
container_html_options:
{
class:
'shortcuts-environments'
},
item_id: :environments
)
end
def
feature_flags_menu_item
return
unless
can?
(
context
.
current_user
,
:read_feature_flag
,
context
.
project
)
::
Sidebars
::
MenuItem
.
new
(
title:
_
(
'Feature Flags'
),
link:
project_feature_flags_path
(
context
.
project
),
active_routes:
{
controller: :feature_flags
},
container_html_options:
{
class:
'shortcuts-feature-flags'
},
item_id: :feature_flags
)
end
def
product_analytics_menu_item
return
if
Feature
.
disabled?
(
:product_analytics
,
context
.
project
)
return
unless
can?
(
context
.
current_user
,
:read_product_analytics
,
context
.
project
)
::
Sidebars
::
MenuItem
.
new
(
title:
_
(
'Product Analytics'
),
link:
project_product_analytics_path
(
context
.
project
),
active_routes:
{
controller: :product_analytics
},
item_id: :product_analytics
)
end
end
end
end
end
Sidebars
::
Projects
::
Menus
::
OperationsMenu
.
prepend_if_ee
(
'EE::Sidebars::Projects::Menus::OperationsMenu'
)
lib/sidebars/projects/panel.rb
View file @
087d90af
...
...
@@ -16,6 +16,7 @@ module Sidebars
add_menu
(
Sidebars
::
Projects
::
Menus
::
MergeRequestsMenu
.
new
(
context
))
add_menu
(
Sidebars
::
Projects
::
Menus
::
CiCdMenu
.
new
(
context
))
add_menu
(
Sidebars
::
Projects
::
Menus
::
SecurityComplianceMenu
.
new
(
context
))
add_menu
(
Sidebars
::
Projects
::
Menus
::
OperationsMenu
.
new
(
context
))
end
override
:render_raw_menus_partial
...
...
qa/qa/page/project/sub_menus/operations.rb
View file @
087d90af
...
...
@@ -12,20 +12,13 @@ module QA
base
.
class_eval
do
include
QA
::
Page
::
Project
::
SubMenus
::
Common
view
'app/views/layouts/nav/sidebar/_project_menus.html.haml'
do
element
:operations_link
element
:operations_environments_link
element
:operations_metrics_link
element
:operations_incidents_link
end
end
end
def
go_to_operations_environments
hover_operations
do
within_submenu
do
click_element
(
:
operations_environments_link
)
click_element
(
:
sidebar_menu_item_link
,
menu_item:
'Environments'
)
end
end
end
...
...
@@ -33,7 +26,7 @@ module QA
def
go_to_operations_metrics
hover_operations
do
within_submenu
do
click_element
(
:
operations_metrics_link
)
click_element
(
:
sidebar_menu_item_link
,
menu_item:
'Metrics'
)
end
end
end
...
...
@@ -49,7 +42,7 @@ module QA
def
go_to_operations_incidents
hover_operations
do
within_submenu
do
click_element
(
:
operations_incidents_link
)
click_element
(
:
sidebar_menu_item_link
,
menu_item:
'Incidents'
)
end
end
end
...
...
@@ -58,8 +51,8 @@ module QA
def
hover_operations
within_sidebar
do
scroll_to_element
(
:
operations_link
)
find_element
(
:
operations_link
).
hover
scroll_to_element
(
:
sidebar_menu_link
,
menu_item:
'Operations'
)
find_element
(
:
sidebar_menu_link
,
menu_item:
'Operations'
).
hover
yield
end
...
...
spec/features/operations_sidebar_link_spec.rb
View file @
087d90af
This diff is collapsed.
Click to expand it.
spec/helpers/projects_helper_spec.rb
View file @
087d90af
...
...
@@ -477,43 +477,6 @@ RSpec.describe ProjectsHelper do
end
end
describe
'#can_view_operations_tab?'
do
before
do
allow
(
helper
).
to
receive
(
:current_user
).
and_return
(
user
)
allow
(
helper
).
to
receive
(
:can?
).
and_return
(
false
)
end
subject
{
helper
.
send
(
:can_view_operations_tab?
,
user
,
project
)
}
where
(
:ability
)
do
[
:metrics_dashboard
,
:read_alert_management_alert
,
:read_environment
,
:read_issue
,
:read_sentry_issue
,
:read_cluster
]
end
with_them
do
it
'includes operations tab'
do
allow
(
helper
).
to
receive
(
:can?
).
with
(
user
,
ability
,
project
).
and_return
(
true
)
is_expected
.
to
be
(
true
)
end
context
'when operations feature is disabled'
do
it
'does not include operations tab'
do
allow
(
helper
).
to
receive
(
:can?
).
with
(
user
,
ability
,
project
).
and_return
(
true
)
project
.
project_feature
.
update_attribute
(
:operations_access_level
,
ProjectFeature
::
DISABLED
)
is_expected
.
to
be
(
false
)
end
end
end
end
describe
'#show_projects'
do
let
(
:projects
)
do
Project
.
all
...
...
spec/lib/sidebars/projects/menus/operations_menu_spec.rb
0 → 100644
View file @
087d90af
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Sidebars
::
Projects
::
Menus
::
OperationsMenu
do
let_it_be_with_refind
(
:project
)
{
create
(
:project
)
}
let
(
:user
)
{
project
.
owner
}
let
(
:show_cluster_hint
)
{
true
}
let
(
:context
)
{
Sidebars
::
Projects
::
Context
.
new
(
current_user:
user
,
container:
project
,
show_cluster_hint:
show_cluster_hint
)
}
subject
{
described_class
.
new
(
context
)
}
describe
'#render?'
do
context
'when operations feature is disabled'
do
it
'returns false'
do
project
.
project_feature
.
update!
(
operations_access_level:
Featurable
::
DISABLED
)
expect
(
subject
.
render?
).
to
be
false
end
end
context
'when operation feature is enabled'
do
context
'when menu does not have any menu items'
do
it
'returns false'
do
allow
(
subject
).
to
receive
(
:has_items?
).
and_return
(
false
)
expect
(
subject
.
render?
).
to
be
false
end
end
context
'when menu has menu items'
do
it
'returns true'
do
expect
(
subject
.
render?
).
to
be
true
end
end
end
end
describe
'#link'
do
context
'when metrics dashboard is visible'
do
it
'returns link to the metrics dashboard page'
do
expect
(
subject
.
link
).
to
include
(
'/-/environments/metrics'
)
end
end
context
'when metrics dashboard is not visible'
do
it
'returns link to the feature flags page'
do
project
.
project_feature
.
update!
(
operations_access_level:
Featurable
::
DISABLED
)
expect
(
subject
.
link
).
to
include
(
'/-/feature_flags'
)
end
end
end
context
'Menu items'
do
subject
{
described_class
.
new
(
context
).
items
.
index
{
|
e
|
e
.
item_id
==
item_id
}
}
describe
'Metrics Dashboard'
do
let
(
:item_id
)
{
:metrics
}
specify
{
is_expected
.
not_to
be_nil
}
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
specify
{
is_expected
.
to
be_nil
}
end
end
describe
'Logs'
do
let
(
:item_id
)
{
:logs
}
specify
{
is_expected
.
not_to
be_nil
}
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
specify
{
is_expected
.
to
be_nil
}
end
end
describe
'Tracing'
do
let
(
:item_id
)
{
:tracing
}
specify
{
is_expected
.
not_to
be_nil
}
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
specify
{
is_expected
.
to
be_nil
}
end
end
describe
'Error Tracking'
do
let
(
:item_id
)
{
:error_tracking
}
specify
{
is_expected
.
not_to
be_nil
}
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
specify
{
is_expected
.
to
be_nil
}
end
end
describe
'Alert Management'
do
let
(
:item_id
)
{
:alert_management
}
specify
{
is_expected
.
not_to
be_nil
}
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
specify
{
is_expected
.
to
be_nil
}
end
end
describe
'Incidents'
do
let
(
:item_id
)
{
:incidents
}
specify
{
is_expected
.
not_to
be_nil
}
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
specify
{
is_expected
.
to
be_nil
}
end
end
describe
'Serverless'
do
let
(
:item_id
)
{
:serverless
}
specify
{
is_expected
.
not_to
be_nil
}
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
specify
{
is_expected
.
to
be_nil
}
end
end
describe
'Terraform'
do
let
(
:item_id
)
{
:terraform
}
specify
{
is_expected
.
not_to
be_nil
}
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
specify
{
is_expected
.
to
be_nil
}
end
end
describe
'Kubernetes'
do
let
(
:item_id
)
{
:kubernetes
}
specify
{
is_expected
.
not_to
be_nil
}
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
specify
{
is_expected
.
to
be_nil
}
end
end
describe
'Environments'
do
let
(
:item_id
)
{
:environments
}
specify
{
is_expected
.
not_to
be_nil
}
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
specify
{
is_expected
.
to
be_nil
}
end
end
describe
'Feature Flags'
do
let
(
:item_id
)
{
:feature_flags
}
specify
{
is_expected
.
not_to
be_nil
}
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
specify
{
is_expected
.
to
be_nil
}
end
end
describe
'Product Analytics'
do
let
(
:item_id
)
{
:product_analytics
}
specify
{
is_expected
.
not_to
be_nil
}
describe
'when feature flag :product_analytics is disabled'
do
specify
do
stub_feature_flags
(
product_analytics:
false
)
is_expected
.
to
be_nil
end
end
end
end
end
spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb
View file @
087d90af
...
...
@@ -348,6 +348,238 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end
end
describe
'Operations'
do
it
'top level navigation link is visible for user with permissions'
do
render
expect
(
rendered
).
to
have_link
(
'Operations'
)
end
describe
'Metrics Dashboard'
do
it
'has a link to the metrics dashboard page'
do
render
expect
(
rendered
).
to
have_link
(
'Metrics'
,
href:
project_metrics_dashboard_path
(
project
))
end
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
it
'does not have a link to the metrics page'
do
render
expect
(
rendered
).
not_to
have_link
(
'Metrics'
)
end
end
end
describe
'Logs'
do
it
'has a link to the pod logs page'
do
render
expect
(
rendered
).
to
have_link
(
'Logs'
,
href:
project_logs_path
(
project
))
end
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
it
'does not have a link to the pod logs page'
do
render
expect
(
rendered
).
not_to
have_link
(
'Logs'
)
end
end
end
describe
'Tracing'
do
it
'has a link to the tracing page'
do
render
expect
(
rendered
).
to
have_link
(
'Tracing'
,
href:
project_tracing_path
(
project
))
end
context
'without project.tracing_external_url'
do
it
'has a link to the tracing page'
do
render
expect
(
rendered
).
to
have_link
(
'Tracing'
,
href:
project_tracing_path
(
project
))
end
end
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
it
'does not have a link to the tracing page'
do
render
expect
(
rendered
).
not_to
have_text
'Tracing'
end
end
end
describe
'Error Tracking'
do
it
'has a link to the error tracking page'
do
render
expect
(
rendered
).
to
have_link
(
'Error Tracking'
,
href:
project_error_tracking_index_path
(
project
))
end
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
it
'does not have a link to the error tracking page'
do
render
expect
(
rendered
).
not_to
have_link
(
'Error Tracking'
)
end
end
end
describe
'Alert Management'
do
it
'has a link to the alert management page'
do
render
expect
(
rendered
).
to
have_link
(
'Alerts'
,
href:
project_alert_management_index_path
(
project
))
end
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
it
'does not have a link to the alert management page'
do
render
expect
(
rendered
).
not_to
have_link
(
'Alerts'
)
end
end
end
describe
'Incidents'
do
it
'has a link to the incidents page'
do
render
expect
(
rendered
).
to
have_link
(
'Incidents'
,
href:
project_incidents_path
(
project
))
end
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
it
'does not have a link to the incidents page'
do
render
expect
(
rendered
).
not_to
have_link
(
'Incidents'
)
end
end
end
describe
'Serverless'
do
it
'has a link to the serverless page'
do
render
expect
(
rendered
).
to
have_link
(
'Serverless'
,
href:
project_serverless_functions_path
(
project
))
end
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
it
'does not have a link to the serverless page'
do
render
expect
(
rendered
).
not_to
have_link
(
'Serverless'
)
end
end
end
describe
'Terraform'
do
it
'has a link to the terraform page'
do
render
expect
(
rendered
).
to
have_link
(
'Terraform'
,
href:
project_terraform_index_path
(
project
))
end
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
it
'does not have a link to the terraform page'
do
render
expect
(
rendered
).
not_to
have_link
(
'Terraform'
)
end
end
end
describe
'Kubernetes'
do
it
'has a link to the kubernetes page'
do
render
expect
(
rendered
).
to
have_link
(
'Kubernetes'
,
href:
project_clusters_path
(
project
))
end
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
it
'does not have a link to the kubernetes page'
do
render
expect
(
rendered
).
not_to
have_link
(
'Kubernetes'
)
end
end
end
describe
'Environments'
do
it
'has a link to the environments page'
do
render
expect
(
rendered
).
to
have_link
(
'Environments'
,
href:
project_environments_path
(
project
))
end
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
it
'does not have a link to the environments page'
do
render
expect
(
rendered
).
not_to
have_link
(
'Environments'
)
end
end
end
describe
'Feature Flags'
do
it
'has a link to the feature flags page'
do
render
expect
(
rendered
).
to
have_link
(
'Feature Flags'
,
href:
project_feature_flags_path
(
project
))
end
describe
'when the user does not have access'
do
let
(
:user
)
{
nil
}
it
'does not have a link to the feature flags page'
do
render
expect
(
rendered
).
not_to
have_link
(
'Feature Flags'
)
end
end
end
describe
'Product Analytics'
do
it
'has a link to the product analytics page'
do
render
expect
(
rendered
).
to
have_link
(
'Product Analytics'
,
href:
project_product_analytics_path
(
project
))
end
describe
'when feature flag :product_analytics is disabled'
do
it
'does not have a link to the feature flags page'
do
stub_feature_flags
(
product_analytics:
false
)
render
expect
(
rendered
).
not_to
have_link
(
'Product Analytics'
)
end
end
end
end
describe
'packages tab'
do
before
do
stub_container_registry_config
(
enabled:
true
)
...
...
@@ -510,6 +742,32 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end
end
describe
'value stream analytics entry'
do
let
(
:read_cycle_analytics
)
{
true
}
before
do
allow
(
view
).
to
receive
(
:can?
).
with
(
user
,
:read_cycle_analytics
,
project
).
and_return
(
read_cycle_analytics
)
end
describe
'when value stream analytics is enabled'
do
it
'shows the value stream analytics entry'
do
render
expect
(
rendered
).
to
have_link
(
'Value Stream'
,
href:
project_cycle_analytics_path
(
project
))
end
end
describe
'when value stream analytics is disabled'
do
let
(
:read_cycle_analytics
)
{
false
}
it
'does not show the value stream analytics entry'
do
render
expect
(
rendered
).
not_to
have_link
(
'Value Stream'
,
href:
project_cycle_analytics_path
(
project
))
end
end
end
describe
'operations settings tab'
do
describe
'archive projects'
do
before
do
...
...
@@ -536,64 +794,6 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end
end
end
describe
'Tracing'
do
it
'is not visible to unauthorized user'
do
allow
(
view
).
to
receive
(
:can?
).
and_return
(
false
)
render
expect
(
rendered
).
not_to
have_text
'Tracing'
end
it
'links to Tracing page'
do
render
expect
(
rendered
).
to
have_link
(
'Tracing'
,
href:
project_tracing_path
(
project
))
end
context
'without project.tracing_external_url'
do
it
'links to Tracing page'
do
render
expect
(
rendered
).
to
have_link
(
'Tracing'
,
href:
project_tracing_path
(
project
))
end
end
end
describe
'Alert Management'
do
it
'shows the Alerts sidebar entry'
do
render
expect
(
rendered
).
to
have_css
(
'a[title="Alerts"]'
)
end
end
end
describe
'value stream analytics entry'
do
let
(
:read_cycle_analytics
)
{
true
}
before
do
allow
(
view
).
to
receive
(
:can?
).
with
(
user
,
:read_cycle_analytics
,
project
).
and_return
(
read_cycle_analytics
)
end
describe
'when value stream analytics is enabled'
do
it
'shows the value stream analytics entry'
do
render
expect
(
rendered
).
to
have_link
(
'Value Stream'
,
href:
project_cycle_analytics_path
(
project
))
end
end
describe
'when value stream analytics is disabled'
do
let
(
:read_cycle_analytics
)
{
false
}
it
'does not show the value stream analytics entry'
do
render
expect
(
rendered
).
not_to
have_link
(
'Value Stream'
,
href:
project_cycle_analytics_path
(
project
))
end
end
end
describe
'project access tokens'
do
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment