Commit 231bdc20 authored by Rémy Coutable's avatar Rémy Coutable

Merge remote-tracking branch 'origin/master' into ce-to-ee-2017-09-13

Signed-off-by: default avatarRémy Coutable <remy@rymai.me>
parents 241d61fc e4aeca5e
...@@ -15,7 +15,6 @@ export default class NewNavSidebar { ...@@ -15,7 +15,6 @@ export default class NewNavSidebar {
this.$openSidebar = $('.toggle-mobile-nav'); this.$openSidebar = $('.toggle-mobile-nav');
this.$closeSidebar = $('.close-nav-button'); this.$closeSidebar = $('.close-nav-button');
this.$sidebarToggle = $('.js-toggle-sidebar'); this.$sidebarToggle = $('.js-toggle-sidebar');
this.$topLevelLinks = $('.sidebar-top-level-items > li > a');
} }
bindEvents() { bindEvents() {
...@@ -56,10 +55,6 @@ export default class NewNavSidebar { ...@@ -56,10 +55,6 @@ export default class NewNavSidebar {
this.$page.toggleClass('page-with-icon-sidebar', breakpoint === 'sm' ? true : collapsed); this.$page.toggleClass('page-with-icon-sidebar', breakpoint === 'sm' ? true : collapsed);
} }
NewNavSidebar.setCollapsedCookie(collapsed); NewNavSidebar.setCollapsedCookie(collapsed);
this.$topLevelLinks.attr('title', function updateTopLevelTitle() {
return collapsed ? this.getAttribute('aria-label') : '';
});
} }
render() { render() {
......
...@@ -119,8 +119,4 @@ module TabHelper ...@@ -119,8 +119,4 @@ module TabHelper
'active' if current_controller?('oauth/applications') 'active' if current_controller?('oauth/applications')
end end
def sidebar_link(href, title: nil, css: nil, &block)
link_to capture(&block), href, title: (title if collapsed_sidebar?), class: css, aria: { label: title }
end
end end
...@@ -15,7 +15,9 @@ class GeoNodeStatus ...@@ -15,7 +15,9 @@ class GeoNodeStatus
end end
def db_replication_lag def db_replication_lag
@db_replication_lag ||= Gitlab::Geo::HealthCheck.db_replication_lag return @db_replication_lag if defined?(@db_replication_lag)
@db_replication_lag = Gitlab::Geo::HealthCheck.db_replication_lag if Gitlab::Geo.secondary?
end end
def db_replication_lag=(value) def db_replication_lag=(value)
...@@ -39,7 +41,9 @@ class GeoNodeStatus ...@@ -39,7 +41,9 @@ class GeoNodeStatus
end end
def cursor_last_event_id def cursor_last_event_id
@cursor_last_event_id ||= cursor_last_processed&.event_id return @cursor_last_event_id if defined?(@cursor_last_event_id)
@cursor_last_event_id = cursor_last_processed&.event_id if Gitlab::Geo.secondary?
end end
def cursor_last_event_id=(value) def cursor_last_event_id=(value)
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
.sidebar-context-title Admin Area .sidebar-context-title Admin Area
%ul.sidebar-top-level-items %ul.sidebar-top-level-items
= nav_link(controller: %w(dashboard admin projects users groups jobs runners cohorts conversational_development_index), html_options: {class: 'home'}) do = nav_link(controller: %w(dashboard admin projects users groups jobs runners cohorts conversational_development_index), html_options: {class: 'home'}) do
= sidebar_link admin_root_path, title: _('Overview'), css: 'shortcuts-tree' do = link_to admin_root_path, class: 'shortcuts-tree' do
.nav-icon-container .nav-icon-container
= custom_icon('overview') = custom_icon('overview')
%span.nav-item-name %span.nav-item-name
...@@ -52,8 +52,8 @@ ...@@ -52,8 +52,8 @@
%span %span
ConvDev Index ConvDev Index
= nav_link(controller: %w(conversational_development_index system_info background_jobs logs health_check requests_profiles audit_logs)) do = nav_link(controller: %w(system_info background_jobs logs health_check requests_profiles audit_logs)) do
= sidebar_link admin_conversational_development_index_path, title: _('Monitoring') do = link_to admin_system_info_path do
.nav-icon-container .nav-icon-container
= custom_icon('monitoring') = custom_icon('monitoring')
%span.nav-item-name %span.nav-item-name
...@@ -88,7 +88,7 @@ ...@@ -88,7 +88,7 @@
= render 'layouts/nav/ee/new_admin_monitoring_sidebar' = render 'layouts/nav/ee/new_admin_monitoring_sidebar'
= nav_link(controller: :broadcast_messages) do = nav_link(controller: :broadcast_messages) do
= sidebar_link admin_broadcast_messages_path, title: _('Messages') do = link_to admin_broadcast_messages_path do
.nav-icon-container .nav-icon-container
= custom_icon('messages') = custom_icon('messages')
%span.nav-item-name %span.nav-item-name
...@@ -100,7 +100,7 @@ ...@@ -100,7 +100,7 @@
#{ _('Messages') } #{ _('Messages') }
= nav_link(controller: [:hooks, :hook_logs]) do = nav_link(controller: [:hooks, :hook_logs]) do
= sidebar_link admin_hooks_path, title: _('Hooks') do = link_to admin_hooks_path do
.nav-icon-container .nav-icon-container
= custom_icon('system_hooks') = custom_icon('system_hooks')
%span.nav-item-name %span.nav-item-name
...@@ -112,7 +112,7 @@ ...@@ -112,7 +112,7 @@
#{ _('System Hooks') } #{ _('System Hooks') }
= nav_link(controller: :applications) do = nav_link(controller: :applications) do
= sidebar_link admin_applications_path, title: _('Applications') do = link_to admin_applications_path do
.nav-icon-container .nav-icon-container
= custom_icon('applications') = custom_icon('applications')
%span.nav-item-name %span.nav-item-name
...@@ -124,7 +124,7 @@ ...@@ -124,7 +124,7 @@
#{ _('Applications') } #{ _('Applications') }
= nav_link(controller: :abuse_reports) do = nav_link(controller: :abuse_reports) do
= sidebar_link admin_abuse_reports_path, title: _("Abuse Reports") do = link_to admin_abuse_reports_path do
.nav-icon-container .nav-icon-container
= custom_icon('abuse_reports') = custom_icon('abuse_reports')
%span.nav-item-name %span.nav-item-name
...@@ -138,7 +138,7 @@ ...@@ -138,7 +138,7 @@
%span.badge.count.merge_counter.js-merge-counter.fly-out-badge= number_with_delimiter(AbuseReport.count(:all)) %span.badge.count.merge_counter.js-merge-counter.fly-out-badge= number_with_delimiter(AbuseReport.count(:all))
= nav_link(controller: :licenses) do = nav_link(controller: :licenses) do
= sidebar_link admin_license_path, title: _('License') do = link_to admin_license_path do
.nav-icon-container .nav-icon-container
= custom_icon('license') = custom_icon('license')
%span.nav-item-name %span.nav-item-name
...@@ -151,7 +151,7 @@ ...@@ -151,7 +151,7 @@
- if akismet_enabled? - if akismet_enabled?
= nav_link(controller: :spam_logs) do = nav_link(controller: :spam_logs) do
= sidebar_link admin_spam_logs_path, title: _("Spam Logs") do = link_to admin_spam_logs_path do
.nav-icon-container .nav-icon-container
= custom_icon('spam_logs') = custom_icon('spam_logs')
%span.nav-item-name %span.nav-item-name
...@@ -163,7 +163,7 @@ ...@@ -163,7 +163,7 @@
#{ _('Spam Logs') } #{ _('Spam Logs') }
= nav_link(controller: :push_rules) do = nav_link(controller: :push_rules) do
= sidebar_link admin_push_rule_path, title: _('Push Rules') do = link_to admin_push_rule_path do
.nav-icon-container .nav-icon-container
= custom_icon('push_rules') = custom_icon('push_rules')
%span.nav-item-name %span.nav-item-name
...@@ -175,7 +175,7 @@ ...@@ -175,7 +175,7 @@
#{ _('Push Rules') } #{ _('Push Rules') }
= nav_link(controller: :geo_nodes) do = nav_link(controller: :geo_nodes) do
= sidebar_link admin_geo_nodes_path, title: _('Geo Nodes') do = link_to admin_geo_nodes_path do
.nav-icon-container .nav-icon-container
= custom_icon('geo_nodes') = custom_icon('geo_nodes')
%span.nav-item-name %span.nav-item-name
...@@ -187,7 +187,7 @@ ...@@ -187,7 +187,7 @@
#{ _('Geo Nodes') } #{ _('Geo Nodes') }
= nav_link(controller: :deploy_keys) do = nav_link(controller: :deploy_keys) do
= sidebar_link admin_deploy_keys_path, title: _('Deploy Keys') do = link_to admin_deploy_keys_path do
.nav-icon-container .nav-icon-container
= custom_icon('key') = custom_icon('key')
%span.nav-item-name %span.nav-item-name
...@@ -199,7 +199,7 @@ ...@@ -199,7 +199,7 @@
#{ _('Deploy Keys') } #{ _('Deploy Keys') }
= nav_link(controller: :services) do = nav_link(controller: :services) do
= sidebar_link admin_application_settings_services_path, title: _('Service Templates') do = link_to admin_application_settings_services_path do
.nav-icon-container .nav-icon-container
= custom_icon('service_templates') = custom_icon('service_templates')
%span.nav-item-name %span.nav-item-name
...@@ -211,7 +211,7 @@ ...@@ -211,7 +211,7 @@
#{ _('Service Templates') } #{ _('Service Templates') }
= nav_link(controller: :labels) do = nav_link(controller: :labels) do
= sidebar_link admin_labels_path, title: _('Labels') do = link_to admin_labels_path do
.nav-icon-container .nav-icon-container
= custom_icon('labels') = custom_icon('labels')
%span.nav-item-name %span.nav-item-name
...@@ -223,7 +223,7 @@ ...@@ -223,7 +223,7 @@
#{ _('Labels') } #{ _('Labels') }
= nav_link(controller: :appearances) do = nav_link(controller: :appearances) do
= sidebar_link admin_appearances_path, title: _('Appearances') do = link_to admin_appearances_path do
.nav-icon-container .nav-icon-container
= custom_icon('appearance') = custom_icon('appearance')
%span.nav-item-name %span.nav-item-name
...@@ -235,7 +235,7 @@ ...@@ -235,7 +235,7 @@
#{ _('Appearance') } #{ _('Appearance') }
= nav_link(controller: :application_settings) do = nav_link(controller: :application_settings) do
= sidebar_link admin_application_settings_path, title: _('Settings') do = link_to admin_application_settings_path do
.nav-icon-container .nav-icon-container
= custom_icon('settings') = custom_icon('settings')
%span.nav-item-name %span.nav-item-name
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
= @group.name = @group.name
%ul.sidebar-top-level-items %ul.sidebar-top-level-items
= nav_link(path: ['groups#show', 'groups#activity', 'groups#subgroups', 'analytics#show'], html_options: { class: 'home' }) do = nav_link(path: ['groups#show', 'groups#activity', 'groups#subgroups', 'analytics#show'], html_options: { class: 'home' }) do
= sidebar_link group_path(@group), title: _('Group overview') do = link_to group_path(@group) do
.nav-icon-container .nav-icon-container
= custom_icon('project') = custom_icon('project')
%span.nav-item-name %span.nav-item-name
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
Contribution Analytics Contribution Analytics
= nav_link(path: issues_sub_menu_items) do = nav_link(path: issues_sub_menu_items) do
= sidebar_link issues_group_path(@group), title: _('Issues') do = link_to issues_group_path(@group) do
.nav-icon-container .nav-icon-container
= custom_icon('issues') = custom_icon('issues')
%span.nav-item-name %span.nav-item-name
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,7 @@
Milestones Milestones
= nav_link(path: 'groups#merge_requests') do = nav_link(path: 'groups#merge_requests') do
= sidebar_link merge_requests_group_path(@group), title: _('Merge Requests') do = link_to merge_requests_group_path(@group) do
.nav-icon-container .nav-icon-container
= custom_icon('mr_bold') = custom_icon('mr_bold')
%span.nav-item-name %span.nav-item-name
...@@ -93,7 +93,7 @@ ...@@ -93,7 +93,7 @@
#{ _('Merge Requests') } #{ _('Merge Requests') }
%span.badge.count.merge_counter.js-merge-counter.fly-out-badge= number_with_delimiter(merge_requests.count) %span.badge.count.merge_counter.js-merge-counter.fly-out-badge= number_with_delimiter(merge_requests.count)
= nav_link(path: 'group_members#index') do = nav_link(path: 'group_members#index') do
= sidebar_link group_group_members_path(@group), title: _('Members') do = link_to group_group_members_path(@group) do
.nav-icon-container .nav-icon-container
= custom_icon('members') = custom_icon('members')
%span.nav-item-name %span.nav-item-name
...@@ -105,7 +105,7 @@ ...@@ -105,7 +105,7 @@
#{ _('Members') } #{ _('Members') }
- if current_user && can?(current_user, :admin_group, @group) - if current_user && can?(current_user, :admin_group, @group)
= nav_link(path: %w[groups#projects groups#edit ci_cd#show ldap_group_links#index hooks#index audit_events#index pipeline_quota#index]) do = nav_link(path: %w[groups#projects groups#edit ci_cd#show ldap_group_links#index hooks#index audit_events#index pipeline_quota#index]) do
= sidebar_link edit_group_path(@group), title: _('Settings') do = link_to edit_group_path(@group) do
.nav-icon-container .nav-icon-container
= custom_icon('settings') = custom_icon('settings')
%span.nav-item-name %span.nav-item-name
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
.sidebar-context-title User Settings .sidebar-context-title User Settings
%ul.sidebar-top-level-items %ul.sidebar-top-level-items
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
= sidebar_link profile_path, title: _('Profile Settings') do = link_to profile_path do
.nav-icon-container .nav-icon-container
= custom_icon('profile') = custom_icon('profile')
%span.nav-item-name %span.nav-item-name
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
%strong.fly-out-top-item-name %strong.fly-out-top-item-name
#{ _('Profile') } #{ _('Profile') }
= nav_link(controller: [:accounts, :two_factor_auths]) do = nav_link(controller: [:accounts, :two_factor_auths]) do
= sidebar_link profile_account_path, title: _('Account') do = link_to profile_account_path do
.nav-icon-container .nav-icon-container
= custom_icon('account') = custom_icon('account')
%span.nav-item-name %span.nav-item-name
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#{ _('Account') } #{ _('Account') }
- if current_application_settings.should_check_namespace_plan? - if current_application_settings.should_check_namespace_plan?
= nav_link(controller: :billings) do = nav_link(controller: :billings) do
= sidebar_link profile_billings_path, title: _('Billing') do = link_to profile_billings_path do
.nav-icon-container .nav-icon-container
= custom_icon('credit_card') = custom_icon('credit_card')
%span.nav-item-name %span.nav-item-name
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
#{ _('Billing') } #{ _('Billing') }
- if current_application_settings.user_oauth_applications? - if current_application_settings.user_oauth_applications?
= nav_link(controller: 'oauth/applications') do = nav_link(controller: 'oauth/applications') do
= sidebar_link applications_profile_path, title: _('Applications') do = link_to applications_profile_path do
.nav-icon-container .nav-icon-container
= custom_icon('applications') = custom_icon('applications')
%span.nav-item-name %span.nav-item-name
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
%strong.fly-out-top-item-name %strong.fly-out-top-item-name
#{ _('Applications') } #{ _('Applications') }
= nav_link(controller: :chat_names) do = nav_link(controller: :chat_names) do
= sidebar_link profile_chat_names_path, title: _('Chat') do = link_to profile_chat_names_path do
.nav-icon-container .nav-icon-container
= custom_icon('chat') = custom_icon('chat')
%span.nav-item-name %span.nav-item-name
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
%strong.fly-out-top-item-name %strong.fly-out-top-item-name
#{ _('Chat') } #{ _('Chat') }
= nav_link(controller: :personal_access_tokens) do = nav_link(controller: :personal_access_tokens) do
= sidebar_link profile_personal_access_tokens_path, title: _('Access Tokens') do = link_to profile_personal_access_tokens_path do
.nav-icon-container .nav-icon-container
= custom_icon('access_tokens') = custom_icon('access_tokens')
%span.nav-item-name %span.nav-item-name
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
%strong.fly-out-top-item-name %strong.fly-out-top-item-name
#{ _('Access Tokens') } #{ _('Access Tokens') }
= nav_link(controller: :emails) do = nav_link(controller: :emails) do
= sidebar_link profile_emails_path, title: _('Emails') do = link_to profile_emails_path do
.nav-icon-container .nav-icon-container
= custom_icon('emails') = custom_icon('emails')
%span.nav-item-name %span.nav-item-name
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
#{ _('Emails') } #{ _('Emails') }
- unless current_user.ldap_user? - unless current_user.ldap_user?
= nav_link(controller: :passwords) do = nav_link(controller: :passwords) do
= sidebar_link edit_profile_password_path, title: _('Password') do = link_to edit_profile_password_path do
.nav-icon-container .nav-icon-container
= custom_icon('lock') = custom_icon('lock')
%span.nav-item-name %span.nav-item-name
...@@ -98,7 +98,7 @@ ...@@ -98,7 +98,7 @@
%strong.fly-out-top-item-name %strong.fly-out-top-item-name
#{ _('Password') } #{ _('Password') }
= nav_link(controller: :notifications) do = nav_link(controller: :notifications) do
= sidebar_link profile_notifications_path, title: _('Notifications') do = link_to profile_notifications_path do
.nav-icon-container .nav-icon-container
= custom_icon('notifications') = custom_icon('notifications')
%span.nav-item-name %span.nav-item-name
...@@ -109,7 +109,7 @@ ...@@ -109,7 +109,7 @@
%strong.fly-out-top-item-name %strong.fly-out-top-item-name
#{ _('Notifications') } #{ _('Notifications') }
= nav_link(controller: :keys) do = nav_link(controller: :keys) do
= sidebar_link profile_keys_path, title: _('SSH Keys') do = link_to profile_keys_path do
.nav-icon-container .nav-icon-container
= custom_icon('key') = custom_icon('key')
%span.nav-item-name %span.nav-item-name
...@@ -120,7 +120,7 @@ ...@@ -120,7 +120,7 @@
%strong.fly-out-top-item-name %strong.fly-out-top-item-name
#{ _('SSH Keys') } #{ _('SSH Keys') }
= nav_link(controller: :gpg_keys) do = nav_link(controller: :gpg_keys) do
= sidebar_link profile_gpg_keys_path, title: _('GPG Keys') do = link_to profile_gpg_keys_path do
.nav-icon-container .nav-icon-container
= custom_icon('key_2') = custom_icon('key_2')
%span.nav-item-name %span.nav-item-name
...@@ -131,7 +131,7 @@ ...@@ -131,7 +131,7 @@
%strong.fly-out-top-item-name %strong.fly-out-top-item-name
#{ _('GPG Keys') } #{ _('GPG Keys') }
= nav_link(controller: :preferences) do = nav_link(controller: :preferences) do
= sidebar_link profile_preferences_path, title: _('Preferences') do = link_to profile_preferences_path do
.nav-icon-container .nav-icon-container
= custom_icon('preferences') = custom_icon('preferences')
%span.nav-item-name %span.nav-item-name
...@@ -142,7 +142,7 @@ ...@@ -142,7 +142,7 @@
%strong.fly-out-top-item-name %strong.fly-out-top-item-name
#{ _('Preferences') } #{ _('Preferences') }
= nav_link(path: 'profiles#audit_log') do = nav_link(path: 'profiles#audit_log') do
= sidebar_link audit_log_profile_path, title: _('Authentication log') do = link_to audit_log_profile_path do
.nav-icon-container .nav-icon-container
= custom_icon('authentication_log') = custom_icon('authentication_log')
%span.nav-item-name %span.nav-item-name
...@@ -153,7 +153,7 @@ ...@@ -153,7 +153,7 @@
%strong.fly-out-top-item-name %strong.fly-out-top-item-name
#{ _('Authentication Log') } #{ _('Authentication Log') }
= nav_link(path: 'profiles#pipeline_quota') do = nav_link(path: 'profiles#pipeline_quota') do
= sidebar_link profile_pipeline_quota_path, title: _('Pipeline quota') do = link_to profile_pipeline_quota_path do
.nav-icon-container .nav-icon-container
= custom_icon('pipeline') = custom_icon('pipeline')
%span.nav-item-name %span.nav-item-name
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
= @project.name = @project.name
%ul.sidebar-top-level-items %ul.sidebar-top-level-items
= nav_link(path: ['projects#show', 'projects#activity', 'cycle_analytics#show'], html_options: { class: 'home' }) do = nav_link(path: ['projects#show', 'projects#activity', 'cycle_analytics#show'], html_options: { class: 'home' }) do
= sidebar_link project_path(@project), title: _('Project overview'), css: 'shortcuts-project' do = link_to project_path(@project), class: 'shortcuts-project' do
.nav-icon-container .nav-icon-container
= custom_icon('project') = custom_icon('project')
%span.nav-item-name %span.nav-item-name
...@@ -35,15 +35,15 @@ ...@@ -35,15 +35,15 @@
%span= _('Cycle Analytics') %span= _('Cycle Analytics')
- if project_nav_tab? :files - if project_nav_tab? :files
= nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare projects/repositories tags branches releases graphs network)) do = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare projects/repositories tags branches releases graphs network path_locks)) do
= sidebar_link project_tree_path(@project), title: _('Repository'), css: 'shortcuts-tree' do = link_to project_tree_path(@project), class: 'shortcuts-tree' do
.nav-icon-container .nav-icon-container
= custom_icon('doc_text') = custom_icon('doc_text')
%span.nav-item-name %span.nav-item-name
Repository Repository
%ul.sidebar-sub-level-items %ul.sidebar-sub-level-items
= nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare projects/repositories tags branches releases graphs network), html_options: { class: "fly-out-top-item" } ) do = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare projects/repositories tags branches releases graphs network path_locks), html_options: { class: "fly-out-top-item" } ) do
= link_to project_tree_path(@project) do = link_to project_tree_path(@project) do
%strong.fly-out-top-item-name %strong.fly-out-top-item-name
#{ _('Repository') } #{ _('Repository') }
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
- if project_nav_tab? :container_registry - if project_nav_tab? :container_registry
= nav_link(controller: %w[projects/registry/repositories]) do = nav_link(controller: %w[projects/registry/repositories]) do
= sidebar_link project_container_registry_index_path(@project), title: _('Container Registry'), css: 'shortcuts-container-registry' do = link_to project_container_registry_index_path(@project), class: 'shortcuts-container-registry' do
.nav-icon-container .nav-icon-container
= custom_icon('container_registry') = custom_icon('container_registry')
%span.nav-item-name %span.nav-item-name
...@@ -100,7 +100,7 @@ ...@@ -100,7 +100,7 @@
- if project_nav_tab? :issues - if project_nav_tab? :issues
= nav_link(controller: @project.issues_enabled? ? [:issues, :labels, :milestones, :boards] : :issues) do = nav_link(controller: @project.issues_enabled? ? [:issues, :labels, :milestones, :boards] : :issues) do
= sidebar_link project_issues_path(@project), title: _('Issues'), css: 'shortcuts-issues' do = link_to project_issues_path(@project), class: 'shortcuts-issues' do
.nav-icon-container .nav-icon-container
= custom_icon('issues') = custom_icon('issues')
%span.nav-item-name %span.nav-item-name
...@@ -124,9 +124,9 @@ ...@@ -124,9 +124,9 @@
List List
= nav_link(controller: :boards) do = nav_link(controller: :boards) do
= link_to project_boards_path(@project), title: 'Board' do = link_to project_boards_path(@project), title: boards_link_text do
%span %span
Board = boards_link_text
.feature-highlight.js-feature-highlight{ disabled: true, data: { trigger: 'manual', container: 'body', toggle: 'popover', placement: 'right', highlight: 'issue-boards' } } .feature-highlight.js-feature-highlight{ disabled: true, data: { trigger: 'manual', container: 'body', toggle: 'popover', placement: 'right', highlight: 'issue-boards' } }
.feature-highlight-popover-content .feature-highlight-popover-content
= render 'feature_highlight/issue_boards.svg' = render 'feature_highlight/issue_boards.svg'
...@@ -159,7 +159,7 @@ ...@@ -159,7 +159,7 @@
- if project_nav_tab? :merge_requests - if project_nav_tab? :merge_requests
= nav_link(controller: @project.issues_enabled? ? :merge_requests : [:merge_requests, :labels, :milestones]) do = nav_link(controller: @project.issues_enabled? ? :merge_requests : [:merge_requests, :labels, :milestones]) do
= sidebar_link project_merge_requests_path(@project), title: _('Merge Requests'), css: 'shortcuts-merge_requests' do = link_to project_merge_requests_path(@project), class: 'shortcuts-merge_requests' do
.nav-icon-container .nav-icon-container
= custom_icon('mr_bold') = custom_icon('mr_bold')
%span.nav-item-name %span.nav-item-name
...@@ -176,7 +176,7 @@ ...@@ -176,7 +176,7 @@
- if project_nav_tab? :pipelines - if project_nav_tab? :pipelines
= nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :environments, :artifacts]) do = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :environments, :artifacts]) do
= sidebar_link project_pipelines_path(@project), title: _('CI / CD'), css: 'shortcuts-pipelines' do = link_to project_pipelines_path(@project), class: 'shortcuts-pipelines' do
.nav-icon-container .nav-icon-container
= custom_icon('pipeline') = custom_icon('pipeline')
%span.nav-item-name %span.nav-item-name
...@@ -220,7 +220,7 @@ ...@@ -220,7 +220,7 @@
- if project_nav_tab? :wiki - if project_nav_tab? :wiki
= nav_link(controller: :wikis) do = nav_link(controller: :wikis) do
= sidebar_link get_project_wiki_path(@project), title: _('Wiki'), css: 'shortcuts-wiki' do = link_to get_project_wiki_path(@project), class: 'shortcuts-wiki' do
.nav-icon-container .nav-icon-container
= custom_icon('wiki') = custom_icon('wiki')
%span.nav-item-name %span.nav-item-name
...@@ -233,7 +233,7 @@ ...@@ -233,7 +233,7 @@
- if project_nav_tab? :snippets - if project_nav_tab? :snippets
= nav_link(controller: :snippets) do = nav_link(controller: :snippets) do
= sidebar_link project_snippets_path(@project), title: _('Snippets'), css: 'shortcuts-snippets' do = link_to project_snippets_path(@project), class: 'shortcuts-snippets' do
.nav-icon-container .nav-icon-container
= custom_icon('snippets') = custom_icon('snippets')
%span.nav-item-name %span.nav-item-name
...@@ -245,8 +245,8 @@ ...@@ -245,8 +245,8 @@
#{ _('Snippets') } #{ _('Snippets') }
- if project_nav_tab? :settings - if project_nav_tab? :settings
= nav_link(path: %w[projects#edit project_members#index integrations#show services#edit repository#show ci_cd#show pages#show]) do = nav_link(path: %w[projects#edit project_members#index integrations#show services#edit repository#show ci_cd#show pages#show audit_events#index]) do
= sidebar_link edit_project_path(@project), title: _('Settings'), css: 'shortcuts-tree' do = link_to edit_project_path(@project), class: 'shortcuts-tree' do
.nav-icon-container .nav-icon-container
= custom_icon('settings') = custom_icon('settings')
%span.nav-item-name %span.nav-item-name
...@@ -255,7 +255,7 @@ ...@@ -255,7 +255,7 @@
%ul.sidebar-sub-level-items %ul.sidebar-sub-level-items
- can_edit = can?(current_user, :admin_project, @project) - can_edit = can?(current_user, :admin_project, @project)
- if can_edit - if can_edit
= nav_link(path: %w[projects#edit project_members#index integrations#show services#edit repository#show ci_cd#show pages#show], html_options: { class: "fly-out-top-item" } ) do = nav_link(path: %w[projects#edit project_members#index integrations#show services#edit repository#show ci_cd#show pages#show audit_events#index], html_options: { class: "fly-out-top-item" } ) do
= link_to edit_project_path(@project) do = link_to edit_project_path(@project) do
%strong.fly-out-top-item-name %strong.fly-out-top-item-name
#{ _('Settings') } #{ _('Settings') }
......
...@@ -5,8 +5,6 @@ ...@@ -5,8 +5,6 @@
- breadcrumb_title "Issue Boards" - breadcrumb_title "Issue Boards"
- page_title "Boards" - page_title "Boards"
- add_to_breadcrumbs("Issues", @issues_path)
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= webpack_bundle_tag 'common_vue' = webpack_bundle_tag 'common_vue'
= webpack_bundle_tag 'filtered_search' = webpack_bundle_tag 'filtered_search'
......
---
title: 'Ensure #route_setting is available before calling it'
merge_request: 2908
author:
type: fixed
---
title: Add Geo rake task descriptions
merge_request: 2925
author:
type: other
...@@ -56,9 +56,9 @@ components below. ...@@ -56,9 +56,9 @@ components below.
### High Availability with Sentinel ### High Availability with Sentinel
>**Notes:** >**Notes:**
- Starting with GitLab `8.11`, you can configure a list of Redis Sentinel - Starting with GitLab 8.11, you can configure a list of Redis Sentinel
servers that will monitor a group of Redis servers to provide failover support. servers that will monitor a group of Redis servers to provide failover support.
- Starting with GitLab `8.14`, the Omnibus GitLab Enterprise Edition package - Starting with GitLab 8.14, the Omnibus GitLab Enterprise Edition package
comes with Redis Sentinel daemon built-in. comes with Redis Sentinel daemon built-in.
High Availability with Redis requires a few things: High Availability with Redis requires a few things:
......
...@@ -116,16 +116,13 @@ _The artifacts are stored by default in ...@@ -116,16 +116,13 @@ _The artifacts are stored by default in
} }
``` ```
NOTE: If you are using AWS IAM profiles, you will need to specify a blank NOTE: For GitLab 9.4+, if you are using AWS IAM profiles, be sure to omit the
AWS access key and ID until [this fog-aws AWS access key and secret acces key/value pairs. For example:
issue](https://github.com/fog/fog-aws/issues/162) is resolved. For example:
```ruby ```ruby
gitlab_rails['artifacts_object_store_connection'] = { gitlab_rails['artifacts_object_store_connection'] = {
'provider' => 'AWS', 'provider' => 'AWS',
'region' => 'eu-central-1', 'region' => 'eu-central-1',
'aws_access_key_id' => '',
'aws_secret_access_key' => '',
'use_iam_profile' => true 'use_iam_profile' => true
} }
``` ```
......
...@@ -284,7 +284,7 @@ POST /todos/mark_as_done ...@@ -284,7 +284,7 @@ POST /todos/mark_as_done
``` ```
```bash ```bash
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/todos/donmark_as_donee curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/todos/mark_as_done
``` ```
......
# GitLab Geo # GitLab Geo
NOTE: GitLab Geo is in ALPHA development. It is considered experimental and >**Note:**
GitLab Geo is in **Beta** development. It is considered experimental and
not production-ready. It will undergo significant changes over the next year, not production-ready. It will undergo significant changes over the next year,
and there is significant chance of data loss. For the latest updates, check the and there is significant chance of data loss. For the latest updates, check the
[meta issue](https://gitlab.com/gitlab-org/gitlab-ee/issues/846). [meta issue](https://gitlab.com/gitlab-org/gitlab-ee/issues/846).
...@@ -32,9 +33,10 @@ and the replicated read-only ones as **secondaries**. ...@@ -32,9 +33,10 @@ and the replicated read-only ones as **secondaries**.
Keep in mind that: Keep in mind that:
- Secondaries talk to primary to get user data for logins (API), and to - Secondaries talk to primary to authorize user logins (OAuth),
clone/pull from repositories (HTTP(S)/SSH). to synchronize data (database replication), and to clone/pull from
- Primary talks to secondaries to notify for changes (API). repositories (SSH).
- Primary talks to secondaries to get their status (API).
## Use-cases ## Use-cases
......
...@@ -3,12 +3,15 @@ ...@@ -3,12 +3,15 @@
After you set up the [database replication and configure the GitLab Geo nodes][req], After you set up the [database replication and configure the GitLab Geo nodes][req],
there are a few things to consider: there are a few things to consider:
1. When you create a new project in the primary node, the Git repository will 1. Users need an extra step to be able to fetch code from the secondary and push
appear in the secondary only _after_ the first `git push`. to primary:
1. You need an extra step to be able to fetch code from the `secondary` and push
to `primary`: 1. Clone the repository as normal do from the secondary node:
```bash
git clone git@secondary.gitlab.example.com:user/repo.git
```
1. Clone your repository as you would normally do from the `secondary` node
1. Change the remote push URL following this example: 1. Change the remote push URL following this example:
```bash ```bash
......
...@@ -33,8 +33,9 @@ can be summed up to: ...@@ -33,8 +33,9 @@ can be summed up to:
1. Configure the primary node 1. Configure the primary node
1. Replicate some required configurations between the primary and the secondaries 1. Replicate some required configurations between the primary and the secondaries
1. Start GitLab in the secondary node's machine 1. Configure a second, tracking database on each secondary
1. Configure every secondary node in the primary's Admin screen 1. Configure every secondary node in the primary's Admin screen
1. Start GitLab on the secondary node's machine
### Prerequisites ### Prerequisites
...@@ -49,6 +50,9 @@ first two steps of the [Setup instructions](README.md#setup-instructions): ...@@ -49,6 +50,9 @@ first two steps of the [Setup instructions](README.md#setup-instructions):
1. Your nodes must have an NTP service running to synchronize the clocks. 1. Your nodes must have an NTP service running to synchronize the clocks.
You can use different timezones, but the hour relative to UTC can't be more You can use different timezones, but the hour relative to UTC can't be more
than 60 seconds off from each node. than 60 seconds off from each node.
1. You have set up another PostgreSQL database that can store writes for the secondary.
Note that this MUST be on another instance, since the primary replicated database
is read-only.
Some of the following steps require to configure the primary and secondary Some of the following steps require to configure the primary and secondary
nodes almost at the same time. For your convenience make sure you have SSH nodes almost at the same time. For your convenience make sure you have SSH
...@@ -106,7 +110,7 @@ sensitive data in the database. Any secondary node must have the ...@@ -106,7 +110,7 @@ sensitive data in the database. Any secondary node must have the
sudo -i sudo -i
``` ```
1. Added in GitLab 9.1: Execute the command below to display current encryption key and copy it: 1. Execute the command below to display the current encryption key and copy it:
``` ```
gitlab-rake geo:db:show_encryption_key gitlab-rake geo:db:show_encryption_key
...@@ -134,16 +138,21 @@ sensitive data in the database. Any secondary node must have the ...@@ -134,16 +138,21 @@ sensitive data in the database. Any secondary node must have the
### Step 4. Regenerating the authorized keys in the secondary node ### Step 4. Regenerating the authorized keys in the secondary node
> **IMPORTANT:** Since GitLab 10.0 `~/.ssh/authorized_keys` no longer
> can be used, and this step is deprecated. Instead, follow the
> instructions on [configuring SSH authorization via database lookups](../administration/operations/speed_up_ssh.html)
> (for both primary AND secondary nodes).
Regenerate the keys for `~/.ssh/authorized_keys` Regenerate the keys for `~/.ssh/authorized_keys`
(HTTPS clone will still work without this extra step). (HTTPS clone will still work without this extra step).
On the **secondary** node where the database is [already replicated](./database.md), 1. On the **secondary** node where the database is [already replicated](./database.md),
run: run:
``` ```
# For Omnibus installations # For Omnibus installations
gitlab-rake gitlab:shell:setup gitlab-rake gitlab:shell:setup
``` ```
This will enable `git` operations to authorize against your existing users. This will enable `git` operations to authorize against your existing users.
New users and SSH keys updated after this step, will be replicated automatically. New users and SSH keys updated after this step, will be replicated automatically.
...@@ -187,10 +196,10 @@ The two most obvious issues that replication can have here are: ...@@ -187,10 +196,10 @@ The two most obvious issues that replication can have here are:
### Step 6. Replicating the repositories data ### Step 6. Replicating the repositories data
Lastly, getting a new secondary Geo node up and running, will also require the Getting a new secondary Geo node up and running, will also require the
repositories data to be synced. repositories data to be synced.
With GitLab **9.0** the syncing process starts automatically from the With GitLab 9.0 the syncing process starts automatically from the
secondary node after the **Add Node** button is pressed. secondary node after the **Add Node** button is pressed.
Currently, this is what is synced: Currently, this is what is synced:
...@@ -212,7 +221,7 @@ repository shards you must duplicate the same configuration on the secondary. ...@@ -212,7 +221,7 @@ repository shards you must duplicate the same configuration on the secondary.
Disabling a secondary node stops the syncing process. Disabling a secondary node stops the syncing process.
With GitLab **8.14** this process is started manually from the primary node. With GitLab 8.14 this process is started manually from the primary node.
You can start the syncing process by clicking the "Backfill all repositories" You can start the syncing process by clicking the "Backfill all repositories"
button on `Admin > Geo Nodes` screen. button on `Admin > Geo Nodes` screen.
...@@ -259,7 +268,7 @@ Point your users to the [after setup steps](after_setup.md). ...@@ -259,7 +268,7 @@ Point your users to the [after setup steps](after_setup.md).
## Selective replication ## Selective replication
With GitLab **9.5**, GitLab Geo now supports the first iteration of selective With GitLab 9.5, GitLab Geo now supports the first iteration of selective
replication, which allows admins to choose which namespaces should be replication, which allows admins to choose which namespaces should be
replicated by secondary nodes. replicated by secondary nodes.
......
...@@ -22,9 +22,9 @@ in your testing/production environment. ...@@ -22,9 +22,9 @@ in your testing/production environment.
## Setting up GitLab ## Setting up GitLab
>**Notes:** >**Notes:**
- Don't setup any custom authentication in the secondary nodes, this will be - **Do not** setup any custom authentication in the secondary nodes, this will be
handled by the primary node. handled by the primary node.
- Do not add anything in the secondaries Geo nodes admin area - **Do not** add anything in the secondaries Geo nodes admin area
(**Admin Area ➔ Geo Nodes**). This is handled solely by the primary node. (**Admin Area ➔ Geo Nodes**). This is handled solely by the primary node.
After having installed GitLab Enterprise Edition in the instance that will serve After having installed GitLab Enterprise Edition in the instance that will serve
...@@ -33,9 +33,9 @@ next steps can be summed up to: ...@@ -33,9 +33,9 @@ next steps can be summed up to:
1. Configure the primary node 1. Configure the primary node
1. Replicate some required configurations between the primary and the secondaries 1. Replicate some required configurations between the primary and the secondaries
1. Configure a second, tracking database for each secondary 1. Configure a second, tracking database on each secondary
1. Start GitLab in the secondary node's machine
1. Configure every secondary node in the primary's Admin screen 1. Configure every secondary node in the primary's Admin screen
1. Start GitLab on the secondary node's machine
### Prerequisites ### Prerequisites
...@@ -47,6 +47,9 @@ first two steps of the [Setup instructions](README.md#setup-instructions): ...@@ -47,6 +47,9 @@ first two steps of the [Setup instructions](README.md#setup-instructions):
1. You have set up the database replication. 1. You have set up the database replication.
1. Your secondary node is allowed to communicate via HTTP/HTTPS and SSH with 1. Your secondary node is allowed to communicate via HTTP/HTTPS and SSH with
your primary node (make sure your firewall is not blocking that). your primary node (make sure your firewall is not blocking that).
1. Your nodes must have an NTP service running to synchronize the clocks.
You can use different timezones, but the hour relative to UTC can't be more
than 60 seconds off from each node.
1. You have set up another PostgreSQL database that can store writes for the secondary. 1. You have set up another PostgreSQL database that can store writes for the secondary.
Note that this MUST be on another instance, since the primary replicated database Note that this MUST be on another instance, since the primary replicated database
is read-only. is read-only.
...@@ -117,56 +120,37 @@ sensitive data in the database. Any secondary node must have the ...@@ -117,56 +120,37 @@ sensitive data in the database. Any secondary node must have the
sudo -i sudo -i
``` ```
1. (This step is required only if you want to enable the new Disaster Recovery 1. Open the secrets file and paste the value of `db_key_base` you copied in the
feature in Alpha shipped in GitLab 9.0) Create `database_geo.yml` with the previous step:
information of your secondary PostgreSQL database.
Note that this must be a totally different instance from the primary, since this
is where the secondary will track its internal state:
```
sudo cp /home/git/gitlab/config/database_geo.yml.postgresql /home/git/gitlab/config/database_geo.yml
```
1. (This step is required only if you want to enable the new Disaster Recovery
feature in Alpha shipped in GitLab 9.0) Edit the content of `database_geo.yml`
in `production:` to be like the following:
```yaml
#
# PRODUCTION
#
production:
adapter: postgresql
encoding: unicode
database: gitlabhq_geo_production
pool: 10
username: gitlab_geo
# password:
host: /var/opt/gitlab/geo-postgresql
port: 5431
``` ```
editor /etc/gitlab/gitlab-secrets.json
```
1. Save and close the file.
1. (This step is required only if you want to enable the new Disaster Recovery ### Step 4. Regenerating the authorized keys in the secondary node
feature in Alpha shipped in GitLab 9.0) Create the database
`gitlabhq_geo_production` in that PostgreSQL instance.
1. (This step is required only if you want to enable the new Disaster Recovery > **IMPORTANT:** Since GitLab 10.0 `~/.ssh/authorized_keys` no longer
feature in Alpha shipped in GitLab 9.0) Set up the Geo tracking database: > can be used, and this step is deprecated. Instead, follow the
> instructions on [configuring SSH authorization via database lookups](../administration/operations/speed_up_ssh.html)
> (for both primary AND secondary nodes).
``` Regenerate the keys for `~/.ssh/authorized_keys`
bundle exec rake geo:db:migrate (HTTPS clone will still work without this extra step).
```
1. Open the secrets file and paste the value of `db_key_base` you copied in the 1. On the **secondary** node where the database is [already replicated](./database.md),
previous step: run:
``` ```
editor /home/git/gitlab/config/secrets.yml # Installations from source
sudo -u git -H bundle exec rake gitlab:shell:setup RAILS_ENV=production
``` ```
1. Save and close the file. This will enable `git` operations to authorize against your existing users.
New users and SSH keys updated after this step, will be replicated automatically.
### Step 4. Enabling the secondary GitLab node ### Step 5. Enabling the secondary GitLab node
1. SSH into the **secondary** node and login as root: 1. SSH into the **secondary** node and login as root:
...@@ -193,6 +177,7 @@ sensitive data in the database. Any secondary node must have the ...@@ -193,6 +177,7 @@ sensitive data in the database. Any secondary node must have the
in your browser. in your browser.
1. Add the secondary node by providing its full URL and the public SSH key 1. Add the secondary node by providing its full URL and the public SSH key
you created previously. **Do NOT** check the box 'This is a primary node'. you created previously. **Do NOT** check the box 'This is a primary node'.
1. Added in GitLab 9.5: Choose which namespaces should be replicated by the secondary node. Leave blank to replicate all. Read more in [selective replication](#selective-replication).
1. Click the **Add node** button. 1. Click the **Add node** button.
--- ---
...@@ -210,12 +195,12 @@ The two most obvious issues that replication can have here are: ...@@ -210,12 +195,12 @@ The two most obvious issues that replication can have here are:
[Troubleshooting](configuration.md#troubleshooting) section) [Troubleshooting](configuration.md#troubleshooting) section)
- Instance is firewalled (check your firewall rules) - Instance is firewalled (check your firewall rules)
### Step 5. Replicating the repositories data ### Step 6. Replicating the repositories data
Getting a new secondary Geo node up and running, will also require the Getting a new secondary Geo node up and running, will also require the
repositories data to be synced. repositories data to be synced.
With GitLab **9.0** the syncing process starts automatically from the With GitLab 9.0 the syncing process starts automatically from the
secondary node after the **Add Node** button is pressed. secondary node after the **Add Node** button is pressed.
Currently, this is what is synced: Currently, this is what is synced:
...@@ -230,11 +215,14 @@ You can monitor the status of the syncing process on a secondary node ...@@ -230,11 +215,14 @@ You can monitor the status of the syncing process on a secondary node
by visiting the primary node's **Admin Area ➔ Geo Nodes** (`/admin/geo_nodes`) by visiting the primary node's **Admin Area ➔ Geo Nodes** (`/admin/geo_nodes`)
in your browser. in your browser.
Please note that if `git_data_dirs` is customized on the primary for multiple
repository shards you must duplicate the same configuration on the secondary.
![GitLab Geo dashboard](img/geo-node-dashboard.png) ![GitLab Geo dashboard](img/geo-node-dashboard.png)
Disabling a secondary node stops the syncing process. Disabling a secondary node stops the syncing process.
With GitLab **8.14** this process is started manually from the primary node. With GitLab 8.14 this process is started manually from the primary node.
You can start the syncing process by clicking the "Backfill all repositories" You can start the syncing process by clicking the "Backfill all repositories"
button on `Admin > Geo Nodes` screen. button on `Admin > Geo Nodes` screen.
...@@ -267,22 +255,6 @@ While active repositories will be eventually replicated, if you don't rsync, ...@@ -267,22 +255,6 @@ While active repositories will be eventually replicated, if you don't rsync,
the files, any archived/inactive repositories will not get in the secondary node the files, any archived/inactive repositories will not get in the secondary node
as Geo doesn't run any routine task to look for missing repositories. as Geo doesn't run any routine task to look for missing repositories.
### Step 6. Regenerating the authorized keys in the secondary node
The final step is to regenerate the keys for `~/.ssh/authorized_keys`
(HTTPS clone will still work without this extra step).
On the **secondary** node where the database is [already replicated](./database.md),
run:
```
# Installations from source
sudo -u git -H bundle exec rake gitlab:shell:setup RAILS_ENV=production
```
This will enable `git` operations to authorize against your existing users.
New users and SSH keys updated after this step, will be replicated automatically.
## Next steps ## Next steps
Your nodes should now be ready to use. You can login to the secondary node Your nodes should now be ready to use. You can login to the secondary node
...@@ -295,6 +267,10 @@ If your installation isn't working properly, check the ...@@ -295,6 +267,10 @@ If your installation isn't working properly, check the
Point your users to the [after setup steps](after_setup.md). Point your users to the [after setup steps](after_setup.md).
## Selective replication
Read [Selective replication](configuration.md#selective-replication).
## Adding another secondary Geo node ## Adding another secondary Geo node
To add another Geo node in an already Geo configured infrastructure, just follow To add another Geo node in an already Geo configured infrastructure, just follow
......
...@@ -8,7 +8,7 @@ from source, follow the ...@@ -8,7 +8,7 @@ from source, follow the
1. [Install GitLab Enterprise Edition][install-ee] on the server that will serve 1. [Install GitLab Enterprise Edition][install-ee] on the server that will serve
as the secondary Geo node. Do not login or set up anything else in the as the secondary Geo node. Do not login or set up anything else in the
secondary node for the moment. secondary node for the moment.
1. **Setup the database replication (`primary (read-write) <-> secondary (read-only)` topology).** 1. **Setup the database replication topology:** `primary (read-write) <-> secondary (read-only)`
1. [Configure GitLab](configuration.md) to set the primary and secondary nodes. 1. [Configure GitLab](configuration.md) to set the primary and secondary nodes.
1. [Follow the after setup steps](after_setup.md). 1. [Follow the after setup steps](after_setup.md).
...@@ -24,14 +24,14 @@ in your testing/production environment. ...@@ -24,14 +24,14 @@ in your testing/production environment.
## PostgreSQL replication ## PostgreSQL replication
The GitLab primary node where the write operations happen will connect to The GitLab primary node where the write operations happen will connect to
`primary` database server, and the secondary ones which are read-only will primary database server, and the secondary ones which are read-only will
connect to `secondary` database servers (which are read-only too). connect to secondary database servers (which are read-only too).
>**Note:** >**Note:**
In many databases documentation you will see `primary` being references as `master` In many databases documentation you will see "primary" being referenced as "master"
and `secondary` as either `slave` or `standby` server (read-only). and "secondary" as either "slave" or "standby" server (read-only).
New for GitLab 9.4: We recommend using [PostgreSQL replication Since GitLab 9.4: We recommend using [PostgreSQL replication
slots](https://medium.com/@tk512/replication-slots-in-postgresql-b4b03d277c75) slots](https://medium.com/@tk512/replication-slots-in-postgresql-b4b03d277c75)
to ensure the primary retains all the data necessary for the secondaries to to ensure the primary retains all the data necessary for the secondaries to
recover. See below for more details. recover. See below for more details.
...@@ -40,17 +40,17 @@ recover. See below for more details. ...@@ -40,17 +40,17 @@ recover. See below for more details.
The following guide assumes that: The following guide assumes that:
- You are using PostgreSQL 9.2 or later which includes the - You are using PostgreSQL 9.6 or later which includes the
[`pg_basebackup` tool][pgback]. If you are using Omnibus it includes the required [`pg_basebackup` tool][pgback]. If you are using Omnibus it includes the required
PostgreSQL version for Geo. PostgreSQL version for Geo.
- You have a primary server already set up (the GitLab server you are - You have a primary server already set up (the GitLab server you are
replicating from), running Omnibus' PostgreSQL (or equivalent version), and you replicating from), running Omnibus' PostgreSQL (or equivalent version), and you
have a new secondary server set up on the same OS and PostgreSQL version. If have a new secondary server set up on the same OS and PostgreSQL version. Also
you are using Omnibus, make sure the GitLab version is the same on all nodes. make sure the GitLab version is the same on all nodes.
- The IP of the primary server for our examples will be `1.2.3.4`, whereas the - The IP of the primary server for our examples will be `1.2.3.4`, whereas the
secondary's IP will be `5.6.7.8`. Note that the primary and secondary servers secondary's IP will be `5.6.7.8`. Note that the primary and secondary servers
MUST be able to communicate over these addresses. These IP addresses can either **must** be able to communicate over these addresses (using HTTPS & SSH).
be public or private. These IP addresses can either be public or private.
### Step 1. Configure the primary server ### Step 1. Configure the primary server
...@@ -177,13 +177,71 @@ The following guide assumes that: ...@@ -177,13 +177,71 @@ The following guide assumes that:
\q \q
``` ```
1. Added in GitLab 9.1: Edit `/etc/gitlab/gitlab.rb` and add the following: 1. Edit `/etc/gitlab/gitlab.rb` and add the following:
```ruby ```ruby
geo_secondary_role['enable'] = true geo_secondary_role['enable'] = true
```
1. Optional since GitLab 9.1, and required for GitLab 10.0 or higher:
[Enable tracking database on the secondary server](#enable-tracking-database-on-the-secondary-server)
1. Otherwise, continue to [initiate the replication process](#step-3-initiate-the-replication-process).
#### Enable tracking database on the secondary server
Geo secondary nodes use a tracking database to keep track of replication status and recover
automatically from some replication issues.
It is added in GitLab 9.1, and since GitLab 10.0 it is required.
> **IMPORTANT:** For this feature to work correctly, all nodes must be
with their clocks synchronized. It is not required for all nodes to be set to
the same time zone, but when the respective times are converted to UTC time,
the clocks must be synchronized to within 60 seconds of each other.
1. Setup clock synchronization service in your Linux distro.
This can easily be done via any NTP-compatible daemon. For example,
here are [instructions for setting up NTP with Ubuntu](https://help.ubuntu.com/lts/serverguide/NTP.html).
1. Edit `/etc/gitlab/gitlab.rb` and add the following:
```ruby
geo_postgresql['enable'] = true geo_postgresql['enable'] = true
``` ```
1. Create `database_geo.yml` with the information of your secondary PostgreSQL
database. Note that GitLab will set up another database instance separate
from the primary, since this is where the secondary will track its internal
state:
```
sudo cp /opt/gitlab/embedded/service/gitlab-rails/config/database_geo.yml.postgresql /opt/gitlab/embedded/service/gitlab-rails/config/database_geo.yml
```
1. Edit the content of `database_geo.yml` in `production:` like the example below:
```yaml
#
# PRODUCTION
#
production:
adapter: postgresql
encoding: unicode
database: gitlabhq_geo_production
pool: 10
username: gitlab_geo
# password:
host: /var/opt/gitlab/geo-postgresql
```
1. Set up the Geo tracking database:
```
sudo gitlab-rake geo:db:migrate
```
1. [Reconfigure GitLab][] for the changes to take effect. 1. [Reconfigure GitLab][] for the changes to take effect.
1. Continue to [initiate the replication process](#step-3-initiate-the-replication-process). 1. Continue to [initiate the replication process](#step-3-initiate-the-replication-process).
......
...@@ -8,7 +8,7 @@ using the Omnibus GitLab packages, follow the ...@@ -8,7 +8,7 @@ using the Omnibus GitLab packages, follow the
1. [Install GitLab Enterprise Edition][install-ee-source] on the server that 1. [Install GitLab Enterprise Edition][install-ee-source] on the server that
will serve as the secondary Geo node. Do not login or set up anything else will serve as the secondary Geo node. Do not login or set up anything else
in the secondary node for the moment. in the secondary node for the moment.
1. **Setup the database replication (`primary (read-write) <-> secondary (read-only)` topology).** 1. **Setup the database replication topology:** `primary (read-write) <-> secondary (read-only)`
1. [Configure GitLab](configuration_source.md) to set the primary and secondary 1. [Configure GitLab](configuration_source.md) to set the primary and secondary
nodes. nodes.
1. [Follow the after setup steps](after_setup.md). 1. [Follow the after setup steps](after_setup.md).
...@@ -25,12 +25,17 @@ in your testing/production environment. ...@@ -25,12 +25,17 @@ in your testing/production environment.
## PostgreSQL replication ## PostgreSQL replication
The GitLab primary node where the write operations happen will connect to The GitLab primary node where the write operations happen will connect to
`primary` database server, and the secondary ones which are read-only will primary database server, and the secondary ones which are read-only will
connect to `secondary` database servers (which are read-only too). connect to secondary database servers (which are read-only too).
>**Note:** >**Note:**
In many databases documentation you will see `primary` being references as `master` In many databases documentation you will see "primary" being referenced as "master"
and `secondary` as either `slave` or `standby` server (read-only). and "secondary" as either "slave" or "standby" server (read-only).
Since GitLab 9.4: We recommend using [PostgreSQL replication
slots](https://medium.com/@tk512/replication-slots-in-postgresql-b4b03d277c75)
to ensure the primary retains all the data necessary for the secondaries to
recover. See below for more details.
### Prerequisites ### Prerequisites
...@@ -41,13 +46,15 @@ The following guide assumes that: ...@@ -41,13 +46,15 @@ The following guide assumes that:
PostgreSQL version for Geo. PostgreSQL version for Geo.
- You have a primary server already set up (the GitLab server you are - You have a primary server already set up (the GitLab server you are
replicating from), and you have a new secondary server set up on the same OS replicating from), and you have a new secondary server set up on the same OS
and PostgreSQL version. and PostgreSQL version. Also make sure the GitLab version is the same on all nodes.
- The IP of the primary server for our examples will be `1.2.3.4`, whereas the - The IP of the primary server for our examples will be `1.2.3.4`, whereas the
secondary's IP will be `5.6.7.8`. secondary's IP will be `5.6.7.8`. Note that the primary and secondary servers
**must** be able to communicate over these addresses. These IP addresses can either
be public or private.
### Step 1. Configure the primary server ### Step 1. Configure the primary server
1. SSH into your database **primary** server and login as root: 1. SSH into your GitLab **primary** server and login as root:
``` ```
sudo -i sudo -i
...@@ -125,10 +132,11 @@ The following guide assumes that: ...@@ -125,10 +132,11 @@ The following guide assumes that:
1. Now that the PostgreSQL server is set up to accept remote connections, run 1. Now that the PostgreSQL server is set up to accept remote connections, run
`netstat -plnt` to make sure that PostgreSQL is listening to the server's `netstat -plnt` to make sure that PostgreSQL is listening to the server's
public IP. public IP.
1. Continue to [set up the secondary server](#step-2-configure-the-secondary-server).
### Step 2. Configure the secondary server ### Step 2. Configure the secondary server
1. SSH into your database **secondary** server and login as root: 1. SSH into your GitLab **secondary** server and login as root:
``` ```
sudo -i sudo -i
...@@ -151,7 +159,7 @@ The following guide assumes that: ...@@ -151,7 +159,7 @@ The following guide assumes that:
``` ```
1. Edit `postgresql.conf` to configure the secondary for streaming replication 1. Edit `postgresql.conf` to configure the secondary for streaming replication
(for Debian/Ubuntu that would be `/etc/postgresql/9.x/main/postgresql.conf`): (for Debian/Ubuntu that would be `/etc/postgresql/9.*/main/postgresql.conf`):
```bash ```bash
wal_level = hot_standby wal_level = hot_standby
...@@ -162,7 +170,61 @@ The following guide assumes that: ...@@ -162,7 +170,61 @@ The following guide assumes that:
``` ```
1. Restart PostgreSQL for the changes to take effect. 1. Restart PostgreSQL for the changes to take effect.
1. Continue to [initiate the replication process](#step-3-initiate-the-replication-process).
1. Optional since GitLab 9.1, and required for GitLab 10.0 or higher:
[Enable tracking database on the secondary server](#enable-tracking-database-on-the-secondary-server)
1. Otherwise, continue to [initiate the replication process](#step-3-initiate-the-replication-process).
#### Enable tracking database on the secondary server
Geo secondary nodes use a tracking database to keep track of replication status and recover
automatically from some replication issues.
It is added in GitLab 9.1, and since GitLab 10.0 it is required.
> **IMPORTANT:** For this feature to work correctly, all nodes must be
with their clocks synchronized. It is not required for all nodes to be set to
the same time zone, but when the respective times are converted to UTC time,
the clocks must be synchronized to within 60 seconds of each other.
1. Setup clock synchronization service in your Linux distro.
This can easily be done via any NTP-compatible daemon. For example,
here are [instructions for setting up NTP with Ubuntu](https://help.ubuntu.com/lts/serverguide/NTP.html).
1. Create `database_geo.yml` with the information of your secondary PostgreSQL
database. Note that GitLab will set up another database instance separate
from the primary, since this is where the secondary will track its internal
state:
```
sudo cp /home/git/gitlab/config/database_geo.yml.postgresql /home/git/gitlab/config/database_geo.yml
```
1. Edit the content of `database_geo.yml` in `production:` like the example below:
```yaml
#
# PRODUCTION
#
production:
adapter: postgresql
encoding: unicode
database: gitlabhq_geo_production
pool: 10
username: gitlab_geo
# password:
host: /var/opt/gitlab/geo-postgresql
```
1. Create the database `gitlabhq_geo_production` in that PostgreSQL
instance.
1. Set up the Geo tracking database:
```
bundle exec rake geo:db:migrate
```
### Step 3. Initiate the replication process ### Step 3. Initiate the replication process
......
# GitLab Geo Disaster Recovery # GitLab Geo Disaster Recovery
> **Note:** > **Note:**
This is not officially supported yet, please don't use as your only GitLab Geo Disaster Recovery is in **Alpha** development. Please don't
Disaster Recovery strategy as you may lose data. use as your only Disaster Recovery strategy as you may lose data.
GitLab Geo replicates your database and your Git repositories. We will GitLab Geo replicates your database and your Git repositories. We will
support and replicate more data in the future, that will enable you to support and replicate more data in the future, that will enable you to
......
...@@ -25,12 +25,12 @@ primary node. ...@@ -25,12 +25,12 @@ primary node.
## How long does it take to have a commit replicated to a secondary node? ## How long does it take to have a commit replicated to a secondary node?
All replication operations are asynchronous and are queued to be dispatched in All replication operations are asynchronous and are queued to be dispatched in
a batched request every 10 seconds. Besides that, it depends on a lot of other a batched request every 10 minutes. Besides that, it depends on a lot of other
factors including the amount of traffic, how big your commit is, the factors including the amount of traffic, how big your commit is, the
connectivity between your nodes, your hardware, etc. connectivity between your nodes, your hardware, etc.
## What happens if the SSH server runs at a different port? ## What if the SSH server runs at a different port?
We send the clone url from the primary server to any secondaries, so it We send the clone url from the primary server to any secondaries, so it
doesn't matter. If primary is running on port `2200` clone url will reflect doesn't matter. If primary is running on port `2200`, clone url will reflect
that. that.
...@@ -6,6 +6,9 @@ single source of truth, Geo needs to be configured to perform SSH fingerprint ...@@ -6,6 +6,9 @@ single source of truth, Geo needs to be configured to perform SSH fingerprint
lookups via database lookup. This approach is also much faster than scanning a lookups via database lookup. This approach is also much faster than scanning a
file. file.
>**Note:**
GitLab 10.0 and higher require database lookups for SSH keys.
Note this feature is only available on operating systems that support OpenSSH Note this feature is only available on operating systems that support OpenSSH
6.9 and above. For CentOS 6 and 7, see the [instructions on building custom 6.9 and above. For CentOS 6 and 7, see the [instructions on building custom
version of OpenSSH for your server] version of OpenSSH for your server]
......
...@@ -10,7 +10,9 @@ all you need to do is update GitLab itself: ...@@ -10,7 +10,9 @@ all you need to do is update GitLab itself:
1. Log into each node (primary and secondaries) 1. Log into each node (primary and secondaries)
1. [Update GitLab][update] 1. [Update GitLab][update]
1. Test primary and secondary nodes, and check version in each. 1. [Update tracking database on secondary node](#update-tracking-database-on-secondary-node) when
the tracking database is enabled.
1. [Test](#check-status-after-updating) primary and secondary nodes, and check version in each.
## Special update notes for 9.0.x ## Special update notes for 9.0.x
...@@ -149,68 +151,18 @@ everything is working correctly: ...@@ -149,68 +151,18 @@ everything is working correctly:
1. Test the data replication by pushing code to the primary and see if it 1. Test the data replication by pushing code to the primary and see if it
is received by the secondaries is received by the secondaries
## Enable tracking database ## Update tracking database on secondary node
NOTE: This step is required only if you want to enable the new Disaster After updating a secondary node, you might need to run migrations on
Recovery feature in Alpha shipped in GitLab 9.0. the tracking database. The tracking database was added in GitLab 9.1,
and it is required since 10.0.
Geo secondary nodes now can keep track of replication status and recover 1. Run database migrations on tracking database
automatically from some replication issues. To get this feature enabled,
you need to activate the Tracking Database.
> **IMPORTANT:** For this feature to work correctly, all nodes must be
with their clocks synchronized. It is not required for all nodes to be set to
the same time zone, but when the respective times are converted to UTC time,
the clocks must be synchronized to within 60 seconds of each other.
1. Setup clock synchronization service in your Linux distro.
This can easily be done via any NTP-compatible daemon. For example,
here are [instructions for setting up NTP with Ubuntu](https://help.ubuntu.com/lts/serverguide/NTP.html).
1. Edit `/etc/gitlab/gitlab.rb`:
```
geo_postgresql['enable'] = true
```
1. Create `database_geo.yml` with the information of your secondary PostgreSQL
database. Note that GitLab will set up another database instance separate
from the primary, since this is where the secondary will track its internal
state:
```
sudo cp /opt/gitlab/embedded/service/gitlab-rails/config/database_geo.yml.postgresql /opt/gitlab/embedded/service/gitlab-rails/config/database_geo.yml
```
1. Edit the content of `database_geo.yml` in `production:` like the example below:
```yaml
#
# PRODUCTION
#
production:
adapter: postgresql
encoding: unicode
database: gitlabhq_geo_production
pool: 10
username: gitlab_geo
# password:
host: /var/opt/gitlab/geo-postgresql
port: 5431
```
1. Reconfigure GitLab:
```
sudo gitlab-ctl start
sudo gitlab-ctl reconfigure
```
1. Set up the Geo tracking database:
``` ```
sudo gitlab-rake geo:db:migrate sudo gitlab-rake geo:db:migrate
``` ```
1. Repeat this step for every secondary node
[update]: ../update/README.md [update]: ../update/README.md
...@@ -113,25 +113,25 @@ started: ...@@ -113,25 +113,25 @@ started:
1. Use the following command to list the private GPG key you just created: 1. Use the following command to list the private GPG key you just created:
``` ```
gpg --list-secret-keys --keyid-format 0xLONG mr@robot.sh gpg --list-secret-keys --keyid-format LONG mr@robot.sh
``` ```
Replace `mr@robot.sh` with the email address you entered above. Replace `mr@robot.sh` with the email address you entered above.
1. Copy the GPG key ID that starts with `sec`. In the following example, that's 1. Copy the GPG key ID that starts with `sec`. In the following example, that's
`0x30F2B65B9246B6CA`: `30F2B65B9246B6CA`:
``` ```
sec rsa4096/0x30F2B65B9246B6CA 2017-08-18 [SC] sec rsa4096/30F2B65B9246B6CA 2017-08-18 [SC]
D5E4F29F3275DC0CDA8FFC8730F2B65B9246B6CA D5E4F29F3275DC0CDA8FFC8730F2B65B9246B6CA
uid [ultimate] Mr. Robot <mr@robot.sh> uid [ultimate] Mr. Robot <mr@robot.sh>
ssb rsa4096/0xB7ABC0813E4028C0 2017-08-18 [E] ssb rsa4096/B7ABC0813E4028C0 2017-08-18 [E]
``` ```
1. Export the public key of that ID (replace your key ID from the previous step): 1. Export the public key of that ID (replace your key ID from the previous step):
``` ```
gpg --armor --export 0x30F2B65B9246B6CA gpg --armor --export 30F2B65B9246B6CA
``` ```
1. Finally, copy the public key and [add it in your profile settings](#adding-a-gpg-key-to-your-account) 1. Finally, copy the public key and [add it in your profile settings](#adding-a-gpg-key-to-your-account)
...@@ -167,28 +167,28 @@ key to use. ...@@ -167,28 +167,28 @@ key to use.
1. Use the following command to list the private GPG key you just created: 1. Use the following command to list the private GPG key you just created:
``` ```
gpg --list-secret-keys --keyid-format 0xLONG mr@robot.sh gpg --list-secret-keys --keyid-format LONG mr@robot.sh
``` ```
Replace `mr@robot.sh` with the email address you entered above. Replace `mr@robot.sh` with the email address you entered above.
1. Copy the GPG key ID that starts with `sec`. In the following example, that's 1. Copy the GPG key ID that starts with `sec`. In the following example, that's
`0x30F2B65B9246B6CA`: `30F2B65B9246B6CA`:
``` ```
sec rsa4096/0x30F2B65B9246B6CA 2017-08-18 [SC] sec rsa4096/30F2B65B9246B6CA 2017-08-18 [SC]
D5E4F29F3275DC0CDA8FFC8730F2B65B9246B6CA D5E4F29F3275DC0CDA8FFC8730F2B65B9246B6CA
uid [ultimate] Mr. Robot <mr@robot.sh> uid [ultimate] Mr. Robot <mr@robot.sh>
ssb rsa4096/0xB7ABC0813E4028C0 2017-08-18 [E] ssb rsa4096/B7ABC0813E4028C0 2017-08-18 [E]
``` ```
1. Tell Git to use that key to sign the commits: 1. Tell Git to use that key to sign the commits:
``` ```
git config --global user.signingkey 0x30F2B65B9246B6CA git config --global user.signingkey 30F2B65B9246B6CA
``` ```
Replace `0x30F2B65B9246B6CA` with your GPG key ID. Replace `30F2B65B9246B6CA` with your GPG key ID.
## Signing commits ## Signing commits
......
...@@ -54,5 +54,13 @@ module EE ...@@ -54,5 +54,13 @@ module EE
def board_sidebar_user_data def board_sidebar_user_data
super.merge(group_id: @group&.id) super.merge(group_id: @group&.id)
end end
def boards_link_text
if @project.multiple_issue_boards_available?(current_user)
"Boards"
else
"Board"
end
end
end end
end end
...@@ -106,6 +106,8 @@ module API ...@@ -106,6 +106,8 @@ module API
private private
def route_authentication_setting def route_authentication_setting
return {} unless respond_to?(:route_setting)
route_setting(:authentication) || {} route_setting(:authentication) || {}
end end
......
...@@ -2,14 +2,28 @@ task spec: ['geo:db:test:prepare'] ...@@ -2,14 +2,28 @@ task spec: ['geo:db:test:prepare']
namespace :geo do namespace :geo do
namespace :db do |ns| namespace :db do |ns|
%i(drop create setup migrate rollback seed version reset).each do |task_name| {
drop: 'Drops the Geo tracking database from config/database_geo.yml for the current RAILS_ENV.',
create: 'Creates the Geo tracking database from config/database_geo.yml for the current RAILS_ENV.',
setup: 'Create the Geo tracking database, load the schema, and initialize with the seed data.',
migrate: 'Migrate the Geo tracking database (options: VERSION=x, VERBOSE=false, SCOPE=blog).',
rollback: 'Rolls the schema back to the previous version (specify steps w/ STEP=n).',
seed: 'Load the seed data from db/geo/seeds.rb',
version: 'Retrieves the current schema version number.',
reset: 'Drops and recreates the database from db/geo/schema.rb for the current environment and loads the seeds.'
}.each do |task_name, task_desc|
desc task_desc
task task_name do task task_name do
Rake::Task["db:#{task_name}"].invoke Rake::Task["db:#{task_name}"].invoke
end end
end end
namespace :schema do namespace :schema do
%i(load dump).each do |task_name| {
load: 'Load a db/geo/schema.rb file into the database',
dump: 'Create a db/geo/schema.rb file that is portable against any DB supported by AR.'
}.each do |task_name, task_desc|
desc task_desc
task task_name do task task_name do
Rake::Task["db:schema:#{task_name}"].invoke Rake::Task["db:schema:#{task_name}"].invoke
end end
...@@ -17,7 +31,12 @@ namespace :geo do ...@@ -17,7 +31,12 @@ namespace :geo do
end end
namespace :migrate do namespace :migrate do
%i(up down redo).each do |task_name| {
up: 'Runs the "up" for a given migration VERSION.',
down: 'Runs the "down" for a given migration VERSION.',
redo: 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).'
}.each do |task_name, task_desc|
desc task_desc
task task_name do task task_name do
Rake::Task["db:migrate:#{task_name}"].invoke Rake::Task["db:migrate:#{task_name}"].invoke
end end
...@@ -25,6 +44,7 @@ namespace :geo do ...@@ -25,6 +44,7 @@ namespace :geo do
end end
namespace :test do namespace :test do
desc 'Check for pending migrations and load the test schema'
task :prepare do task :prepare do
Rake::Task['db:test:prepare'].invoke Rake::Task['db:test:prepare'].invoke
end end
......
...@@ -7,7 +7,7 @@ describe Groups::BillingsController do ...@@ -7,7 +7,7 @@ describe Groups::BillingsController do
describe 'GET index' do describe 'GET index' do
before do before do
stub_application_setting(check_namespace_plan: true) stub_application_setting(check_namespace_plan: true)
allow(Gitlab).to receive(:com?) { true } allow(Gitlab).to receive(:dev_env_or_com?) { true }
end end
context 'authorized' do context 'authorized' do
...@@ -46,7 +46,7 @@ describe Groups::BillingsController do ...@@ -46,7 +46,7 @@ describe Groups::BillingsController do
end end
it 'renders 404 when it is not gitlab.com' do it 'renders 404 when it is not gitlab.com' do
allow(Gitlab).to receive(:com?) { false } allow(Gitlab).to receive(:dev_env_or_com?) { false }
group.add_owner(user) group.add_owner(user)
sign_in(user) sign_in(user)
......
...@@ -47,7 +47,7 @@ feature 'Groups > Audit Events', :js do ...@@ -47,7 +47,7 @@ feature 'Groups > Audit Events', :js do
end end
# This is to avoid a Capybara::Poltergeist::MouseEventFailed error # This is to avoid a Capybara::Poltergeist::MouseEventFailed error
find('a[aria-label=Settings]').trigger('click') find(:link, text: 'Settings').trigger('click')
click_link 'Audit Events' click_link 'Audit Events'
......
...@@ -25,7 +25,7 @@ feature 'Group merge requests page' do ...@@ -25,7 +25,7 @@ feature 'Group merge requests page' do
end end
it 'ignores archived merge request count badges in navbar' do it 'ignores archived merge request count badges in navbar' do
expect( page.find('[aria-label="Merge Requests"] span.badge.count').text).to eq("1") expect(first(:link, text: 'Merge Requests').find('.badge').text).to eq("1")
end end
it 'ignores archived merge request count badges in state-filters' do it 'ignores archived merge request count badges in state-filters' do
......
...@@ -98,7 +98,7 @@ feature 'Projects > Audit Events', :js do ...@@ -98,7 +98,7 @@ feature 'Projects > Audit Events', :js do
end end
# This is to avoid a Capybara::Poltergeist::MouseEventFailed error # This is to avoid a Capybara::Poltergeist::MouseEventFailed error
find('a[aria-label=Settings]').trigger('click') find(:link, text: 'Settings').trigger('click')
click_link 'Audit Events' click_link 'Audit Events'
......
...@@ -104,6 +104,13 @@ describe GeoNodeStatus do ...@@ -104,6 +104,13 @@ describe GeoNodeStatus do
expect(subject.db_replication_lag).to eq(1000) expect(subject.db_replication_lag).to eq(1000)
end end
it "doesn't attempt to set replication lag if primary" do
expect(Gitlab::Geo::HealthCheck).not_to receive(:db_replication_lag)
expect(Gitlab::Geo).to receive(:secondary?).and_return(false)
expect(subject.db_replication_lag).to eq(nil)
end
end end
describe '#lfs_objects_synced_in_percentage' do describe '#lfs_objects_synced_in_percentage' do
...@@ -196,6 +203,14 @@ describe GeoNodeStatus do ...@@ -196,6 +203,14 @@ describe GeoNodeStatus do
expect(subject.cursor_last_event_id).to eq(event.event_id) expect(subject.cursor_last_event_id).to eq(event.event_id)
end end
it "doesn't attempt to retrieve cursor if primary" do
create(:geo_event_log_state)
expect(Gitlab::Geo).to receive(:secondary?).exactly(2).times.and_return(false)
expect(subject.cursor_last_event_date).to eq(nil)
expect(subject.cursor_last_event_id).to eq(nil)
end
end end
context 'when no values are available' do context 'when no values are available' do
......
require 'spec_helper' require 'spec_helper'
describe 'layouts/nav/sidebar/_project' do describe 'layouts/nav/sidebar/_project' do
let(:project) { create(:project, :repository) }
before do
assign(:project, project)
assign(:repository, project.repository)
allow(view).to receive(:current_ref).and_return('master')
allow(view).to receive(:can?).and_return(true)
end
describe 'issue boards' do
it 'has boards tab when multiple issue boards available' do
render
expect(rendered).to have_css('a[title="Boards"]')
end
it 'has board tab when multiple issue boards is not available' do
allow(License).to receive(:feature_available?).and_call_original
allow(License).to receive(:feature_available?).with(:multiple_issue_boards) { false }
render
expect(rendered).to have_css('a[title="Board"]')
end
end
describe 'container registry tab' do describe 'container registry tab' do
before do before do
project = create(:project, :repository)
stub_container_registry_config(enabled: true) stub_container_registry_config(enabled: true)
assign(:project, project)
assign(:repository, project.repository)
allow(view).to receive(:current_ref).and_return('master')
allow(view).to receive(:can?).and_return(true)
allow(controller).to receive(:controller_name) allow(controller).to receive(:controller_name)
.and_return('repositories') .and_return('repositories')
allow(controller).to receive(:controller_path) allow(controller).to receive(:controller_path)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment