From fcca3e6edd4eb83875d77564e98d1fa6ef504332 Mon Sep 17 00:00:00 2001 From: jean Date: Mon, 1 Aug 2016 03:38:16 +0000 Subject: [PATCH 001/177] add star for action scope, in order to delete image from registry --- app/services/auth/container_registry_authentication_service.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb index 5e151b0f044..c066fab04ab 100644 --- a/app/services/auth/container_registry_authentication_service.rb +++ b/app/services/auth/container_registry_authentication_service.rb @@ -103,6 +103,8 @@ module Auth build_can_pull?(requested_project) || user_can_pull?(requested_project) when 'push' build_can_push?(requested_project) || user_can_push?(requested_project) + when '*' + requested_project == project || can?(current_user, :create_container_image, requested_project) else false end From 8ef46b9f46711145496da4b3e64b0b7ace80c2ad Mon Sep 17 00:00:00 2001 From: Jean Praloran Date: Fri, 9 Sep 2016 11:16:42 +1200 Subject: [PATCH 002/177] change ability requirement --- app/services/auth/container_registry_authentication_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb index c066fab04ab..99a3d9c2cf9 100644 --- a/app/services/auth/container_registry_authentication_service.rb +++ b/app/services/auth/container_registry_authentication_service.rb @@ -104,7 +104,7 @@ module Auth when 'push' build_can_push?(requested_project) || user_can_push?(requested_project) when '*' - requested_project == project || can?(current_user, :create_container_image, requested_project) + requested_project == project || can?(current_user, :admin_container_image, requested_project) else false end From 6c9da292418c606aefe34aab40923d5730ae9aa5 Mon Sep 17 00:00:00 2001 From: Jean Praloran Date: Fri, 17 Mar 2017 11:19:12 +1300 Subject: [PATCH 003/177] add test and rebase --- ...ntainer_registry_authentication_service.rb | 7 +- ...er_registry_authentication_service_spec.rb | 92 ++++++++++++++++++- 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb index 99a3d9c2cf9..335cfdbc231 100644 --- a/app/services/auth/container_registry_authentication_service.rb +++ b/app/services/auth/container_registry_authentication_service.rb @@ -104,7 +104,7 @@ module Auth when 'push' build_can_push?(requested_project) || user_can_push?(requested_project) when '*' - requested_project == project || can?(current_user, :admin_container_image, requested_project) + user_can_delete?(requested_project) else false end @@ -122,6 +122,11 @@ module Auth (requested_project == project || can?(current_user, :build_read_container_image, requested_project)) end + def user_can_delete(requested_project) + has_authentication_ability?(:admin_container_image) && + can?(current_user, :admin_container_image, requested_project) + end + def user_can_pull?(requested_project) has_authentication_ability?(:read_container_image) && can?(current_user, :read_container_image, requested_project) diff --git a/spec/services/auth/container_registry_authentication_service_spec.rb b/spec/services/auth/container_registry_authentication_service_spec.rb index e273dfe1552..e8d222a2a7f 100644 --- a/spec/services/auth/container_registry_authentication_service_spec.rb +++ b/spec/services/auth/container_registry_authentication_service_spec.rb @@ -57,6 +57,12 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do it { expect(payload).to include('access' => []) } end + shared_examples 'a deletable' do + it_behaves_like 'a accessible' do + let(:actions) { ['*'] } + end + end + shared_examples 'a pullable' do it_behaves_like 'an accessible' do let(:actions) { ['pull'] } @@ -127,6 +133,16 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do it_behaves_like 'container repository factory' end + context 'disallow developer to delete images' do + before { project.team << [current_user, :developer] } + + let(:current_params) do + { scope: "repository:#{project.path_with_namespace}:*" } + end + + it_behaves_like 'an inaccessible' + end + context 'allow reporter to pull images' do before { project.team << [current_user, :reporter] } @@ -140,6 +156,16 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do end end + context 'disallow reporter to delete images' do + before { project.team << [current_user, :reporter] } + + let(:current_params) do + { scope: "repository:#{project.path_with_namespace}:*" } + end + + it_behaves_like 'an inaccessible' + end + context 'return a least of privileges' do before { project.team << [current_user, :reporter] } @@ -161,6 +187,16 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do it_behaves_like 'an inaccessible' it_behaves_like 'not a container repository factory' end + + context 'disallow guest to delete images' do + before { project.team << [current_user, :guest] } + + let(:current_params) do + { scope: "repository:#{project.path_with_namespace}:*" } + end + + it_behaves_like 'an inaccessible' + end end context 'for public project' do @@ -192,6 +228,14 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do it_behaves_like 'an inaccessible' it_behaves_like 'not a container repository factory' end + + context 'disallow anyone to delete images' do + let(:current_params) do + { scope: "repository:#{project.path_with_namespace}:*" } + end + + it_behaves_like 'an inaccessible' + end end context 'for internal project' do @@ -215,17 +259,53 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do it_behaves_like 'an inaccessible' it_behaves_like 'not a container repository factory' end + + context 'disallow anyone to delete images' do + let(:current_params) do + { scope: "repository:#{project.path_with_namespace}:*" } + end + + it_behaves_like 'an inaccessible' + end end context 'for external user' do let(:current_user) { create(:user, external: true) } let(:current_params) do - { scope: "repository:#{project.path_with_namespace}:pull,push" } + { scope: "repository:#{project.path_with_namespace}:pull,push,*" } end it_behaves_like 'an inaccessible' it_behaves_like 'not a container repository factory' end + + end + end + + context 'delete authorized as admin' do + let(:current_project) { create(:empty_project) } + let(:current_user) { create(:user) } + let(:authentication_abilities) do + [ + :build_read_container_image, + :build_create_container_image + ] + end + + before do + current_project.team << [current_project, :admin] + end + + it_behaves_like 'a valid token' + + context 'allow to delete images' do + let(:current_params) do + { scope: "repository:#{current_project.path_with_namespace}:*" } + end + + it_behaves_like 'a deletable' do + let(:project) { current_project } + end end end @@ -257,6 +337,16 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do end end + context 'disallow to delete images' do + let(:current_params) do + { scope: "repository:#{current_project.path_with_namespace}:*" } + end + + it_behaves_like 'an inaccessible' do + let(:project) { current_project } + end + end + context 'for other projects' do context 'when pulling' do let(:current_params) do From d890c6e81b696a5c02fe8138a76a4d113ee8ba93 Mon Sep 17 00:00:00 2001 From: Jean Praloran Date: Fri, 17 Mar 2017 16:40:57 +1300 Subject: [PATCH 004/177] fix typo and check --- .../auth/container_registry_authentication_service.rb | 2 +- .../container_registry_authentication_service_spec.rb | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb index 335cfdbc231..9622ce64d9f 100644 --- a/app/services/auth/container_registry_authentication_service.rb +++ b/app/services/auth/container_registry_authentication_service.rb @@ -122,7 +122,7 @@ module Auth (requested_project == project || can?(current_user, :build_read_container_image, requested_project)) end - def user_can_delete(requested_project) + def user_can_delete?(requested_project) has_authentication_ability?(:admin_container_image) && can?(current_user, :admin_container_image, requested_project) end diff --git a/spec/services/auth/container_registry_authentication_service_spec.rb b/spec/services/auth/container_registry_authentication_service_spec.rb index e8d222a2a7f..e617f1b0c04 100644 --- a/spec/services/auth/container_registry_authentication_service_spec.rb +++ b/spec/services/auth/container_registry_authentication_service_spec.rb @@ -278,7 +278,6 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do it_behaves_like 'an inaccessible' it_behaves_like 'not a container repository factory' end - end end @@ -287,15 +286,10 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do let(:current_user) { create(:user) } let(:authentication_abilities) do [ - :build_read_container_image, - :build_create_container_image + :admin_container_image ] end - before do - current_project.team << [current_project, :admin] - end - it_behaves_like 'a valid token' context 'allow to delete images' do From 2822081821f3f1e1e8cf8cfd8228ddb282b2d198 Mon Sep 17 00:00:00 2001 From: Jean Praloran Date: Fri, 17 Mar 2017 18:31:05 +1300 Subject: [PATCH 005/177] fix unit testing for admin --- .../auth/container_registry_authentication_service_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/services/auth/container_registry_authentication_service_spec.rb b/spec/services/auth/container_registry_authentication_service_spec.rb index e617f1b0c04..0609790893d 100644 --- a/spec/services/auth/container_registry_authentication_service_spec.rb +++ b/spec/services/auth/container_registry_authentication_service_spec.rb @@ -283,7 +283,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do context 'delete authorized as admin' do let(:current_project) { create(:empty_project) } - let(:current_user) { create(:user) } + let(:current_user) { create(:admin) } let(:authentication_abilities) do [ :admin_container_image From 9b9c86787a009c420536c65aecfa5823af88f665 Mon Sep 17 00:00:00 2001 From: Simon Knox Date: Tue, 25 Jul 2017 21:02:17 +1000 Subject: [PATCH 006/177] fix Jump to next discussion Notes tab was renamed to show, was previously overridden in merge_request_tabs.js --- .../diff_notes/components/jump_to_discussion.js | 10 +++++----- changelogs/unreleased/35232-next-unresolved.yml | 4 ++++ 2 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 changelogs/unreleased/35232-next-unresolved.yml diff --git a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js index 37ddca29e71..298f737a2bc 100644 --- a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js +++ b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js @@ -94,7 +94,7 @@ const JumpToDiscussion = Vue.extend({ hasDiscussionsToJumpTo = false; } } - } else if (activeTab !== 'notes') { + } else if (activeTab !== 'show') { // If we are on the commits or builds tabs, // there are no discussions to jump to. hasDiscussionsToJumpTo = false; @@ -103,12 +103,12 @@ const JumpToDiscussion = Vue.extend({ if (!hasDiscussionsToJumpTo) { // If there are no discussions to jump to on the current page, // switch to the notes tab and jump to the first disucssion there. - window.mrTabs.activateTab('notes'); - activeTab = 'notes'; + window.mrTabs.activateTab('show'); + activeTab = 'show'; jumpToFirstDiscussion = true; } - if (activeTab === 'notes') { + if (activeTab === 'show') { discussionsSelector = '.discussion[data-discussion-id]'; discussionIdsInScope = discussionIdsForElements($(discussionsSelector)); } @@ -156,7 +156,7 @@ const JumpToDiscussion = Vue.extend({ let $target = $(`${discussionsSelector}[data-discussion-id="${nextUnresolvedDiscussionId}"]`); - if (activeTab === 'notes') { + if (activeTab === 'show') { $target = $target.closest('.note-discussion'); // If the next discussion is closed, toggle it open. diff --git a/changelogs/unreleased/35232-next-unresolved.yml b/changelogs/unreleased/35232-next-unresolved.yml new file mode 100644 index 00000000000..45f3fb429a8 --- /dev/null +++ b/changelogs/unreleased/35232-next-unresolved.yml @@ -0,0 +1,4 @@ +--- +title: fix jump to next discussion button +merge_request: +author: From aaaa252e30e25afe58a39f97489a9a6eef92093e Mon Sep 17 00:00:00 2001 From: tauriedavis Date: Mon, 3 Jul 2017 10:51:32 -0700 Subject: [PATCH 007/177] 34060 Simply general project settings to use expanded panels --- app/assets/javascripts/dispatcher.js | 2 + app/assets/stylesheets/pages/projects.scss | 1 - app/assets/stylesheets/pages/settings.scss | 15 +- .../_merge_request_settings.html.haml | 7 +- app/views/projects/edit.html.haml | 367 +++++++++--------- 5 files changed, 202 insertions(+), 190 deletions(-) diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index 9d706b5ba59..8bd10b4954b 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -329,6 +329,8 @@ import GpgBadges from './gpg_badges'; break; case 'projects:edit': setupProjectEdit(); + // Initialize expandable settings panels + initSettingsPanels(); break; case 'projects:pipelines:builds': case 'projects:pipelines:failures': diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index b3a90dff89a..ab8b7defc72 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -36,7 +36,6 @@ } select { - background: transparent; transition: background 2s ease-out; &.highlight-changes { diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss index d69a8e0995c..1b53e78c954 100644 --- a/app/assets/stylesheets/pages/settings.scss +++ b/app/assets/stylesheets/pages/settings.scss @@ -54,8 +54,7 @@ .settings-content { max-height: 1px; overflow-y: scroll; - margin-right: -20px; - padding-right: 130px; + padding-right: 110px; animation: collapseMaxHeight 300ms ease-out; &.expanded { @@ -87,6 +86,18 @@ overflow: hidden; margin-top: 20px; } + + .sub-section { + margin-bottom: 32px; + padding: 16px; + border: 1px solid $border-color; + background-color: $gray-light; + } + + .bs-callout, + .checkbox:first-child { + margin-top: 0; + } } .settings-list-icon { diff --git a/app/views/projects/_merge_request_settings.html.haml b/app/views/projects/_merge_request_settings.html.haml index 818010bc7d3..2054a1ac787 100644 --- a/app/views/projects/_merge_request_settings.html.haml +++ b/app/views/projects/_merge_request_settings.html.haml @@ -1,8 +1,3 @@ - form = local_assigns.fetch(:form) -%fieldset.features.merge-requests-feature.append-bottom-default - %hr - %h5.prepend-top-0 - Merge Requests - - = render 'projects/merge_request_merge_settings', form: form += render 'projects/merge_request_merge_settings', form: form \ No newline at end of file diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 087cb804449..ef8b58f041c 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -1,13 +1,19 @@ +- page_title "General" - @content_class = "limit-container-width" unless fluid_layout +- expanded = Rails.env.test? = render "projects/settings/head" -.project-edit-container - .row.prepend-top-default - .col-lg-4.profile-settings-sidebar - %h4.prepend-top-0 - Project settings - .col-lg-8 - .project-edit-errors + +%section.settings.general-settings + .settings-header + %h4 + General project settings + %button.btn.js-settings-toggle + = expanded ? 'Collapse' : 'Expand' + %p + Update your project name, description, avatar, and other general settings. + .settings-content.no-animate{ class: ('expanded' if expanded) } + .project-edit-errors = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "edit-project" }, authenticity_token: true do |f| %fieldset .row @@ -35,89 +41,7 @@ = f.label :tag_list, "Tags", class: 'label-light' = f.text_field :tag_list, value: @project.tag_list.sort.join(', '), maxlength: 2000, class: "form-control" %p.help-block Separate tags with commas. - %hr - %fieldset - %h5.prepend-top-0 - Sharing & Permissions - .form_group.prepend-top-20.sharing-and-permissions - .row.js-visibility-select - .col-md-8 - .label-light - = label_tag :project_visibility, 'Project Visibility', class: 'label-light', for: :project_visibility_level - = link_to icon('question-circle'), help_page_path("public_access/public_access") - %span.help-block - .col-md-4.visibility-select-container - = render('projects/visibility_select', model_method: :visibility_level, form: f, selected_level: @project.visibility_level) - = f.fields_for :project_feature do |feature_fields| - %fieldset.features - .row - .col-md-8.project-feature - = feature_fields.label :repository_access_level, "Repository", class: 'label-light' - %span.help-block View and edit files in this project - .col-md-4.js-repo-access-level - = project_feature_access_select(:repository_access_level) - - .row - .col-md-8.project-feature.nested - = feature_fields.label :merge_requests_access_level, "Merge requests", class: 'label-light' - %span.help-block Submit changes to be merged upstream - .col-md-4 - = project_feature_access_select(:merge_requests_access_level) - - .row - .col-md-8.project-feature.nested - = feature_fields.label :builds_access_level, "Pipelines", class: 'label-light' - %span.help-block Build, test, and deploy your changes - .col-md-4 - = project_feature_access_select(:builds_access_level) - - .row - .col-md-8.project-feature - = feature_fields.label :snippets_access_level, "Snippets", class: 'label-light' - %span.help-block Share code pastes with others out of Git repository - .col-md-4 - = project_feature_access_select(:snippets_access_level) - - .row - .col-md-8.project-feature - = feature_fields.label :issues_access_level, "Issues", class: 'label-light' - %span.help-block Lightweight issue tracking system for this project - .col-md-4 - = project_feature_access_select(:issues_access_level) - - .row - .col-md-8.project-feature - = feature_fields.label :wiki_access_level, "Wiki", class: 'label-light' - %span.help-block Pages for project documentation - .col-md-4 - = project_feature_access_select(:wiki_access_level) - .form-group - = render 'shared/allow_request_access', form: f - - if Gitlab.config.lfs.enabled && current_user.admin? - .row.js-lfs-enabled - .col-md-8 - = f.label :lfs_enabled, 'LFS', class: 'label-light' - %span.help-block - Git Large File Storage - = link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs') - .col-md-4 - .select-wrapper - = f.select :lfs_enabled, [%w(Enabled true), %w(Disabled false)], {}, selected: @project.lfs_enabled?, class: 'pull-right form-control project-repo-select select-control', data: { field: 'lfs_enabled' } - = icon('chevron-down') - - if Gitlab.config.registry.enabled - .form-group.js-container-registry{ style: ("display: none;" if @project.project_feature.send(:repository_access_level) == 0) } - .checkbox - = f.label :container_registry_enabled do - = f.check_box :container_registry_enabled - %strong Container Registry - %br - %span.descr Enable Container Registry for this project - = link_to icon('question-circle'), help_page_path('user/project/container_registry'), target: '_blank' - - = render 'merge_request_settings', form: f - - %hr - %fieldset.features.append-bottom-default + %fieldset.features %h5.prepend-top-0 Project avatar .form-group @@ -137,91 +61,183 @@ = link_to 'Remove avatar', project_avatar_path(@project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar" = f.submit 'Save changes', class: "btn btn-save" - .row.prepend-top-default - %hr - .row.prepend-top-default - .col-lg-4 - %h4.prepend-top-0 - Housekeeping +%section.settings.sharing-permissions + .settings-header + %h4 + Sharing and permissions + %button.btn.js-settings-toggle + = expanded ? 'Collapse' : 'Expand' + %p + Enable or disable certain project features and choose access levels. + .settings-content.no-animate{ class: ('expaneded' if expanded) } + = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "sharing-permissions-form" }, authenticity_token: true do |f| + .form_group.sharing-and-permissions + .row.js-visibility-select + .col-md-8 + .label-light + = label_tag :project_visibility, 'Project Visibility', class: 'label-light', for: :project_visibility_level + = link_to icon('question-circle'), help_page_path("public_access/public_access") + %span.help-block + .col-md-4.visibility-select-container + = render('projects/visibility_select', model_method: :visibility_level, form: f, selected_level: @project.visibility_level) + = f.fields_for :project_feature do |feature_fields| + %fieldset.features + .row + .col-md-8.project-feature + = feature_fields.label :repository_access_level, "Repository", class: 'label-light' + %span.help-block View and edit files in this project + .col-md-4.js-repo-access-level + = project_feature_access_select(:repository_access_level) + + .row + .col-md-8.project-feature.nested + = feature_fields.label :merge_requests_access_level, "Merge requests", class: 'label-light' + %span.help-block Submit changes to be merged upstream + .col-md-4 + = project_feature_access_select(:merge_requests_access_level) + + .row + .col-md-8.project-feature.nested + = feature_fields.label :builds_access_level, "Pipelines", class: 'label-light' + %span.help-block Build, test, and deploy your changes + .col-md-4 + = project_feature_access_select(:builds_access_level) + + .row + .col-md-8.project-feature + = feature_fields.label :snippets_access_level, "Snippets", class: 'label-light' + %span.help-block Share code pastes with others out of Git repository + .col-md-4 + = project_feature_access_select(:snippets_access_level) + + .row + .col-md-8.project-feature + = feature_fields.label :issues_access_level, "Issues", class: 'label-light' + %span.help-block Lightweight issue tracking system for this project + .col-md-4 + = project_feature_access_select(:issues_access_level) + + .row + .col-md-8.project-feature + = feature_fields.label :wiki_access_level, "Wiki", class: 'label-light' + %span.help-block Pages for project documentation + .col-md-4 + = project_feature_access_select(:wiki_access_level) + .form-group + = render 'shared/allow_request_access', form: f + - if Gitlab.config.lfs.enabled && current_user.admin? + .row.js-lfs-enabled.form-group.sharing-and-permissions + .col-md-8 + = f.label :lfs_enabled, 'Git Large File Storage', class: 'label-light' + = link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs') + %span.help-block Manages large files such as audio, video and graphics files. + .col-md-4 + .select-wrapper + = f.select :lfs_enabled, [%w(Enabled true), %w(Disabled false)], {}, selected: @project.lfs_enabled?, class: 'pull-right form-control project-repo-select select-control', data: { field: 'lfs_enabled' } + = icon('chevron-down') + - if Gitlab.config.registry.enabled + .form-group.js-container-registry{ style: ("display: none;" if @project.project_feature.send(:repository_access_level) == 0) } + .checkbox + = f.label :container_registry_enabled do + = f.check_box :container_registry_enabled + %strong Container Registry + %br + %span.descr Enable Container Registry for this project + = link_to icon('question-circle'), help_page_path('user/project/container_registry'), target: '_blank' + = f.submit 'Save changes', class: "btn btn-save" + + +%section.settings.merge-request-settings{ style: ("display: none;" if @project.project_feature.send(:merge_requests_access_level) == 0) } + .settings-header + %h4 + Merge request settings + %button.btn.js-settings-toggle + = expanded ? 'Collapse' : 'Expand' + %p + Customize your merge request restrictions. + .settings-content.no-animate{ class: ('expanded' if expanded) } + = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "merge-request-settings" }, authenticity_token: true do |f| + = render 'merge_request_settings', form: f + = f.submit 'Save changes', class: "btn btn-save" + +%section.settings + .settings-header + %h4 + Export project + %button.btn.js-settings-toggle + = expanded ? 'Collapse' : 'Expand' + %p + Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the "New Project" page. + .settings-content.no-animate{ class: ('expanded' if expanded) } + .bs-callout.bs-callout-info %p.append-bottom-0 %p - Runs a number of housekeeping tasks within the current repository, - such as compressing file revisions and removing unreachable objects. - .col-lg-8 + The following items will be exported: + %ul + %li Project and wiki repositories + %li Project uploads + %li Project configuration including web hooks and services + %li Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities + %p + The following items will NOT be exported: + %ul + %li Job traces and artifacts + %li LFS objects + %li Container registry images + %li CI variables + %li Any encrypted tokens + %p + Once the exported file is ready, you will receive a notification email with a download link. + - if @project.export_project_path + = link_to 'Download export', download_export_project_path(@project), + rel: 'nofollow', download: '', method: :get, class: "btn btn-default" + = link_to 'Generate new export', generate_new_export_project_path(@project), + method: :post, class: "btn btn-default" + - else + = link_to 'Export project', export_project_path(@project), + method: :post, class: "btn btn-default" + +%section.settings.advanced-settings + .settings-header + %h4 + Advanced settings + %button.btn.js-settings-toggle + = expanded ? 'Collapse' : 'Expand' + %p + Perform advanced options such as housekeeping, exporting, archiveing, renameing, transfering, or removeing your project. + .settings-content.no-animate{ class: ('expanded' if expanded) } + .sub-section + %h4 Housekeeping + %p + Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects. = link_to 'Housekeeping', housekeeping_project_path(@project), method: :post, class: "btn btn-default" - %hr - .row.prepend-top-default - .col-lg-4 - %h4.prepend-top-0 - Export project - %p.append-bottom-0 - %p - Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the "New Project" page. - %p - Once the exported file is ready, you will receive a notification email with a download link. - - .col-lg-8 - - - if @project.export_project_path - = link_to 'Download export', download_export_project_path(@project), - rel: 'nofollow', download: '', method: :get, class: "btn btn-default" - = link_to 'Generate new export', generate_new_export_project_path(@project), - method: :post, class: "btn btn-default" - - else - = link_to 'Export project', export_project_path(@project), - method: :post, class: "btn btn-default" - - .bs-callout.bs-callout-info - %p.append-bottom-0 - %p - The following items will be exported: - %ul - %li Project and wiki repositories - %li Project uploads - %li Project configuration including web hooks and services - %li Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities - %p - The following items will NOT be exported: - %ul - %li Job traces and artifacts - %li LFS objects - %li Container registry images - %li CI variables - %li Any encrypted tokens - - if can? current_user, :archive_project, @project - %hr - .row.prepend-top-default - .col-lg-4 - %h4.warning-title.prepend-top-0 + - if can? current_user, :archive_project, @project + .sub-section + %h4.warning-title - if @project.archived? Unarchive project - else Archive project - %p.append-bottom-0 - - if @project.archived? - Unarchiving the project will mark its repository as active. The project can be committed to. - - else - Archiving the project will mark its repository as read-only. It is hidden from the dashboard and doesn't show up in searches. - .col-lg-8 - if @project.archived? %p + Unarchiving the project will mark its repository as active. The project can be committed to. %strong Once active this project shows up in the search and on the dashboard. = link_to 'Unarchive project', unarchive_project_path(@project), data: { confirm: "Are you sure that you want to unarchive this project?\nWhen this project is unarchived it is active and can be committed to again." }, method: :post, class: "btn btn-success" - else %p + Archiving the project will mark its repository as read-only. It is hidden from the dashboard and doesn't show up in searches. %strong Archived projects cannot be committed to! = link_to 'Archive project', archive_project_path(@project), data: { confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to." }, method: :post, class: "btn btn-warning" - %hr - .row.prepend-top-default - .col-lg-4 - %h4.prepend-top-0.warning-title + .sub-section.rename-respository + %h4.warning-title Rename repository - .col-lg-8 + %p + Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the "New Project" page. = render 'projects/errors' = form_for([@project.namespace.becomes(Namespace), @project]) do |f| .form-group.project_name_holder @@ -243,15 +259,11 @@ - if @project.deployment_services.any? %li Your deployment services will be broken, you will need to manually fix the services after renaming. = f.submit 'Rename project', class: "btn btn-warning" - - if can?(current_user, :change_namespace, @project) - %hr - .row.prepend-top-default - .col-lg-4 - %h4.prepend-top-0.danger-title - Transfer project to new group - %p.append-bottom-0 - Please select the group you want to transfer this project to in the dropdown to the right. - .col-lg-8 + + - if can?(current_user, :change_namespace, @project) + .sub-section + %h4.danger-title + Transfer project = form_for([@project.namespace.becomes(Namespace), @project], url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'js-project-transfer-form' } ) do |f| .form-group = label_tag :new_namespace_id, nil, class: 'label-light' do @@ -264,31 +276,24 @@ %li You will need to update your local repositories to point to the new location. %li Project visibility level will be changed to match namespace rules when transfering to a group. = f.submit 'Transfer project', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => transfer_project_message(@project) } - - if @project.forked? && can?(current_user, :remove_fork_project, @project) - %hr - .row.prepend-top-default.append-bottom-default - .col-lg-4 - %h4.prepend-top-0.danger-title + - if @project.forked? && can?(current_user, :remove_fork_project, @project) + .sub-section + %h4.danger-title Remove fork relationship - %p.append-bottom-0 - %p - This will remove the fork relationship to source project - = succeed "." do - = link_to @project.forked_from_project.name_with_namespace, project_path(@project.forked_from_project) - .col-lg-8 + %p + This will remove the fork relationship to source project + = succeed "." do + = link_to @project.forked_from_project.name_with_namespace, project_path(@project.forked_from_project) = form_for([@project.namespace.becomes(Namespace), @project], url: remove_fork_project_path(@project), method: :delete, remote: true, html: { class: 'transfer-project' }) do |f| %p %strong Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source. = button_to 'Remove fork relationship', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_message(@project) } - - if can?(current_user, :remove_project, @project) - %hr - .row.prepend-top-default.append-bottom-default - .col-lg-4 - %h4.prepend-top-0.danger-title + - if can?(current_user, :remove_project, @project) + .sub-section + %h4.danger-title Remove project - %p.append-bottom-0 + %p Removing the project will delete its repository and all related resources including issues, merge requests etc. - .col-lg-8 = form_tag(project_path(@project), method: :delete) do %p %strong Removed projects cannot be restored! From d7b8b38db7e22e247b0cac30645b1bc7647eeb3a Mon Sep 17 00:00:00 2001 From: tauriedavis Date: Wed, 12 Jul 2017 14:32:04 -0700 Subject: [PATCH 008/177] try and fix some tests --- app/views/projects/_merge_request_settings.html.haml | 2 +- spec/features/projects/features_visibility_spec.rb | 12 +++++++++--- spec/features/projects/project_settings_spec.rb | 8 ++++++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/app/views/projects/_merge_request_settings.html.haml b/app/views/projects/_merge_request_settings.html.haml index 2054a1ac787..cc5afa943cf 100644 --- a/app/views/projects/_merge_request_settings.html.haml +++ b/app/views/projects/_merge_request_settings.html.haml @@ -1,3 +1,3 @@ - form = local_assigns.fetch(:form) -= render 'projects/merge_request_merge_settings', form: form \ No newline at end of file += render 'projects/merge_request_merge_settings', form: form diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb index 37fa61d038e..bc58a8695d8 100644 --- a/spec/features/projects/features_visibility_spec.rb +++ b/spec/features/projects/features_visibility_spec.rb @@ -20,17 +20,23 @@ describe 'Edit Project Settings' do visit edit_project_path(project) select 'Disabled', from: "project_project_feature_attributes_#{tool_name}_access_level" - click_button 'Save changes' + page.within('.sharing-permissions') do + click_button 'Save changes' + end wait_for_requests expect(page).not_to have_selector(".shortcuts-#{shortcut_name}") select 'Everyone with access', from: "project_project_feature_attributes_#{tool_name}_access_level" - click_button 'Save changes' + page.within('.sharing-permissions') do + click_button 'Save changes' + end wait_for_requests expect(page).to have_selector(".shortcuts-#{shortcut_name}") select 'Only team members', from: "project_project_feature_attributes_#{tool_name}_access_level" - click_button 'Save changes' + page.within('.sharing-permissions') do + click_button 'Save changes' + end wait_for_requests expect(page).to have_selector(".shortcuts-#{shortcut_name}") diff --git a/spec/features/projects/project_settings_spec.rb b/spec/features/projects/project_settings_spec.rb index 6001bcfff0a..f9a24db648a 100644 --- a/spec/features/projects/project_settings_spec.rb +++ b/spec/features/projects/project_settings_spec.rb @@ -14,7 +14,9 @@ describe 'Edit Project Settings' do it 'shows errors for invalid project name' do visit edit_project_path(project) fill_in 'project_name_edit', with: 'foo&bar' - click_button 'Save changes' + page.within('.general-settings') do + click_button 'Save changes' + end expect(page).to have_field 'project_name_edit', with: 'foo&bar' expect(page).to have_content "Name can contain only letters, digits, emojis, '_', '.', dash, space. It must start with letter, digit, emoji or '_'." expect(page).to have_button 'Save changes' @@ -23,7 +25,9 @@ describe 'Edit Project Settings' do it 'shows a successful notice when the project is updated' do visit edit_project_path(project) fill_in 'project_name_edit', with: 'hello world' - click_button 'Save changes' + page.within('.general-settings') do + click_button 'Save changes' + end expect(page).to have_content "Project 'hello world' was successfully updated." end end From c8fbba43a8a92f3b96a0940d3439534c6b340f10 Mon Sep 17 00:00:00 2001 From: tauriedavis Date: Fri, 14 Jul 2017 08:40:15 -0700 Subject: [PATCH 009/177] css fixes --- app/assets/stylesheets/pages/settings.scss | 7 +- app/views/projects/edit.html.haml | 114 ++++++++++----------- 2 files changed, 63 insertions(+), 58 deletions(-) diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss index 1b53e78c954..15df51e9c69 100644 --- a/app/assets/stylesheets/pages/settings.scss +++ b/app/assets/stylesheets/pages/settings.scss @@ -95,9 +95,14 @@ } .bs-callout, - .checkbox:first-child { + .checkbox:first-child, + .help-block { margin-top: 0; } + + .label-light { + margin-bottom: 0; + } } .settings-list-icon { diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index ef8b58f041c..7af21df2834 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -61,68 +61,68 @@ = link_to 'Remove avatar', project_avatar_path(@project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar" = f.submit 'Save changes', class: "btn btn-save" -%section.settings.sharing-permissions - .settings-header - %h4 - Sharing and permissions - %button.btn.js-settings-toggle - = expanded ? 'Collapse' : 'Expand' - %p - Enable or disable certain project features and choose access levels. - .settings-content.no-animate{ class: ('expaneded' if expanded) } - = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "sharing-permissions-form" }, authenticity_token: true do |f| - .form_group.sharing-and-permissions - .row.js-visibility-select - .col-md-8 - .label-light - = label_tag :project_visibility, 'Project Visibility', class: 'label-light', for: :project_visibility_level - = link_to icon('question-circle'), help_page_path("public_access/public_access") - %span.help-block - .col-md-4.visibility-select-container - = render('projects/visibility_select', model_method: :visibility_level, form: f, selected_level: @project.visibility_level) - = f.fields_for :project_feature do |feature_fields| - %fieldset.features - .row - .col-md-8.project-feature - = feature_fields.label :repository_access_level, "Repository", class: 'label-light' - %span.help-block View and edit files in this project - .col-md-4.js-repo-access-level - = project_feature_access_select(:repository_access_level) + %section.settings.sharing-permissions + .settings-header + %h4 + Sharing and permissions + %button.btn.js-settings-toggle + = expanded ? 'Collapse' : 'Expand' + %p + Enable or disable certain project features and choose access levels. + .settings-content.no-animate{ class: ('expaneded' if expanded) } + = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "sharing-permissions-form" }, authenticity_token: true do |f| + .form-group.sharing-and-permissions + .row.js-visibility-select + .col-md-8 + .label-light + = label_tag :project_visibility, 'Project Visibility', class: 'label-light', for: :project_visibility_level + = link_to icon('question-circle'), help_page_path("public_access/public_access") + %span.help-block + .col-md-4.visibility-select-container + = render('projects/visibility_select', model_method: :visibility_level, form: f, selected_level: @project.visibility_level) + = f.fields_for :project_feature do |feature_fields| + %fieldset.features + .row + .col-md-8.project-feature + = feature_fields.label :repository_access_level, "Repository", class: 'label-light' + %span.help-block View and edit files in this project + .col-md-4.js-repo-access-level + = project_feature_access_select(:repository_access_level) - .row - .col-md-8.project-feature.nested - = feature_fields.label :merge_requests_access_level, "Merge requests", class: 'label-light' - %span.help-block Submit changes to be merged upstream - .col-md-4 - = project_feature_access_select(:merge_requests_access_level) + .row + .col-md-8.project-feature.nested + = feature_fields.label :merge_requests_access_level, "Merge requests", class: 'label-light' + %span.help-block Submit changes to be merged upstream + .col-md-4 + = project_feature_access_select(:merge_requests_access_level) + .row + .col-md-8.project-feature.nested + = feature_fields.label :builds_access_level, "Pipelines", class: 'label-light' + %span.help-block Build, test, and deploy your changes + .col-md-4 + = project_feature_access_select(:builds_access_level) - .row - .col-md-8.project-feature.nested - = feature_fields.label :builds_access_level, "Pipelines", class: 'label-light' - %span.help-block Build, test, and deploy your changes - .col-md-4 - = project_feature_access_select(:builds_access_level) + .row + .col-md-8.project-feature + = feature_fields.label :snippets_access_level, "Snippets", class: 'label-light' + %span.help-block Share code pastes with others out of Git repository + .col-md-4 + = project_feature_access_select(:snippets_access_level) - .row - .col-md-8.project-feature - = feature_fields.label :snippets_access_level, "Snippets", class: 'label-light' - %span.help-block Share code pastes with others out of Git repository - .col-md-4 - = project_feature_access_select(:snippets_access_level) + .row + .col-md-8.project-feature + = feature_fields.label :issues_access_level, "Issues", class: 'label-light' + %span.help-block Lightweight issue tracking system for this project + .col-md-4 + = project_feature_access_select(:issues_access_level) - .row - .col-md-8.project-feature - = feature_fields.label :issues_access_level, "Issues", class: 'label-light' - %span.help-block Lightweight issue tracking system for this project - .col-md-4 - = project_feature_access_select(:issues_access_level) + .row + .col-md-8.project-feature + = feature_fields.label :wiki_access_level, "Wiki", class: 'label-light' + %span.help-block Pages for project documentation + .col-md-4 + = project_feature_access_select(:wiki_access_level) - .row - .col-md-8.project-feature - = feature_fields.label :wiki_access_level, "Wiki", class: 'label-light' - %span.help-block Pages for project documentation - .col-md-4 - = project_feature_access_select(:wiki_access_level) .form-group = render 'shared/allow_request_access', form: f - if Gitlab.config.lfs.enabled && current_user.admin? From 7ea89083060d5f44f9b3fd4e3258798269ac883a Mon Sep 17 00:00:00 2001 From: tauriedavis Date: Tue, 25 Jul 2017 10:34:44 -0700 Subject: [PATCH 010/177] fix merge conflicts --- app/views/projects/edit.html.haml | 434 +++++++++++++++--------------- 1 file changed, 217 insertions(+), 217 deletions(-) diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 7af21df2834..8b1ea8fb6cb 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -4,62 +4,63 @@ = render "projects/settings/head" -%section.settings.general-settings - .settings-header - %h4 - General project settings - %button.btn.js-settings-toggle - = expanded ? 'Collapse' : 'Expand' - %p - Update your project name, description, avatar, and other general settings. - .settings-content.no-animate{ class: ('expanded' if expanded) } - .project-edit-errors - = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "edit-project" }, authenticity_token: true do |f| - %fieldset - .row - .form-group.col-md-9 - = f.label :name, class: 'label-light', for: 'project_name_edit' do - Project name - = f.text_field :name, class: "form-control", id: "project_name_edit" +.project-edit-container + %section.settings.general-settings + .settings-header + %h4 + General project settings + %button.btn.js-settings-toggle + = expanded ? 'Collapse' : 'Expand' + %p + Update your project name, description, avatar, and other general settings. + .settings-content.no-animate{ class: ('expanded' if expanded) } + .project-edit-errors + = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "edit-project" }, authenticity_token: true do |f| + %fieldset + .row + .form-group.col-md-9 + = f.label :name, class: 'label-light', for: 'project_name_edit' do + Project name + = f.text_field :name, class: "form-control", id: "project_name_edit" - .form-group.col-md-3 - = f.label :id, class: 'label-light' do - Project ID - = f.text_field :id, class: 'form-control', readonly: true + .form-group.col-md-3 + = f.label :id, class: 'label-light' do + Project ID + = f.text_field :id, class: 'form-control', readonly: true - .form-group - = f.label :description, class: 'label-light' do - Project description - %span.light (optional) - = f.text_area :description, class: "form-control", rows: 3, maxlength: 250 - - - unless @project.empty_repo? .form-group - = f.label :default_branch, "Default Branch", class: 'label-light' - = f.select(:default_branch, @project.repository.branch_names, {}, {class: 'select2 select-wide'}) - .form-group - = f.label :tag_list, "Tags", class: 'label-light' - = f.text_field :tag_list, value: @project.tag_list.sort.join(', '), maxlength: 2000, class: "form-control" - %p.help-block Separate tags with commas. - %fieldset.features - %h5.prepend-top-0 - Project avatar + = f.label :description, class: 'label-light' do + Project description + %span.light (optional) + = f.text_area :description, class: "form-control", rows: 3, maxlength: 250 + + - unless @project.empty_repo? + .form-group + = f.label :default_branch, "Default Branch", class: 'label-light' + = f.select(:default_branch, @project.repository.branch_names, {}, {class: 'select2 select-wide'}) .form-group - - if @project.avatar? - .avatar-container.s160 - = project_icon(@project.full_path, alt: '', class: 'avatar project-avatar s160') - %p.light - - if @project.avatar_in_git - Project avatar in repository: #{ @project.avatar_in_git } - %a.choose-btn.btn.js-choose-project-avatar-button - Browse file... - %span.file_name.prepend-left-default.js-avatar-filename No file chosen - = f.file_field :avatar, class: "js-project-avatar-input hidden" - .help-block The maximum file size allowed is 200KB. - - if @project.avatar? - %hr - = link_to 'Remove avatar', project_avatar_path(@project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar" - = f.submit 'Save changes', class: "btn btn-save" + = f.label :tag_list, "Tags", class: 'label-light' + = f.text_field :tag_list, value: @project.tag_list.sort.join(', '), maxlength: 2000, class: "form-control" + %p.help-block Separate tags with commas. + %fieldset.features + %h5.prepend-top-0 + Project avatar + .form-group + - if @project.avatar? + .avatar-container.s160 + = project_icon(@project.full_path, alt: '', class: 'avatar project-avatar s160') + %p.light + - if @project.avatar_in_git + Project avatar in repository: #{ @project.avatar_in_git } + %a.choose-btn.btn.js-choose-project-avatar-button + Browse file... + %span.file_name.prepend-left-default.js-avatar-filename No file chosen + = f.file_field :avatar, class: "js-project-avatar-input hidden" + .help-block The maximum file size allowed is 200KB. + - if @project.avatar? + %hr + = link_to 'Remove avatar', project_avatar_path(@project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar" + = f.submit 'Save changes', class: "btn btn-save" %section.settings.sharing-permissions .settings-header @@ -71,7 +72,7 @@ Enable or disable certain project features and choose access levels. .settings-content.no-animate{ class: ('expaneded' if expanded) } = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "sharing-permissions-form" }, authenticity_token: true do |f| - .form-group.sharing-and-permissions + .form_group.sharing-and-permissions .row.js-visibility-select .col-md-8 .label-light @@ -95,6 +96,7 @@ %span.help-block Submit changes to be merged upstream .col-md-4 = project_feature_access_select(:merge_requests_access_level) + .row .col-md-8.project-feature.nested = feature_fields.label :builds_access_level, "Pipelines", class: 'label-light' @@ -122,182 +124,180 @@ %span.help-block Pages for project documentation .col-md-4 = project_feature_access_select(:wiki_access_level) - - .form-group - = render 'shared/allow_request_access', form: f - - if Gitlab.config.lfs.enabled && current_user.admin? - .row.js-lfs-enabled.form-group.sharing-and-permissions - .col-md-8 - = f.label :lfs_enabled, 'Git Large File Storage', class: 'label-light' - = link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs') - %span.help-block Manages large files such as audio, video and graphics files. - .col-md-4 - .select-wrapper - = f.select :lfs_enabled, [%w(Enabled true), %w(Disabled false)], {}, selected: @project.lfs_enabled?, class: 'pull-right form-control project-repo-select select-control', data: { field: 'lfs_enabled' } - = icon('chevron-down') - - if Gitlab.config.registry.enabled - .form-group.js-container-registry{ style: ("display: none;" if @project.project_feature.send(:repository_access_level) == 0) } - .checkbox - = f.label :container_registry_enabled do - = f.check_box :container_registry_enabled - %strong Container Registry - %br - %span.descr Enable Container Registry for this project - = link_to icon('question-circle'), help_page_path('user/project/container_registry'), target: '_blank' - = f.submit 'Save changes', class: "btn btn-save" + .form-group + = render 'shared/allow_request_access', form: f + - if Gitlab.config.lfs.enabled && current_user.admin? + .row.js-lfs-enabled.form-group.sharing-and-permissions + .col-md-8 + = f.label :lfs_enabled, 'Git Large File Storage', class: 'label-light' + = link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs') + %span.help-block Manages large files such as audio, video and graphics files. + .col-md-4 + .select-wrapper + = f.select :lfs_enabled, [%w(Enabled true), %w(Disabled false)], {}, selected: @project.lfs_enabled?, class: 'pull-right form-control project-repo-select select-control', data: { field: 'lfs_enabled' } + = icon('chevron-down') + - if Gitlab.config.registry.enabled + .form-group.js-container-registry{ style: ("display: none;" if @project.project_feature.send(:repository_access_level) == 0) } + .checkbox + = f.label :container_registry_enabled do + = f.check_box :container_registry_enabled + %strong Container Registry + %br + %span.descr Enable Container Registry for this project + = link_to icon('question-circle'), help_page_path('user/project/container_registry'), target: '_blank' + = f.submit 'Save changes', class: "btn btn-save" -%section.settings.merge-request-settings{ style: ("display: none;" if @project.project_feature.send(:merge_requests_access_level) == 0) } - .settings-header - %h4 - Merge request settings - %button.btn.js-settings-toggle - = expanded ? 'Collapse' : 'Expand' - %p - Customize your merge request restrictions. - .settings-content.no-animate{ class: ('expanded' if expanded) } - = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "merge-request-settings" }, authenticity_token: true do |f| - = render 'merge_request_settings', form: f - = f.submit 'Save changes', class: "btn btn-save" - -%section.settings - .settings-header - %h4 - Export project - %button.btn.js-settings-toggle - = expanded ? 'Collapse' : 'Expand' - %p - Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the "New Project" page. - .settings-content.no-animate{ class: ('expanded' if expanded) } - .bs-callout.bs-callout-info - %p.append-bottom-0 - %p - The following items will be exported: - %ul - %li Project and wiki repositories - %li Project uploads - %li Project configuration including web hooks and services - %li Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities - %p - The following items will NOT be exported: - %ul - %li Job traces and artifacts - %li LFS objects - %li Container registry images - %li CI variables - %li Any encrypted tokens - %p - Once the exported file is ready, you will receive a notification email with a download link. - - if @project.export_project_path - = link_to 'Download export', download_export_project_path(@project), - rel: 'nofollow', download: '', method: :get, class: "btn btn-default" - = link_to 'Generate new export', generate_new_export_project_path(@project), - method: :post, class: "btn btn-default" - - else - = link_to 'Export project', export_project_path(@project), - method: :post, class: "btn btn-default" - -%section.settings.advanced-settings - .settings-header - %h4 - Advanced settings - %button.btn.js-settings-toggle - = expanded ? 'Collapse' : 'Expand' - %p - Perform advanced options such as housekeeping, exporting, archiveing, renameing, transfering, or removeing your project. - .settings-content.no-animate{ class: ('expanded' if expanded) } - .sub-section - %h4 Housekeeping + %section.settings.merge-request-settings{ style: ("display: none;" if @project.project_feature.send(:merge_requests_access_level) == 0) } + .settings-header + %h4 + Merge request settings + %button.btn.js-settings-toggle + = expanded ? 'Collapse' : 'Expand' %p - Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects. - = link_to 'Housekeeping', housekeeping_project_path(@project), - method: :post, class: "btn btn-default" - - if can? current_user, :archive_project, @project - .sub-section - %h4.warning-title - - if @project.archived? - Unarchive project - - else - Archive project - - if @project.archived? - %p - Unarchiving the project will mark its repository as active. The project can be committed to. - %strong Once active this project shows up in the search and on the dashboard. - = link_to 'Unarchive project', unarchive_project_path(@project), - data: { confirm: "Are you sure that you want to unarchive this project?\nWhen this project is unarchived it is active and can be committed to again." }, - method: :post, class: "btn btn-success" - - else - %p - Archiving the project will mark its repository as read-only. It is hidden from the dashboard and doesn't show up in searches. - %strong Archived projects cannot be committed to! - = link_to 'Archive project', archive_project_path(@project), - data: { confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to." }, - method: :post, class: "btn btn-warning" - .sub-section.rename-respository - %h4.warning-title - Rename repository + Customize your merge request restrictions. + .settings-content.no-animate{ class: ('expanded' if expanded) } + = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "merge-request-settings" }, authenticity_token: true do |f| + = render 'merge_request_settings', form: f + = f.submit 'Save changes', class: "btn btn-save" + + %section.settings + .settings-header + %h4 + Export project + %button.btn.js-settings-toggle + = expanded ? 'Collapse' : 'Expand' %p Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the "New Project" page. - = render 'projects/errors' - = form_for([@project.namespace.becomes(Namespace), @project]) do |f| - .form-group.project_name_holder - = f.label :name, class: 'label-light' do - Project name - .form-group - = f.text_field :name, class: "form-control" - .form-group - = f.label :path, class: 'label-light' do - %span Path - .form-group - .input-group - .input-group-addon - #{URI.join(root_url, @project.namespace.full_path)}/ - = f.text_field :path, class: 'form-control' + .settings-content.no-animate{ class: ('expanded' if expanded) } + .bs-callout.bs-callout-info + %p.append-bottom-0 + %p + The following items will be exported: %ul - %li Be careful. Renaming a project's repository can have unintended side effects. - %li You will need to update your local repositories to point to the new location. - - if @project.deployment_services.any? - %li Your deployment services will be broken, you will need to manually fix the services after renaming. - = f.submit 'Rename project', class: "btn btn-warning" + %li Project and wiki repositories + %li Project uploads + %li Project configuration including web hooks and services + %li Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities + %p + The following items will NOT be exported: + %ul + %li Job traces and artifacts + %li LFS objects + %li Container registry images + %li CI variables + %li Any encrypted tokens + %p + Once the exported file is ready, you will receive a notification email with a download link. + - if @project.export_project_path + = link_to 'Download export', download_export_project_path(@project), + rel: 'nofollow', download: '', method: :get, class: "btn btn-default" + = link_to 'Generate new export', generate_new_export_project_path(@project), + method: :post, class: "btn btn-default" + - else + = link_to 'Export project', export_project_path(@project), + method: :post, class: "btn btn-default" - - if can?(current_user, :change_namespace, @project) + %section.settings.advanced-settings + .settings-header + %h4 + Advanced settings + %button.btn.js-settings-toggle + = expanded ? 'Collapse' : 'Expand' + %p + Perform advanced options such as housekeeping, exporting, archiveing, renameing, transfering, or removeing your project. + .settings-content.no-animate{ class: ('expanded' if expanded) } .sub-section - %h4.danger-title - Transfer project - = form_for([@project.namespace.becomes(Namespace), @project], url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'js-project-transfer-form' } ) do |f| - .form-group - = label_tag :new_namespace_id, nil, class: 'label-light' do - %span Select a new namespace + %h4 Housekeeping + %p + Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects. + = link_to 'Run housekeeping', housekeeping_project_path(@project), + method: :post, class: "btn btn-default" + - if can? current_user, :archive_project, @project + .sub-section + %h4.warning-title + - if @project.archived? + Unarchive project + - else + Archive project + - if @project.archived? + %p + Unarchiving the project will mark its repository as active. The project can be committed to. + %strong Once active this project shows up in the search and on the dashboard. + = link_to 'Unarchive project', unarchive_project_path(@project), + data: { confirm: "Are you sure that you want to unarchive this project?\nWhen this project is unarchived it is active and can be committed to again." }, + method: :post, class: "btn btn-success" + - else + %p + Archiving the project will mark its repository as read-only. It is hidden from the dashboard and doesn't show up in searches. + %strong Archived projects cannot be committed to! + = link_to 'Archive project', archive_project_path(@project), + data: { confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to." }, + method: :post, class: "btn btn-warning" + .sub-section.rename-respository + %h4.warning-title + Rename repository + %p + Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the "New Project" page. + = render 'projects/errors' + = form_for([@project.namespace.becomes(Namespace), @project]) do |f| + .form-group.project_name_holder + = f.label :name, class: 'label-light' do + Project name .form-group - = select_tag :new_namespace_id, namespaces_options(nil), include_blank: true, class: 'select2' + = f.text_field :name, class: "form-control" + .form-group + = f.label :path, class: 'label-light' do + %span Path + .form-group + .input-group + .input-group-addon + #{URI.join(root_url, @project.namespace.full_path)}/ + = f.text_field :path, class: 'form-control' %ul - %li Be careful. Changing the project's namespace can have unintended side effects. - %li You can only transfer the project to namespaces you manage. + %li Be careful. Renaming a project's repository can have unintended side effects. %li You will need to update your local repositories to point to the new location. - %li Project visibility level will be changed to match namespace rules when transfering to a group. - = f.submit 'Transfer project', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => transfer_project_message(@project) } - - if @project.forked? && can?(current_user, :remove_fork_project, @project) - .sub-section - %h4.danger-title - Remove fork relationship - %p - This will remove the fork relationship to source project - = succeed "." do - = link_to @project.forked_from_project.name_with_namespace, project_path(@project.forked_from_project) - = form_for([@project.namespace.becomes(Namespace), @project], url: remove_fork_project_path(@project), method: :delete, remote: true, html: { class: 'transfer-project' }) do |f| + - if @project.deployment_services.any? + %li Your deployment services will be broken, you will need to manually fix the services after renaming. + = f.submit 'Rename project', class: "btn btn-warning" + - if can?(current_user, :change_namespace, @project) + .sub-section + %h4.danger-title + Transfer project + = form_for([@project.namespace.becomes(Namespace), @project], url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'js-project-transfer-form' } ) do |f| + .form-group + = label_tag :new_namespace_id, nil, class: 'label-light' do + %span Select a new namespace + .form-group + = select_tag :new_namespace_id, namespaces_options(nil), include_blank: true, class: 'select2' + %ul + %li Be careful. Changing the project's namespace can have unintended side effects. + %li You can only transfer the project to namespaces you manage. + %li You will need to update your local repositories to point to the new location. + %li Project visibility level will be changed to match namespace rules when transfering to a group. + = f.submit 'Transfer project', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => transfer_project_message(@project) } + - if @project.forked? && can?(current_user, :remove_fork_project, @project) + .sub-section + %h4.danger-title + Remove fork relationship %p - %strong Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source. - = button_to 'Remove fork relationship', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_message(@project) } - - if can?(current_user, :remove_project, @project) - .sub-section - %h4.danger-title - Remove project - %p - Removing the project will delete its repository and all related resources including issues, merge requests etc. - = form_tag(project_path(@project), method: :delete) do + This will remove the fork relationship to source project + = succeed "." do + = link_to @project.forked_from_project.name_with_namespace, project_path(@project.forked_from_project) + = form_for([@project.namespace.becomes(Namespace), @project], url: remove_fork_project_path(@project), method: :delete, remote: true, html: { class: 'transfer-project' }) do |f| + %p + %strong Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source. + = button_to 'Remove fork relationship', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_message(@project) } + - if can?(current_user, :remove_project, @project) + .sub-section + %h4.danger-title + Remove project %p - %strong Removed projects cannot be restored! - = button_to 'Remove project', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_project_message(@project) } + Removing the project will delete its repository and all related resources including issues, merge requests etc. + = form_tag(project_path(@project), method: :delete) do + %p + %strong Removed projects cannot be restored! + = button_to 'Remove project', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_project_message(@project) } .save-project-loader.hide .center @@ -306,4 +306,4 @@ Saving project. %p Please wait a moment, this page will automatically refresh when ready. -= render 'shared/confirm_modal', phrase: @project.path += render 'shared/confirm_modal', phrase: @project.path \ No newline at end of file From f8e5941d372b9b41dc76668932920b2af3fd3c28 Mon Sep 17 00:00:00 2001 From: tauriedavis Date: Tue, 25 Jul 2017 12:38:25 -0700 Subject: [PATCH 011/177] trying to fix tests --- app/views/projects/edit.html.haml | 4 ++-- .../settings/merge_requests_settings_spec.rb | 13 ++++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 8b1ea8fb6cb..3a2a544b205 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -157,7 +157,7 @@ %p Customize your merge request restrictions. .settings-content.no-animate{ class: ('expanded' if expanded) } - = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "merge-request-settings" }, authenticity_token: true do |f| + = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "merge-request-settings-form" }, authenticity_token: true do |f| = render 'merge_request_settings', form: f = f.submit 'Save changes', class: "btn btn-save" @@ -306,4 +306,4 @@ Saving project. %p Please wait a moment, this page will automatically refresh when ready. -= render 'shared/confirm_modal', phrase: @project.path \ No newline at end of file += render 'shared/confirm_modal', phrase: @project.path diff --git a/spec/features/projects/settings/merge_requests_settings_spec.rb b/spec/features/projects/settings/merge_requests_settings_spec.rb index 796e2026905..620f769995f 100644 --- a/spec/features/projects/settings/merge_requests_settings_spec.rb +++ b/spec/features/projects/settings/merge_requests_settings_spec.rb @@ -20,6 +20,9 @@ feature 'Project settings > Merge Requests', :js do expect(page).to have_content('Only allow merge requests to be merged if all discussions are resolved') select 'Disabled', from: "project_project_feature_attributes_merge_requests_access_level" + within('.sharing-permissions-form') do + click_on('Save changes') + end expect(page).not_to have_content('Only allow merge requests to be merged if the pipeline succeeds') expect(page).not_to have_content('Only allow merge requests to be merged if all discussions are resolved') @@ -37,6 +40,9 @@ feature 'Project settings > Merge Requests', :js do expect(page).to have_content('Only allow merge requests to be merged if all discussions are resolved') select 'Everyone with access', from: "project_project_feature_attributes_builds_access_level" + within('.sharing-permissions-form') do + click_on('Save changes') + end expect(page).to have_content('Only allow merge requests to be merged if the pipeline succeeds') expect(page).to have_content('Only allow merge requests to be merged if all discussions are resolved') @@ -55,6 +61,9 @@ feature 'Project settings > Merge Requests', :js do expect(page).not_to have_content('Only allow merge requests to be merged if all discussions are resolved') select 'Everyone with access', from: "project_project_feature_attributes_merge_requests_access_level" + within('.sharing-permissions-form') do + click_on('Save changes') + end expect(page).to have_content('Only allow merge requests to be merged if the pipeline succeeds') expect(page).to have_content('Only allow merge requests to be merged if all discussions are resolved') @@ -73,7 +82,9 @@ feature 'Project settings > Merge Requests', :js do scenario 'when unchecked sets :printing_merge_request_link_enabled to false' do uncheck('project_printing_merge_request_link_enabled') - click_on('Save') + within('.merge-request-settings-form') do + click_on('Save changes') + end # Wait for save to complete and page to reload checkbox = find_field('project_printing_merge_request_link_enabled') From 6ec561a2f7384e6de59821fa4bcd5b63f605cb51 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 28 Jul 2017 15:26:25 +0100 Subject: [PATCH 012/177] fixed up specs --- app/views/projects/edit.html.haml | 88 +++++++++---------- features/steps/project/project.rb | 16 +++- features/steps/shared/project.rb | 2 +- .../projects/features_visibility_spec.rb | 20 +++-- 4 files changed, 71 insertions(+), 55 deletions(-) diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 3a2a544b205..20fceda26dc 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -15,52 +15,52 @@ Update your project name, description, avatar, and other general settings. .settings-content.no-animate{ class: ('expanded' if expanded) } .project-edit-errors - = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "edit-project" }, authenticity_token: true do |f| - %fieldset - .row - .form-group.col-md-9 - = f.label :name, class: 'label-light', for: 'project_name_edit' do - Project name - = f.text_field :name, class: "form-control", id: "project_name_edit" + = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "edit-project" }, authenticity_token: true do |f| + %fieldset + .row + .form-group.col-md-9 + = f.label :name, class: 'label-light', for: 'project_name_edit' do + Project name + = f.text_field :name, class: "form-control", id: "project_name_edit" - .form-group.col-md-3 - = f.label :id, class: 'label-light' do - Project ID - = f.text_field :id, class: 'form-control', readonly: true + .form-group.col-md-3 + = f.label :id, class: 'label-light' do + Project ID + = f.text_field :id, class: 'form-control', readonly: true - .form-group - = f.label :description, class: 'label-light' do - Project description - %span.light (optional) - = f.text_area :description, class: "form-control", rows: 3, maxlength: 250 - - - unless @project.empty_repo? - .form-group - = f.label :default_branch, "Default Branch", class: 'label-light' - = f.select(:default_branch, @project.repository.branch_names, {}, {class: 'select2 select-wide'}) .form-group - = f.label :tag_list, "Tags", class: 'label-light' - = f.text_field :tag_list, value: @project.tag_list.sort.join(', '), maxlength: 2000, class: "form-control" - %p.help-block Separate tags with commas. - %fieldset.features - %h5.prepend-top-0 - Project avatar + = f.label :description, class: 'label-light' do + Project description + %span.light (optional) + = f.text_area :description, class: "form-control", rows: 3, maxlength: 250 + + - unless @project.empty_repo? .form-group - - if @project.avatar? - .avatar-container.s160 - = project_icon(@project.full_path, alt: '', class: 'avatar project-avatar s160') - %p.light - - if @project.avatar_in_git - Project avatar in repository: #{ @project.avatar_in_git } - %a.choose-btn.btn.js-choose-project-avatar-button - Browse file... - %span.file_name.prepend-left-default.js-avatar-filename No file chosen - = f.file_field :avatar, class: "js-project-avatar-input hidden" - .help-block The maximum file size allowed is 200KB. - - if @project.avatar? - %hr - = link_to 'Remove avatar', project_avatar_path(@project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar" - = f.submit 'Save changes', class: "btn btn-save" + = f.label :default_branch, "Default Branch", class: 'label-light' + = f.select(:default_branch, @project.repository.branch_names, {}, {class: 'select2 select-wide'}) + .form-group + = f.label :tag_list, "Tags", class: 'label-light' + = f.text_field :tag_list, value: @project.tag_list.sort.join(', '), maxlength: 2000, class: "form-control" + %p.help-block Separate tags with commas. + %fieldset.features + %h5.prepend-top-0 + Project avatar + .form-group + - if @project.avatar? + .avatar-container.s160 + = project_icon(@project.full_path, alt: '', class: 'avatar project-avatar s160') + %p.light + - if @project.avatar_in_git + Project avatar in repository: #{ @project.avatar_in_git } + %a.choose-btn.btn.js-choose-project-avatar-button + Browse file... + %span.file_name.prepend-left-default.js-avatar-filename No file chosen + = f.file_field :avatar, class: "js-project-avatar-input hidden" + .help-block The maximum file size allowed is 200KB. + - if @project.avatar? + %hr + = link_to 'Remove avatar', project_avatar_path(@project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar" + = f.submit 'Save changes', class: "btn btn-save" %section.settings.sharing-permissions .settings-header @@ -70,7 +70,7 @@ = expanded ? 'Collapse' : 'Expand' %p Enable or disable certain project features and choose access levels. - .settings-content.no-animate{ class: ('expaneded' if expanded) } + .settings-content.no-animate{ class: ('expanded' if expanded) } = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "sharing-permissions-form" }, authenticity_token: true do |f| .form_group.sharing-and-permissions .row.js-visibility-select @@ -148,7 +148,7 @@ = f.submit 'Save changes', class: "btn btn-save" - %section.settings.merge-request-settings{ style: ("display: none;" if @project.project_feature.send(:merge_requests_access_level) == 0) } + %section.settings.merge-requests-feature{ style: ("display: none;" if @project.project_feature.send(:merge_requests_access_level) == 0) } .settings-header %h4 Merge request settings diff --git a/features/steps/project/project.rb b/features/steps/project/project.rb index 170e2f16c80..0a89c1baf20 100644 --- a/features/steps/project/project.rb +++ b/features/steps/project/project.rb @@ -10,7 +10,9 @@ class Spinach::Features::Project < Spinach::FeatureSteps end step 'I save project' do - click_button 'Save changes' + page.within '.general-settings' do + click_button 'Save changes' + end end step 'I should see project with new settings' do @@ -31,7 +33,9 @@ class Spinach::Features::Project < Spinach::FeatureSteps :project_avatar, File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif') ) - click_button 'Save changes' + page.within '.general-settings' do + click_button 'Save changes' + end @project.reload end @@ -50,7 +54,9 @@ class Spinach::Features::Project < Spinach::FeatureSteps :project_avatar, File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif') ) - click_button 'Save changes' + page.within '.general-settings' do + click_button 'Save changes' + end @project.reload end @@ -69,7 +75,9 @@ class Spinach::Features::Project < Spinach::FeatureSteps step 'change project default branch' do select 'fix', from: 'project_default_branch' - click_button 'Save changes' + page.within '.general-settings' do + click_button 'Save changes' + end end step 'I should see project default branch changed' do diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb index da1cdd9f897..c9a63723212 100644 --- a/features/steps/shared/project.rb +++ b/features/steps/shared/project.rb @@ -103,7 +103,7 @@ module SharedProject step 'I should see project settings' do expect(current_path).to eq edit_project_path(@project) expect(page).to have_content("Project name") - expect(page).to have_content("Sharing & Permissions") + expect(page).to have_content("Sharing and permissions") end def current_project diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb index bc58a8695d8..4f2dd410b82 100644 --- a/spec/features/projects/features_visibility_spec.rb +++ b/spec/features/projects/features_visibility_spec.rb @@ -39,8 +39,6 @@ describe 'Edit Project Settings' do end wait_for_requests expect(page).to have_selector(".shortcuts-#{shortcut_name}") - - sleep 0.1 end end end @@ -180,7 +178,11 @@ describe 'Edit Project Settings' do it "disables repository related features" do select "Disabled", from: "project_project_feature_attributes_repository_access_level" - expect(find(".edit-project")).to have_selector("select.disabled", count: 2) + page.within('.sharing-permissions') do + click_button "Save changes" + end + + expect(find(".sharing-permissions")).to have_selector("select.disabled", count: 2) end it "shows empty features project homepage" do @@ -188,7 +190,9 @@ describe 'Edit Project Settings' do select "Disabled", from: "project_project_feature_attributes_issues_access_level" select "Disabled", from: "project_project_feature_attributes_wiki_access_level" - click_button "Save changes" + page.within('.sharing-permissions') do + click_button "Save changes" + end wait_for_requests visit project_path(project) @@ -201,7 +205,9 @@ describe 'Edit Project Settings' do select "Disabled", from: "project_project_feature_attributes_issues_access_level" select "Disabled", from: "project_project_feature_attributes_wiki_access_level" - click_button "Save changes" + page.within('.sharing-permissions') do + click_button "Save changes" + end wait_for_requests visit activity_project_path(project) @@ -242,7 +248,9 @@ describe 'Edit Project Settings' do end def save_changes_and_check_activity_tab - click_button "Save changes" + page.within('.sharing-permissions') do + click_button "Save changes" + end wait_for_requests visit activity_project_path(project) From a2ac5720ef982b9ed1012e9b64ab36679a303c52 Mon Sep 17 00:00:00 2001 From: AJ Jordan Date: Fri, 28 Jul 2017 21:19:05 +0000 Subject: [PATCH 013/177] Move API "basic usage" to be more visible --- doc/api/README.md | 62 +++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/doc/api/README.md b/doc/api/README.md index fe29563eaca..b16f31306a8 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -75,6 +75,37 @@ controller-specific endpoints. GraphQL has a number of benefits: It will co-exist with the current v4 REST API. If we have a v5 API, this should be a compatibility layer on top of GraphQL. +## Basic usage + +API requests should be prefixed with `api` and the API version. The API version +is defined in [`lib/api.rb`][lib-api-url]. + +For endpoints that require [authentication](#authentication), you need to pass +a `private_token` parameter via query string or header. If passed as a header, +the header name must be `PRIVATE-TOKEN` (uppercase and with a dash instead of +an underscore). + +Example of a valid API request: + +``` +GET /projects?private_token=9koXpg98eAheJpvBs5tK +``` + +Example of a valid API request using cURL and authentication via header: + +```shell +curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects" +``` + +Example of a valid API request using cURL and authentication via a query string: + +```shell +curl "https://gitlab.example.com/api/v4/projects?private_token=9koXpg98eAheJpvBs5tK" +``` + +The API uses JSON to serialize data. You don't need to specify `.json` at the +end of an API URL. + ## Authentication Most API requests require authentication via a session cookie or token. For @@ -205,37 +236,6 @@ GET /projects?private_token=9koXpg98eAheJpvBs5tK&sudo=23 curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --header "SUDO: 23" "https://gitlab.example.com/api/v4/projects" ``` -## Basic usage - -API requests should be prefixed with `api` and the API version. The API version -is defined in [`lib/api.rb`][lib-api-url]. - -For endpoints that require [authentication](#authentication), you need to pass -a `private_token` parameter via query string or header. If passed as a header, -the header name must be `PRIVATE-TOKEN` (uppercase and with a dash instead of -an underscore). - -Example of a valid API request: - -``` -GET /projects?private_token=9koXpg98eAheJpvBs5tK -``` - -Example of a valid API request using cURL and authentication via header: - -```shell -curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects" -``` - -Example of a valid API request using cURL and authentication via a query string: - -```shell -curl "https://gitlab.example.com/api/v4/projects?private_token=9koXpg98eAheJpvBs5tK" -``` - -The API uses JSON to serialize data. You don't need to specify `.json` at the -end of an API URL. - ## Status codes The API is designed to return different status codes according to context and From 97f58c78311c453a40498e74114817ffc6f79476 Mon Sep 17 00:00:00 2001 From: AJ Jordan Date: Fri, 28 Jul 2017 14:30:42 -0700 Subject: [PATCH 014/177] Explicitly spell out where the API root is I found this basic information extrememly hard to find when I looked at this page. --- doc/api/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/api/README.md b/doc/api/README.md index b16f31306a8..cb4ec88e868 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -78,7 +78,8 @@ be a compatibility layer on top of GraphQL. ## Basic usage API requests should be prefixed with `api` and the API version. The API version -is defined in [`lib/api.rb`][lib-api-url]. +is defined in [`lib/api.rb`][lib-api-url]. For example, the root of the v4 API +is at `/api/v4`. For endpoints that require [authentication](#authentication), you need to pass a `private_token` parameter via query string or header. If passed as a header, From 037b37297572eadab8b50917892eb285efc4383b Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Thu, 27 Jul 2017 17:49:49 -0500 Subject: [PATCH 015/177] ensure user profile calendar is generated based on server timezone, not local timezone --- app/assets/javascripts/users/activity_calendar.js | 12 ++++++++++-- app/assets/javascripts/users/user_tabs.js | 3 ++- app/views/users/show.html.haml | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/users/activity_calendar.js b/app/assets/javascripts/users/activity_calendar.js index f091e319f44..97b05fbd39e 100644 --- a/app/assets/javascripts/users/activity_calendar.js +++ b/app/assets/javascripts/users/activity_calendar.js @@ -6,6 +6,14 @@ const LOADING_HTML = ` `; +function getSystemDate(systemUtcOffsetSeconds) { + const date = new Date(); + const localUtcOffsetMinutes = 0 - date.getTimezoneOffset(); + const systemUtcOffsetMinutes = systemUtcOffsetSeconds / 60; + date.setMinutes((date.getMinutes() - localUtcOffsetMinutes) + systemUtcOffsetMinutes); + return date; +} + function formatTooltipText({ date, count }) { const dateObject = new Date(date); const dateDayName = gl.utils.getDayName(dateObject); @@ -21,7 +29,7 @@ function formatTooltipText({ date, count }) { const initColorKey = () => d3.scale.linear().range(['#acd5f2', '#254e77']).domain([0, 3]); export default class ActivityCalendar { - constructor(container, timestamps, calendarActivitiesPath) { + constructor(container, timestamps, calendarActivitiesPath, utcOffset = 0) { this.calendarActivitiesPath = calendarActivitiesPath; this.clickDay = this.clickDay.bind(this); this.currentSelectedDate = ''; @@ -36,7 +44,7 @@ export default class ActivityCalendar { this.timestampsTmp = []; let group = 0; - const today = new Date(); + const today = getSystemDate(utcOffset); today.setHours(0, 0, 0, 0, 0); const oneYearAgo = new Date(today); diff --git a/app/assets/javascripts/users/user_tabs.js b/app/assets/javascripts/users/user_tabs.js index 5fe6603ce7b..1f717f08c88 100644 --- a/app/assets/javascripts/users/user_tabs.js +++ b/app/assets/javascripts/users/user_tabs.js @@ -150,6 +150,7 @@ export default class UserTabs { const $calendarWrap = this.$parentEl.find('.user-calendar'); const calendarPath = $calendarWrap.data('calendarPath'); const calendarActivitiesPath = $calendarWrap.data('calendarActivitiesPath'); + const utcOffset = $calendarWrap.data('utcOffset'); $.ajax({ dataType: 'json', @@ -158,7 +159,7 @@ export default class UserTabs { $calendarWrap.html(CALENDAR_TEMPLATE); // eslint-disable-next-line no-new - new ActivityCalendar('.js-contrib-calendar', activityData, calendarActivitiesPath); + new ActivityCalendar('.js-contrib-calendar', activityData, calendarActivitiesPath, utcOffset); }, }); diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index a449706c567..879e0f99b14 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -104,7 +104,7 @@ .tab-content #activity.tab-pane .row-content-block.calender-block.white.second-block.hidden-xs - .user-calendar{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path } } + .user-calendar{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: Time.zone.utc_offset } } %h4.center.light %i.fa.fa-spinner.fa-spin .user-calendar-activities From 68de3ac129c59dc168bdef84b47954d684d5f074 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Thu, 27 Jul 2017 18:21:56 -0500 Subject: [PATCH 016/177] display system timezone underneath activity calendar --- app/assets/javascripts/users/user_tabs.js | 5 +++++ app/assets/stylesheets/framework/calendar.scss | 1 + 2 files changed, 6 insertions(+) diff --git a/app/assets/javascripts/users/user_tabs.js b/app/assets/javascripts/users/user_tabs.js index 1f717f08c88..1215b265e28 100644 --- a/app/assets/javascripts/users/user_tabs.js +++ b/app/assets/javascripts/users/user_tabs.js @@ -151,12 +151,17 @@ export default class UserTabs { const calendarPath = $calendarWrap.data('calendarPath'); const calendarActivitiesPath = $calendarWrap.data('calendarActivitiesPath'); const utcOffset = $calendarWrap.data('utcOffset'); + let utcFormatted = 'UTC'; + if (utcOffset !== 0) { + utcFormatted = `UTC${utcOffset > 0 ? '+' : ''}${(utcOffset / 3600)}`; + } $.ajax({ dataType: 'json', url: calendarPath, success: (activityData) => { $calendarWrap.html(CALENDAR_TEMPLATE); + $calendarWrap.find('.calendar-hint').append(`(Timezone: ${utcFormatted})`); // eslint-disable-next-line no-new new ActivityCalendar('.js-contrib-calendar', activityData, calendarActivitiesPath, utcOffset); diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss index 0ac095f7d8f..0ded4a3b423 100644 --- a/app/assets/stylesheets/framework/calendar.scss +++ b/app/assets/stylesheets/framework/calendar.scss @@ -45,6 +45,7 @@ margin-top: -23px; float: right; font-size: 12px; + direction: ltr; } .pika-single.gitlab-theme { From be77d76e7338ee40ecdad54cc40b3b5afa55f2b1 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Sat, 29 Jul 2017 00:36:54 -0500 Subject: [PATCH 017/177] use timezone-aware Date.current instead of Date.today in ContributionsCalendar class --- lib/gitlab/contributions_calendar.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/contributions_calendar.rb b/lib/gitlab/contributions_calendar.rb index bf557103cfd..b3d84e4b6d5 100644 --- a/lib/gitlab/contributions_calendar.rb +++ b/lib/gitlab/contributions_calendar.rb @@ -48,7 +48,7 @@ module Gitlab end def starting_month - Date.today.month + Date.current.month end private @@ -66,7 +66,7 @@ module Gitlab .select(:id) conditions = t[:created_at].gteq(date_from.beginning_of_day) - .and(t[:created_at].lteq(Date.today.end_of_day)) + .and(t[:created_at].lteq(Date.current.end_of_day)) .and(t[:author_id].eq(contributor.id)) Event.reorder(nil) From d1f5e81e8b80d8c322bb47c70728a2536d4708cc Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Sat, 29 Jul 2017 01:50:17 -0500 Subject: [PATCH 018/177] adjust timezone for date grouping in contributions calendar --- lib/gitlab/contributions_calendar.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/contributions_calendar.rb b/lib/gitlab/contributions_calendar.rb index b3d84e4b6d5..c1f84d07477 100644 --- a/lib/gitlab/contributions_calendar.rb +++ b/lib/gitlab/contributions_calendar.rb @@ -69,9 +69,11 @@ module Gitlab .and(t[:created_at].lteq(Date.current.end_of_day)) .and(t[:author_id].eq(contributor.id)) + timezone_adjust = "INTERVAL '#{Time.zone.now.utc_offset} SECONDS'" + Event.reorder(nil) - .select(t[:project_id], t[:target_type], t[:action], 'date(created_at) AS date', 'count(id) as total_amount') - .group(t[:project_id], t[:target_type], t[:action], 'date(created_at)') + .select(t[:project_id], t[:target_type], t[:action], "date(created_at + #{timezone_adjust}) AS date", 'count(id) as total_amount') + .group(t[:project_id], t[:target_type], t[:action], "date(created_at + #{timezone_adjust})") .where(conditions) .having(t[:project_id].in(Arel::Nodes::SqlLiteral.new(authed_projects.to_sql))) end From cf2d2cd323ad07783a4953144a7abedf37927633 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Mon, 31 Jul 2017 16:45:40 -0500 Subject: [PATCH 019/177] add tests for proper timezone date grouping within ContributionsCalendar --- .../lib/gitlab/contributions_calendar_spec.rb | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/spec/lib/gitlab/contributions_calendar_spec.rb b/spec/lib/gitlab/contributions_calendar_spec.rb index 79632e2b6a3..5f2fef42910 100644 --- a/spec/lib/gitlab/contributions_calendar_spec.rb +++ b/spec/lib/gitlab/contributions_calendar_spec.rb @@ -22,12 +22,14 @@ describe Gitlab::ContributionsCalendar do end end - let(:today) { Time.now.to_date } + let(:today) { Time.now.utc.to_date } + let(:yesterday) { today - 1.day } + let(:tomorrow) { today + 1.day } let(:last_week) { today - 7.days } let(:last_year) { today - 1.year } before do - travel_to today + travel_to Time.now.utc.end_of_day end after do @@ -38,7 +40,7 @@ describe Gitlab::ContributionsCalendar do described_class.new(contributor, current_user) end - def create_event(project, day) + def create_event(project, day, hour = 0) @targets ||= {} @targets[project] ||= create(:issue, project: project, author: contributor) @@ -47,7 +49,7 @@ describe Gitlab::ContributionsCalendar do action: Event::CREATED, target: @targets[project], author: contributor, - created_at: day + created_at: DateTime.new(day.year, day.month, day.day, hour) ) end @@ -68,6 +70,34 @@ describe Gitlab::ContributionsCalendar do expect(calendar(user).activity_dates[today]).to eq(0) expect(calendar(contributor).activity_dates[today]).to eq(2) end + + context "when events fall under different dates depending on the time zone" do + before do + create_event(public_project, today, 1) + create_event(public_project, today, 4) + create_event(public_project, today, 10) + create_event(public_project, today, 16) + create_event(public_project, today, 23) + end + + it "renders correct event counts within the UTC timezone" do + Time.use_zone('UTC') do + expect(calendar.activity_dates).to eq(today => 5) + end + end + + it "renders correct event counts within the Sydney timezone" do + Time.use_zone('Sydney') do + expect(calendar.activity_dates).to eq(today => 3, tomorrow => 2) + end + end + + it "renders correct event counts within the US Central timezone" do + Time.use_zone('Central Time (US & Canada)') do + expect(calendar.activity_dates).to eq(yesterday => 2, today => 3) + end + end + end end describe '#events_by_date' do From 1b9b6974fdfb49f10dfdd4bddde05aa8399ff9b1 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Mon, 31 Jul 2017 17:09:41 -0500 Subject: [PATCH 020/177] fix mysql syntax for date INTERVAL arithmatic --- lib/gitlab/contributions_calendar.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/gitlab/contributions_calendar.rb b/lib/gitlab/contributions_calendar.rb index c1f84d07477..aa261929fa9 100644 --- a/lib/gitlab/contributions_calendar.rb +++ b/lib/gitlab/contributions_calendar.rb @@ -69,11 +69,15 @@ module Gitlab .and(t[:created_at].lteq(Date.current.end_of_day)) .and(t[:author_id].eq(contributor.id)) - timezone_adjust = "INTERVAL '#{Time.zone.now.utc_offset} SECONDS'" + date_interval = if Gitlab::Database.postgresql? + "INTERVAL '#{Time.zone.now.utc_offset} seconds'" + else + "INTERVAL #{Time.zone.now.utc_offset} SECOND" + end Event.reorder(nil) - .select(t[:project_id], t[:target_type], t[:action], "date(created_at + #{timezone_adjust}) AS date", 'count(id) as total_amount') - .group(t[:project_id], t[:target_type], t[:action], "date(created_at + #{timezone_adjust})") + .select(t[:project_id], t[:target_type], t[:action], "date(created_at + #{date_interval}) AS date", 'count(id) as total_amount') + .group(t[:project_id], t[:target_type], t[:action], "date(created_at + #{date_interval})") .where(conditions) .having(t[:project_id].in(Arel::Nodes::SqlLiteral.new(authed_projects.to_sql))) end From 08c513b6d95c34d96bcc779f4c10318fafda2cb7 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Mon, 31 Jul 2017 18:19:18 -0500 Subject: [PATCH 021/177] =?UTF-8?q?fix=20rubocop=20violations=20?= =?UTF-8?q?=F0=9F=91=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/gitlab/contributions_calendar.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/gitlab/contributions_calendar.rb b/lib/gitlab/contributions_calendar.rb index aa261929fa9..0735243e021 100644 --- a/lib/gitlab/contributions_calendar.rb +++ b/lib/gitlab/contributions_calendar.rb @@ -70,10 +70,10 @@ module Gitlab .and(t[:author_id].eq(contributor.id)) date_interval = if Gitlab::Database.postgresql? - "INTERVAL '#{Time.zone.now.utc_offset} seconds'" - else - "INTERVAL #{Time.zone.now.utc_offset} SECOND" - end + "INTERVAL '#{Time.zone.now.utc_offset} seconds'" + else + "INTERVAL #{Time.zone.now.utc_offset} SECOND" + end Event.reorder(nil) .select(t[:project_id], t[:target_type], t[:action], "date(created_at + #{date_interval}) AS date", 'count(id) as total_amount') From 00e38789fef816eb787bf68a3db427f0f325c0e0 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Mon, 31 Jul 2017 23:14:32 -0500 Subject: [PATCH 022/177] adjust user contribution calendar time formatting --- app/views/users/calendar_activities.html.haml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/users/calendar_activities.html.haml b/app/views/users/calendar_activities.html.haml index 805a346a85e..6b1d75c6e72 100644 --- a/app/views/users/calendar_activities.html.haml +++ b/app/views/users/calendar_activities.html.haml @@ -1,6 +1,6 @@ %h4.prepend-top-20 Contributions for - %strong= @calendar_date.to_s(:short) + %strong= @calendar_date.to_s(:medium) - if @events.any? %ul.bordered-list @@ -8,7 +8,7 @@ %li %span.light %i.fa.fa-clock-o - = event.created_at.to_s(:time) + = event.created_at.strftime('%-I:%M%P') - if event.push? #{event.action_name} #{event.ref_type} %strong @@ -30,4 +30,4 @@ = event.project_name - else %p - No contributions found for #{@calendar_date.to_s(:short)} + No contributions found for #{@calendar_date.to_s(:medium)} From 013fe7643a531d2d705c364940155983a17d95c8 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Mon, 31 Jul 2017 23:24:05 -0500 Subject: [PATCH 023/177] add CHANGELOG.md for !13208 --- .../27616-fix-contributions-graph-utc-offset-mysql.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelogs/unreleased/27616-fix-contributions-graph-utc-offset-mysql.yml diff --git a/changelogs/unreleased/27616-fix-contributions-graph-utc-offset-mysql.yml b/changelogs/unreleased/27616-fix-contributions-graph-utc-offset-mysql.yml new file mode 100644 index 00000000000..1b3c3b8538d --- /dev/null +++ b/changelogs/unreleased/27616-fix-contributions-graph-utc-offset-mysql.yml @@ -0,0 +1,4 @@ +--- +title: Fix timezone inconsistencies in user contribution graph +merge_request: 13208 +author: From 15643ff91e3a01d6f090c0566abe4ded20ad1eb4 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Tue, 1 Aug 2017 13:20:22 -0700 Subject: [PATCH 024/177] implement #inspect for all Referables --- app/models/concerns/referable.rb | 12 ++++++++++++ app/models/user.rb | 5 +++++ 2 files changed, 17 insertions(+) diff --git a/app/models/concerns/referable.rb b/app/models/concerns/referable.rb index da803c7f481..10f4be72016 100644 --- a/app/models/concerns/referable.rb +++ b/app/models/concerns/referable.rb @@ -25,6 +25,18 @@ module Referable to_reference(from_project) end + def referable_inspect + if respond_to?(:id) + "#<#{self.class.name} id:#{id} #{to_reference(full: true)}>" + else + "#<#{self.class.name} #{to_reference(full: true)}>" + end + end + + def inspect + referable_inspect + end + module ClassMethods # The character that prefixes the actual reference identifier # diff --git a/app/models/user.rb b/app/models/user.rb index 6e66c587a1f..267eebb42ff 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -47,6 +47,11 @@ class User < ActiveRecord::Base devise :lockable, :recoverable, :rememberable, :trackable, :validatable, :omniauthable, :confirmable, :registerable + # devise overrides #inspect, so we manually use the Referable one + def inspect + referable_inspect + end + # Override Devise::Models::Trackable#update_tracked_fields! # to limit database writes to at most once every hour def update_tracked_fields!(request) From 215e0911e553eb4aa3fe81734006c9b3ba8eb6ba Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Thu, 27 Jul 2017 08:45:04 +0200 Subject: [PATCH 025/177] Migrate Gitlab::Git::Repository#count_commits to Gitaly Closes gitaly#415 --- Gemfile | 2 +- Gemfile.lock | 4 +- lib/gitlab/git/repository.rb | 33 ++++++++++----- lib/gitlab/gitaly_client/commit_service.rb | 5 ++- spec/lib/gitlab/git/repository_spec.rb | 48 +++++++++++++--------- 5 files changed, 59 insertions(+), 33 deletions(-) diff --git a/Gemfile b/Gemfile index a9a1cbc144d..403b104a9d6 100644 --- a/Gemfile +++ b/Gemfile @@ -391,7 +391,7 @@ gem 'vmstat', '~> 2.3.0' gem 'sys-filesystem', '~> 1.1.6' # Gitaly GRPC client -gem 'gitaly', '~> 0.21.0' +gem 'gitaly', '~> 0.23.0' gem 'toml-rb', '~> 0.3.15', require: false diff --git a/Gemfile.lock b/Gemfile.lock index 5a327a14c4a..9f90965a567 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -269,7 +269,7 @@ GEM po_to_json (>= 1.0.0) rails (>= 3.2.0) gherkin-ruby (0.3.2) - gitaly (0.21.0) + gitaly (0.23.0) google-protobuf (~> 3.1) grpc (~> 1.0) github-linguist (4.7.6) @@ -978,7 +978,7 @@ DEPENDENCIES gettext (~> 3.2.2) gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails_js (~> 1.2.0) - gitaly (~> 0.21.0) + gitaly (~> 0.23.0) github-linguist (~> 4.7.0) gitlab-flowdock-git-hook (~> 1.0.1) gitlab-markup (~> 1.5.1) diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 88529ba2c47..d79589dfca5 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -300,17 +300,14 @@ module Gitlab raw_log(options).map { |c| Commit.decorate(c) } end - # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/382 def count_commits(options) - cmd = %W[#{Gitlab.config.git.bin_path} --git-dir=#{path} rev-list] - cmd << "--after=#{options[:after].iso8601}" if options[:after] - cmd << "--before=#{options[:before].iso8601}" if options[:before] - cmd += %W[--count #{options[:ref]}] - cmd += %W[-- #{options[:path]}] if options[:path].present? - - raw_output = IO.popen(cmd) { |io| io.read } - - raw_output.to_i + gitaly_migrate(:count_commits) do |is_enabled| + if is_enabled + count_commits_by_gitaly(options) + else + count_commits_by_shelling_out(options) + end + end end def sha_from_ref(ref) @@ -998,6 +995,22 @@ module Gitlab gitaly_ref_client.tags end + def count_commits_by_gitaly(options) + gitaly_commit_client.commit_count(options[:ref], options) + end + + def count_commits_by_shelling_out(options) + cmd = %W[#{Gitlab.config.git.bin_path} --git-dir=#{path} rev-list] + cmd << "--after=#{options[:after].iso8601}" if options[:after] + cmd << "--before=#{options[:before].iso8601}" if options[:before] + cmd += %W[--count #{options[:ref]}] + cmd += %W[-- #{options[:path]}] if options[:path].present? + + raw_output = IO.popen(cmd) { |io| io.read } + + raw_output.to_i + end + def gitaly_migrate(method, &block) Gitlab::GitalyClient.migrate(method, &block) rescue GRPC::NotFound => e diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb index a834781b1f1..b1424a458e9 100644 --- a/lib/gitlab/gitaly_client/commit_service.rb +++ b/lib/gitlab/gitaly_client/commit_service.rb @@ -85,11 +85,14 @@ module Gitlab end end - def commit_count(ref) + def commit_count(ref, options = {}) request = Gitaly::CountCommitsRequest.new( repository: @gitaly_repo, revision: ref ) + request.after = Google::Protobuf::Timestamp.new(seconds: options[:after].to_i) if options[:after].present? + request.before = Google::Protobuf::Timestamp.new(seconds: options[:before].to_i) if options[:before].present? + request.path = options[:path] if options[:path].present? GitalyClient.call(@repository.storage, :commit_service, :count_commits, request).count end diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index 8e4a1f31ced..9bfad0c9bdf 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -361,20 +361,20 @@ describe Gitlab::Git::Repository, seed_helper: true do end describe '#commit_count' do - shared_examples 'counting commits' do + shared_examples 'simple commit counting' do it { expect(repository.commit_count("master")).to eq(25) } it { expect(repository.commit_count("feature")).to eq(9) } end context 'when Gitaly commit_count feature is enabled' do - it_behaves_like 'counting commits' + it_behaves_like 'simple commit counting' it_behaves_like 'wrapping gRPC errors', Gitlab::GitalyClient::CommitService, :commit_count do subject { repository.commit_count('master') } end end context 'when Gitaly commit_count feature is disabled', skip_gitaly_mock: true do - it_behaves_like 'counting commits' + it_behaves_like 'simple commit counting' end end @@ -797,28 +797,38 @@ describe Gitlab::Git::Repository, seed_helper: true do end describe '#count_commits' do - context 'with after timestamp' do - it 'returns the number of commits after timestamp' do - options = { ref: 'master', limit: nil, after: Time.iso8601('2013-03-03T20:15:01+00:00') } + shared_examples 'extended commit counting' do + context 'with after timestamp' do + it 'returns the number of commits after timestamp' do + options = { ref: 'master', limit: nil, after: Time.iso8601('2013-03-03T20:15:01+00:00') } - expect(repository.count_commits(options)).to eq(25) + expect(repository.count_commits(options)).to eq(25) + end + end + + context 'with before timestamp' do + it 'returns the number of commits before timestamp' do + options = { ref: 'feature', limit: nil, before: Time.iso8601('2015-03-03T20:15:01+00:00') } + + expect(repository.count_commits(options)).to eq(9) + end + end + + context 'with path' do + it 'returns the number of commits with path ' do + options = { ref: 'master', limit: nil, path: "encoding" } + + expect(repository.count_commits(options)).to eq(2) + end end end - context 'with before timestamp' do - it 'returns the number of commits after timestamp' do - options = { ref: 'feature', limit: nil, before: Time.iso8601('2015-03-03T20:15:01+00:00') } - - expect(repository.count_commits(options)).to eq(9) - end + context 'when Gitaly count_commits feature is enabled' do + it_behaves_like 'extended commit counting' end - context 'with path' do - it 'returns the number of commits with path ' do - options = { ref: 'master', limit: nil, path: "encoding" } - - expect(repository.count_commits(options)).to eq(2) - end + context 'when Gitaly count_commits feature is disabled', skip_gitaly_mock: true do + it_behaves_like 'extended commit counting' end end From 1cdc76f4559ff6d1ee0a1e6f277923094bff6f6c Mon Sep 17 00:00:00 2001 From: Maxime Visonneau Date: Tue, 23 May 2017 23:45:01 +0200 Subject: [PATCH 026/177] Implemented star auth capabilities on docker registry to enable deletion of images --- ...er_registry_authentication_service_spec.rb | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/spec/services/auth/container_registry_authentication_service_spec.rb b/spec/services/auth/container_registry_authentication_service_spec.rb index 7f704629bfa..a19ac911315 100644 --- a/spec/services/auth/container_registry_authentication_service_spec.rb +++ b/spec/services/auth/container_registry_authentication_service_spec.rb @@ -163,7 +163,9 @@ describe Auth::ContainerRegistryAuthenticationService do end context 'disallow reporter to delete images' do - before { project.team << [current_user, :reporter] } + before do + project.add_reporter(current_user) + end let(:current_params) do { scope: "repository:#{project.path_with_namespace}:*" } @@ -230,6 +232,14 @@ describe Auth::ContainerRegistryAuthenticationService do it_behaves_like 'not a container repository factory' end + context 'disallow anyone to delete images' do + let(:current_params) do + { scope: "repository:#{project.path_with_namespace}:*" } + end + + it_behaves_like 'an inaccessible' + end + context 'when repository name is invalid' do let(:current_params) do { scope: 'repository:invalid:push' } @@ -280,13 +290,25 @@ describe Auth::ContainerRegistryAuthenticationService do end context 'for external user' do - let(:current_user) { create(:user, external: true) } - let(:current_params) do - { scope: "repository:#{project.full_path}:pull,push,*" } + context 'disallow anyone to pull or push images' do + let(:current_user) { create(:user, external: true) } + let(:current_params) do + { scope: "repository:#{project.path_with_namespace}:pull,push" } + end + + it_behaves_like 'an inaccessible' + it_behaves_like 'not a container repository factory' end - it_behaves_like 'an inaccessible' - it_behaves_like 'not a container repository factory' + context 'disallow anyone to delete images' do + let(:current_user) { create(:user, external: true) } + let(:current_params) do + { scope: "repository:#{project.path_with_namespace}:*" } + end + + it_behaves_like 'an inaccessible' + it_behaves_like 'not a container repository factory' + end end end end From b3e058996c70aeae6f00cad7195bce421e02b39b Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 2 Aug 2017 17:27:21 +0800 Subject: [PATCH 027/177] Cleanup tests and add admin_container_image to full_authentication_abilities. This is fine because we're going to check with can?(..) anyway --- lib/gitlab/auth.rb | 3 +- spec/lib/gitlab/auth_spec.rb | 3 +- ...er_registry_authentication_service_spec.rb | 54 ++++++++++--------- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb index 9bed81e7327..7d3aa532750 100644 --- a/lib/gitlab/auth.rb +++ b/lib/gitlab/auth.rb @@ -218,7 +218,8 @@ module Gitlab def full_authentication_abilities read_authentication_abilities + [ :push_code, - :create_container_image + :create_container_image, + :admin_container_image ] end alias_method :api_scope_authentication_abilities, :full_authentication_abilities diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index a9db0d5164d..20bca4306fb 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -313,7 +313,8 @@ describe Gitlab::Auth do def full_authentication_abilities read_authentication_abilities + [ :push_code, - :create_container_image + :create_container_image, + :admin_container_image ] end end diff --git a/spec/services/auth/container_registry_authentication_service_spec.rb b/spec/services/auth/container_registry_authentication_service_spec.rb index a19ac911315..7ae7f4688a2 100644 --- a/spec/services/auth/container_registry_authentication_service_spec.rb +++ b/spec/services/auth/container_registry_authentication_service_spec.rb @@ -8,7 +8,7 @@ describe Auth::ContainerRegistryAuthenticationService do let(:payload) { JWT.decode(subject[:token], rsa_key).first } let(:authentication_abilities) do - [:read_container_image, :create_container_image] + [:read_container_image, :create_container_image, :admin_container_image] end subject do @@ -60,7 +60,7 @@ describe Auth::ContainerRegistryAuthenticationService do end shared_examples 'a deletable' do - it_behaves_like 'a accessible' do + it_behaves_like 'an accessible' do let(:actions) { ['*'] } end end @@ -126,7 +126,7 @@ describe Auth::ContainerRegistryAuthenticationService do context 'allow developer to push images' do before do - project.team << [current_user, :developer] + project.add_developer(current_user) end let(:current_params) do @@ -138,18 +138,21 @@ describe Auth::ContainerRegistryAuthenticationService do end context 'disallow developer to delete images' do - before { project.team << [current_user, :developer] } + before do + project.add_developer(current_user) + end let(:current_params) do { scope: "repository:#{project.path_with_namespace}:*" } end it_behaves_like 'an inaccessible' + it_behaves_like 'not a container repository factory' end context 'allow reporter to pull images' do before do - project.team << [current_user, :reporter] + project.add_reporter(current_user) end context 'when pulling from root level repository' do @@ -172,11 +175,12 @@ describe Auth::ContainerRegistryAuthenticationService do end it_behaves_like 'an inaccessible' + it_behaves_like 'not a container repository factory' end context 'return a least of privileges' do before do - project.team << [current_user, :reporter] + project.add_reporter(current_user) end let(:current_params) do @@ -189,7 +193,7 @@ describe Auth::ContainerRegistryAuthenticationService do context 'disallow guest to pull or push images' do before do - project.team << [current_user, :guest] + project.add_guest(current_user) end let(:current_params) do @@ -201,13 +205,16 @@ describe Auth::ContainerRegistryAuthenticationService do end context 'disallow guest to delete images' do - before { project.team << [current_user, :guest] } + before do + project.add_guest(current_user) + end let(:current_params) do { scope: "repository:#{project.path_with_namespace}:*" } end it_behaves_like 'an inaccessible' + it_behaves_like 'not a container repository factory' end end @@ -238,6 +245,7 @@ describe Auth::ContainerRegistryAuthenticationService do end it_behaves_like 'an inaccessible' + it_behaves_like 'not a container repository factory' end context 'when repository name is invalid' do @@ -248,14 +256,6 @@ describe Auth::ContainerRegistryAuthenticationService do it_behaves_like 'an inaccessible' it_behaves_like 'not a container repository factory' end - - context 'disallow anyone to delete images' do - let(:current_params) do - { scope: "repository:#{project.path_with_namespace}:*" } - end - - it_behaves_like 'an inaccessible' - end end context 'for internal project' do @@ -286,6 +286,7 @@ describe Auth::ContainerRegistryAuthenticationService do end it_behaves_like 'an inaccessible' + it_behaves_like 'not a container repository factory' end end @@ -313,13 +314,16 @@ describe Auth::ContainerRegistryAuthenticationService do end end - context 'delete authorized as admin' do + context 'delete authorized as master' do let(:current_project) { create(:empty_project) } - let(:current_user) { create(:admin) } + let(:current_user) { create(:user) } + let(:authentication_abilities) do - [ - :admin_container_image - ] + [:admin_container_image] + end + + before do + current_project.add_master(current_user) end it_behaves_like 'a valid token' @@ -344,7 +348,7 @@ describe Auth::ContainerRegistryAuthenticationService do end before do - current_project.team << [current_user, :developer] + current_project.add_developer(current_user) end it_behaves_like 'a valid token' @@ -394,7 +398,7 @@ describe Auth::ContainerRegistryAuthenticationService do context 'when you are member' do before do - project.team << [current_user, :developer] + project.add_developer(current_user) end it_behaves_like 'a pullable' @@ -424,7 +428,7 @@ describe Auth::ContainerRegistryAuthenticationService do context 'when you are member' do before do - project.team << [current_user, :developer] + project.add_developer(current_user) end it_behaves_like 'a pullable' @@ -451,7 +455,7 @@ describe Auth::ContainerRegistryAuthenticationService do let(:project) { create(:empty_project, :public) } before do - project.team << [current_user, :developer] + project.add_developer(current_user) end it_behaves_like 'an inaccessible' From f097e4dbcd26a0d122776b72ca4370890a0a3f76 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 2 Aug 2017 23:13:27 +0800 Subject: [PATCH 028/177] Don't send rejection mails for all auto-generated mails Also make it easier to have mailer helper --- app/workers/email_receiver_worker.rb | 2 -- .../28472-ignore-auto-generated-mails.yml | 4 +++ .../email/handler/create_note_handler.rb | 1 - lib/gitlab/email/receiver.rb | 4 +++ .../email/handler/create_note_handler_spec.rb | 9 ------- spec/lib/gitlab/email/receiver_spec.rb | 16 ++++++------ spec/spec_helper.rb | 6 ++++- spec/workers/email_receiver_worker_spec.rb | 26 +++++++++++++++---- 8 files changed, 42 insertions(+), 26 deletions(-) create mode 100644 changelogs/unreleased/28472-ignore-auto-generated-mails.yml diff --git a/app/workers/email_receiver_worker.rb b/app/workers/email_receiver_worker.rb index d3f7e479a8d..1afa24c8e2a 100644 --- a/app/workers/email_receiver_worker.rb +++ b/app/workers/email_receiver_worker.rb @@ -31,8 +31,6 @@ class EmailReceiverWorker when Gitlab::Email::EmptyEmailError can_retry = true "It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies." - when Gitlab::Email::AutoGeneratedEmailError - "The email was marked as 'auto generated', which we can't accept. Please create your comment through the web interface." when Gitlab::Email::UserNotFoundError "We couldn't figure out what user corresponds to the email. Please create your comment through the web interface." when Gitlab::Email::UserBlockedError diff --git a/changelogs/unreleased/28472-ignore-auto-generated-mails.yml b/changelogs/unreleased/28472-ignore-auto-generated-mails.yml new file mode 100644 index 00000000000..af63b43e62e --- /dev/null +++ b/changelogs/unreleased/28472-ignore-auto-generated-mails.yml @@ -0,0 +1,4 @@ +--- +title: Don't send rejection mails for all auto-generated mails +merge_request: 13254 +author: diff --git a/lib/gitlab/email/handler/create_note_handler.rb b/lib/gitlab/email/handler/create_note_handler.rb index 31579e94a87..8eea33b9ab5 100644 --- a/lib/gitlab/email/handler/create_note_handler.rb +++ b/lib/gitlab/email/handler/create_note_handler.rb @@ -15,7 +15,6 @@ module Gitlab def execute raise SentNotificationNotFoundError unless sent_notification - raise AutoGeneratedEmailError if mail.header.to_s =~ /auto-(generated|replied)/ validate_permission!(:create_note) diff --git a/lib/gitlab/email/receiver.rb b/lib/gitlab/email/receiver.rb index 0d6b08b5d29..b3c2a8fad3e 100644 --- a/lib/gitlab/email/receiver.rb +++ b/lib/gitlab/email/receiver.rb @@ -26,6 +26,10 @@ module Gitlab raise EmptyEmailError if @raw.blank? mail = build_mail + + raise AutoGeneratedEmailError if + mail.header.to_s =~ /auto-(generated|replied)/ + mail_key = extract_mail_key(mail) handler = Handler.for(mail, mail_key) diff --git a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb index 0127b012c91..d0fa16ce4d1 100644 --- a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb +++ b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb @@ -36,15 +36,6 @@ describe Gitlab::Email::Handler::CreateNoteHandler do end end - context "when the email was auto generated" do - let!(:mail_key) { '636ca428858779856c226bb145ef4fad' } - let!(:email_raw) { fixture_file("emails/auto_reply.eml") } - - it "raises an AutoGeneratedEmailError" do - expect { receiver.execute }.to raise_error(Gitlab::Email::AutoGeneratedEmailError) - end - end - context "when the noteable could not be found" do before do noteable.destroy diff --git a/spec/lib/gitlab/email/receiver_spec.rb b/spec/lib/gitlab/email/receiver_spec.rb index 88565ea5311..59f43abf26d 100644 --- a/spec/lib/gitlab/email/receiver_spec.rb +++ b/spec/lib/gitlab/email/receiver_spec.rb @@ -28,14 +28,6 @@ describe Gitlab::Email::Receiver do it "raises an UnknownIncomingEmail error" do expect { receiver.execute }.to raise_error(Gitlab::Email::UnknownIncomingEmail) end - - context "and the email contains no references header" do - let(:email_raw) { fixture_file("emails/auto_reply.eml").gsub(mail_key, "!!!") } - - it "raises an UnknownIncomingEmail error" do - expect { receiver.execute }.to raise_error(Gitlab::Email::UnknownIncomingEmail) - end - end end context "when the email is blank" do @@ -45,4 +37,12 @@ describe Gitlab::Email::Receiver do expect { receiver.execute }.to raise_error(Gitlab::Email::EmptyEmailError) end end + + context "when the email was auto generated" do + let(:email_raw) { fixture_file("emails/auto_reply.eml") } + + it "raises an AutoGeneratedEmailError" do + expect { receiver.execute }.to raise_error(Gitlab::Email::AutoGeneratedEmailError) + end + end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 609998d6e9c..06769b241ad 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -49,7 +49,7 @@ RSpec.configure do |config| config.include SearchHelpers, type: :feature config.include WaitForRequests, :js config.include StubConfiguration - config.include EmailHelpers, type: :mailer + config.include EmailHelpers, :mailer, type: :mailer config.include TestEnv config.include ActiveJob::TestHelper config.include ActiveSupport::Testing::TimeHelpers @@ -93,6 +93,10 @@ RSpec.configure do |config| RequestStore.clear! end + config.before(:example, :mailer) do + reset_delivered_emails! + end + if ENV['CI'] config.around(:each) do |ex| ex.run_with_retry retry: 2 diff --git a/spec/workers/email_receiver_worker_spec.rb b/spec/workers/email_receiver_worker_spec.rb index fe70501eeac..e4e77c667b3 100644 --- a/spec/workers/email_receiver_worker_spec.rb +++ b/spec/workers/email_receiver_worker_spec.rb @@ -1,6 +1,6 @@ require "spec_helper" -describe EmailReceiverWorker do +describe EmailReceiverWorker, :mailer do let(:raw_message) { fixture_file('emails/valid_reply.eml') } context "when reply by email is enabled" do @@ -17,12 +17,16 @@ describe EmailReceiverWorker do context "when an error occurs" do before do - allow_any_instance_of(Gitlab::Email::Receiver).to receive(:execute).and_raise(Gitlab::Email::EmptyEmailError) + allow_any_instance_of(Gitlab::Email::Receiver).to receive(:execute).and_raise(error) end - it "sends out a rejection email" do - perform_enqueued_jobs do - described_class.new.perform(raw_message) + context 'when the error is Gitlab::Email::EmptyEmailError' do + let(:error) { Gitlab::Email::EmptyEmailError } + + it 'sends out a rejection email' do + perform_enqueued_jobs do + described_class.new.perform(raw_message) + end email = ActionMailer::Base.deliveries.last expect(email).not_to be_nil @@ -30,6 +34,18 @@ describe EmailReceiverWorker do expect(email.subject).to include("Rejected") end end + + context 'when the error is Gitlab::Email::AutoGeneratedEmailError' do + let(:error) { Gitlab::Email::AutoGeneratedEmailError } + + it 'does not send out any rejection email' do + perform_enqueued_jobs do + described_class.new.perform(raw_message) + end + + should_not_email_anyone + end + end end end From 6a29d3a4875fa25bfe3ea0a8afb747cb7708e6a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Wed, 2 Aug 2017 11:39:16 +0200 Subject: [PATCH 029/177] Ensure we run installation Rake tasks in a clean env in TestEnv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we call `system('rake', 'taks_name')`, `ENV['RUBYOPT']` is set to `'-rbundler/setup'` but some tasks (e.g. `gitlab:gitaly:install` need a clean env since they install their own Gem bundle. Signed-off-by: Rémy Coutable --- lib/tasks/gitlab/gitaly.rake | 2 +- spec/support/test_env.rb | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/tasks/gitlab/gitaly.rake b/lib/tasks/gitlab/gitaly.rake index 680e76af471..3703f9cfb5c 100644 --- a/lib/tasks/gitlab/gitaly.rake +++ b/lib/tasks/gitlab/gitaly.rake @@ -21,7 +21,7 @@ namespace :gitlab do create_gitaly_configuration # In CI we run scripts/gitaly-test-build instead of this command unless ENV['CI'].present? - Bundler.with_original_env { run_command!(%w[/usr/bin/env -u BUNDLE_GEMFILE] + [command]) } + Bundler.with_original_env { run_command!([command]) } end end end diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index f0603dfadde..8a509cf8a9c 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -63,6 +63,8 @@ module TestEnv # See gitlab.yml.example test section for paths # def init(opts = {}) + Gitlab::Application.load_tasks + # Disable mailer for spinach tests disable_mailer if opts[:mailer] == false @@ -122,11 +124,13 @@ module TestEnv end def setup_gitlab_shell - shell_needs_update = component_needs_update?(Gitlab.config.gitlab_shell.path, + gitlab_shell_dir = File.dirname(Gitlab.config.gitlab_shell.path) + gitlab_shell_needs_update = component_needs_update?(gitlab_shell_dir, Gitlab::Shell.version_required) - unless !shell_needs_update || system('rake', 'gitlab:shell:install') - raise 'Can`t clone gitlab-shell' + unless !gitlab_shell_needs_update || Rake.application.invoke_task('gitlab:shell:install') + FileUtils.rm_rf(gitlab_shell_dir) + raise "Can't install gitlab-shell" end end @@ -136,8 +140,9 @@ module TestEnv gitaly_needs_update = component_needs_update?(gitaly_dir, Gitlab::GitalyClient.expected_server_version) - unless !gitaly_needs_update || system('rake', "gitlab:gitaly:install[#{gitaly_dir}]") - raise "Can't clone gitaly" + unless !gitaly_needs_update || Rake.application.invoke_task("gitlab:gitaly:install[#{gitaly_dir}]") + FileUtils.rm_rf(gitaly_dir) + raise "Can't install gitaly" end start_gitaly(gitaly_dir) From 532ad2e56e10ff0e7922980d48a8c639efac8809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Wed, 2 Aug 2017 19:01:14 +0200 Subject: [PATCH 030/177] Don't call load_tasks as this would load the tasks twice MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/support/test_env.rb | 6 ++++-- spec/tasks/gitlab/gitaly_rake_spec.rb | 10 ++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index 8a509cf8a9c..f88924e84fd 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -63,8 +63,8 @@ module TestEnv # See gitlab.yml.example test section for paths # def init(opts = {}) - Gitlab::Application.load_tasks - + Rake.application.rake_require 'tasks/gitlab/helpers' + Rake::Task.define_task :environment # Disable mailer for spinach tests disable_mailer if opts[:mailer] == false @@ -128,6 +128,7 @@ module TestEnv gitlab_shell_needs_update = component_needs_update?(gitlab_shell_dir, Gitlab::Shell.version_required) + Rake.application.rake_require 'tasks/gitlab/shell' unless !gitlab_shell_needs_update || Rake.application.invoke_task('gitlab:shell:install') FileUtils.rm_rf(gitlab_shell_dir) raise "Can't install gitlab-shell" @@ -140,6 +141,7 @@ module TestEnv gitaly_needs_update = component_needs_update?(gitaly_dir, Gitlab::GitalyClient.expected_server_version) + Rake.application.rake_require 'tasks/gitlab/gitaly' unless !gitaly_needs_update || Rake.application.invoke_task("gitlab:gitaly:install[#{gitaly_dir}]") FileUtils.rm_rf(gitaly_dir) raise "Can't install gitaly" diff --git a/spec/tasks/gitlab/gitaly_rake_spec.rb b/spec/tasks/gitlab/gitaly_rake_spec.rb index 695231c7d15..a2f4ec39d89 100644 --- a/spec/tasks/gitlab/gitaly_rake_spec.rb +++ b/spec/tasks/gitlab/gitaly_rake_spec.rb @@ -41,8 +41,6 @@ describe 'gitlab:gitaly namespace rake task' do end describe 'gmake/make' do - let(:command_preamble) { %w[/usr/bin/env -u BUNDLE_GEMFILE] } - before(:all) do @old_env_ci = ENV.delete('CI') end @@ -59,12 +57,12 @@ describe 'gitlab:gitaly namespace rake task' do context 'gmake is available' do before do expect_any_instance_of(Object).to receive(:checkout_or_clone_version) - allow_any_instance_of(Object).to receive(:run_command!).with(command_preamble + ['gmake']).and_return(true) + allow_any_instance_of(Object).to receive(:run_command!).with(['gmake']).and_return(true) end it 'calls gmake in the gitaly directory' do expect(Gitlab::Popen).to receive(:popen).with(%w[which gmake]).and_return(['/usr/bin/gmake', 0]) - expect_any_instance_of(Object).to receive(:run_command!).with(command_preamble + ['gmake']).and_return(true) + expect_any_instance_of(Object).to receive(:run_command!).with(['gmake']).and_return(true) run_rake_task('gitlab:gitaly:install', clone_path) end @@ -73,12 +71,12 @@ describe 'gitlab:gitaly namespace rake task' do context 'gmake is not available' do before do expect_any_instance_of(Object).to receive(:checkout_or_clone_version) - allow_any_instance_of(Object).to receive(:run_command!).with(command_preamble + ['make']).and_return(true) + allow_any_instance_of(Object).to receive(:run_command!).with(['make']).and_return(true) end it 'calls make in the gitaly directory' do expect(Gitlab::Popen).to receive(:popen).with(%w[which gmake]).and_return(['', 42]) - expect_any_instance_of(Object).to receive(:run_command!).with(command_preamble + ['make']).and_return(true) + expect_any_instance_of(Object).to receive(:run_command!).with(['make']).and_return(true) run_rake_task('gitlab:gitaly:install', clone_path) end From 29be4e0f58622aea146aa8c362eb30c08b082839 Mon Sep 17 00:00:00 2001 From: wendy0402 Date: Sun, 23 Jul 2017 15:19:10 +0700 Subject: [PATCH 031/177] Allow wiki pages to be renamed in the UI --- app/models/project_wiki.rb | 4 +- app/models/wiki_page.rb | 80 ++++++++++--------- app/services/wiki_pages/update_service.rb | 2 +- app/views/projects/wikis/_form.html.haml | 5 +- changelogs/unreleased/wiki_title.yml | 4 + features/steps/project/wiki.rb | 2 +- .../wiki/user_updates_wiki_page_spec.rb | 2 +- spec/models/project_wiki_spec.rb | 14 +++- spec/models/wiki_page_spec.rb | 35 +++++--- .../wiki_pages/update_service_spec.rb | 4 +- 10 files changed, 96 insertions(+), 56 deletions(-) create mode 100644 changelogs/unreleased/wiki_title.yml diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb index e8929a35836..698fdf7a20c 100644 --- a/app/models/project_wiki.rb +++ b/app/models/project_wiki.rb @@ -113,10 +113,10 @@ class ProjectWiki return false end - def update_page(page, content, format = :markdown, message = nil) + def update_page(page, content:, title: nil, format: :markdown, message: nil) commit = commit_details(:updated, message, page.title) - wiki.update_page(page, page.name, format.to_sym, content, commit) + wiki.update_page(page, title || page.name, format.to_sym, content, commit) update_project_activity end diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb index 148998bc9be..5c7c2204374 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -180,31 +180,50 @@ class WikiPage # # Returns the String SHA1 of the newly created page # or False if the save was unsuccessful. - def create(attr = {}) - @attributes.merge!(attr) + def create(attrs = {}) + @attributes.merge!(attrs) - save :create_page, title, content, format, message + save(page_details: title) do + wiki.create_page(title, content, format, message) + end end # Updates an existing Wiki Page, creating a new version. # - # new_content - The raw markup content to replace the existing. - # format - Optional symbol representing the content format. - # See ProjectWiki::MARKUPS Hash for available formats. - # message - Optional commit message to set on the new version. - # last_commit_sha - Optional last commit sha to validate the page unchanged. + # attrs - Hash of attributes to be updated on the page. + # :content - The raw markup content to replace the existing. + # :format - Optional symbol representing the content format. + # See ProjectWiki::MARKUPS Hash for available formats. + # :message - Optional commit message to set on the new version. + # :last_commit_sha - Optional last commit sha to validate the page unchanged. + # :title - The Title to replace existing title # # Returns the String SHA1 of the newly created page # or False if the save was unsuccessful. - def update(new_content, format: :markdown, message: nil, last_commit_sha: nil) - @attributes[:content] = new_content - @attributes[:format] = format - + def update(attrs = {}) + last_commit_sha = attrs.delete(:last_commit_sha) if last_commit_sha && last_commit_sha != self.last_commit_sha raise PageChangedError.new("You are attempting to update a page that has changed since you started editing it.") end - save :update_page, @page, content, format, message + attrs.slice!(:content, :format, :message, :title) + @attributes.merge!(attrs) + page_details = + if title.present? && @page.title != title + title + else + @page.url_path + end + + save(page_details: page_details) do + wiki.update_page( + @page, + content: content, + format: format, + message: attrs[:message], + title: title + ) + end end # Destroys the Wiki Page. @@ -236,30 +255,19 @@ class WikiPage attributes[:format] = @page.format end - def save(method, *args) - saved = false + def save(page_details:) + return unless valid? - project_wiki = wiki - if valid? && project_wiki.send(method, *args) - - page_details = if method == :update_page - # Use url_path instead of path to omit format extension - @page.url_path - else - title - end - - page_title, page_dir = project_wiki.page_title_and_dir(page_details) - gollum_wiki = project_wiki.wiki - @page = gollum_wiki.paged(page_title, page_dir) - - set_attributes - - @persisted = true - saved = true - else - errors.add(:base, project_wiki.error_message) if project_wiki.error_message + unless yield + errors.add(:base, wiki.error_message) + return false end - saved + + page_title, page_dir = wiki.page_title_and_dir(page_details) + gollum_wiki = wiki.wiki + @page = gollum_wiki.paged(page_title, page_dir) + + set_attributes + @persisted = errors.blank? end end diff --git a/app/services/wiki_pages/update_service.rb b/app/services/wiki_pages/update_service.rb index c628e6781af..93cbd9a509f 100644 --- a/app/services/wiki_pages/update_service.rb +++ b/app/services/wiki_pages/update_service.rb @@ -1,7 +1,7 @@ module WikiPages class UpdateService < WikiPages::BaseService def execute(page) - if page.update(@params[:content], format: @params[:format], message: @params[:message], last_commit_sha: @params[:last_commit_sha]) + if page.update(@params) execute_hooks(page, 'update') end diff --git a/app/views/projects/wikis/_form.html.haml b/app/views/projects/wikis/_form.html.haml index adb8d5aaecb..e5a1fccf9ba 100644 --- a/app/views/projects/wikis/_form.html.haml +++ b/app/views/projects/wikis/_form.html.haml @@ -3,9 +3,12 @@ = form_for [@project.namespace.becomes(Namespace), @project, @page], method: @page.persisted? ? :put : :post, html: { class: 'form-horizontal wiki-form common-note-form prepend-top-default js-quick-submit' } do |f| = form_errors(@page) - = f.hidden_field :title, value: @page.title - if @page.persisted? = f.hidden_field :last_commit_sha, value: @page.last_commit_sha + + .form-group + .col-sm-12= f.label :title, class: 'control-label-full-width' + .col-sm-12= f.text_field :title, class: 'form-control', value: @page.title .form-group .col-sm-12= f.label :format, class: 'control-label-full-width' .col-sm-12 diff --git a/changelogs/unreleased/wiki_title.yml b/changelogs/unreleased/wiki_title.yml new file mode 100644 index 00000000000..3ef5fa2969b --- /dev/null +++ b/changelogs/unreleased/wiki_title.yml @@ -0,0 +1,4 @@ +--- +title: Allow wiki pages to be renamed in the UI +merge_request: 10069 +author: wendy0402 diff --git a/features/steps/project/wiki.rb b/features/steps/project/wiki.rb index 2b8da2a6f19..855757e34b3 100644 --- a/features/steps/project/wiki.rb +++ b/features/steps/project/wiki.rb @@ -63,7 +63,7 @@ class Spinach::Features::ProjectWiki < Spinach::FeatureSteps end step 'That page has two revisions' do - @page.update("new content", message: "second commit") + @page.update(content: "new content", message: "second commit") end step 'I click the History button' do diff --git a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb index 8271428582d..90983ad60f4 100644 --- a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb +++ b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb @@ -55,7 +55,7 @@ feature 'Projects > Wiki > User updates wiki page' do scenario 'page has been updated since the user opened the edit page' do click_link 'Edit' - wiki_page.update('Update') + wiki_page.update(content: 'Update') click_button 'Save changes' diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb index 484fcfc88a3..a6f210f4bd5 100644 --- a/spec/models/project_wiki_spec.rb +++ b/spec/models/project_wiki_spec.rb @@ -223,7 +223,12 @@ describe ProjectWiki do before do create_page("update-page", "some content") @gollum_page = subject.wiki.paged("update-page") - subject.update_page(@gollum_page, "some other content", :markdown, "updated page") + subject.update_page( + @gollum_page, + content: "some other content", + format: :markdown, + message: "updated page" + ) @page = subject.pages.first.page end @@ -240,7 +245,12 @@ describe ProjectWiki do end it 'updates project activity' do - subject.update_page(@gollum_page, 'Yet more content', :markdown, 'Updated page again') + subject.update_page( + @gollum_page, + content: 'Yet more content', + format: :markdown, + message: 'Updated page again' + ) project.reload diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb index 55d9c4ddd7b..f3ef11aa3a8 100644 --- a/spec/models/wiki_page_spec.rb +++ b/spec/models/wiki_page_spec.rb @@ -178,12 +178,12 @@ describe WikiPage do end it "updates the content of the page" do - @page.update("new content") + @page.update(content: "new content") @page = wiki.find_page(title) end it "returns true" do - expect(@page.update("more content")).to be_truthy + expect(@page.update(content: "more content")).to be_truthy end end end @@ -195,29 +195,42 @@ describe WikiPage do end after do - destroy_page("Update") + destroy_page(@page.title) end context "with valid attributes" do it "updates the content of the page" do - @page.update("new content") + new_content = "new content" + + @page.update(content: new_content) @page = wiki.find_page("Update") + + expect(@page.content).to eq("new content") + end + + it "updates the title of the page" do + new_title = "Index v.1.2.4" + + @page.update(title: new_title) + @page = wiki.find_page(new_title) + + expect(@page.title).to eq(new_title) end it "returns true" do - expect(@page.update("more content")).to be_truthy + expect(@page.update(content: "more content")).to be_truthy end end context 'with same last commit sha' do it 'returns true' do - expect(@page.update('more content', last_commit_sha: @page.last_commit_sha)).to be_truthy + expect(@page.update(content: 'more content', last_commit_sha: @page.last_commit_sha)).to be_truthy end end context 'with different last commit sha' do it 'raises exception' do - expect { @page.update('more content', last_commit_sha: 'xxx') }.to raise_error(WikiPage::PageChangedError) + expect { @page.update(content: 'more content', last_commit_sha: 'xxx') }.to raise_error(WikiPage::PageChangedError) end end end @@ -249,7 +262,7 @@ describe WikiPage do end it "returns an array of all commits for the page" do - 3.times { |i| @page.update("content #{i}") } + 3.times { |i| @page.update(content: "content #{i}") } expect(@page.versions.count).to eq(4) end end @@ -294,7 +307,7 @@ describe WikiPage do before do create_page('Update', 'content') @page = wiki.find_page('Update') - 3.times { |i| @page.update("content #{i}") } + 3.times { |i| @page.update(content: "content #{i}") } end after do @@ -338,7 +351,7 @@ describe WikiPage do end it 'returns false for updated wiki page' do - updated_wiki_page = original_wiki_page.update("Updated content") + updated_wiki_page = original_wiki_page.update(content: "Updated content") expect(original_wiki_page).not_to eq(updated_wiki_page) end end @@ -360,7 +373,7 @@ describe WikiPage do it 'is changed after page updated' do last_commit_sha_before_update = @page.last_commit_sha - @page.update("new content") + @page.update(content: "new content") @page = wiki.find_page("Update") expect(@page.last_commit_sha).not_to eq last_commit_sha_before_update diff --git a/spec/services/wiki_pages/update_service_spec.rb b/spec/services/wiki_pages/update_service_spec.rb index a672c84034b..ec3613f74f7 100644 --- a/spec/services/wiki_pages/update_service_spec.rb +++ b/spec/services/wiki_pages/update_service_spec.rb @@ -9,7 +9,8 @@ describe WikiPages::UpdateService do { content: 'New content for wiki page', format: 'markdown', - message: 'New wiki message' + message: 'New wiki message', + title: 'New Title' } end @@ -27,6 +28,7 @@ describe WikiPages::UpdateService do expect(updated_page.message).to eq(opts[:message]) expect(updated_page.content).to eq(opts[:content]) expect(updated_page.format).to eq(opts[:format].to_sym) + expect(updated_page.title).to eq(opts[:title]) end it 'executes webhooks' do From 42feb55f20a6d2bab2d07f2f32bccb1b4ae28ba8 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 3 Aug 2017 10:20:02 +0100 Subject: [PATCH 032/177] Fixed sign-in restrictions buttons not toggling active state Closes #35882 --- app/assets/javascripts/commons/bootstrap.js | 1 + changelogs/unreleased/fix-oauth-checkboxes.yml | 4 ++++ spec/features/admin/admin_settings_spec.rb | 8 ++++++++ 3 files changed, 13 insertions(+) create mode 100644 changelogs/unreleased/fix-oauth-checkboxes.yml diff --git a/app/assets/javascripts/commons/bootstrap.js b/app/assets/javascripts/commons/bootstrap.js index 510bedbf641..389587a2596 100644 --- a/app/assets/javascripts/commons/bootstrap.js +++ b/app/assets/javascripts/commons/bootstrap.js @@ -9,6 +9,7 @@ import 'bootstrap-sass/assets/javascripts/bootstrap/tab'; import 'bootstrap-sass/assets/javascripts/bootstrap/transition'; import 'bootstrap-sass/assets/javascripts/bootstrap/tooltip'; import 'bootstrap-sass/assets/javascripts/bootstrap/popover'; +import 'bootstrap-sass/assets/javascripts/bootstrap/button'; // custom jQuery functions $.fn.extend({ diff --git a/changelogs/unreleased/fix-oauth-checkboxes.yml b/changelogs/unreleased/fix-oauth-checkboxes.yml new file mode 100644 index 00000000000..2839ccc42cb --- /dev/null +++ b/changelogs/unreleased/fix-oauth-checkboxes.yml @@ -0,0 +1,4 @@ +--- +title: Fixed sign-in restrictions buttons not toggling active state +merge_request: +author: diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index c1eced417cf..c9591a7d854 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -69,6 +69,14 @@ feature 'Admin updates settings' do expect(find('#service_push_channel').value).to eq '#test_channel' end + context 'sign-in restrictions', :js do + it 'de-activates oauth sign-in source' do + find('.btn', text: 'GitLab.com').click + + expect(find('.btn', text: 'GitLab.com')).not_to have_css('.active') + end + end + def check_all_events page.check('Active') page.check('Push') From 86e1f41b83448423a035707a971acc7ee76a0a8d Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 3 Aug 2017 19:29:18 +0800 Subject: [PATCH 033/177] Check against "Auto-Submitted: no" instead This would be much more accurate. We assume this is an auto-generated email if such header is provided, and the value is not "no". It could also be: "auto-generated", "auto-replied", or other values from extension. It seems that only "no" could mean that this is sent by a human. See: https://tools.ietf.org/html/rfc3834 --- lib/gitlab/email/receiver.rb | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/email/receiver.rb b/lib/gitlab/email/receiver.rb index b3c2a8fad3e..c8f4591d060 100644 --- a/lib/gitlab/email/receiver.rb +++ b/lib/gitlab/email/receiver.rb @@ -27,8 +27,7 @@ module Gitlab mail = build_mail - raise AutoGeneratedEmailError if - mail.header.to_s =~ /auto-(generated|replied)/ + ignore_auto_submitted!(mail) mail_key = extract_mail_key(mail) handler = Handler.for(mail, mail_key) @@ -91,6 +90,16 @@ module Gitlab break key if key end end + + def ignore_auto_submitted!(mail) + # Mail::Header#[] is case-insensitive + auto_submitted = mail.header['Auto-Submitted']&.value + + # Mail::Field#value would strip leading and trailing whitespace + raise AutoGeneratedEmailError if + # See also https://tools.ietf.org/html/rfc3834 + auto_submitted && auto_submitted != 'no' + end end end end From 6c95abf1734bf7bcfb52a9be28837b99a6a7cf8c Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 3 Aug 2017 13:44:09 +0200 Subject: [PATCH 034/177] Install 'yarn' globally to avoid PATH issues --- doc/install/installation.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 8ded607bcab..769c1fd3664 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -168,8 +168,10 @@ are out of date, so we'll need to install through the following commands: curl --location https://deb.nodesource.com/setup_7.x | sudo bash - sudo apt-get install -y nodejs - # install yarn - curl --location https://yarnpkg.com/install.sh | bash - + curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - + echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list + sudo apt-get update + sudo apt-get install yarn Visit the official websites for [node](https://nodejs.org/en/download/package-manager/) and [yarn](https://yarnpkg.com/en/docs/install/) if you have any trouble with these steps. From f2d50af917b878a98e06b994ac32c0718f3d0b78 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Mon, 3 Jul 2017 15:48:59 +0100 Subject: [PATCH 035/177] Migrate MR commits and diffs to new tables Previously, we stored these as serialised fields - `st_{commits,diffs}` - on the `merge_request_diffs` table. These now have their own tables - `merge_request_diff_{commits,diffs}` - with a column for each attribute of the serialised data. Add a background migration to go through the existing MR diffs and migrate them to the new format. Ignore any contents that cannot be displayed. Assuming that we have 5 million rows to migrate, and each batch of 2,500 rows can be completed in 5 minutes, this will take about 7 days to migrate everything. --- app/models/merge_request_diff.rb | 6 +- ..._schedule_merge_request_diff_migrations.rb | 33 +++ ...rialize_merge_request_diffs_and_commits.rb | 107 ++++++++++ ...ze_merge_request_diffs_and_commits_spec.rb | 188 ++++++++++++++++++ ...dule_merge_request_diff_migrations_spec.rb | 59 ++++++ 5 files changed, 388 insertions(+), 5 deletions(-) create mode 100644 db/post_migrate/20170703130158_schedule_merge_request_diff_migrations.rb create mode 100644 lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb create mode 100644 spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb create mode 100644 spec/migrations/schedule_merge_request_diff_migrations_spec.rb diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index ec87aee9310..d9d746ccf41 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -85,11 +85,7 @@ class MergeRequestDiff < ActiveRecord::Base def raw_diffs(options = {}) if options[:ignore_whitespace_change] - @diffs_no_whitespace ||= - Gitlab::Git::Compare.new( - repository.raw_repository, - safe_start_commit_sha, - head_commit_sha).diffs(options) + @diffs_no_whitespace ||= compare.diffs(options) else @raw_diffs ||= {} @raw_diffs[options] ||= load_diffs(options) diff --git a/db/post_migrate/20170703130158_schedule_merge_request_diff_migrations.rb b/db/post_migrate/20170703130158_schedule_merge_request_diff_migrations.rb new file mode 100644 index 00000000000..17a9dc293f1 --- /dev/null +++ b/db/post_migrate/20170703130158_schedule_merge_request_diff_migrations.rb @@ -0,0 +1,33 @@ +class ScheduleMergeRequestDiffMigrations < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + BATCH_SIZE = 2500 + MIGRATION = 'DeserializeMergeRequestDiffsAndCommits' + + disable_ddl_transaction! + + class MergeRequestDiff < ActiveRecord::Base + self.table_name = 'merge_request_diffs' + + include ::EachBatch + end + + # Assuming that there are 5 million rows affected (which is more than on + # GitLab.com), and that each batch of 2,500 rows takes up to 5 minutes, then + # we can migrate all the rows in 7 days. + # + # On staging, plucking the IDs themselves takes 5 seconds. + def up + non_empty = 'st_commits IS NOT NULL OR st_diffs IS NOT NULL' + + MergeRequestDiff.where(non_empty).each_batch(of: BATCH_SIZE) do |relation, index| + range = relation.pluck('MIN(id)', 'MAX(id)').first + + BackgroundMigrationWorker.perform_in(index * 5.minutes, MIGRATION, range) + end + end + + def down + end +end diff --git a/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb b/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb new file mode 100644 index 00000000000..0fbc6b70989 --- /dev/null +++ b/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb @@ -0,0 +1,107 @@ +module Gitlab + module BackgroundMigration + class DeserializeMergeRequestDiffsAndCommits + attr_reader :diff_ids, :commit_rows, :file_rows + + class MergeRequestDiff < ActiveRecord::Base + self.table_name = 'merge_request_diffs' + end + + BUFFER_ROWS = 1000 + + def perform(start_id, stop_id) + merge_request_diffs = MergeRequestDiff + .select(:id, :st_commits, :st_diffs) + .where('st_commits IS NOT NULL OR st_diffs IS NOT NULL') + .where(id: start_id..stop_id) + + reset_buffers! + + merge_request_diffs.each do |merge_request_diff| + commits, files = single_diff_rows(merge_request_diff) + + diff_ids << merge_request_diff.id + commit_rows.concat(commits) + file_rows.concat(files) + + if diff_ids.length > BUFFER_ROWS || + commit_rows.length > BUFFER_ROWS || + file_rows.length > BUFFER_ROWS + + flush_buffers! + end + end + + flush_buffers! + end + + private + + def reset_buffers! + @diff_ids = [] + @commit_rows = [] + @file_rows = [] + end + + def flush_buffers! + if diff_ids.any? + MergeRequestDiff.transaction do + Gitlab::Database.bulk_insert('merge_request_diff_commits', commit_rows) + Gitlab::Database.bulk_insert('merge_request_diff_files', file_rows) + + MergeRequestDiff.where(id: diff_ids).update_all(st_commits: nil, st_diffs: nil) + end + end + + reset_buffers! + end + + def single_diff_rows(merge_request_diff) + sha_attribute = Gitlab::Database::ShaAttribute.new + commits = YAML.load(merge_request_diff.st_commits) rescue [] + + commit_rows = commits.map.with_index do |commit, index| + commit_hash = commit.to_hash.with_indifferent_access.except(:parent_ids) + sha = commit_hash.delete(:id) + + commit_hash.merge( + merge_request_diff_id: merge_request_diff.id, + relative_order: index, + sha: sha_attribute.type_cast_for_database(sha) + ) + end + + diffs = YAML.load(merge_request_diff.st_diffs) rescue [] + diffs = [] unless valid_raw_diffs?(diffs) + + file_rows = diffs.map.with_index do |diff, index| + diff_hash = diff.to_hash.with_indifferent_access.merge( + binary: false, + merge_request_diff_id: merge_request_diff.id, + relative_order: index + ) + + # Compatibility with old diffs created with Psych. + diff_hash.tap do |hash| + diff_text = hash[:diff] + + if diff_text.encoding == Encoding::BINARY && !diff_text.ascii_only? + hash[:binary] = true + hash[:diff] = [diff_text].pack('m0') + end + end + end + + [commit_rows, file_rows] + end + + # Unlike MergeRequestDiff#valid_raw_diff?, don't count Rugged objects as + # valid, because we don't render them usefully anyway. + def valid_raw_diffs?(diffs) + return false unless diffs.respond_to?(:each) + + diffs.all? { |diff| diff.is_a?(Hash) } + end + end + end +end diff --git a/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb b/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb new file mode 100644 index 00000000000..18843cbe992 --- /dev/null +++ b/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb @@ -0,0 +1,188 @@ +require 'spec_helper' + +describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits do + describe '#perform' do + set(:merge_request) { create(:merge_request) } + set(:merge_request_diff) { merge_request.merge_request_diff } + let(:updated_merge_request_diff) { MergeRequestDiff.find(merge_request_diff.id) } + + def diffs_to_hashes(diffs) + diffs.as_json(only: Gitlab::Git::Diff::SERIALIZE_KEYS).map(&:with_indifferent_access) + end + + def quote_yaml(value) + MergeRequestDiff.connection.quote(YAML.dump(value)) + end + + def convert_to_yaml(merge_request_diff_id, commits, diffs) + MergeRequestDiff.where(id: merge_request_diff_id).update_all( + "st_commits = #{quote_yaml(commits)}, st_diffs = #{quote_yaml(diffs)}" + ) + end + + shared_examples 'updated MR diff' do + before do + convert_to_yaml(merge_request_diff.id, commits, diffs) + + MergeRequestDiffCommit.delete_all + MergeRequestDiffFile.delete_all + + subject.perform(merge_request_diff.id, merge_request_diff.id) + end + + it 'creates correct entries in the merge_request_diff_commits table' do + expect(updated_merge_request_diff.merge_request_diff_commits.count).to eq(commits.count) + expect(updated_merge_request_diff.commits.map(&:to_hash)).to eq(commits) + end + + it 'creates correct entries in the merge_request_diff_files table' do + expect(updated_merge_request_diff.merge_request_diff_files.count).to eq(expected_diffs.count) + expect(diffs_to_hashes(updated_merge_request_diff.raw_diffs)).to eq(expected_diffs) + end + + it 'sets the st_commits and st_diffs columns to nil' do + expect(updated_merge_request_diff.st_commits_before_type_cast).to be_nil + expect(updated_merge_request_diff.st_diffs_before_type_cast).to be_nil + end + end + + context 'when the diff IDs passed do not exist' do + it 'does not raise' do + expect { subject.perform(0, 0) }.not_to raise_exception + end + end + + context 'when the merge request diff has no serialised commits or diffs' do + before do + merge_request_diff.update(st_commits: nil, st_diffs: nil) + end + + it 'does not raise' do + expect { subject.perform(merge_request_diff.id, merge_request_diff.id) } + .not_to raise_exception + end + end + + context 'processing multiple merge request diffs' do + let(:start_id) { described_class::MergeRequestDiff.minimum(:id) } + let(:stop_id) { described_class::MergeRequestDiff.maximum(:id) } + + before do + merge_request.reload_diff(true) + + convert_to_yaml(start_id, merge_request_diff.commits, merge_request_diff.diffs) + convert_to_yaml(stop_id, updated_merge_request_diff.commits, updated_merge_request_diff.diffs) + + MergeRequestDiffCommit.delete_all + MergeRequestDiffFile.delete_all + end + + context 'when BUFFER_ROWS is exceeded' do + before do + stub_const("#{described_class}::BUFFER_ROWS", 1) + end + + it 'updates and continues' do + expect(described_class::MergeRequestDiff).to receive(:transaction).twice + + subject.perform(start_id, stop_id) + end + end + + context 'when BUFFER_ROWS is not exceeded' do + it 'only updates once' do + expect(described_class::MergeRequestDiff).to receive(:transaction).once + + subject.perform(start_id, stop_id) + end + end + end + + context 'when the merge request diff update fails' do + before do + allow(described_class::MergeRequestDiff) + .to receive(:update_all).and_raise(ActiveRecord::Rollback) + end + + it 'does not add any diff commits' do + expect { subject.perform(merge_request_diff.id, merge_request_diff.id) } + .not_to change { MergeRequestDiffCommit.count } + end + + it 'does not add any diff files' do + expect { subject.perform(merge_request_diff.id, merge_request_diff.id) } + .not_to change { MergeRequestDiffFile.count } + end + end + + context 'when the merge request diff has valid commits and diffs' do + let(:commits) { merge_request_diff.commits.map(&:to_hash) } + let(:diffs) { diffs_to_hashes(merge_request_diff.merge_request_diff_files) } + let(:expected_diffs) { diffs } + + include_examples 'updated MR diff' + end + + context 'when the merge request diffs have binary content' do + let(:commits) { merge_request_diff.commits.map(&:to_hash) } + let(:expected_diffs) { diffs } + + # The start of a PDF created by Illustrator + let(:binary_string) do + "\x25\x50\x44\x46\x2d\x31\x2e\x35\x0d\x25\xe2\xe3\xcf\xd3\x0d\x0a".force_encoding(Encoding::BINARY) + end + + let(:diffs) do + [ + { + 'diff' => binary_string, + 'new_path' => 'path', + 'old_path' => 'path', + 'a_mode' => '100644', + 'b_mode' => '100644', + 'new_file' => false, + 'renamed_file' => false, + 'deleted_file' => false, + 'too_large' => false + } + ] + end + + include_examples 'updated MR diff' + end + + context 'when the merge request diff has commits, but no diffs' do + let(:commits) { merge_request_diff.commits.map(&:to_hash) } + let(:diffs) { [] } + let(:expected_diffs) { diffs } + + include_examples 'updated MR diff' + end + + context 'when the merge request diffs have invalid content' do + let(:commits) { merge_request_diff.commits.map(&:to_hash) } + let(:diffs) { ['--broken-diff'] } + let(:expected_diffs) { [] } + + include_examples 'updated MR diff' + end + + context 'when the merge request diffs are Rugged::Patch instances' do + let(:commits) { merge_request_diff.commits.map(&:to_hash) } + let(:first_commit) { merge_request.project.repository.commit(merge_request_diff.head_commit_sha) } + let(:diffs) { first_commit.diff_from_parent.patches } + let(:expected_diffs) { [] } + + include_examples 'updated MR diff' + end + + context 'when the merge request diffs are Rugged::Diff::Delta instances' do + let(:commits) { merge_request_diff.commits.map(&:to_hash) } + let(:first_commit) { merge_request.project.repository.commit(merge_request_diff.head_commit_sha) } + let(:diffs) { first_commit.diff_from_parent.deltas } + let(:expected_diffs) { [] } + + include_examples 'updated MR diff' + end + end +end diff --git a/spec/migrations/schedule_merge_request_diff_migrations_spec.rb b/spec/migrations/schedule_merge_request_diff_migrations_spec.rb new file mode 100644 index 00000000000..f95bd6e3511 --- /dev/null +++ b/spec/migrations/schedule_merge_request_diff_migrations_spec.rb @@ -0,0 +1,59 @@ +require 'spec_helper' +require Rails.root.join('db', 'post_migrate', '20170703130158_schedule_merge_request_diff_migrations') + +describe ScheduleMergeRequestDiffMigrations, :migration, :sidekiq do + matcher :be_scheduled_migration do |time, *expected| + match do |migration| + BackgroundMigrationWorker.jobs.any? do |job| + job['args'] == [migration, expected] && + job['at'].to_i == time.to_i + end + end + + failure_message do |migration| + "Migration `#{migration}` with args `#{expected.inspect}` not scheduled!" + end + end + + let(:merge_request_diffs) { table(:merge_request_diffs) } + let(:merge_requests) { table(:merge_requests) } + let(:projects) { table(:projects) } + + before do + stub_const("#{described_class.name}::BATCH_SIZE", 1) + + projects.create!(id: 1, name: 'gitlab', path: 'gitlab') + + merge_requests.create!(id: 1, target_project_id: 1, source_project_id: 1, target_branch: 'feature', source_branch: 'master') + + merge_request_diffs.create!(id: 1, merge_request_id: 1, st_commits: YAML.dump([]), st_diffs: nil) + merge_request_diffs.create!(id: 2, merge_request_id: 1, st_commits: nil, st_diffs: YAML.dump([])) + merge_request_diffs.create!(id: 3, merge_request_id: 1, st_commits: nil, st_diffs: nil) + merge_request_diffs.create!(id: 4, merge_request_id: 1, st_commits: YAML.dump([]), st_diffs: YAML.dump([])) + end + + it 'correctly schedules background migrations' do + Sidekiq::Testing.fake! do + Timecop.freeze do + migrate! + + expect(described_class::MIGRATION).to be_scheduled_migration(5.minutes.from_now, 1, 1) + expect(described_class::MIGRATION).to be_scheduled_migration(10.minutes.from_now, 2, 2) + expect(described_class::MIGRATION).to be_scheduled_migration(15.minutes.from_now, 4, 4) + expect(BackgroundMigrationWorker.jobs.size).to eq 3 + end + end + end + + it 'schedules background migrations' do + Sidekiq::Testing.inline! do + non_empty = 'st_commits IS NOT NULL OR st_diffs IS NOT NULL' + + expect(merge_request_diffs.where(non_empty).count).to eq 3 + + migrate! + + expect(merge_request_diffs.where(non_empty).count).to eq 0 + end + end +end From a7102fb7908afe893dc2e8622a286a3a3edfba74 Mon Sep 17 00:00:00 2001 From: Winnie Hellmann Date: Thu, 3 Aug 2017 13:11:17 +0000 Subject: [PATCH 036/177] Make dropdown style on project page consistent --- app/assets/javascripts/project.js | 9 +++- .../stylesheets/framework/dropdowns.scss | 45 +++++++++++++++++++ app/assets/stylesheets/pages/projects.scss | 2 + app/views/shared/_clone_panel.html.haml | 2 +- 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/project.js b/app/assets/javascripts/project.js index a3f7d69b98d..6e1744e8e72 100644 --- a/app/assets/javascripts/project.js +++ b/app/assets/javascripts/project.js @@ -10,14 +10,19 @@ import Cookies from 'js-cookie'; const $projectCloneField = $('#project_clone'); const $cloneBtnText = $('a.clone-dropdown-btn span'); + const selectedCloneOption = $cloneBtnText.text().trim(); + if (selectedCloneOption.length > 0) { + $(`a:contains('${selectedCloneOption}')`, $cloneOptions).addClass('is-active'); + } + $('a', $cloneOptions).on('click', (e) => { const $this = $(e.currentTarget); const url = $this.attr('href'); e.preventDefault(); - $('.active', $cloneOptions).not($this).removeClass('active'); - $this.toggleClass('active'); + $('.is-active', $cloneOptions).not($this).removeClass('is-active'); + $this.toggleClass('is-active'); $projectCloneField.val(url); $cloneBtnText.text($this.text()); diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index 3f934403147..572203bce34 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -722,3 +722,48 @@ @include set-invisible; overflow: hidden; } + +// TODO: change global style and remove mixin +@mixin new-style-dropdown { + .dropdown-menu { + li { + padding: 0 1px; + + &.dropdown-header { + padding: 8px 16px; + } + + a { + border-radius: 0; + padding: 8px 16px; + + &.is-focused, + &:hover, + &:active, + &:focus { + background-color: $gray-darker; + } + + &.is-active { + font-weight: inherit; + + &::before { + top: 16px; + } + } + } + } + + &.dropdown-menu-selectable { + li { + a { + padding: 8px 40px; + + &.is-active::before { + left: 16px; + } + } + } + } + } +} diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index b3a90dff89a..d29421aa1b3 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -282,6 +282,8 @@ } .project-repo-buttons { + @include new-style-dropdown; + .project-action-button .dropdown-menu { max-height: 250px; overflow-y: auto; diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml index b4843eafdb7..3d9c90c38fe 100644 --- a/app/views/shared/_clone_panel.html.haml +++ b/app/views/shared/_clone_panel.html.haml @@ -11,7 +11,7 @@ %span = default_clone_protocol.upcase = icon('caret-down') - %ul.dropdown-menu.dropdown-menu-right.clone-options-dropdown + %ul.dropdown-menu.dropdown-menu-selectable.dropdown-menu-right.clone-options-dropdown %li = ssh_clone_button(project) %li From 9b3f0569fa298f192735af10d685ffc68b86afe3 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Thu, 3 Aug 2017 15:18:57 +0200 Subject: [PATCH 037/177] Re-organise "issues" indexes for faster ordering By adding various composite indexes we can reduce the time spent retrieving issue lists. Because of the way these indexes are built column wise we can also remove some standalone indexes, keeping the total number of indexes in check. --- .../reorganise-issues-indexes-for-sorting.yml | 4 ++ ...anise_issues_indexes_for_faster_sorting.rb | 43 +++++++++++++++++++ db/schema.rb | 7 +-- 3 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 changelogs/unreleased/reorganise-issues-indexes-for-sorting.yml create mode 100644 db/migrate/20170803130232_reorganise_issues_indexes_for_faster_sorting.rb diff --git a/changelogs/unreleased/reorganise-issues-indexes-for-sorting.yml b/changelogs/unreleased/reorganise-issues-indexes-for-sorting.yml new file mode 100644 index 00000000000..5bfe55e562f --- /dev/null +++ b/changelogs/unreleased/reorganise-issues-indexes-for-sorting.yml @@ -0,0 +1,4 @@ +--- +title: Re-organise "issues" indexes for faster ordering +merge_request: +author: diff --git a/db/migrate/20170803130232_reorganise_issues_indexes_for_faster_sorting.rb b/db/migrate/20170803130232_reorganise_issues_indexes_for_faster_sorting.rb new file mode 100644 index 00000000000..eb7d1be1732 --- /dev/null +++ b/db/migrate/20170803130232_reorganise_issues_indexes_for_faster_sorting.rb @@ -0,0 +1,43 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class ReorganiseIssuesIndexesForFasterSorting < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + # Set this constant to true if this migration requires downtime. + DOWNTIME = false + + disable_ddl_transaction! + + REMOVE_INDEX_COLUMNS = %i[project_id created_at due_date updated_at].freeze + + ADD_INDEX_COLUMNS = [ + %i[project_id created_at id state], + %i[project_id due_date id state], + %i[project_id updated_at id state] + ].freeze + + TABLE = :issues + + def up + add_indexes(ADD_INDEX_COLUMNS) + remove_indexes(REMOVE_INDEX_COLUMNS) + end + + def down + add_indexes(REMOVE_INDEX_COLUMNS) + remove_indexes(ADD_INDEX_COLUMNS) + end + + def add_indexes(columns) + columns.each do |column| + add_concurrent_index(TABLE, column) unless index_exists?(TABLE, column) + end + end + + def remove_indexes(columns) + columns.each do |column| + remove_concurrent_index(TABLE, column) if index_exists?(TABLE, column) + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 4ba218e1e0d..f2f35acef95 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170728101014) do +ActiveRecord::Schema.define(version: 20170803130232) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -641,12 +641,13 @@ ActiveRecord::Schema.define(version: 20170728101014) do add_index "issues", ["assignee_id"], name: "index_issues_on_assignee_id", using: :btree add_index "issues", ["author_id"], name: "index_issues_on_author_id", using: :btree add_index "issues", ["confidential"], name: "index_issues_on_confidential", using: :btree - add_index "issues", ["created_at"], name: "index_issues_on_created_at", using: :btree add_index "issues", ["deleted_at"], name: "index_issues_on_deleted_at", using: :btree add_index "issues", ["description"], name: "index_issues_on_description_trigram", using: :gin, opclasses: {"description"=>"gin_trgm_ops"} - add_index "issues", ["due_date"], name: "index_issues_on_due_date", using: :btree add_index "issues", ["milestone_id"], name: "index_issues_on_milestone_id", using: :btree + add_index "issues", ["project_id", "created_at", "id", "state"], name: "index_issues_on_project_id_and_created_at_and_id_and_state", using: :btree + add_index "issues", ["project_id", "due_date", "id", "state"], name: "index_issues_on_project_id_and_due_date_and_id_and_state", using: :btree add_index "issues", ["project_id", "iid"], name: "index_issues_on_project_id_and_iid", unique: true, using: :btree + add_index "issues", ["project_id", "updated_at", "id", "state"], name: "index_issues_on_project_id_and_updated_at_and_id_and_state", using: :btree add_index "issues", ["relative_position"], name: "index_issues_on_relative_position", using: :btree add_index "issues", ["state"], name: "index_issues_on_state", using: :btree add_index "issues", ["title"], name: "index_issues_on_title_trigram", using: :gin, opclasses: {"title"=>"gin_trgm_ops"} From 03d199fb10bd03c6d6602b23e5f5454dd956e945 Mon Sep 17 00:00:00 2001 From: Mehdi Lahmam Date: Tue, 1 Aug 2017 21:19:54 +0200 Subject: [PATCH 038/177] Ensure `JIRA::Resource::Issue` responds to `resolution` before calling it --- app/models/project_services/jira_service.rb | 8 ++++++-- spec/models/project_services/jira_service_spec.rb | 9 +++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb index c2414885368..9ee3a533c1e 100644 --- a/app/models/project_services/jira_service.rb +++ b/app/models/project_services/jira_service.rb @@ -104,7 +104,7 @@ class JiraService < IssueTrackerService def close_issue(entity, external_issue) issue = jira_request { client.Issue.find(external_issue.iid) } - return if issue.nil? || issue.resolution.present? || !jira_issue_transition_id.present? + return if issue.nil? || has_resolution?(issue) || !jira_issue_transition_id.present? commit_id = if entity.is_a?(Commit) entity.id @@ -118,7 +118,7 @@ class JiraService < IssueTrackerService # may or may not be allowed. Refresh the issue after transition and check # if it is closed, so we don't have one comment for every commit. issue = jira_request { client.Issue.find(issue.key) } if transition_issue(issue) - add_issue_solved_comment(issue, commit_id, commit_url) if issue.resolution + add_issue_solved_comment(issue, commit_id, commit_url) if has_resolution?(issue) end def create_cross_reference_note(mentioned, noteable, author) @@ -216,6 +216,10 @@ class JiraService < IssueTrackerService end end + def has_resolution?(issue) + issue.respond_to?(:resolution) && issue.resolution.present? + end + def comment_exists?(issue, message) comments = jira_request { issue.comments } diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index bc9374d6dbb..fcc0f00d01d 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -153,6 +153,15 @@ describe JiraService do expect(WebMock).not_to have_requested(:post, @remote_link_url) end + it "does not send comment or remote links to issues with unknown resolution" do + allow_any_instance_of(JIRA::Resource::Issue).to receive(:respond_to?).with(:resolution).and_return(false) + + @jira_service.close_issue(merge_request, ExternalIssue.new("JIRA-123", project)) + + expect(WebMock).not_to have_requested(:post, @comment_url) + expect(WebMock).not_to have_requested(:post, @remote_link_url) + end + it "references the GitLab commit/merge request" do stub_config_setting(base_url: custom_base_url) From 3c8b2ae168edafbd6158d392f14a757873f817fd Mon Sep 17 00:00:00 2001 From: Tony Date: Thu, 3 Aug 2017 10:43:24 +0300 Subject: [PATCH 039/177] Expose more attributes to unauthenticated GET /projects/:id --- lib/api/entities.rb | 25 +++++++++++-------------- spec/requests/api/environments_spec.rb | 9 ++++++++- spec/requests/api/projects_spec.rb | 10 +++++++++- spec/requests/api/v3/projects_spec.rb | 10 +++++++++- 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 298831a8fdb..3afa44a7428 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -66,13 +66,6 @@ module API expose :job_events end - class BasicProjectDetails < Grape::Entity - expose :id - expose :http_url_to_repo, :web_url - expose :name, :name_with_namespace - expose :path, :path_with_namespace - end - class SharedGroup < Grape::Entity expose :group_id expose :group_name do |group_link, options| @@ -81,7 +74,16 @@ module API expose :group_access, as: :group_access_level end - class Project < Grape::Entity + class BasicProjectDetails < Grape::Entity + expose :id, :description, :default_branch, :tag_list + expose :ssh_url_to_repo, :http_url_to_repo, :web_url + expose :name, :name_with_namespace + expose :path, :path_with_namespace + expose :star_count, :forks_count + expose :created_at, :last_activity_at + end + + class Project < BasicProjectDetails include ::API::Helpers::RelatedResourcesHelpers expose :_links do @@ -114,12 +116,9 @@ module API end end - expose :id, :description, :default_branch, :tag_list expose :archived?, as: :archived - expose :visibility, :ssh_url_to_repo, :http_url_to_repo, :web_url + expose :visibility expose :owner, using: Entities::UserBasic, unless: ->(project, options) { project.group } - expose :name, :name_with_namespace - expose :path, :path_with_namespace expose :container_registry_enabled # Expose old field names with the new permissions methods to keep API compatible @@ -129,7 +128,6 @@ module API expose(:jobs_enabled) { |project, options| project.feature_available?(:builds, options[:current_user]) } expose(:snippets_enabled) { |project, options| project.feature_available?(:snippets, options[:current_user]) } - expose :created_at, :last_activity_at expose :shared_runners_enabled expose :lfs_enabled?, as: :lfs_enabled expose :creator_id @@ -140,7 +138,6 @@ module API expose :avatar_url do |user, options| user.avatar_url(only_path: false) end - expose :star_count, :forks_count expose :open_issues_count, if: lambda { |project, options| project.feature_available?(:issues, options[:current_user]) } expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] } expose :public_builds, as: :public_jobs diff --git a/spec/requests/api/environments_spec.rb b/spec/requests/api/environments_spec.rb index 4c5ded7a492..87716c6fe3a 100644 --- a/spec/requests/api/environments_spec.rb +++ b/spec/requests/api/environments_spec.rb @@ -13,7 +13,14 @@ describe API::Environments do describe 'GET /projects/:id/environments' do context 'as member of the project' do it 'returns project environments' do - project_data_keys = %w(id http_url_to_repo web_url name name_with_namespace path path_with_namespace) + project_data_keys = %w( + id description default_branch tag_list + ssh_url_to_repo http_url_to_repo web_url + name name_with_namespace + path path_with_namespace + star_count forks_count + created_at last_activity_at + ) get api("/projects/#{project.id}/environments", user) diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index b9ebf6c4c16..9baac12821f 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -186,7 +186,14 @@ describe API::Projects do context 'and with simple=true' do it 'returns a simplified version of all the projects' do - expected_keys = %w(id http_url_to_repo web_url name name_with_namespace path path_with_namespace) + expected_keys = %w( + id description default_branch tag_list + ssh_url_to_repo http_url_to_repo web_url + name name_with_namespace + path path_with_namespace + star_count forks_count + created_at last_activity_at + ) get api('/projects?simple=true', user) @@ -689,6 +696,7 @@ describe API::Projects do expect(response).to have_http_status(200) expect(json_response['id']).to eq(public_project.id) expect(json_response['description']).to eq(public_project.description) + expect(json_response['default_branch']).to eq(public_project.default_branch) expect(json_response.keys).not_to include('permissions') end end diff --git a/spec/requests/api/v3/projects_spec.rb b/spec/requests/api/v3/projects_spec.rb index c211cc20e53..fca5b5b5d82 100644 --- a/spec/requests/api/v3/projects_spec.rb +++ b/spec/requests/api/v3/projects_spec.rb @@ -82,7 +82,14 @@ describe API::V3::Projects do context 'GET /projects?simple=true' do it 'returns a simplified version of all the projects' do - expected_keys = %w(id http_url_to_repo web_url name name_with_namespace path path_with_namespace) + expected_keys = %w( + id description default_branch tag_list + ssh_url_to_repo http_url_to_repo web_url + name name_with_namespace + path path_with_namespace + star_count forks_count + created_at last_activity_at + ) get v3_api('/projects?simple=true', user) @@ -644,6 +651,7 @@ describe API::V3::Projects do expect(response).to have_http_status(200) expect(json_response['id']).to eq(public_project.id) expect(json_response['description']).to eq(public_project.description) + expect(json_response['default_branch']).to eq(public_project.default_branch) expect(json_response.keys).not_to include('permissions') end end From 29a07fd3a12115377f726248a342052a5ae07ed2 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 3 Aug 2017 15:47:43 +0200 Subject: [PATCH 040/177] Rename 'commits_between' to 'rugged_commits_between' --- lib/gitlab/git/commit.rb | 2 +- lib/gitlab/git/repository.rb | 4 +++- spec/lib/gitlab/git/repository_spec.rb | 10 +++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb index ca7e3a7c4be..600d886e818 100644 --- a/lib/gitlab/git/commit.rb +++ b/lib/gitlab/git/commit.rb @@ -102,7 +102,7 @@ module Gitlab if is_enabled repo.gitaly_commit_client.between(base, head) else - repo.commits_between(base, head).map { |c| decorate(c) } + repo.rugged_commits_between(base, head).map { |c| decorate(c) } end end rescue Rugged::ReferenceError diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 70d793f8e4a..26ad40c3eed 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -327,7 +327,9 @@ module Gitlab # Return a collection of Rugged::Commits between the two revspec arguments. # See http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions for # a detailed list of valid arguments. - def commits_between(from, to) + # + # Gitaly note: JV: to be deprecated in favor of Commit.between + def rugged_commits_between(from, to) walker = Rugged::Walker.new(rugged) walker.sorting(Rugged::SORT_NONE | Rugged::SORT_REVERSE) diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index 8e4a1f31ced..e375dbfc078 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -757,13 +757,13 @@ describe Gitlab::Git::Repository, seed_helper: true do end end - describe "#commits_between" do + describe "#rugged_commits_between" do context 'two SHAs' do let(:first_sha) { 'b0e52af38d7ea43cf41d8a6f2471351ac036d6c9' } let(:second_sha) { '0e50ec4d3c7ce42ab74dda1d422cb2cbffe1e326' } it 'returns the number of commits between' do - expect(repository.commits_between(first_sha, second_sha).count).to eq(3) + expect(repository.rugged_commits_between(first_sha, second_sha).count).to eq(3) end end @@ -772,11 +772,11 @@ describe Gitlab::Git::Repository, seed_helper: true do let(:branch) { 'master' } it 'returns the number of commits between a sha and a branch' do - expect(repository.commits_between(sha, branch).count).to eq(5) + expect(repository.rugged_commits_between(sha, branch).count).to eq(5) end it 'returns the number of commits between a branch and a sha' do - expect(repository.commits_between(branch, sha).count).to eq(0) # sha is before branch + expect(repository.rugged_commits_between(branch, sha).count).to eq(0) # sha is before branch end end @@ -785,7 +785,7 @@ describe Gitlab::Git::Repository, seed_helper: true do let(:second_branch) { 'master' } it 'returns the number of commits between' do - expect(repository.commits_between(first_branch, second_branch).count).to eq(17) + expect(repository.rugged_commits_between(first_branch, second_branch).count).to eq(17) end end end From 3a8f4a34604d8b15d3e602269934ea5c073ff0d9 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 3 Aug 2017 15:52:14 +0200 Subject: [PATCH 041/177] Remove unnecessary 'raw' alias --- lib/gitlab/git/repository.rb | 5 ----- spec/lib/gitlab/git/commit_spec.rb | 2 +- spec/lib/gitlab/git/repository_spec.rb | 1 - 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 26ad40c3eed..3a9740092cd 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -58,11 +58,6 @@ module Gitlab end end - # Alias to old method for compatibility - def raw - rugged - end - def rugged @rugged ||= Rugged::Repository.new(path, alternates: alternate_object_directories) rescue Rugged::RepositoryError, Rugged::OSError diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb index 730fdb112d9..26d7a364f5b 100644 --- a/spec/lib/gitlab/git/commit_spec.rb +++ b/spec/lib/gitlab/git/commit_spec.rb @@ -114,7 +114,7 @@ describe Gitlab::Git::Commit, seed_helper: true do describe '.find' do it "should return first head commit if without params" do expect(Gitlab::Git::Commit.last(repository).id).to eq( - repository.raw.head.target.oid + repository.rugged.head.target.oid ) end diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index e375dbfc078..cadca6cee23 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -22,7 +22,6 @@ describe Gitlab::Git::Repository, seed_helper: true do describe "Respond to" do subject { repository } - it { is_expected.to respond_to(:raw) } it { is_expected.to respond_to(:rugged) } it { is_expected.to respond_to(:root_ref) } it { is_expected.to respond_to(:tags) } From bb5f79d43e0bb20bacd5ecd8b66832d9857bd079 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 3 Aug 2017 00:43:51 +0800 Subject: [PATCH 042/177] Don't include EmailHelpers manually, pick with rspec `:mailer` is needed to pick it easily, while `type: :mailer` is needed for picking it automatically for tests located in spec/mailers/*_spec.rb It's a bit complicated in spec/services/notification_service_spec.rb but we'll leave it alone for now. --- spec/models/ci/pipeline_spec.rb | 6 +----- spec/models/deploy_key_spec.rb | 4 +--- spec/models/gpg_key_spec.rb | 4 +--- spec/models/key_spec.rb | 4 +--- .../project_services/pipelines_email_service_spec.rb | 8 +------- spec/requests/api/issues_spec.rb | 4 +--- spec/requests/api/v3/issues_spec.rb | 4 +--- spec/services/issues/update_service_spec.rb | 4 +--- spec/services/merge_requests/update_service_spec.rb | 4 +--- spec/services/notification_service_spec.rb | 11 ++++------- spec/support/notify_shared_examples.rb | 1 - spec/support/updating_mentions_shared_examples.rb | 2 -- spec/workers/emails_on_push_worker_spec.rb | 6 +----- spec/workers/pipeline_notification_worker_spec.rb | 4 +--- 14 files changed, 15 insertions(+), 51 deletions(-) diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index f63ff19c2fc..ac75c6501ee 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe Ci::Pipeline do - include EmailHelpers - +describe Ci::Pipeline, :mailer do let(:user) { create(:user) } let(:project) { create(:project) } @@ -1248,8 +1246,6 @@ describe Ci::Pipeline do pipeline.user.global_notification_setting .update(level: 'custom', failed_pipeline: true, success_pipeline: true) - reset_delivered_emails! - perform_enqueued_jobs do pipeline.enqueue pipeline.run diff --git a/spec/models/deploy_key_spec.rb b/spec/models/deploy_key_spec.rb index 2aece75b817..3d7283e2164 100644 --- a/spec/models/deploy_key_spec.rb +++ b/spec/models/deploy_key_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe DeployKey do - include EmailHelpers - +describe DeployKey, :mailer do describe "Associations" do it { is_expected.to have_many(:deploy_keys_projects) } it { is_expected.to have_many(:projects) } diff --git a/spec/models/gpg_key_spec.rb b/spec/models/gpg_key_spec.rb index 59c074199db..e48f20bf53b 100644 --- a/spec/models/gpg_key_spec.rb +++ b/spec/models/gpg_key_spec.rb @@ -114,9 +114,7 @@ describe GpgKey do end end - describe 'notification' do - include EmailHelpers - + describe 'notification', :mailer do let(:user) { create(:user) } it 'sends a notification' do diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb index d41717d0223..882522c0a97 100644 --- a/spec/models/key_spec.rb +++ b/spec/models/key_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe Key do - include EmailHelpers - +describe Key, :mailer do describe "Associations" do it { is_expected.to belong_to(:user) } end diff --git a/spec/models/project_services/pipelines_email_service_spec.rb b/spec/models/project_services/pipelines_email_service_spec.rb index 03932895b0e..5faab9ba38b 100644 --- a/spec/models/project_services/pipelines_email_service_spec.rb +++ b/spec/models/project_services/pipelines_email_service_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe PipelinesEmailService do - include EmailHelpers - +describe PipelinesEmailService, :mailer do let(:pipeline) do create(:ci_pipeline, project: project, sha: project.commit('master').sha) end @@ -14,10 +12,6 @@ describe PipelinesEmailService do Gitlab::DataBuilder::Pipeline.build(pipeline) end - before do - reset_delivered_emails! - end - describe 'Validations' do context 'when service is active' do before do diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index 60687db9316..7d120e4a234 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::Issues do - include EmailHelpers - +describe API::Issues, :mailer do set(:user) { create(:user) } set(:project) do create(:project, :public, creator_id: user.id, namespace: user.namespace) diff --git a/spec/requests/api/v3/issues_spec.rb b/spec/requests/api/v3/issues_spec.rb index b092c863c8a..9eb538c4b09 100644 --- a/spec/requests/api/v3/issues_spec.rb +++ b/spec/requests/api/v3/issues_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe API::V3::Issues do - include EmailHelpers - +describe API::V3::Issues, :mailer do let(:user) { create(:user) } let(:user2) { create(:user) } let(:non_member) { create(:user) } diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb index ff0d876e6da..814e2cfbed0 100644 --- a/spec/services/issues/update_service_spec.rb +++ b/spec/services/issues/update_service_spec.rb @@ -1,9 +1,7 @@ # coding: utf-8 require 'spec_helper' -describe Issues::UpdateService do - include EmailHelpers - +describe Issues::UpdateService, :mailer do let(:user) { create(:user) } let(:user2) { create(:user) } let(:user3) { create(:user) } diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index dd3ac9c4ac6..9368594bc86 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe MergeRequests::UpdateService do - include EmailHelpers - +describe MergeRequests::UpdateService, :mailer do let(:project) { create(:project, :repository) } let(:user) { create(:user) } let(:user2) { create(:user) } diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 882ee7751b5..5354591642b 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe NotificationService do - include EmailHelpers - +describe NotificationService, :mailer do let(:notification) { described_class.new } let(:assignee) { create(:user) } @@ -14,7 +12,6 @@ describe NotificationService do shared_examples 'notifications for new mentions' do def send_notifications(*new_mentions) - reset_delivered_emails! notification.send(notification_method, mentionable, new_mentions, @u_disabled) end @@ -137,12 +134,11 @@ describe NotificationService do describe '#new_note' do it do add_users_with_subscription(note.project, issue) + reset_delivered_emails! # Ensure create SentNotification by noteable = issue 6 times, not noteable = note expect(SentNotification).to receive(:record).with(issue, any_args).exactly(8).times - reset_delivered_emails! - notification.new_note(note) should_email(@u_watcher) @@ -165,9 +161,10 @@ describe NotificationService do it "emails the note author if they've opted into notifications about their activity" do add_users_with_subscription(note.project, issue) - note.author.notified_of_own_activity = true reset_delivered_emails! + note.author.notified_of_own_activity = true + notification.new_note(note) should_email(note.author) diff --git a/spec/support/notify_shared_examples.rb b/spec/support/notify_shared_examples.rb index d6117d604f2..136f92c6419 100644 --- a/spec/support/notify_shared_examples.rb +++ b/spec/support/notify_shared_examples.rb @@ -7,7 +7,6 @@ shared_context 'gitlab email notification' do let(:new_user_address) { 'newguy@example.com' } before do - reset_delivered_emails! email = recipient.emails.create(email: "notifications@example.com") recipient.update_attribute(:notification_email, email.email) stub_incoming_email_setting(enabled: true, address: "reply+%{key}@#{Gitlab.config.gitlab.host}") diff --git a/spec/support/updating_mentions_shared_examples.rb b/spec/support/updating_mentions_shared_examples.rb index eeec3e1d79b..565d3203e4f 100644 --- a/spec/support/updating_mentions_shared_examples.rb +++ b/spec/support/updating_mentions_shared_examples.rb @@ -7,8 +7,6 @@ RSpec.shared_examples 'updating mentions' do |service_class| end def update_mentionable(opts) - reset_delivered_emails! - perform_enqueued_jobs do service_class.new(project, user, opts).execute(mentionable) end diff --git a/spec/workers/emails_on_push_worker_spec.rb b/spec/workers/emails_on_push_worker_spec.rb index 5b6b38e0f76..318aad4bc1e 100644 --- a/spec/workers/emails_on_push_worker_spec.rb +++ b/spec/workers/emails_on_push_worker_spec.rb @@ -1,8 +1,7 @@ require 'spec_helper' -describe EmailsOnPushWorker do +describe EmailsOnPushWorker, :mailer do include RepoHelpers - include EmailHelpers include EmailSpec::Matchers let(:project) { create(:project, :repository) } @@ -90,7 +89,6 @@ describe EmailsOnPushWorker do context "when there is an SMTP error" do before do - reset_delivered_emails! allow(Notify).to receive(:repository_push_email).and_raise(Net::SMTPFatalError) allow(subject).to receive_message_chain(:logger, :info) perform @@ -114,8 +112,6 @@ describe EmailsOnPushWorker do allow_any_instance_of(Mail::TestMailer).to receive(:deliver!).and_wrap_original do |original, mail| original.call(Mail.new(mail.encoded)) end - - reset_delivered_emails! end it "sends the mail to each of the recipients" do diff --git a/spec/workers/pipeline_notification_worker_spec.rb b/spec/workers/pipeline_notification_worker_spec.rb index 139032d77bd..eb539ffd893 100644 --- a/spec/workers/pipeline_notification_worker_spec.rb +++ b/spec/workers/pipeline_notification_worker_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' -describe PipelineNotificationWorker do - include EmailHelpers - +describe PipelineNotificationWorker, :mailer do let(:pipeline) { create(:ci_pipeline) } describe '#execute' do From 00c9c6b458f3aff3d378aa53a3c3652f04368fc9 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 3 Aug 2017 15:58:36 +0200 Subject: [PATCH 043/177] Remove unused methods --- lib/gitlab/git/repository.rb | 77 ------------------------------------ 1 file changed, 77 deletions(-) diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 3a9740092cd..779c6117bb2 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -849,46 +849,6 @@ module Gitlab submodule_data.select { |path, data| data['id'] } end - # Returns true if +commit+ introduced changes to +path+, using commit - # trees to make that determination. Uses the history simplification - # rules that `git log` uses by default, where a commit is omitted if it - # is TREESAME to any parent. - # - # If the +follow+ option is true and the file specified by +path+ was - # renamed, then the path value is set to the old path. - def commit_touches_path?(commit, path, follow, walker) - entry = tree_entry(commit, path) - - if commit.parents.empty? - # This is the root commit, return true if it has +path+ in its tree - return !entry.nil? - end - - num_treesame = 0 - commit.parents.each do |parent| - parent_entry = tree_entry(parent, path) - - # Only follow the first TREESAME parent for merge commits - if num_treesame > 0 - walker.hide(parent) - next - end - - if entry.nil? && parent_entry.nil? - num_treesame += 1 - elsif entry && parent_entry && entry[:oid] == parent_entry[:oid] - num_treesame += 1 - end - end - - case num_treesame - when 0 - detect_rename(commit, commit.parents.first, path) if follow - true - else false - end - end - # Find the entry for +path+ in the tree for +commit+ def tree_entry(commit, path) pathname = Pathname.new(path) @@ -916,43 +876,6 @@ module Gitlab tmp_entry end - # Compare +commit+ and +parent+ for +path+. If +path+ is a file and was - # renamed in +commit+, then set +path+ to the old filename. - def detect_rename(commit, parent, path) - diff = parent.diff(commit, paths: [path], disable_pathspec_match: true) - - # If +path+ is a filename, not a directory, then we should only have - # one delta. We don't need to follow renames for directories. - return nil if diff.each_delta.count > 1 - - delta = diff.each_delta.first - if delta.added? - full_diff = parent.diff(commit) - full_diff.find_similar! - - full_diff.each_delta do |full_delta| - if full_delta.renamed? && path == full_delta.new_file[:path] - # Look for the old path in ancestors - path.replace(full_delta.old_file[:path]) - end - end - end - end - - # Returns true if the index entry has the special file mode that denotes - # a submodule. - def submodule?(index_entry) - index_entry[:mode] == 57344 - end - - # Return a Rugged::Index that has read from the tree at +ref_name+ - def populated_index(ref_name) - commit = rev_parse_target(ref_name) - index = rugged.index - index.read_tree(commit.tree) - index - end - # Return the Rugged patches for the diff between +from+ and +to+. def diff_patches(from, to, options = {}, *paths) options ||= {} From fbdfafe6ed469fdca9a735428b4636e74b1dd255 Mon Sep 17 00:00:00 2001 From: Abubakar Ango Date: Thu, 3 Aug 2017 14:07:16 +0000 Subject: [PATCH 044/177] Update reply_by_email_postfix_setup.md, included starting courier-authdaemon after installation. --- doc/administration/reply_by_email_postfix_setup.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/administration/reply_by_email_postfix_setup.md b/doc/administration/reply_by_email_postfix_setup.md index 3b8c716eff5..a1bb3851951 100644 --- a/doc/administration/reply_by_email_postfix_setup.md +++ b/doc/administration/reply_by_email_postfix_setup.md @@ -177,6 +177,20 @@ Courier, which we will install later to add IMAP authentication, requires mailbo ```sh sudo apt-get install courier-imap ``` + + And start `imapd`: + ```sh + imapd start + ``` + +1. The courier-authdaemon isn't started after installation. Without it, imap authentication will fail: + ```sh + sudo service courier-authdaemon start + ``` + You can also configure courier-authdaemon to start on boot: + ```sh + sudo systemctl enable courier-authdaemon + ``` ## Configure Postfix to receive email from the internet From a723cba57493ec3220596ca8543a8b1b1ec118fe Mon Sep 17 00:00:00 2001 From: Toon Claes Date: Fri, 21 Apr 2017 11:36:34 +0200 Subject: [PATCH 045/177] Avoid plucking Todo ids and use sub-queries instead TodoService should not call `.select(&:id)` on todos, because this is bad performance. So instead use sub-queries, which will result in a single SQL query to the database. https://docs.gitlab.com/ee/development/sql.html#plucking-ids --- app/controllers/dashboard/todos_controller.rb | 4 +-- app/services/issuable_base_service.rb | 2 +- app/services/todo_service.rb | 16 +++++---- .../unreleased/tc-no-todo-service-select.yml | 4 +++ lib/api/todos.rb | 6 ++-- lib/api/v3/todos.rb | 6 ++-- spec/services/todo_service_spec.rb | 33 ++++++++++++++++--- 7 files changed, 51 insertions(+), 20 deletions(-) create mode 100644 changelogs/unreleased/tc-no-todo-service-select.yml diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb index 59e5b5e4775..a8b2b93b458 100644 --- a/app/controllers/dashboard/todos_controller.rb +++ b/app/controllers/dashboard/todos_controller.rb @@ -13,7 +13,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController end def destroy - TodoService.new.mark_todos_as_done_by_ids([params[:id]], current_user) + TodoService.new.mark_todos_as_done_by_ids(params[:id], current_user) respond_to do |format| format.html do @@ -37,7 +37,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController end def restore - TodoService.new.mark_todos_as_pending_by_ids([params[:id]], current_user) + TodoService.new.mark_todos_as_pending_by_ids(params[:id], current_user) render json: todos_counts end diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb index ea497729115..760a15e3ed0 100644 --- a/app/services/issuable_base_service.rb +++ b/app/services/issuable_base_service.rb @@ -288,7 +288,7 @@ class IssuableBaseService < BaseService todo_service.mark_todo(issuable, current_user) when 'done' todo = TodosFinder.new(current_user).execute.find_by(target: issuable) - todo_service.mark_todos_as_done([todo], current_user) if todo + todo_service.mark_todos_as_done_by_ids(todo, current_user) if todo end end diff --git a/app/services/todo_service.rb b/app/services/todo_service.rb index 322c6286365..6ee96d6a0f8 100644 --- a/app/services/todo_service.rb +++ b/app/services/todo_service.rb @@ -170,20 +170,22 @@ class TodoService # When user marks some todos as done def mark_todos_as_done(todos, current_user) - update_todos_state_by_ids(todos.select(&:id), current_user, :done) + update_todos_state(todos, current_user, :done) end def mark_todos_as_done_by_ids(ids, current_user) - update_todos_state_by_ids(ids, current_user, :done) + todos = todos_by_ids(ids, current_user) + mark_todos_as_done(todos, current_user) end # When user marks some todos as pending def mark_todos_as_pending(todos, current_user) - update_todos_state_by_ids(todos.select(&:id), current_user, :pending) + update_todos_state(todos, current_user, :pending) end def mark_todos_as_pending_by_ids(ids, current_user) - update_todos_state_by_ids(ids, current_user, :pending) + todos = todos_by_ids(ids, current_user) + mark_todos_as_pending(todos, current_user) end # When user marks an issue as todo @@ -198,9 +200,11 @@ class TodoService private - def update_todos_state_by_ids(ids, current_user, state) - todos = current_user.todos.where(id: ids) + def todos_by_ids(ids, current_user) + current_user.todos.where(id: Array(ids)) + end + def update_todos_state(todos, current_user, state) # Only update those that are not really on that state todos = todos.where.not(state: state) todos_ids = todos.pluck(:id) diff --git a/changelogs/unreleased/tc-no-todo-service-select.yml b/changelogs/unreleased/tc-no-todo-service-select.yml new file mode 100644 index 00000000000..ddcae334aa7 --- /dev/null +++ b/changelogs/unreleased/tc-no-todo-service-select.yml @@ -0,0 +1,4 @@ +--- +title: Avoid plucking Todo ids in TodoService +merge_request: 10845 +author: diff --git a/lib/api/todos.rb b/lib/api/todos.rb index d1f7e364029..55191169dd4 100644 --- a/lib/api/todos.rb +++ b/lib/api/todos.rb @@ -59,10 +59,10 @@ module API requires :id, type: Integer, desc: 'The ID of the todo being marked as done' end post ':id/mark_as_done' do - todo = current_user.todos.find(params[:id]) - TodoService.new.mark_todos_as_done([todo], current_user) + TodoService.new.mark_todos_as_done_by_ids(params[:id], current_user) + todo = Todo.find(params[:id]) - present todo.reload, with: Entities::Todo, current_user: current_user + present todo, with: Entities::Todo, current_user: current_user end desc 'Mark all todos as done' diff --git a/lib/api/v3/todos.rb b/lib/api/v3/todos.rb index e3b311d61cd..2f2cf259987 100644 --- a/lib/api/v3/todos.rb +++ b/lib/api/v3/todos.rb @@ -11,10 +11,10 @@ module API requires :id, type: Integer, desc: 'The ID of the todo being marked as done' end delete ':id' do - todo = current_user.todos.find(params[:id]) - TodoService.new.mark_todos_as_done([todo], current_user) + TodoService.new.mark_todos_as_done_by_ids(params[:id], current_user) + todo = Todo.find(params[:id]) - present todo.reload, with: ::API::Entities::Todo, current_user: current_user + present todo, with: ::API::Entities::Todo, current_user: current_user end desc 'Mark all todos as done' diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb index 534d3e65be2..80d05451e09 100644 --- a/spec/services/todo_service_spec.rb +++ b/spec/services/todo_service_spec.rb @@ -336,7 +336,7 @@ describe TodoService do describe '#mark_todos_as_done' do it_behaves_like 'updating todos state', :mark_todos_as_done, :pending, :done do - let(:collection) { [first_todo, second_todo] } + let(:collection) { Todo.all } end end @@ -348,7 +348,7 @@ describe TodoService do describe '#mark_todos_as_pending' do it_behaves_like 'updating todos state', :mark_todos_as_pending, :done, :pending do - let(:collection) { [first_todo, second_todo] } + let(:collection) { Todo.all } end end @@ -880,14 +880,16 @@ describe TodoService do it 'marks an array of todos as done' do todo = create(:todo, :mentioned, user: john_doe, target: issue, project: project) - expect { described_class.new.mark_todos_as_done([todo], john_doe) } + todos = TodosFinder.new(john_doe, {}).execute + expect { described_class.new.mark_todos_as_done(todos, john_doe) } .to change { todo.reload.state }.from('pending').to('done') end it 'returns the ids of updated todos' do # Needed on API todo = create(:todo, :mentioned, user: john_doe, target: issue, project: project) - expect(described_class.new.mark_todos_as_done([todo], john_doe)).to eq([todo.id]) + todos = TodosFinder.new(john_doe, {}).execute + expect(described_class.new.mark_todos_as_done(todos, john_doe)).to eq([todo.id]) end context 'when some of the todos are done already' do @@ -907,11 +909,32 @@ describe TodoService do expect(described_class.new.mark_todos_as_done(Todo.all, john_doe)).to eq([]) end end + end + + describe '#mark_todos_as_done_by_ids' do + let(:issue) { create(:issue, project: project, author: author, assignees: [john_doe]) } + let(:another_issue) { create(:issue, project: project, author: author, assignees: [john_doe]) } + + it 'marks an array of todo ids as done' do + todo = create(:todo, :mentioned, user: john_doe, target: issue, project: project) + another_todo = create(:todo, :mentioned, user: john_doe, target: another_issue, project: project) + + expect { described_class.new.mark_todos_as_done_by_ids([todo.id, another_todo.id], john_doe) } + .to change { john_doe.todos.done.count }.from(0).to(2) + end + + it 'marks a single todo id as done' do + todo = create(:todo, :mentioned, user: john_doe, target: issue, project: project) + + expect { described_class.new.mark_todos_as_done_by_ids(todo.id, john_doe) } + .to change { todo.reload.state }.from('pending').to('done') + end it 'caches the number of todos of a user', :use_clean_rails_memory_store_caching do create(:todo, :mentioned, user: john_doe, target: issue, project: project) todo = create(:todo, :mentioned, user: john_doe, target: issue, project: project) - described_class.new.mark_todos_as_done([todo], john_doe) + + described_class.new.mark_todos_as_done_by_ids(todo, john_doe) expect_any_instance_of(TodosFinder).not_to receive(:execute) From a488fc0add73963c4839f49a7fe0f7b5b014d15a Mon Sep 17 00:00:00 2001 From: Toon Claes Date: Fri, 14 Jul 2017 16:56:36 +0200 Subject: [PATCH 046/177] Add workaround for UPDATE with subquery when using MySQL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When trying to run an UPDATE, this query is ran: ```sql UPDATE `todos` INNER JOIN `projects` ON `projects`.`id` = `todos`.`project_id` SET `todos`.`state` = 'done' WHERE `todos`.`user_id` = 4 AND (`todos`.`state` IN ('pending')) AND (EXISTS (SELECT 1 FROM `project_authorizations` WHERE `project_authorizations`.`user_id` = 4 AND (project_authorizations.project_id = projects.id)) OR projects.visibility_level IN (10, 20)) AND `projects`.`id` IN (SELECT `todos`.`project_id` FROM `todos` WHERE `todos`.`user_id` = 4 AND (`todos`.`state` IN ('pending'))) AND (`todos`.`state` != 'done') ``` But MySQL does not like the subquery used to filter on `projects.id IN (SELECT ...` Because the subquery queries from the same table: > Error: You can’t specify target table ‘todos’ for update in FROM clause So as workaround, wrap it in another subquery, where the original subquery is aliased using the `AS` statement. Mostly inspired by https://stackoverflow.com/a/43610081/89376 --- app/finders/todos_finder.rb | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/finders/todos_finder.rb b/app/finders/todos_finder.rb index 3fe37c75381..b276116f0c6 100644 --- a/app/finders/todos_finder.rb +++ b/app/finders/todos_finder.rb @@ -95,9 +95,18 @@ class TodosFinder @project end + def project_ids(items) + ids = items.except(:order).select(:project_id) + if Gitlab::Database.mysql? + # To make UPDATE work on MySQL, wrap it in a SELECT with an alias + ids = Todo.except(:order).select('*').from("(#{ids.to_sql}) AS t") + end + + ids + end + def projects(items) - item_project_ids = items.reorder(nil).select(:project_id) - ProjectsFinder.new(current_user: current_user, project_ids_relation: item_project_ids).execute + ProjectsFinder.new(current_user: current_user, project_ids_relation: project_ids(items)).execute end def type? From e15d339a5cca13bc476b87cbac89975e7a76e37b Mon Sep 17 00:00:00 2001 From: Toon Claes Date: Mon, 8 May 2017 14:28:15 +0200 Subject: [PATCH 047/177] Add spec to test combining API merge_requests query parameters To investigate gitlab-org/gitlab-ce#31599 --- spec/requests/api/merge_requests_spec.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index d8dfe71342d..9eda6836ded 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -293,6 +293,26 @@ describe API::MergeRequests do expect(json_response.length).to eq(0) end + it 'returns an array of labeled merge requests that are merged for a milestone' do + bug_label = create(:label, title: 'bug', color: '#FFAABB', project: project) + + mr1 = create(:merge_request, state: "merged", source_project: project, target_project: project, milestone: milestone) + mr2 = create(:merge_request, state: "merged", source_project: project, target_project: project, milestone: milestone1) + mr3 = create(:merge_request, state: "closed", source_project: project, target_project: project, milestone: milestone1) + _mr = create(:merge_request, state: "merged", source_project: project, target_project: project, milestone: milestone1) + + create(:label_link, label: bug_label, target: mr1) + create(:label_link, label: bug_label, target: mr2) + create(:label_link, label: bug_label, target: mr3) + + get api("/projects/#{project.id}/merge_requests?labels=#{bug_label.title}&milestone=#{milestone1.title}&state=merged", user) + + expect(response).to have_http_status(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['id']).to eq(mr2.id) + end + context "with ordering" do before do @mr_later = mr_with_later_created_and_updated_at_time From f7a61c4a444cafd52fa8b90cc3c0a700dcefc26b Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 3 Aug 2017 10:47:11 -0400 Subject: [PATCH 048/177] Ensure DeviseHelpers is loaded before inclusion in LoginHelpers --- spec/support/login_helpers.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb index c714d1b08a6..3e117530151 100644 --- a/spec/support/login_helpers.rb +++ b/spec/support/login_helpers.rb @@ -1,3 +1,5 @@ +require_relative 'devise_helpers' + module LoginHelpers include DeviseHelpers From 25a6a0725c5388872cba4df880be6bfe9f6c1340 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 3 Aug 2017 16:48:11 +0200 Subject: [PATCH 049/177] Migration link for Repository#log --- lib/gitlab/git/repository.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 779c6117bb2..b0f51a96718 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -291,6 +291,7 @@ module Gitlab # after: Time.new(2016, 4, 21, 14, 32, 10) # ) # + # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/446 def log(options) raw_log(options).map { |c| Commit.decorate(c) } end From 86a66647a7a3ee926772bdc055b089e4e4c8447f Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 3 Aug 2017 16:23:04 +0100 Subject: [PATCH 050/177] Increase the z-index of the navbar Closes #35935 --- app/assets/stylesheets/framework/header.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 1c4238bc564..15de46dc5a9 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -24,7 +24,7 @@ header { &.navbar-gitlab { padding: 0 16px; - z-index: 400; + z-index: 2000; margin-bottom: 0; min-height: $header-height; background-color: $gray-light; From 85582b0537c50304f30b71a0de61954b1f6c508a Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 27 Jul 2017 11:01:09 +0100 Subject: [PATCH 051/177] Moved changed files into a dropdown This makes navigating through diff files quickly. Currently we just toggle a list, which could be pretty big. This moves it into a dropdown to make it much easier. Also includes a filter bar to quickly search for certain files/extensions. Closes #29778 --- app/assets/javascripts/merge_request_tabs.js | 9 +++ app/assets/stylesheets/pages/diff.scss | 17 +++++- app/helpers/diff_helper.rb | 18 ++++++ app/views/projects/diffs/_stats.html.haml | 60 ++++++++----------- .../diff-changed-files-dropdown.yml | 4 ++ 5 files changed, 70 insertions(+), 38 deletions(-) create mode 100644 changelogs/unreleased/diff-changed-files-dropdown.yml diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js index 7840f05a8ae..d3faa2d8e51 100644 --- a/app/assets/javascripts/merge_request_tabs.js +++ b/app/assets/javascripts/merge_request_tabs.js @@ -266,6 +266,8 @@ import BlobForkSuggestion from './blob/blob_fork_suggestion'; const $container = $('#diffs'); $container.html(data.html); + this.initChangesDropdown(); + if (typeof gl.diffNotesCompileComponents !== 'undefined') { gl.diffNotesCompileComponents(); } @@ -314,6 +316,13 @@ import BlobForkSuggestion from './blob/blob_fork_suggestion'; }); } + initChangesDropdown() { + $('.js-diff-stats-dropdown').glDropdown({ + filterable: true, + remoteFilter: false, + }); + } + // Show or hide the loading spinner // // status - Boolean, true to show, false to hide diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index 398fd4444ea..972e6c7425f 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -395,12 +395,11 @@ background-color: transparent; border: 0; color: $gl-link-color; - transition: color 0.1s linear; + font-weight: 600; &:hover, &:focus { outline: none; - text-decoration: underline; color: $gl-link-hover-color; } } @@ -559,3 +558,17 @@ outline: 0; } } + +.diff-file-changes { + width: 450px; + z-index: 150; + + a { + padding-top: 8px; + padding-bottom: 8px; + } +} + +.diff-file-changes-path { + @include str-truncated(78%); +} diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 91ddd73fac1..087f7f88fb5 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -148,6 +148,24 @@ module DiffHelper options end + def diff_file_changed_icon(diff_file) + if diff_file.deleted_file? || diff_file.renamed_file? + "minus" + elsif diff_file.new_file? + "plus" + else + "adjust" + end + end + + def diff_file_changed_icon_color(diff_file) + if diff_file.deleted_file? + "cred" + elsif diff_file.new_file? + "cgreen" + end + end + private def diff_btn(title, name, selected) diff --git a/app/views/projects/diffs/_stats.html.haml b/app/views/projects/diffs/_stats.html.haml index e69c7f20d49..4c7af37e305 100644 --- a/app/views/projects/diffs/_stats.html.haml +++ b/app/views/projects/diffs/_stats.html.haml @@ -1,36 +1,24 @@ -.js-toggle-container - .commit-stat-summary - Showing - %button.diff-stats-summary-toggler.js-toggle-button{ type: "button" } - %strong= pluralize(diff_files.size, "changed file") - with - %strong.cgreen #{diff_files.sum(&:added_lines)} additions - and - %strong.cred #{diff_files.sum(&:removed_lines)} deletions - .file-stats.js-toggle-content.hide - %ul - - diff_files.each do |diff_file| - - file_hash = hexdigest(diff_file.file_path) - %li - - if diff_file.deleted_file? - %span.deleted-file - %a{ href: "##{file_hash}" } - %i.fa.fa-minus - = diff_file.old_path - - elsif diff_file.renamed_file? - %span.renamed-file - %a{ href: "##{file_hash}" } - %i.fa.fa-minus - = diff_file.old_path - → - = diff_file.new_path - - elsif diff_file.new_file? - %span.new-file - %a{ href: "##{file_hash}" } - %i.fa.fa-plus - = diff_file.new_path - - else - %span.edit-file - %a{ href: "##{file_hash}" } - %i.fa.fa-adjust - = diff_file.new_path +.commit-stat-summary.dropdown + Showing + %button.diff-stats-summary-toggler.js-diff-stats-dropdown{ type: "button", data: { toggle: "dropdown" } }< + = pluralize(diff_files.size, "changed file") + = icon("caret-down fw") + with + %strong.cgreen #{diff_files.sum(&:added_lines)} additions + and + %strong.cred #{diff_files.sum(&:removed_lines)} deletions + .dropdown-menu.diff-file-changes + = dropdown_filter("Search file") + .dropdown-content + %ul + - diff_files.each do |diff_file| + - file_hash = hexdigest(diff_file.file_path) + - added_lines = diff_file.added_lines + - removed_lines = diff_file.removed_lines + %li + %a{ href: "##{file_hash}", title: diff_file.new_path } + = icon("#{diff_file_changed_icon(diff_file)} fw", class: "#{diff_file_changed_icon_color(diff_file)} append-right-5") + %span.diff-file-changes-path= diff_file.new_path + .pull-right + %span.cgreen= "+#{added_lines}" + %span.cred= "-#{removed_lines}" diff --git a/changelogs/unreleased/diff-changed-files-dropdown.yml b/changelogs/unreleased/diff-changed-files-dropdown.yml new file mode 100644 index 00000000000..2d2a26ffea2 --- /dev/null +++ b/changelogs/unreleased/diff-changed-files-dropdown.yml @@ -0,0 +1,4 @@ +--- +title: Moved diff changed files into a dropdown +merge_request: +author: From 655510ec9a658c28f50ccb0caea394f5db7cae59 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 27 Jul 2017 15:30:57 +0100 Subject: [PATCH 052/177] fixed haml lint --- app/assets/javascripts/gl_dropdown.js | 6 ++++++ app/assets/stylesheets/framework/dropdowns.scss | 1 + app/views/projects/diffs/_diffs.html.haml | 2 +- app/views/projects/diffs/_stats.html.haml | 6 ++++-- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index 9475498e176..85d720c3a69 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -731,9 +731,15 @@ GitLabDropdown = (function() { GitLabDropdown.prototype.focusTextInput = function(triggerFocus = false) { if (this.options.filterable) { this.dropdown.one('transitionend', () => { + const initialScrollTop = $(window).scrollTop(); + if (this.dropdown.is('.open')) { this.filterInput.focus(); } + + if ($(window).scrollTop() < initialScrollTop) { + $(window).scrollTop(initialScrollTop); + } }); if (triggerFocus) { diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index 572203bce34..9b8176a4a90 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -574,6 +574,7 @@ .dropdown-input-field, .default-dropdown-input { + display: block; width: 100%; min-height: 30px; padding: 0 7px; diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml index f9385459a66..8c8aa4c78f5 100644 --- a/app/views/projects/diffs/_diffs.html.haml +++ b/app/views/projects/diffs/_diffs.html.haml @@ -3,7 +3,7 @@ - can_create_note = !@diff_notes_disabled && can?(current_user, :create_note, diffs.project) - diff_files = diffs.diff_files -.content-block.oneline-block.files-changed +.content-block.oneline-block.files-changed.diff-files-changed.js-diff-files-changed .inline-parallel-buttons - if !diffs_expanded? && diff_files.any? { |diff_file| diff_file.collapsed? } = link_to 'Expand all', url_for(params.merge(expanded: 1, format: nil)), class: 'btn btn-default' diff --git a/app/views/projects/diffs/_stats.html.haml b/app/views/projects/diffs/_stats.html.haml index 4c7af37e305..307311a090f 100644 --- a/app/views/projects/diffs/_stats.html.haml +++ b/app/views/projects/diffs/_stats.html.haml @@ -20,5 +20,7 @@ = icon("#{diff_file_changed_icon(diff_file)} fw", class: "#{diff_file_changed_icon_color(diff_file)} append-right-5") %span.diff-file-changes-path= diff_file.new_path .pull-right - %span.cgreen= "+#{added_lines}" - %span.cred= "-#{removed_lines}" + %span.cgreen< + +#{added_lines} + %span.cred< + \-#{removed_lines} From b507682d6e799f737c05f27201dc4a0dbe3aba1d Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 27 Jul 2017 15:53:04 +0100 Subject: [PATCH 053/177] made the changed files holder sticky --- app/assets/javascripts/lib/utils/sticky.js | 21 ++++++++++ app/assets/javascripts/merge_request_tabs.js | 3 ++ app/assets/stylesheets/pages/diff.scss | 41 ++++++++++++++++++++ app/views/projects/diffs/_stats.html.haml | 16 ++++++-- 4 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 app/assets/javascripts/lib/utils/sticky.js diff --git a/app/assets/javascripts/lib/utils/sticky.js b/app/assets/javascripts/lib/utils/sticky.js new file mode 100644 index 00000000000..f53acaa17b1 --- /dev/null +++ b/app/assets/javascripts/lib/utils/sticky.js @@ -0,0 +1,21 @@ +export const isSticky = (el, stickyTop) => { + const top = el.getBoundingClientRect().top; + + if (top === stickyTop) { + el.classList.add('is-stuck'); + } else { + el.classList.remove('is-stuck'); + } +}; + +export default (el) => { + const computedStyle = window.getComputedStyle(el); + + if (!/sticky/.test(computedStyle.position)) return; + + const stickyTop = parseInt(computedStyle.top, 10); + + document.addEventListener('scroll', () => isSticky(el, stickyTop), { + passive: true, + }); +}; diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js index d3faa2d8e51..4ffd71d9de5 100644 --- a/app/assets/javascripts/merge_request_tabs.js +++ b/app/assets/javascripts/merge_request_tabs.js @@ -7,6 +7,7 @@ import Cookies from 'js-cookie'; import './breakpoints'; import './flash'; import BlobForkSuggestion from './blob/blob_fork_suggestion'; +import stickyMonitor from './lib/utils/sticky'; /* eslint-disable max-len */ // MergeRequestTabs @@ -268,6 +269,8 @@ import BlobForkSuggestion from './blob/blob_fork_suggestion'; this.initChangesDropdown(); + stickyMonitor(document.querySelector('.js-diff-files-changed')); + if (typeof gl.diffNotesCompileComponents !== 'undefined') { gl.diffNotesCompileComponents(); } diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index 972e6c7425f..7d765f45812 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -559,6 +559,47 @@ } } +.diff-files-changed { + .commit-stat-summary { + z-index: -1; + } + + @media (min-width: $screen-sm-min) { + position: -webkit-sticky; + position: sticky; + top: 100px; + background-color: $white-light; + z-index: 190; + + + .files { + margin-top: 1px; + } + + .diff-stats-additions-deletions-collapsed { + display: none; + } + + &.is-stuck { + padding-top: 0; + padding-bottom: 0; + border-bottom: 1px solid $white-dark; + + .diff-stats-additions-deletions-expanded, + .inline-parallel-buttons { + display: none; + } + + .diff-stats-additions-deletions-collapsed { + display: block; + } + + + .files { + margin-top: 16px; + } + } + } +} + .diff-file-changes { width: 450px; z-index: 150; diff --git a/app/views/projects/diffs/_stats.html.haml b/app/views/projects/diffs/_stats.html.haml index 307311a090f..4f784f87f2b 100644 --- a/app/views/projects/diffs/_stats.html.haml +++ b/app/views/projects/diffs/_stats.html.haml @@ -1,12 +1,20 @@ +- sum_added_lines = diff_files.sum(&:added_lines) +- sum_removed_lines = diff_files.sum(&:removed_lines) .commit-stat-summary.dropdown Showing %button.diff-stats-summary-toggler.js-diff-stats-dropdown{ type: "button", data: { toggle: "dropdown" } }< = pluralize(diff_files.size, "changed file") = icon("caret-down fw") - with - %strong.cgreen #{diff_files.sum(&:added_lines)} additions - and - %strong.cred #{diff_files.sum(&:removed_lines)} deletions + %span.diff-stats-additions-deletions-expanded + with + %strong.cgreen #{sum_added_lines} additions + and + %strong.cred #{sum_removed_lines} deletions + .diff-stats-additions-deletions-collapsed.pull-right{ "aria-hidden": "true" } + %strong.cgreen< + +#{sum_added_lines} + %strong.cred< + \-#{sum_removed_lines} .dropdown-menu.diff-file-changes = dropdown_filter("Search file") .dropdown-content From 30777178e3311c8aa7f4ecae82bd970fda63d85c Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 28 Jul 2017 11:54:51 +0100 Subject: [PATCH 054/177] fixed jumping when bar gets stuck added specs to sticky util file added `No files found.` text when results are empty --- app/assets/javascripts/gl_dropdown.js | 6 ++- app/assets/javascripts/lib/utils/sticky.js | 6 +-- app/assets/stylesheets/pages/diff.scss | 21 ++++++--- app/views/projects/diffs/_stats.html.haml | 7 ++- spec/javascripts/lib/utils/sticky_spec.js | 52 ++++++++++++++++++++++ 5 files changed, 78 insertions(+), 14 deletions(-) create mode 100644 spec/javascripts/lib/utils/sticky_spec.js diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index 85d720c3a69..73874363c1f 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -114,7 +114,7 @@ GitLabDropdownFilter = (function() { } else { elements = this.options.elements(); if (search_text) { - return elements.each(function() { + elements.each(function() { var $el, matches; $el = $(this); matches = fuzzaldrinPlus.match($el.text().trim(), search_text); @@ -127,8 +127,10 @@ GitLabDropdownFilter = (function() { } }); } else { - return elements.show().removeClass('option-hidden'); + elements.show().removeClass('option-hidden'); } + + elements.parent().find('.dropdown-menu-empty-link').toggleClass('hidden', elements.is(':visible')); } }; diff --git a/app/assets/javascripts/lib/utils/sticky.js b/app/assets/javascripts/lib/utils/sticky.js index f53acaa17b1..b5fde040a17 100644 --- a/app/assets/javascripts/lib/utils/sticky.js +++ b/app/assets/javascripts/lib/utils/sticky.js @@ -1,5 +1,5 @@ -export const isSticky = (el, stickyTop) => { - const top = el.getBoundingClientRect().top; +export const isSticky = (el, scrollY, stickyTop) => { + const top = el.offsetTop - scrollY; if (top === stickyTop) { el.classList.add('is-stuck'); @@ -15,7 +15,7 @@ export default (el) => { const stickyTop = parseInt(computedStyle.top, 10); - document.addEventListener('scroll', () => isSticky(el, stickyTop), { + document.addEventListener('scroll', () => isSticky(el, window.scrollY, stickyTop), { passive: true, }); }; diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index 7d765f45812..f98129bc09d 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -562,12 +562,18 @@ .diff-files-changed { .commit-stat-summary { z-index: -1; + + @media (min-width: $screen-sm-min) { + margin-left: -$gl-padding; + padding-left: $gl-padding; + background-color: $white-light; + } } @media (min-width: $screen-sm-min) { position: -webkit-sticky; position: sticky; - top: 100px; + top: 84px; background-color: $white-light; z-index: 190; @@ -575,7 +581,7 @@ margin-top: 1px; } - .diff-stats-additions-deletions-collapsed { + &:not(.is-stuck) .diff-stats-additions-deletions-collapsed { display: none; } @@ -583,18 +589,15 @@ padding-top: 0; padding-bottom: 0; border-bottom: 1px solid $white-dark; + transform: translateY(16px); .diff-stats-additions-deletions-expanded, .inline-parallel-buttons { display: none; } - .diff-stats-additions-deletions-collapsed { - display: block; - } - + .files { - margin-top: 16px; + margin-top: 30px; } } } @@ -604,6 +607,10 @@ width: 450px; z-index: 150; + @media (min-width: $screen-sm-min) { + left: $gl-padding; + } + a { padding-top: 8px; padding-bottom: 8px; diff --git a/app/views/projects/diffs/_stats.html.haml b/app/views/projects/diffs/_stats.html.haml index 4f784f87f2b..7c2941e6be3 100644 --- a/app/views/projects/diffs/_stats.html.haml +++ b/app/views/projects/diffs/_stats.html.haml @@ -5,12 +5,12 @@ %button.diff-stats-summary-toggler.js-diff-stats-dropdown{ type: "button", data: { toggle: "dropdown" } }< = pluralize(diff_files.size, "changed file") = icon("caret-down fw") - %span.diff-stats-additions-deletions-expanded + %span.diff-stats-additions-deletions-expanded#diff-stats with %strong.cgreen #{sum_added_lines} additions and %strong.cred #{sum_removed_lines} deletions - .diff-stats-additions-deletions-collapsed.pull-right{ "aria-hidden": "true" } + .diff-stats-additions-deletions-collapsed.pull-right{ "aria-hidden": "true", "aria-describedby": "diff-stats" } %strong.cgreen< +#{sum_added_lines} %strong.cred< @@ -32,3 +32,6 @@ +#{added_lines} %span.cred< \-#{removed_lines} + %li.dropdown-menu-empty-link.hidden + %a{ href: "#" } + No files found. diff --git a/spec/javascripts/lib/utils/sticky_spec.js b/spec/javascripts/lib/utils/sticky_spec.js new file mode 100644 index 00000000000..c3ee3ef9825 --- /dev/null +++ b/spec/javascripts/lib/utils/sticky_spec.js @@ -0,0 +1,52 @@ +import { isSticky } from '~/lib/utils/sticky'; + +describe('sticky', () => { + const el = { + offsetTop: 0, + classList: {}, + }; + + beforeEach(() => { + el.offsetTop = 0; + el.classList.add = jasmine.createSpy('spy'); + el.classList.remove = jasmine.createSpy('spy'); + }); + + describe('classList.remove', () => { + it('does not call classList.remove when stuck', () => { + isSticky(el, 0, 0); + + expect( + el.classList.remove, + ).not.toHaveBeenCalled(); + }); + + it('calls classList.remove when not stuck', () => { + el.offsetTop = 10; + isSticky(el, 0, 0); + + expect( + el.classList.remove, + ).toHaveBeenCalledWith('is-stuck'); + }); + }); + + describe('classList.add', () => { + it('calls classList.add when stuck', () => { + isSticky(el, 0, 0); + + expect( + el.classList.add, + ).toHaveBeenCalledWith('is-stuck'); + }); + + it('does not call classList.add when not stuck', () => { + el.offsetTop = 10; + isSticky(el, 0, 0); + + expect( + el.classList.add, + ).not.toHaveBeenCalled(); + }); + }); +}); From d86cbe69410a9a20bdeb996435a134c71ee87863 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 28 Jul 2017 12:11:05 +0100 Subject: [PATCH 055/177] fixed alignment in button correctly scroll to element with sticky height offset --- app/assets/javascripts/lib/utils/common_utils.js | 10 ++++++++-- app/views/projects/diffs/_stats.html.haml | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js index 122ec138c59..e916724b666 100644 --- a/app/assets/javascripts/lib/utils/common_utils.js +++ b/app/assets/javascripts/lib/utils/common_utils.js @@ -86,8 +86,9 @@ // This is required to handle non-unicode characters in hash hash = decodeURIComponent(hash); - var fixedTabs = document.querySelector('.js-tabs-affix'); - var fixedNav = document.querySelector('.navbar-gitlab'); + const fixedTabs = document.querySelector('.js-tabs-affix'); + const fixedDiffStats = document.querySelector('.js-diff-files-changed.is-stuck'); + const fixedNav = document.querySelector('.navbar-gitlab'); var adjustment = 0; if (fixedNav) adjustment -= fixedNav.offsetHeight; @@ -104,6 +105,11 @@ if (fixedTabs) { adjustment -= fixedTabs.offsetHeight; } + + if (fixedDiffStats) { + adjustment -= fixedDiffStats.offsetHeight; + } + window.scrollBy(0, adjustment); } }; diff --git a/app/views/projects/diffs/_stats.html.haml b/app/views/projects/diffs/_stats.html.haml index 7c2941e6be3..38fccb3d44f 100644 --- a/app/views/projects/diffs/_stats.html.haml +++ b/app/views/projects/diffs/_stats.html.haml @@ -4,7 +4,7 @@ Showing %button.diff-stats-summary-toggler.js-diff-stats-dropdown{ type: "button", data: { toggle: "dropdown" } }< = pluralize(diff_files.size, "changed file") - = icon("caret-down fw") + = icon("caret-down", class: "prepend-left-5") %span.diff-stats-additions-deletions-expanded#diff-stats with %strong.cgreen #{sum_added_lines} additions @@ -16,7 +16,7 @@ %strong.cred< \-#{sum_removed_lines} .dropdown-menu.diff-file-changes - = dropdown_filter("Search file") + = dropdown_filter("Search files") .dropdown-content %ul - diff_files.each do |diff_file| From b8770ba98bf5e077a81b8f543a045580088a548e Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 31 Jul 2017 11:23:19 +0100 Subject: [PATCH 056/177] fixed karma failure --- app/assets/javascripts/lib/utils/sticky.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/assets/javascripts/lib/utils/sticky.js b/app/assets/javascripts/lib/utils/sticky.js index b5fde040a17..43a808b6ab3 100644 --- a/app/assets/javascripts/lib/utils/sticky.js +++ b/app/assets/javascripts/lib/utils/sticky.js @@ -9,6 +9,8 @@ export const isSticky = (el, scrollY, stickyTop) => { }; export default (el) => { + if (!el) return; + const computedStyle = window.getComputedStyle(el); if (!/sticky/.test(computedStyle.position)) return; From 0c5e41a20fcdafb351eb2e62279b89eed81de426 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 31 Jul 2017 13:50:41 +0100 Subject: [PATCH 057/177] fixed z-index issue with merge request versions widget --- app/assets/stylesheets/pages/merge_requests.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 4693b2434c7..a4e19094508 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -691,8 +691,10 @@ } .mr-version-controls { + position: relative; background: $gray-light; color: $gl-text-color; + z-index: 199; .mr-version-menus-container { display: -webkit-flex; From 86d34921fee9ec324fdce3d36a8557604851a619 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 1 Aug 2017 17:56:09 +0100 Subject: [PATCH 058/177] dont assign to variable, just output directly --- app/views/projects/diffs/_stats.html.haml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/app/views/projects/diffs/_stats.html.haml b/app/views/projects/diffs/_stats.html.haml index 38fccb3d44f..efc0ea31917 100644 --- a/app/views/projects/diffs/_stats.html.haml +++ b/app/views/projects/diffs/_stats.html.haml @@ -20,18 +20,15 @@ .dropdown-content %ul - diff_files.each do |diff_file| - - file_hash = hexdigest(diff_file.file_path) - - added_lines = diff_file.added_lines - - removed_lines = diff_file.removed_lines %li - %a{ href: "##{file_hash}", title: diff_file.new_path } + %a{ href: "##{hexdigest(diff_file.file_path)}", title: diff_file.new_path } = icon("#{diff_file_changed_icon(diff_file)} fw", class: "#{diff_file_changed_icon_color(diff_file)} append-right-5") %span.diff-file-changes-path= diff_file.new_path .pull-right %span.cgreen< - +#{added_lines} + +#{diff_file.added_lines} %span.cred< - \-#{removed_lines} + \-#{diff_file.removed_lines} %li.dropdown-menu-empty-link.hidden %a{ href: "#" } No files found. From 370839cf10828e791893adaf81ab2e39c2b419cb Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 1 Aug 2017 18:04:03 +0100 Subject: [PATCH 059/177] fixed alert box moving when is-stuck gets added --- app/assets/stylesheets/pages/diff.scss | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index f98129bc09d..cfc801859a7 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -577,7 +577,8 @@ background-color: $white-light; z-index: 190; - + .files { + + .files, + + .alert { margin-top: 1px; } @@ -596,7 +597,8 @@ display: none; } - + .files { + + .files, + + .alert { margin-top: 30px; } } From 80647364ffaad3d100c64dd8a1ab32e8a9b4bcf9 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Wed, 19 Jul 2017 11:17:29 -0700 Subject: [PATCH 060/177] move the ability check to reject_users_without_access --- app/services/notification_recipient_service.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 9ac561e4bd2..1abf0335dc4 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -253,7 +253,6 @@ class NotificationRecipientService end users = users.to_a.compact.uniq - users = users.select { |u| u.can?(:receive_notifications) } users.reject do |user| global_notification_setting = user.global_notification_setting @@ -287,6 +286,8 @@ class NotificationRecipientService end def reject_users_without_access(recipients, target) + recipients = recipients.select { |u| u.can?(:receive_notifications) } + ability = case target when Issuable :"read_#{target.to_ability_name}" From b188e1b9e66eb02ac9b51364dfa33e206ea636c3 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Thu, 20 Jul 2017 11:57:42 -0700 Subject: [PATCH 061/177] move notification_setting_for_user_project to a public class method --- .../notification_recipient_service.rb | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 1abf0335dc4..07f5655b826 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -4,6 +4,18 @@ class NotificationRecipientService attr_reader :project + def self.notification_setting_for_user_project(user, project) + project_setting = user.notification_settings_for(project) + + return project_setting unless project_setting.global? + + group_setting = user.notification_settings_for(project.group) + + return group_setting unless group_setting.global? + + user.global_notification_setting + end + def initialize(project) @project = project end @@ -55,7 +67,7 @@ class NotificationRecipientService :success_pipeline end - notification_setting = notification_setting_for_user_project(current_user, target.project) + notification_setting = NotificationRecipientService.notification_setting_for_user_project(current_user, target.project) return [] if notification_setting.mention? || notification_setting.disabled? @@ -317,16 +329,4 @@ class NotificationRecipientService def build_custom_key(action, object) "#{action}_#{object.class.model_name.name.underscore}".to_sym end - - def notification_setting_for_user_project(user, project) - project_setting = user.notification_settings_for(project) - - return project_setting unless project_setting.global? - - group_setting = user.notification_settings_for(project.group) - - return group_setting unless group_setting.global? - - user.global_notification_setting - end end From 9cd46811d3dd2e6a0cb1b68ba390f9ab3fc587b7 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Thu, 20 Jul 2017 11:58:30 -0700 Subject: [PATCH 062/177] protect against nil project/group/setting --- app/services/notification_recipient_service.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 07f5655b826..e1456158ff7 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -5,13 +5,13 @@ class NotificationRecipientService attr_reader :project def self.notification_setting_for_user_project(user, project) - project_setting = user.notification_settings_for(project) + project_setting = project && user.notification_settings_for(project) - return project_setting unless project_setting.global? + return project_setting unless project_setting.nil? || project_setting.global? - group_setting = user.notification_settings_for(project.group) + group_setting = project&.group && user.notification_settings_for(project.group) - return group_setting unless group_setting.global? + return group_setting unless group_setting.nil? || group_setting.global? user.global_notification_setting end From cce1bc9a2f3bbba5ad2a256c96d85eb2276e6ac6 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Thu, 20 Jul 2017 12:02:12 -0700 Subject: [PATCH 063/177] use notification_setting_for_user_project in reject_users --- .../notification_recipient_service.rb | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index e1456158ff7..92049add32d 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -267,24 +267,8 @@ class NotificationRecipientService users = users.to_a.compact.uniq users.reject do |user| - global_notification_setting = user.global_notification_setting - - next global_notification_setting.level == level unless project - - setting = user.notification_settings_for(project) - - if project.group && (setting.nil? || setting.global?) - setting = user.notification_settings_for(project.group) - end - - # reject users who globally set mention notification and has no setting per project/group - next global_notification_setting.level == level unless setting - - # reject users who set mention notification in project - next true if setting.level == level - - # reject users who have mention level in project and disabled in global settings - setting.global? && global_notification_setting.level == level + setting = NotificationRecipientService.notification_setting_for_user_project(user, project) + setting.present? && setting.level == level end end From b1334ed94e09f584505f9804566e51a34817c8da Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Thu, 20 Jul 2017 12:21:47 -0700 Subject: [PATCH 064/177] move the builders to classes with a #build --- .../notification_recipient_service.rb | 598 ++++++++++-------- 1 file changed, 318 insertions(+), 280 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 92049add32d..97bbc47efb3 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -20,297 +20,335 @@ class NotificationRecipientService @project = project end - def build_recipients(target, current_user, action:, previous_assignee: nil, skip_current_user: true) - custom_action = build_custom_key(action, target) + module Builder - recipients = participants(target, current_user) - recipients = add_project_watchers(recipients) - recipients = add_custom_notifications(recipients, custom_action) - recipients = reject_mention_users(recipients) - - # Re-assign is considered as a mention of the new assignee so we add the - # new assignee to the list of recipients after we rejected users with - # the "on mention" notification level - case custom_action - when :reassign_merge_request - recipients << previous_assignee if previous_assignee - recipients << target.assignee - when :reassign_issue - previous_assignees = Array(previous_assignee) - recipients.concat(previous_assignees) - recipients.concat(target.assignees) - end - - recipients = reject_muted_users(recipients) - recipients = add_subscribed_users(recipients, target) - - if [:new_issue, :new_merge_request].include?(custom_action) - recipients = add_labels_subscribers(recipients, target) - end - - recipients = reject_unsubscribed_users(recipients, target) - recipients = reject_users_without_access(recipients, target) - - recipients.delete(current_user) if skip_current_user && !current_user.notified_of_own_activity? - - recipients.uniq - end - - def build_pipeline_recipients(target, current_user, action:) - return [] unless current_user - - custom_action = - case action.to_s - when 'failed' - :failed_pipeline - when 'success' - :success_pipeline + class Base + attr_reader :project + def initialize(project) + @project = project end - notification_setting = NotificationRecipientService.notification_setting_for_user_project(current_user, target.project) + def build(*) + raise 'abstract' + end - return [] if notification_setting.mention? || notification_setting.disabled? + # Remove users with disabled notifications from array + # Also remove duplications and nil recipients + def reject_muted_users(users) + reject_users(users, :disabled) + end - return [] if notification_setting.custom? && !notification_setting.event_enabled?(custom_action) + protected - return [] if (notification_setting.watch? || notification_setting.participating?) && NotificationSetting::EXCLUDED_WATCHER_EVENTS.include?(custom_action) + # Ensure that if we modify this array, we aren't modifying the memoised + # participants on the target. + def participants(target, user) + return unless target.respond_to?(:participants) - reject_users_without_access([current_user], target) + target.participants(user).dup + end + + # Get project/group users with CUSTOM notification level + def add_custom_notifications(recipients, action) + user_ids = [] + + # Users with a notification setting on group or project + user_ids += user_ids_notifiable_on(project, :custom, action) + user_ids += user_ids_notifiable_on(project.group, :custom, action) + + # Users with global level custom + user_ids_with_project_level_global = user_ids_notifiable_on(project, :global) + user_ids_with_group_level_global = user_ids_notifiable_on(project.group, :global) + + global_users_ids = user_ids_with_project_level_global.concat(user_ids_with_group_level_global) + user_ids += user_ids_with_global_level_custom(global_users_ids, action) + + recipients.concat(User.find(user_ids)) + end + + def add_project_watchers(recipients) + recipients.concat(project_watchers).compact + end + + # Get project users with WATCH notification level + def project_watchers + project_members_ids = user_ids_notifiable_on(project) + + user_ids_with_project_global = user_ids_notifiable_on(project, :global) + user_ids_with_group_global = user_ids_notifiable_on(project.group, :global) + + user_ids = user_ids_with_global_level_watch((user_ids_with_project_global + user_ids_with_group_global).uniq) + + user_ids_with_project_setting = select_project_members_ids(project, user_ids_with_project_global, user_ids) + user_ids_with_group_setting = select_group_members_ids(project.group, project_members_ids, user_ids_with_group_global, user_ids) + + User.where(id: user_ids_with_project_setting.concat(user_ids_with_group_setting).uniq).to_a + end + + # Remove users with notification level 'Mentioned' + def reject_mention_users(users) + reject_users(users, :mention) + end + + def add_subscribed_users(recipients, target) + return recipients unless target.respond_to? :subscribers + + recipients + target.subscribers(project) + end + + def user_ids_notifiable_on(resource, notification_level = nil, action = nil) + return [] unless resource + + if notification_level + settings = resource.notification_settings.where(level: NotificationSetting.levels[notification_level]) + settings = settings.select { |setting| setting.event_enabled?(action) } if action.present? + settings.map(&:user_id) + else + resource.notification_settings.pluck(:user_id) + end + end + + # Build a list of user_ids based on project notification settings + def select_project_members_ids(project, global_setting, user_ids_global_level_watch) + user_ids = user_ids_notifiable_on(project, :watch) + + # If project setting is global, add to watch list if global setting is watch + global_setting.each do |user_id| + if user_ids_global_level_watch.include?(user_id) + user_ids << user_id + end + end + + user_ids + end + + # Build a list of user_ids based on group notification settings + def select_group_members_ids(group, project_members, global_setting, user_ids_global_level_watch) + uids = user_ids_notifiable_on(group, :watch) + + # Group setting is watch, add to user_ids list if user is not project member + user_ids = [] + uids.each do |user_id| + if project_members.exclude?(user_id) + user_ids << user_id + end + end + + # Group setting is global, add to user_ids list if global setting is watch + global_setting.each do |user_id| + if project_members.exclude?(user_id) && user_ids_global_level_watch.include?(user_id) + user_ids << user_id + end + end + + user_ids + end + + def user_ids_with_global_level_watch(ids) + settings_with_global_level_of(:watch, ids).pluck(:user_id) + end + + def user_ids_with_global_level_custom(ids, action) + settings = settings_with_global_level_of(:custom, ids) + settings = settings.select { |setting| setting.event_enabled?(action) } + settings.map(&:user_id) + end + + def settings_with_global_level_of(level, ids) + NotificationSetting.where( + user_id: ids, + source_type: nil, + level: NotificationSetting.levels[level] + ) + end + + # Reject users which has certain notification level + # + # Example: + # reject_users(users, :watch, project) + # + def reject_users(users, level) + level = level.to_s + + unless NotificationSetting.levels.keys.include?(level) + raise 'Invalid notification level' + end + + users = users.to_a.compact.uniq + + users.reject do |user| + setting = NotificationRecipientService.notification_setting_for_user_project(user, project) + setting.present? && setting.level == level + end + end + + def reject_unsubscribed_users(recipients, target) + return recipients unless target.respond_to? :subscriptions + + recipients.reject do |user| + subscription = target.subscriptions.find_by_user_id(user.id) + subscription && !subscription.subscribed + end + end + + def reject_users_without_access(recipients, target) + recipients = recipients.select { |u| u.can?(:receive_notifications) } + + ability = case target + when Issuable + :"read_#{target.to_ability_name}" + when Ci::Pipeline + :read_build # We have build trace in pipeline emails + end + + return recipients unless ability + + recipients.select do |user| + user.can?(ability, target) + end + end + + def add_labels_subscribers(recipients, target, labels: nil) + return recipients unless target.respond_to? :labels + + (labels || target.labels).each do |label| + recipients += label.subscribers(project) + end + + recipients + end + + # Build event key to search on custom notification level + # Check NotificationSetting::EMAIL_EVENTS + def build_custom_key(action, object) + "#{action}_#{object.class.model_name.name.underscore}".to_sym + end + end + + class Default < Base + def build(target, current_user, action:, previous_assignee: nil, skip_current_user: true) + custom_action = build_custom_key(action, target) + + recipients = participants(target, current_user) + recipients = add_project_watchers(recipients) + recipients = add_custom_notifications(recipients, custom_action) + recipients = reject_mention_users(recipients) + + # Re-assign is considered as a mention of the new assignee so we add the + # new assignee to the list of recipients after we rejected users with + # the "on mention" notification level + case custom_action + when :reassign_merge_request + recipients << previous_assignee if previous_assignee + recipients << target.assignee + when :reassign_issue + previous_assignees = Array(previous_assignee) + recipients.concat(previous_assignees) + recipients.concat(target.assignees) + end + + recipients = reject_muted_users(recipients) + recipients = add_subscribed_users(recipients, target) + + if [:new_issue, :new_merge_request].include?(custom_action) + recipients = add_labels_subscribers(recipients, target) + end + + recipients = reject_unsubscribed_users(recipients, target) + recipients = reject_users_without_access(recipients, target) + + recipients.delete(current_user) if skip_current_user && !current_user.notified_of_own_activity? + + recipients.uniq + end + end + + class Pipeline < Base + def build(target, current_user, action:) + return [] unless current_user + + custom_action = + case action.to_s + when 'failed' + :failed_pipeline + when 'success' + :success_pipeline + end + + notification_setting = NotificationRecipientService.notification_setting_for_user_project(current_user, target.project) + + return [] if notification_setting.mention? || notification_setting.disabled? + + return [] if notification_setting.custom? && !notification_setting.event_enabled?(custom_action) + + return [] if (notification_setting.watch? || notification_setting.participating?) && NotificationSetting::EXCLUDED_WATCHER_EVENTS.include?(custom_action) + + reject_users_without_access([current_user], target) + end + end + + class Relabeled < Base + def build(target, current_user, labels:) + recipients = add_labels_subscribers([], target, labels: labels) + recipients = reject_unsubscribed_users(recipients, target) + recipients = reject_users_without_access(recipients, target) + recipients.delete(current_user) unless current_user.notified_of_own_activity? + recipients.uniq + end + end + + class NewNote < Base + def build(note) + target = note.noteable + + ability, subject = if note.for_personal_snippet? + [:read_personal_snippet, note.noteable] + else + [:read_project, note.project] + end + + mentioned_users = note.mentioned_users.select { |user| user.can?(ability, subject) } + + # Add all users participating in the thread (author, assignee, comment authors) + recipients = participants(target, note.author) || mentioned_users + + unless note.for_personal_snippet? + # Merge project watchers + recipients = add_project_watchers(recipients) + + # Merge project with custom notification + recipients = add_custom_notifications(recipients, :new_note) + end + + # Reject users with Mention notification level, except those mentioned in _this_ note. + recipients = reject_mention_users(recipients - mentioned_users) + recipients = recipients + mentioned_users + + recipients = reject_muted_users(recipients) + + recipients = add_subscribed_users(recipients, note.noteable) + recipients = reject_unsubscribed_users(recipients, note.noteable) + recipients = reject_users_without_access(recipients, note.noteable) + + recipients.delete(note.author) unless note.author.notified_of_own_activity? + recipients.uniq + end + end end - def build_relabeled_recipients(target, current_user, labels:) - recipients = add_labels_subscribers([], target, labels: labels) - recipients = reject_unsubscribed_users(recipients, target) - recipients = reject_users_without_access(recipients, target) - recipients.delete(current_user) unless current_user.notified_of_own_activity? - recipients.uniq + def build_recipients(*a) + Builder::Default.new(@project).build(*a) + end + + def build_pipeline_recipients(*a) + Builder::Pipeline.new(@project).build(*a) + end + + def build_relabeled_recipients(*a) + Builder::Relabeled.new(@project).build(*a) end def build_new_note_recipients(note) - target = note.noteable - - ability, subject = if note.for_personal_snippet? - [:read_personal_snippet, note.noteable] - else - [:read_project, note.project] - end - - mentioned_users = note.mentioned_users.select { |user| user.can?(ability, subject) } - - # Add all users participating in the thread (author, assignee, comment authors) - recipients = participants(target, note.author) || mentioned_users - - unless note.for_personal_snippet? - # Merge project watchers - recipients = add_project_watchers(recipients) - - # Merge project with custom notification - recipients = add_custom_notifications(recipients, :new_note) - end - - # Reject users with Mention notification level, except those mentioned in _this_ note. - recipients = reject_mention_users(recipients - mentioned_users) - recipients = recipients + mentioned_users - - recipients = reject_muted_users(recipients) - - recipients = add_subscribed_users(recipients, note.noteable) - recipients = reject_unsubscribed_users(recipients, note.noteable) - recipients = reject_users_without_access(recipients, note.noteable) - - recipients.delete(note.author) unless note.author.notified_of_own_activity? - recipients.uniq - end - - # Remove users with disabled notifications from array - # Also remove duplications and nil recipients - def reject_muted_users(users) - reject_users(users, :disabled) - end - - protected - - # Ensure that if we modify this array, we aren't modifying the memoised - # participants on the target. - def participants(target, user) - return unless target.respond_to?(:participants) - - target.participants(user).dup - end - - # Get project/group users with CUSTOM notification level - def add_custom_notifications(recipients, action) - user_ids = [] - - # Users with a notification setting on group or project - user_ids += user_ids_notifiable_on(project, :custom, action) - user_ids += user_ids_notifiable_on(project.group, :custom, action) - - # Users with global level custom - user_ids_with_project_level_global = user_ids_notifiable_on(project, :global) - user_ids_with_group_level_global = user_ids_notifiable_on(project.group, :global) - - global_users_ids = user_ids_with_project_level_global.concat(user_ids_with_group_level_global) - user_ids += user_ids_with_global_level_custom(global_users_ids, action) - - recipients.concat(User.find(user_ids)) - end - - def add_project_watchers(recipients) - recipients.concat(project_watchers).compact - end - - # Get project users with WATCH notification level - def project_watchers - project_members_ids = user_ids_notifiable_on(project) - - user_ids_with_project_global = user_ids_notifiable_on(project, :global) - user_ids_with_group_global = user_ids_notifiable_on(project.group, :global) - - user_ids = user_ids_with_global_level_watch((user_ids_with_project_global + user_ids_with_group_global).uniq) - - user_ids_with_project_setting = select_project_members_ids(project, user_ids_with_project_global, user_ids) - user_ids_with_group_setting = select_group_members_ids(project.group, project_members_ids, user_ids_with_group_global, user_ids) - - User.where(id: user_ids_with_project_setting.concat(user_ids_with_group_setting).uniq).to_a - end - - # Remove users with notification level 'Mentioned' - def reject_mention_users(users) - reject_users(users, :mention) - end - - def add_subscribed_users(recipients, target) - return recipients unless target.respond_to? :subscribers - - recipients + target.subscribers(project) - end - - def user_ids_notifiable_on(resource, notification_level = nil, action = nil) - return [] unless resource - - if notification_level - settings = resource.notification_settings.where(level: NotificationSetting.levels[notification_level]) - settings = settings.select { |setting| setting.event_enabled?(action) } if action.present? - settings.map(&:user_id) - else - resource.notification_settings.pluck(:user_id) - end - end - - # Build a list of user_ids based on project notification settings - def select_project_members_ids(project, global_setting, user_ids_global_level_watch) - user_ids = user_ids_notifiable_on(project, :watch) - - # If project setting is global, add to watch list if global setting is watch - global_setting.each do |user_id| - if user_ids_global_level_watch.include?(user_id) - user_ids << user_id - end - end - - user_ids - end - - # Build a list of user_ids based on group notification settings - def select_group_members_ids(group, project_members, global_setting, user_ids_global_level_watch) - uids = user_ids_notifiable_on(group, :watch) - - # Group setting is watch, add to user_ids list if user is not project member - user_ids = [] - uids.each do |user_id| - if project_members.exclude?(user_id) - user_ids << user_id - end - end - - # Group setting is global, add to user_ids list if global setting is watch - global_setting.each do |user_id| - if project_members.exclude?(user_id) && user_ids_global_level_watch.include?(user_id) - user_ids << user_id - end - end - - user_ids - end - - def user_ids_with_global_level_watch(ids) - settings_with_global_level_of(:watch, ids).pluck(:user_id) - end - - def user_ids_with_global_level_custom(ids, action) - settings = settings_with_global_level_of(:custom, ids) - settings = settings.select { |setting| setting.event_enabled?(action) } - settings.map(&:user_id) - end - - def settings_with_global_level_of(level, ids) - NotificationSetting.where( - user_id: ids, - source_type: nil, - level: NotificationSetting.levels[level] - ) - end - - # Reject users which has certain notification level - # - # Example: - # reject_users(users, :watch, project) - # - def reject_users(users, level) - level = level.to_s - - unless NotificationSetting.levels.keys.include?(level) - raise 'Invalid notification level' - end - - users = users.to_a.compact.uniq - - users.reject do |user| - setting = NotificationRecipientService.notification_setting_for_user_project(user, project) - setting.present? && setting.level == level - end - end - - def reject_unsubscribed_users(recipients, target) - return recipients unless target.respond_to? :subscriptions - - recipients.reject do |user| - subscription = target.subscriptions.find_by_user_id(user.id) - subscription && !subscription.subscribed - end - end - - def reject_users_without_access(recipients, target) - recipients = recipients.select { |u| u.can?(:receive_notifications) } - - ability = case target - when Issuable - :"read_#{target.to_ability_name}" - when Ci::Pipeline - :read_build # We have build trace in pipeline emails - end - - return recipients unless ability - - recipients.select do |user| - user.can?(ability, target) - end - end - - def add_labels_subscribers(recipients, target, labels: nil) - return recipients unless target.respond_to? :labels - - (labels || target.labels).each do |label| - recipients += label.subscribers(project) - end - - recipients - end - - # Build event key to search on custom notification level - # Check NotificationSetting::EMAIL_EVENTS - def build_custom_key(action, object) - "#{action}_#{object.class.model_name.name.underscore}".to_sym + Builder::NewNote.new(@project).build(note) end end From 947bff886ba62087715dbc8b4d48e85588bd5322 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Thu, 20 Jul 2017 12:25:32 -0700 Subject: [PATCH 065/177] move the build arguments to the initializers --- .../notification_recipient_service.rb | 74 +++++++++++++++---- 1 file changed, 60 insertions(+), 14 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 97bbc47efb3..a68967d38b9 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -21,11 +21,13 @@ class NotificationRecipientService end module Builder - class Base - attr_reader :project - def initialize(project) - @project = project + def initialize(*) + raise 'abstract' + end + + def build + raise 'abstract' end def build(*) @@ -226,7 +228,22 @@ class NotificationRecipientService end class Default < Base - def build(target, current_user, action:, previous_assignee: nil, skip_current_user: true) + attr_reader :project + attr_reader :target + attr_reader :current_user + attr_reader :action + attr_reader :previous_assignee + attr_reader :skip_current_user + def initialize(project, target, current_user, action:, previous_assignee: nil, skip_current_user: true) + @project = project + @target = target + @current_user = current_user + @action = action + @previous_assignee = previous_assignee + @skip_current_user = skip_current_user + end + + def build custom_action = build_custom_key(action, target) recipients = participants(target, current_user) @@ -264,7 +281,18 @@ class NotificationRecipientService end class Pipeline < Base - def build(target, current_user, action:) + attr_reader :project + attr_reader :target + attr_reader :current_user + attr_reader :action + def initialize(project, target, current_user, action:) + @project = project + @target = target + @current_user = current_user + @action = action + end + + def build return [] unless current_user custom_action = @@ -288,7 +316,18 @@ class NotificationRecipientService end class Relabeled < Base - def build(target, current_user, labels:) + attr_reader :project + attr_reader :target + attr_reader :current_user + attr_reader :labels + def initialize(project, target, current_user, labels:) + @project = project + @target = target + @current_user = current_user + @labels = labels + end + + def build recipients = add_labels_subscribers([], target, labels: labels) recipients = reject_unsubscribed_users(recipients, target) recipients = reject_users_without_access(recipients, target) @@ -298,9 +337,16 @@ class NotificationRecipientService end class NewNote < Base - def build(note) - target = note.noteable + attr_reader :project + attr_reader :note + attr_reader :target + def initialize(project, note) + @project = project + @note = note + @target = note.noteable + end + def build(note) ability, subject = if note.for_personal_snippet? [:read_personal_snippet, note.noteable] else @@ -337,18 +383,18 @@ class NotificationRecipientService end def build_recipients(*a) - Builder::Default.new(@project).build(*a) + Builder::Default.new(@project, *a).build end def build_pipeline_recipients(*a) - Builder::Pipeline.new(@project).build(*a) + Builder::Pipeline.new(@project, *a).build end def build_relabeled_recipients(*a) - Builder::Relabeled.new(@project).build(*a) + Builder::Relabeled.new(@project, *a).build end - def build_new_note_recipients(note) - Builder::NewNote.new(@project).build(note) + def build_new_note_recipients(*a) + Builder::NewNote.new(@project, *a).build end end From b010a556b6b0314b333eb13ecc7095dc361f67a2 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Thu, 20 Jul 2017 12:36:37 -0700 Subject: [PATCH 066/177] factor out the `target` argument to helpers --- .../notification_recipient_service.rb | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index a68967d38b9..edad4ff021a 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -30,7 +30,7 @@ class NotificationRecipientService raise 'abstract' end - def build(*) + def target raise 'abstract' end @@ -44,7 +44,7 @@ class NotificationRecipientService # Ensure that if we modify this array, we aren't modifying the memoised # participants on the target. - def participants(target, user) + def participants(user) return unless target.respond_to?(:participants) target.participants(user).dup @@ -92,7 +92,7 @@ class NotificationRecipientService reject_users(users, :mention) end - def add_subscribed_users(recipients, target) + def add_subscribed_users(recipients) return recipients unless target.respond_to? :subscribers recipients + target.subscribers(project) @@ -184,7 +184,7 @@ class NotificationRecipientService end end - def reject_unsubscribed_users(recipients, target) + def reject_unsubscribed_users(recipients) return recipients unless target.respond_to? :subscriptions recipients.reject do |user| @@ -193,7 +193,7 @@ class NotificationRecipientService end end - def reject_users_without_access(recipients, target) + def reject_users_without_access(recipients) recipients = recipients.select { |u| u.can?(:receive_notifications) } ability = case target @@ -210,7 +210,7 @@ class NotificationRecipientService end end - def add_labels_subscribers(recipients, target, labels: nil) + def add_labels_subscribers(recipients, labels: nil) return recipients unless target.respond_to? :labels (labels || target.labels).each do |label| @@ -246,7 +246,7 @@ class NotificationRecipientService def build custom_action = build_custom_key(action, target) - recipients = participants(target, current_user) + recipients = participants(current_user) recipients = add_project_watchers(recipients) recipients = add_custom_notifications(recipients, custom_action) recipients = reject_mention_users(recipients) @@ -265,14 +265,14 @@ class NotificationRecipientService end recipients = reject_muted_users(recipients) - recipients = add_subscribed_users(recipients, target) + recipients = add_subscribed_users(recipients) if [:new_issue, :new_merge_request].include?(custom_action) - recipients = add_labels_subscribers(recipients, target) + recipients = add_labels_subscribers(recipients) end - recipients = reject_unsubscribed_users(recipients, target) - recipients = reject_users_without_access(recipients, target) + recipients = reject_unsubscribed_users(recipients) + recipients = reject_users_without_access(recipients) recipients.delete(current_user) if skip_current_user && !current_user.notified_of_own_activity? @@ -311,7 +311,7 @@ class NotificationRecipientService return [] if (notification_setting.watch? || notification_setting.participating?) && NotificationSetting::EXCLUDED_WATCHER_EVENTS.include?(custom_action) - reject_users_without_access([current_user], target) + reject_users_without_access([current_user]) end end @@ -328,9 +328,9 @@ class NotificationRecipientService end def build - recipients = add_labels_subscribers([], target, labels: labels) - recipients = reject_unsubscribed_users(recipients, target) - recipients = reject_users_without_access(recipients, target) + recipients = add_labels_subscribers([], labels: labels) + recipients = reject_unsubscribed_users(recipients) + recipients = reject_users_without_access(recipients) recipients.delete(current_user) unless current_user.notified_of_own_activity? recipients.uniq end @@ -356,7 +356,7 @@ class NotificationRecipientService mentioned_users = note.mentioned_users.select { |user| user.can?(ability, subject) } # Add all users participating in the thread (author, assignee, comment authors) - recipients = participants(target, note.author) || mentioned_users + recipients = participants(note.author) || mentioned_users unless note.for_personal_snippet? # Merge project watchers @@ -372,9 +372,9 @@ class NotificationRecipientService recipients = reject_muted_users(recipients) - recipients = add_subscribed_users(recipients, note.noteable) - recipients = reject_unsubscribed_users(recipients, note.noteable) - recipients = reject_users_without_access(recipients, note.noteable) + recipients = add_subscribed_users(recipients) + recipients = reject_unsubscribed_users(recipients) + recipients = reject_users_without_access(recipients) recipients.delete(note.author) unless note.author.notified_of_own_activity? recipients.uniq From 734e21054a71be06aec897404d95b0905e6ed6c7 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Thu, 20 Jul 2017 12:37:36 -0700 Subject: [PATCH 067/177] move build_custom_key to Default --- app/services/notification_recipient_service.rb | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index edad4ff021a..3b7a13ffed6 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -219,12 +219,6 @@ class NotificationRecipientService recipients end - - # Build event key to search on custom notification level - # Check NotificationSetting::EMAIL_EVENTS - def build_custom_key(action, object) - "#{action}_#{object.class.model_name.name.underscore}".to_sym - end end class Default < Base @@ -244,8 +238,6 @@ class NotificationRecipientService end def build - custom_action = build_custom_key(action, target) - recipients = participants(current_user) recipients = add_project_watchers(recipients) recipients = add_custom_notifications(recipients, custom_action) @@ -278,6 +270,12 @@ class NotificationRecipientService recipients.uniq end + + # Build event key to search on custom notification level + # Check NotificationSetting::EMAIL_EVENTS + def custom_action + @custom_action ||= "#{action}_#{target.class.model_name.name.underscore}".to_sym + end end class Pipeline < Base From cdc4b4d7a0ef75d5ecb5e7e8e69d35cf2a3bcf1c Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Thu, 20 Jul 2017 16:10:01 -0700 Subject: [PATCH 068/177] make recipients mutative during the build --- .../notification_recipient_service.rb | 137 ++++++++++-------- 1 file changed, 73 insertions(+), 64 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 3b7a13ffed6..0bada20444d 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -34,24 +34,35 @@ class NotificationRecipientService raise 'abstract' end + def recipients + @recipients ||= [] + end + + def to_a + return recipients if @already_built + @already_built = true + build + recipients.uniq! + recipients.freeze + recipients + end + # Remove users with disabled notifications from array # Also remove duplications and nil recipients - def reject_muted_users(users) - reject_users(users, :disabled) + def reject_muted_users + reject_users(:disabled) end protected - # Ensure that if we modify this array, we aren't modifying the memoised - # participants on the target. - def participants(user) + def add_participants(user) return unless target.respond_to?(:participants) - target.participants(user).dup + recipients.concat(target.participants(user)) end # Get project/group users with CUSTOM notification level - def add_custom_notifications(recipients, action) + def add_custom_notifications(action) user_ids = [] # Users with a notification setting on group or project @@ -68,8 +79,9 @@ class NotificationRecipientService recipients.concat(User.find(user_ids)) end - def add_project_watchers(recipients) - recipients.concat(project_watchers).compact + def add_project_watchers + recipients.concat(project_watchers) + recipients.compact! end # Get project users with WATCH notification level @@ -88,14 +100,14 @@ class NotificationRecipientService end # Remove users with notification level 'Mentioned' - def reject_mention_users(users) - reject_users(users, :mention) + def reject_mention_users + reject_users(:mention) end - def add_subscribed_users(recipients) - return recipients unless target.respond_to? :subscribers + def add_subscribed_users + return unless target.respond_to? :subscribers - recipients + target.subscribers(project) + recipients.concat(target.subscribers(project)) end def user_ids_notifiable_on(resource, notification_level = nil, action = nil) @@ -167,34 +179,35 @@ class NotificationRecipientService # Reject users which has certain notification level # # Example: - # reject_users(users, :watch, project) + # reject_users(:watch, project) # - def reject_users(users, level) + def reject_users(level) level = level.to_s unless NotificationSetting.levels.keys.include?(level) raise 'Invalid notification level' end - users = users.to_a.compact.uniq + recipients.compact! + recipients.uniq! - users.reject do |user| + recipients.reject! do |user| setting = NotificationRecipientService.notification_setting_for_user_project(user, project) setting.present? && setting.level == level end end - def reject_unsubscribed_users(recipients) - return recipients unless target.respond_to? :subscriptions + def reject_unsubscribed_users + return unless target.respond_to? :subscriptions - recipients.reject do |user| + recipients.reject! do |user| subscription = target.subscriptions.find_by_user_id(user.id) subscription && !subscription.subscribed end end - def reject_users_without_access(recipients) - recipients = recipients.select { |u| u.can?(:receive_notifications) } + def reject_users_without_access + recipients.select! { |u| u.can?(:receive_notifications) } ability = case target when Issuable @@ -203,21 +216,19 @@ class NotificationRecipientService :read_build # We have build trace in pipeline emails end - return recipients unless ability + return unless ability - recipients.select do |user| + recipients.select! do |user| user.can?(ability, target) end end - def add_labels_subscribers(recipients, labels: nil) - return recipients unless target.respond_to? :labels + def add_labels_subscribers(labels: nil) + return unless target.respond_to? :labels (labels || target.labels).each do |label| - recipients += label.subscribers(project) + recipients.concat(label.subscribers(project)) end - - recipients end end @@ -238,10 +249,10 @@ class NotificationRecipientService end def build - recipients = participants(current_user) - recipients = add_project_watchers(recipients) - recipients = add_custom_notifications(recipients, custom_action) - recipients = reject_mention_users(recipients) + add_participants(current_user) + add_project_watchers + add_custom_notifications(custom_action) + reject_mention_users # Re-assign is considered as a mention of the new assignee so we add the # new assignee to the list of recipients after we rejected users with @@ -256,19 +267,17 @@ class NotificationRecipientService recipients.concat(target.assignees) end - recipients = reject_muted_users(recipients) - recipients = add_subscribed_users(recipients) + reject_muted_users + add_subscribed_users if [:new_issue, :new_merge_request].include?(custom_action) - recipients = add_labels_subscribers(recipients) + add_labels_subscribers end - recipients = reject_unsubscribed_users(recipients) - recipients = reject_users_without_access(recipients) + reject_unsubscribed_users + reject_users_without_access recipients.delete(current_user) if skip_current_user && !current_user.notified_of_own_activity? - - recipients.uniq end # Build event key to search on custom notification level @@ -303,13 +312,14 @@ class NotificationRecipientService notification_setting = NotificationRecipientService.notification_setting_for_user_project(current_user, target.project) - return [] if notification_setting.mention? || notification_setting.disabled? + return if notification_setting.mention? || notification_setting.disabled? - return [] if notification_setting.custom? && !notification_setting.event_enabled?(custom_action) + return if notification_setting.custom? && !notification_setting.event_enabled?(custom_action) - return [] if (notification_setting.watch? || notification_setting.participating?) && NotificationSetting::EXCLUDED_WATCHER_EVENTS.include?(custom_action) + return if (notification_setting.watch? || notification_setting.participating?) && NotificationSetting::EXCLUDED_WATCHER_EVENTS.include?(custom_action) - reject_users_without_access([current_user]) + recipients << current_user + reject_users_without_access end end @@ -326,11 +336,10 @@ class NotificationRecipientService end def build - recipients = add_labels_subscribers([], labels: labels) - recipients = reject_unsubscribed_users(recipients) - recipients = reject_users_without_access(recipients) + add_labels_subscribers(labels: labels) + reject_unsubscribed_users + reject_users_without_access recipients.delete(current_user) unless current_user.notified_of_own_activity? - recipients.uniq end end @@ -344,7 +353,7 @@ class NotificationRecipientService @target = note.noteable end - def build(note) + def build ability, subject = if note.for_personal_snippet? [:read_personal_snippet, note.noteable] else @@ -354,45 +363,45 @@ class NotificationRecipientService mentioned_users = note.mentioned_users.select { |user| user.can?(ability, subject) } # Add all users participating in the thread (author, assignee, comment authors) - recipients = participants(note.author) || mentioned_users + add_participants(note.author) + recipients.concat(mentioned_users) if recipients.empty? unless note.for_personal_snippet? # Merge project watchers - recipients = add_project_watchers(recipients) + add_project_watchers # Merge project with custom notification - recipients = add_custom_notifications(recipients, :new_note) + add_custom_notifications(:new_note) end # Reject users with Mention notification level, except those mentioned in _this_ note. - recipients = reject_mention_users(recipients - mentioned_users) - recipients = recipients + mentioned_users + reject_mention_users + recipients.concat(mentioned_users) - recipients = reject_muted_users(recipients) + reject_muted_users - recipients = add_subscribed_users(recipients) - recipients = reject_unsubscribed_users(recipients) - recipients = reject_users_without_access(recipients) + add_subscribed_users + reject_unsubscribed_users + reject_users_without_access recipients.delete(note.author) unless note.author.notified_of_own_activity? - recipients.uniq end end end def build_recipients(*a) - Builder::Default.new(@project, *a).build + Builder::Default.new(@project, *a).to_a end def build_pipeline_recipients(*a) - Builder::Pipeline.new(@project, *a).build + Builder::Pipeline.new(@project, *a).to_a end def build_relabeled_recipients(*a) - Builder::Relabeled.new(@project, *a).build + Builder::Relabeled.new(@project, *a).to_a end def build_new_note_recipients(*a) - Builder::NewNote.new(@project, *a).build + Builder::NewNote.new(@project, *a).to_a end end From b05e6efd535990c8a54f470faa319e4b59ec12a3 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Tue, 1 Aug 2017 12:55:04 -0700 Subject: [PATCH 069/177] add builder helpers with levels and start to separate out #filter! --- .../notification_recipient_service.rb | 167 ++++++++++++------ spec/services/notification_service_spec.rb | 5 + 2 files changed, 118 insertions(+), 54 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 0bada20444d..8d15202ef1c 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -20,13 +20,35 @@ class NotificationRecipientService @project = project end + class Recipient + attr_reader :user, :type + def initialize(builder, user, type) + @builder = builder + @user = user + @type = type + end + + def notification_setting + @notification_setting ||= + NotificationRecipientService.notification_setting_for_user_project(user, @builder.project) + end + + def notification_level + notification_setting&.level&.to_sym + end + end + module Builder class Base def initialize(*) raise 'abstract' end - def build + def build! + raise 'abstract' + end + + def filter! raise 'abstract' end @@ -38,13 +60,22 @@ class NotificationRecipientService @recipients ||= [] end - def to_a - return recipients if @already_built - @already_built = true - build - recipients.uniq! - recipients.freeze - recipients + def <<(arg) + users, type = arg + users = Array(users) + users.compact! + recipients.concat(users.map { |u| Recipient.new(self, u, type) }) + end + + def recipient_users + @recipient_users ||= + begin + build! + filter! + users = recipients.map(&:user) + users.uniq! + users.freeze + end end # Remove users with disabled notifications from array @@ -53,12 +84,22 @@ class NotificationRecipientService reject_users(:disabled) end + def read_ability + @read_ability ||= + case target + when Issuable + :"read_#{target.to_ability_name}" + when Ci::Pipeline + :read_build # We have build trace in pipeline emails + end + end + protected def add_participants(user) return unless target.respond_to?(:participants) - recipients.concat(target.participants(user)) + self << [target.participants(user), :participating] end # Get project/group users with CUSTOM notification level @@ -76,12 +117,11 @@ class NotificationRecipientService global_users_ids = user_ids_with_project_level_global.concat(user_ids_with_group_level_global) user_ids += user_ids_with_global_level_custom(global_users_ids, action) - recipients.concat(User.find(user_ids)) + self << [User.find(user_ids), :watch] end def add_project_watchers - recipients.concat(project_watchers) - recipients.compact! + self << [project_watchers, :watch] end # Get project users with WATCH notification level @@ -101,13 +141,17 @@ class NotificationRecipientService # Remove users with notification level 'Mentioned' def reject_mention_users - reject_users(:mention) + recipients.select! do |r| + next true if r.type == :mention + next true if r.type == :subscription + r.notification_level != :mention + end end def add_subscribed_users return unless target.respond_to? :subscribers - recipients.concat(target.subscribers(project)) + self << [target.subscribers(project), :subscription] end def user_ids_notifiable_on(resource, notification_level = nil, action = nil) @@ -188,10 +232,9 @@ class NotificationRecipientService raise 'Invalid notification level' end - recipients.compact! - recipients.uniq! + recipients.reject! do |recipient| + user = recipient.user - recipients.reject! do |user| setting = NotificationRecipientService.notification_setting_for_user_project(user, project) setting.present? && setting.level == level end @@ -200,34 +243,34 @@ class NotificationRecipientService def reject_unsubscribed_users return unless target.respond_to? :subscriptions - recipients.reject! do |user| + recipients.reject! do |recipient| + user = recipient.user subscription = target.subscriptions.find_by_user_id(user.id) subscription && !subscription.subscribed end end def reject_users_without_access - recipients.select! { |u| u.can?(:receive_notifications) } + recipients.select! { |r| r.user.can?(:receive_notifications) } - ability = case target - when Issuable - :"read_#{target.to_ability_name}" - when Ci::Pipeline - :read_build # We have build trace in pipeline emails - end + return unless read_ability - return unless ability - - recipients.select! do |user| - user.can?(ability, target) + DeclarativePolicy.subject_scope do + recipients.select! do |recipient| + recipient.user.can?(read_ability, target) + end end end + def reject_user(user) + recipients.reject! { |r| r.user == user } + end + def add_labels_subscribers(labels: nil) return unless target.respond_to? :labels (labels || target.labels).each do |label| - recipients.concat(label.subscribers(project)) + self << [label.subscribers(project), :subscription] end end end @@ -248,7 +291,7 @@ class NotificationRecipientService @skip_current_user = skip_current_user end - def build + def build! add_participants(current_user) add_project_watchers add_custom_notifications(custom_action) @@ -259,12 +302,12 @@ class NotificationRecipientService # the "on mention" notification level case custom_action when :reassign_merge_request - recipients << previous_assignee if previous_assignee - recipients << target.assignee + self << [previous_assignee, :mention] + self << [target.assignee, :mention] when :reassign_issue previous_assignees = Array(previous_assignee) - recipients.concat(previous_assignees) - recipients.concat(target.assignees) + self << [previous_assignees, :mention] + self << [target.assignees, :mention] end reject_muted_users @@ -273,13 +316,16 @@ class NotificationRecipientService if [:new_issue, :new_merge_request].include?(custom_action) add_labels_subscribers end + end + def filter! reject_unsubscribed_users reject_users_without_access - recipients.delete(current_user) if skip_current_user && !current_user.notified_of_own_activity? + reject_user(current_user) if skip_current_user && !current_user.notified_of_own_activity? end + private # Build event key to search on custom notification level # Check NotificationSetting::EMAIL_EVENTS def custom_action @@ -299,7 +345,7 @@ class NotificationRecipientService @action = action end - def build + def build! return [] unless current_user custom_action = @@ -318,7 +364,10 @@ class NotificationRecipientService return if (notification_setting.watch? || notification_setting.participating?) && NotificationSetting::EXCLUDED_WATCHER_EVENTS.include?(custom_action) - recipients << current_user + self << [current_user, :subscriber] + end + + def filter! reject_users_without_access end end @@ -335,11 +384,14 @@ class NotificationRecipientService @labels = labels end - def build + def build! add_labels_subscribers(labels: labels) + end + + def filter! reject_unsubscribed_users reject_users_without_access - recipients.delete(current_user) unless current_user.notified_of_own_activity? + reject_user(current_user) unless current_user.notified_of_own_activity? end end @@ -353,18 +405,22 @@ class NotificationRecipientService @target = note.noteable end - def build - ability, subject = if note.for_personal_snippet? - [:read_personal_snippet, note.noteable] - else - [:read_project, note.project] - end + def read_ability + @read_ability ||= + case target + when Commit then nil + else :"read_#{target.class.model_name.name.underscore}" + end + end - mentioned_users = note.mentioned_users.select { |user| user.can?(ability, subject) } + def subject + note.for_personal_snippet? ? note.noteable : note.project + end + def build! # Add all users participating in the thread (author, assignee, comment authors) add_participants(note.author) - recipients.concat(mentioned_users) if recipients.empty? + self << [note.mentioned_users, :mention] if recipients.empty? unless note.for_personal_snippet? # Merge project watchers @@ -376,32 +432,35 @@ class NotificationRecipientService # Reject users with Mention notification level, except those mentioned in _this_ note. reject_mention_users - recipients.concat(mentioned_users) + self << [note.mentioned_users, :mention] reject_muted_users add_subscribed_users + end + + def filter! reject_unsubscribed_users reject_users_without_access - recipients.delete(note.author) unless note.author.notified_of_own_activity? + reject_user(note.author) unless note.author.notified_of_own_activity? end end end def build_recipients(*a) - Builder::Default.new(@project, *a).to_a + Builder::Default.new(@project, *a).recipient_users end def build_pipeline_recipients(*a) - Builder::Pipeline.new(@project, *a).to_a + Builder::Pipeline.new(@project, *a).recipient_users end def build_relabeled_recipients(*a) - Builder::Relabeled.new(@project, *a).to_a + Builder::Relabeled.new(@project, *a).recipient_users end def build_new_note_recipients(*a) - Builder::NewNote.new(@project, *a).to_a + Builder::NewNote.new(@project, *a).recipient_users end end diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 882ee7751b5..45d5d0ac9e0 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -309,6 +309,11 @@ describe NotificationService do before do build_team(note.project) + + # make sure these users can read the project snippet! + project.add_guest(@u_guest_watcher) + project.add_guest(@u_guest_custom) + note.project.add_master(note.author) reset_delivered_emails! end From 943baa13922a5a2b7aab5a46765846996f23486b Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Tue, 1 Aug 2017 12:55:13 -0700 Subject: [PATCH 070/177] move filtering logic into Recipient class --- .../notification_recipient_service.rb | 201 +++++++++--------- 1 file changed, 102 insertions(+), 99 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 8d15202ef1c..3d3ace29c16 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -33,9 +33,69 @@ class NotificationRecipientService NotificationRecipientService.notification_setting_for_user_project(user, @builder.project) end - def notification_level + def raw_notification_level notification_setting&.level&.to_sym end + + def notification_level + # custom is treated the same as watch if it's enabled - otherwise it's + # as :disabled. + @notification_level ||= + case raw_notification_level + when :custom + notification_setting.event_enabled?(@builder.custom_action) ? :watch : :custom + else + raw_notification_level + end + end + + def notifiable? + return false unless has_access? + return false if own_activity? + + return true if @type == :subscription + + return false if notification_level.nil? || notification_level == :disabled + + return %i[participating mention].include?(@type) if notification_level == :custom + + return false if %i[watch participating].include?(notification_level) && excluded_watcher_action? + + return false unless NotificationSetting.levels[notification_level] <= NotificationSetting.levels[type] + + return false if unsubscribed? + + true + end + + def unsubscribed? + return false unless @builder.target.respond_to?(:subscriptions) + + subscription = @builder.target.subscriptions.find_by_user_id(@user.id) + subscription && !subscription.subscribed + end + + def own_activity? + return false unless @builder.acting_user + return false if @builder.acting_user.notified_of_own_activity? + + user == @builder.acting_user + end + + def has_access? + return false unless user.can?(:receive_notifications) + return true unless @builder.read_ability + + DeclarativePolicy.subject_scope do + user.can?(@builder.read_ability, @builder.target) + end + end + + def excluded_watcher_action? + return false if raw_notification_level == :custom + + NotificationSetting::EXCLUDED_WATCHER_EVENTS.include?(@builder.custom_action) + end end module Builder @@ -49,7 +109,11 @@ class NotificationRecipientService end def filter! - raise 'abstract' + recipients.select!(&:notifiable?) + end + + def acting_user + current_user end def target @@ -78,12 +142,6 @@ class NotificationRecipientService end end - # Remove users with disabled notifications from array - # Also remove duplications and nil recipients - def reject_muted_users - reject_users(:disabled) - end - def read_ability @read_ability ||= case target @@ -99,23 +157,23 @@ class NotificationRecipientService def add_participants(user) return unless target.respond_to?(:participants) - self << [target.participants(user), :participating] + self << [target.participants(user), :watch] end # Get project/group users with CUSTOM notification level - def add_custom_notifications(action) + def add_custom_notifications user_ids = [] # Users with a notification setting on group or project - user_ids += user_ids_notifiable_on(project, :custom, action) - user_ids += user_ids_notifiable_on(project.group, :custom, action) + user_ids += user_ids_notifiable_on(project, :custom) + user_ids += user_ids_notifiable_on(project.group, :custom) # Users with global level custom user_ids_with_project_level_global = user_ids_notifiable_on(project, :global) user_ids_with_group_level_global = user_ids_notifiable_on(project.group, :global) global_users_ids = user_ids_with_project_level_global.concat(user_ids_with_group_level_global) - user_ids += user_ids_with_global_level_custom(global_users_ids, action) + user_ids += user_ids_with_global_level_custom(global_users_ids, custom_action) self << [User.find(user_ids), :watch] end @@ -139,31 +197,22 @@ class NotificationRecipientService User.where(id: user_ids_with_project_setting.concat(user_ids_with_group_setting).uniq).to_a end - # Remove users with notification level 'Mentioned' - def reject_mention_users - recipients.select! do |r| - next true if r.type == :mention - next true if r.type == :subscription - r.notification_level != :mention - end - end - def add_subscribed_users return unless target.respond_to? :subscribers self << [target.subscribers(project), :subscription] end - def user_ids_notifiable_on(resource, notification_level = nil, action = nil) + def user_ids_notifiable_on(resource, notification_level = nil) return [] unless resource + scope = resource.notification_settings + if notification_level - settings = resource.notification_settings.where(level: NotificationSetting.levels[notification_level]) - settings = settings.select { |setting| setting.event_enabled?(action) } if action.present? - settings.map(&:user_id) - else - resource.notification_settings.pluck(:user_id) + scope = scope.where(level: NotificationSetting.levels[notification_level]) end + + scope.pluck(:user_id) end # Build a list of user_ids based on project notification settings @@ -220,26 +269,6 @@ class NotificationRecipientService ) end - # Reject users which has certain notification level - # - # Example: - # reject_users(:watch, project) - # - def reject_users(level) - level = level.to_s - - unless NotificationSetting.levels.keys.include?(level) - raise 'Invalid notification level' - end - - recipients.reject! do |recipient| - user = recipient.user - - setting = NotificationRecipientService.notification_setting_for_user_project(user, project) - setting.present? && setting.level == level - end - end - def reject_unsubscribed_users return unless target.respond_to? :subscriptions @@ -294,12 +323,9 @@ class NotificationRecipientService def build! add_participants(current_user) add_project_watchers - add_custom_notifications(custom_action) - reject_mention_users + add_custom_notifications - # Re-assign is considered as a mention of the new assignee so we add the - # new assignee to the list of recipients after we rejected users with - # the "on mention" notification level + # Re-assign is considered as a mention of the new assignee case custom_action when :reassign_merge_request self << [previous_assignee, :mention] @@ -310,7 +336,6 @@ class NotificationRecipientService self << [target.assignees, :mention] end - reject_muted_users add_subscribed_users if [:new_issue, :new_merge_request].include?(custom_action) @@ -318,14 +343,10 @@ class NotificationRecipientService end end - def filter! - reject_unsubscribed_users - reject_users_without_access - - reject_user(current_user) if skip_current_user && !current_user.notified_of_own_activity? + def acting_user + current_user if skip_current_user end - private # Build event key to search on custom notification level # Check NotificationSetting::EMAIL_EVENTS def custom_action @@ -345,30 +366,23 @@ class NotificationRecipientService @action = action end + def acting_user + nil + end + + def custom_action + case action.to_s + when 'failed' + :failed_pipeline + when 'success' + :success_pipeline + end + end + def build! return [] unless current_user - custom_action = - case action.to_s - when 'failed' - :failed_pipeline - when 'success' - :success_pipeline - end - - notification_setting = NotificationRecipientService.notification_setting_for_user_project(current_user, target.project) - - return if notification_setting.mention? || notification_setting.disabled? - - return if notification_setting.custom? && !notification_setting.event_enabled?(custom_action) - - return if (notification_setting.watch? || notification_setting.participating?) && NotificationSetting::EXCLUDED_WATCHER_EVENTS.include?(custom_action) - - self << [current_user, :subscriber] - end - - def filter! - reject_users_without_access + self << [current_user, :watch] end end @@ -387,12 +401,6 @@ class NotificationRecipientService def build! add_labels_subscribers(labels: labels) end - - def filter! - reject_unsubscribed_users - reject_users_without_access - reject_user(current_user) unless current_user.notified_of_own_activity? - end end class NewNote < Base @@ -420,30 +428,25 @@ class NotificationRecipientService def build! # Add all users participating in the thread (author, assignee, comment authors) add_participants(note.author) - self << [note.mentioned_users, :mention] if recipients.empty? + self << [note.mentioned_users, :mention] unless note.for_personal_snippet? # Merge project watchers add_project_watchers # Merge project with custom notification - add_custom_notifications(:new_note) + add_custom_notifications end - # Reject users with Mention notification level, except those mentioned in _this_ note. - reject_mention_users - self << [note.mentioned_users, :mention] - - reject_muted_users - add_subscribed_users end - def filter! - reject_unsubscribed_users - reject_users_without_access + def custom_action + :new_note + end - reject_user(note.author) unless note.author.notified_of_own_activity? + def acting_user + note.author end end end From b69e81c3e993939228046516be897233dcaf4442 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Tue, 25 Jul 2017 22:22:31 -0700 Subject: [PATCH 071/177] rm the @builder argument and factor out .notifiable_users --- .../notification_recipient_service.rb | 50 ++++++++++++++----- app/services/notification_service.rb | 3 +- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 3d3ace29c16..f944c1ae7f4 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -21,16 +21,25 @@ class NotificationRecipientService end class Recipient + def self.notifiable_users(users, *args) + users.map { |u| new(u, *args) }.select(&:notifiable?).map(&:user) + end + attr_reader :user, :type - def initialize(builder, user, type) - @builder = builder + def initialize(user, project, type, + custom_action: nil, target: nil, acting_user: nil, read_ability: nil) + @project = project + @custom_action = custom_action + @acting_user = acting_user + @read_ability = read_ability + @target = target @user = user @type = type end def notification_setting @notification_setting ||= - NotificationRecipientService.notification_setting_for_user_project(user, @builder.project) + NotificationRecipientService.notification_setting_for_user_project(user, @project) end def raw_notification_level @@ -43,7 +52,11 @@ class NotificationRecipientService @notification_level ||= case raw_notification_level when :custom - notification_setting.event_enabled?(@builder.custom_action) ? :watch : :custom + if !@custom_action || notification_setting.event_enabled?(@custom_action) + :watch + else + :custom + end else raw_notification_level end @@ -69,32 +82,34 @@ class NotificationRecipientService end def unsubscribed? - return false unless @builder.target.respond_to?(:subscriptions) + return false unless @target + return false unless @target.respond_to?(:subscriptions) - subscription = @builder.target.subscriptions.find_by_user_id(@user.id) + subscription = @target.subscriptions.find_by_user_id(@user.id) subscription && !subscription.subscribed end def own_activity? - return false unless @builder.acting_user - return false if @builder.acting_user.notified_of_own_activity? + return false unless @acting_user + return false if @acting_user.notified_of_own_activity? - user == @builder.acting_user + user == @acting_user end def has_access? return false unless user.can?(:receive_notifications) - return true unless @builder.read_ability + return true unless @read_ability DeclarativePolicy.subject_scope do - user.can?(@builder.read_ability, @builder.target) + user.can?(@read_ability, @target) end end def excluded_watcher_action? + return false unless @custom_action return false if raw_notification_level == :custom - NotificationSetting::EXCLUDED_WATCHER_EVENTS.include?(@builder.custom_action) + NotificationSetting::EXCLUDED_WATCHER_EVENTS.include?(@custom_action) end end @@ -128,7 +143,16 @@ class NotificationRecipientService users, type = arg users = Array(users) users.compact! - recipients.concat(users.map { |u| Recipient.new(self, u, type) }) + recipients.concat(users.map { |u| make_recipient(u, type) }) + end + + def make_recipient(user, type) + Recipient.new(user, project, type, + custom_action: custom_action, + target: target, + acting_user: acting_user, + read_ability: read_ability + ) end def recipient_users diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index b94921d2a08..a094d97a295 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -270,8 +270,7 @@ class NotificationService end def project_was_moved(project, old_path_with_namespace) - recipients = project.team.members - recipients = NotificationRecipientService.new(project).reject_muted_users(recipients) + recipients = NotificationRecipientService::Recipient.notifiable_users(project.team.members, project, :watch) recipients.each do |recipient| mailer.project_was_moved_email( From a4932d2da72af14eeea99e466117bdb767d111c7 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Tue, 25 Jul 2017 22:24:22 -0700 Subject: [PATCH 072/177] don't elevate to :watch if no @custom_action is provided --- app/services/notification_recipient_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index f944c1ae7f4..20d8a06903c 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -52,7 +52,7 @@ class NotificationRecipientService @notification_level ||= case raw_notification_level when :custom - if !@custom_action || notification_setting.event_enabled?(@custom_action) + if @custom_action && notification_setting.event_enabled?(@custom_action) :watch else :custom From 4caa5a7e14a8aa1e973662bd1394468eac74f3ad Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Wed, 26 Jul 2017 08:25:29 -0700 Subject: [PATCH 073/177] factor out .notifiable_users --- .../notification_recipient_service.rb | 40 ++----------------- app/services/notification_service.rb | 9 ++--- 2 files changed, 8 insertions(+), 41 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 20d8a06903c..3d36660495f 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -378,38 +378,6 @@ class NotificationRecipientService end end - class Pipeline < Base - attr_reader :project - attr_reader :target - attr_reader :current_user - attr_reader :action - def initialize(project, target, current_user, action:) - @project = project - @target = target - @current_user = current_user - @action = action - end - - def acting_user - nil - end - - def custom_action - case action.to_s - when 'failed' - :failed_pipeline - when 'success' - :success_pipeline - end - end - - def build! - return [] unless current_user - - self << [current_user, :watch] - end - end - class Relabeled < Base attr_reader :project attr_reader :target @@ -475,12 +443,12 @@ class NotificationRecipientService end end - def build_recipients(*a) - Builder::Default.new(@project, *a).recipient_users + def self.notifiable_users(*a) + Recipient.notifiable_users(*a) end - def build_pipeline_recipients(*a) - Builder::Pipeline.new(@project, *a).recipient_users + def build_recipients(*a) + Builder::Default.new(@project, *a).recipient_users end def build_relabeled_recipients(*a) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index a094d97a295..8a6ed88923d 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -270,7 +270,7 @@ class NotificationService end def project_was_moved(project, old_path_with_namespace) - recipients = NotificationRecipientService::Recipient.notifiable_users(project.team.members, project, :watch) + recipients = NotificationRecipientService.notifiable_users(project.team.members, project, :mention) recipients.each do |recipient| mailer.project_was_moved_email( @@ -304,10 +304,9 @@ class NotificationService return unless mailer.respond_to?(email_template) - recipients ||= NotificationRecipientService.new(pipeline.project).build_pipeline_recipients( - pipeline, - pipeline.user, - action: pipeline.status + recipients ||= NotificationRecipientService.notifiable_users( + [pipeline.user], pipeline.project, :watch, + custom_action: :"#{pipeline.status}_pipeline" ).map(&:notification_email) if recipients.any? From 6aa44382acbe1439c48da056ab9089e36124878f Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Wed, 26 Jul 2017 08:36:14 -0700 Subject: [PATCH 074/177] rm a now-useless spec --- .../notification_recipient_service_spec.rb | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 spec/services/notification_recipient_service_spec.rb diff --git a/spec/services/notification_recipient_service_spec.rb b/spec/services/notification_recipient_service_spec.rb deleted file mode 100644 index 0eb0771fd29..00000000000 --- a/spec/services/notification_recipient_service_spec.rb +++ /dev/null @@ -1,34 +0,0 @@ -require 'spec_helper' - -describe NotificationRecipientService do - set(:user) { create(:user) } - set(:project) { create(:project, :public) } - set(:issue) { create(:issue, project: project) } - - set(:watcher) do - watcher = create(:user) - setting = watcher.notification_settings_for(project) - setting.level = :watch - setting.save - - watcher - end - - subject { described_class.new(project) } - - describe '#build_recipients' do - it 'does not modify the participants of the target' do - expect { subject.build_recipients(issue, user, action: :new_issue) } - .not_to change { issue.participants(user) } - end - end - - describe '#build_new_note_recipients' do - set(:note) { create(:note_on_issue, noteable: issue, project: project) } - - it 'does not modify the participants of the target' do - expect { subject.build_new_note_recipients(note) } - .not_to change { note.noteable.participants(note.author) } - end - end -end From 618b5d34463b1a54cca0d47d3d815b7e388a1db2 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Wed, 26 Jul 2017 08:36:49 -0700 Subject: [PATCH 075/177] move the #build_* methods to static, parameterize the project --- .../notification_recipient_service.rb | 61 +++++++++---------- app/services/notification_service.rb | 24 +++++--- 2 files changed, 42 insertions(+), 43 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 3d36660495f..788e06502ee 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -1,23 +1,21 @@ # # Used by NotificationService to determine who should receive notification # -class NotificationRecipientService - attr_reader :project - - def self.notification_setting_for_user_project(user, project) - project_setting = project && user.notification_settings_for(project) - - return project_setting unless project_setting.nil? || project_setting.global? - - group_setting = project&.group && user.notification_settings_for(project.group) - - return group_setting unless group_setting.nil? || group_setting.global? - - user.global_notification_setting +module NotificationRecipientService + def self.notifiable_users(*a) + Recipient.notifiable_users(*a) end - def initialize(project) - @project = project + def self.build_recipients(*a) + Builder::Default.new(*a).recipient_users + end + + def self.build_relabeled_recipients(*a) + Builder::Relabeled.new(*a).recipient_users + end + + def self.build_new_note_recipients(*a) + Builder::NewNote.new(*a).recipient_users end class Recipient @@ -38,8 +36,7 @@ class NotificationRecipientService end def notification_setting - @notification_setting ||= - NotificationRecipientService.notification_setting_for_user_project(user, @project) + @notification_setting ||= find_notification_setting end def raw_notification_level @@ -111,6 +108,20 @@ class NotificationRecipientService NotificationSetting::EXCLUDED_WATCHER_EVENTS.include?(@custom_action) end + + private + + def find_notification_setting + project_setting = project && user.notification_settings_for(project) + + return project_setting unless project_setting.nil? || project_setting.global? + + group_setting = project&.group && user.notification_settings_for(project.group) + + return group_setting unless group_setting.nil? || group_setting.global? + + user.global_notification_setting + end end module Builder @@ -442,20 +453,4 @@ class NotificationRecipientService end end end - - def self.notifiable_users(*a) - Recipient.notifiable_users(*a) - end - - def build_recipients(*a) - Builder::Default.new(@project, *a).recipient_users - end - - def build_relabeled_recipients(*a) - Builder::Relabeled.new(@project, *a).recipient_users - end - - def build_new_note_recipients(*a) - Builder::NewNote.new(@project, *a).recipient_users - end end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 8a6ed88923d..675b4536a26 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -77,7 +77,8 @@ class NotificationService # * users with custom level checked with "reassign issue" # def reassigned_issue(issue, current_user, previous_assignees = []) - recipients = NotificationRecipientService.new(issue.project).build_recipients( + recipients = NotificationRecipientService.build_recipients( + issue.project, issue, current_user, action: "reassign", @@ -177,7 +178,8 @@ class NotificationService end def resolve_all_discussions(merge_request, current_user) - recipients = NotificationRecipientService.new(merge_request.target_project).build_recipients( + recipients = NotificationRecipientService.build_recipients( + merge_request.target_project, merge_request, current_user, action: "resolve_all_discussions") @@ -202,7 +204,7 @@ class NotificationService notify_method = "note_#{note.to_ability_name}_email".to_sym - recipients = NotificationRecipientService.new(note.project).build_new_note_recipients(note) + recipients = NotificationRecipientService.build_new_note_recipients(note.project, note) recipients.each do |recipient| mailer.send(notify_method, recipient.id, note.id).deliver_later end @@ -282,7 +284,7 @@ class NotificationService end def issue_moved(issue, new_issue, current_user) - recipients = NotificationRecipientService.new(issue.project).build_recipients(issue, current_user, action: 'moved') + recipients = NotificationRecipientService.build_recipients(issue.project, issue, current_user, action: 'moved') recipients.map do |recipient| email = mailer.issue_moved_email(recipient, issue, new_issue, current_user) @@ -317,7 +319,7 @@ class NotificationService protected def new_resource_email(target, project, method) - recipients = NotificationRecipientService.new(project).build_recipients(target, target.author, action: "new") + recipients = NotificationRecipientService.build_recipients(project, target, target.author, action: "new") recipients.each do |recipient| mailer.send(method, recipient.id, target.id).deliver_later @@ -325,7 +327,7 @@ class NotificationService end def new_mentions_in_resource_email(target, project, new_mentioned_users, current_user, method) - recipients = NotificationRecipientService.new(project).build_recipients(target, current_user, action: "new") + recipients = NotificationRecipientService.build_recipients(project, target, current_user, action: "new") recipients = recipients & new_mentioned_users recipients.each do |recipient| @@ -336,7 +338,8 @@ class NotificationService def close_resource_email(target, project, current_user, method, skip_current_user: true) action = method == :merged_merge_request_email ? "merge" : "close" - recipients = NotificationRecipientService.new(project).build_recipients( + recipients = NotificationRecipientService.build_recipients( + project, target, current_user, action: action, @@ -352,7 +355,8 @@ class NotificationService previous_assignee_id = previous_record(target, 'assignee_id') previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id - recipients = NotificationRecipientService.new(project).build_recipients( + recipients = NotificationRecipientService.build_recipients( + project, target, current_user, action: "reassign", @@ -371,7 +375,7 @@ class NotificationService end def relabeled_resource_email(target, project, labels, current_user, method) - recipients = NotificationRecipientService.new(project).build_relabeled_recipients(target, current_user, labels: labels) + recipients = NotificationRecipientService.build_relabeled_recipients(project, target, current_user, labels: labels) label_names = labels.map(&:name) recipients.each do |recipient| @@ -380,7 +384,7 @@ class NotificationService end def reopen_resource_email(target, project, current_user, method, status) - recipients = NotificationRecipientService.new(project).build_recipients(target, current_user, action: "reopen") + recipients = NotificationRecipientService.build_recipients(project, target, current_user, action: "reopen") recipients.each do |recipient| mailer.send(method, recipient.id, target.id, status, current_user.id).deliver_later From 618a3d125c0faf3b6e0484bc9955ffd0a597ad33 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Wed, 26 Jul 2017 08:43:27 -0700 Subject: [PATCH 076/177] move Recipient to its own NotificationRecipient file --- app/models/notification_recipient.rb | 102 +++++++++++++++ .../notification_recipient_service.rb | 116 ++---------------- 2 files changed, 109 insertions(+), 109 deletions(-) create mode 100644 app/models/notification_recipient.rb diff --git a/app/models/notification_recipient.rb b/app/models/notification_recipient.rb new file mode 100644 index 00000000000..0b2eee56ff8 --- /dev/null +++ b/app/models/notification_recipient.rb @@ -0,0 +1,102 @@ +class NotificationRecipient + attr_reader :user, :project, :type + def initialize(user, project, type, + custom_action: nil, target: nil, acting_user: nil, read_ability: nil) + @project = project + @custom_action = custom_action + @acting_user = acting_user + @read_ability = read_ability + @target = target + @user = user + @type = type + end + + def notification_setting + @notification_setting ||= find_notification_setting + end + + def raw_notification_level + notification_setting&.level&.to_sym + end + + def notification_level + # custom is treated the same as watch if it's enabled - otherwise it's + # as :disabled. + @notification_level ||= + case raw_notification_level + when :custom + if @custom_action && notification_setting.event_enabled?(@custom_action) + :watch + else + :custom + end + else + raw_notification_level + end + end + + def notifiable? + return false unless has_access? + return false if own_activity? + + return true if @type == :subscription + + return false if notification_level.nil? || notification_level == :disabled + + return %i[participating mention].include?(@type) if notification_level == :custom + + return false if %i[watch participating].include?(notification_level) && excluded_watcher_action? + + return false unless NotificationSetting.levels[notification_level] <= NotificationSetting.levels[type] + + return false if unsubscribed? + + true + end + + def unsubscribed? + return false unless @target + return false unless @target.respond_to?(:subscriptions) + + subscription = @target.subscriptions.find_by_user_id(@user.id) + subscription && !subscription.subscribed + end + + def own_activity? + return false unless @acting_user + return false if @acting_user.notified_of_own_activity? + + user == @acting_user + end + + def has_access? + return false unless user.can?(:receive_notifications) + return true unless @read_ability + + DeclarativePolicy.subject_scope do + user.can?(@read_ability, @target) + end + end + + def excluded_watcher_action? + return false unless @custom_action + return false if raw_notification_level == :custom + + NotificationSetting::EXCLUDED_WATCHER_EVENTS.include?(@custom_action) + end + + private + + def find_notification_setting + project_setting = @project && user.notification_settings_for(@project) + + return project_setting unless project_setting.nil? || project_setting.global? + + group_setting = @project&.group && user.notification_settings_for(@project.group) + + return group_setting unless group_setting.nil? || group_setting.global? + + user.global_notification_setting + end +end + diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 788e06502ee..5d8c3a39af1 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -2,8 +2,12 @@ # Used by NotificationService to determine who should receive notification # module NotificationRecipientService - def self.notifiable_users(*a) - Recipient.notifiable_users(*a) + def self.notifiable_users(users, *args) + users.map { |u| NotificationRecipient.new(u, *args) }.select(&:notifiable?).map(&:user) + end + + def self.notifiable?(user, *args) + NotificationRecipient.new(user, *args).notifiable? end def self.build_recipients(*a) @@ -18,112 +22,6 @@ module NotificationRecipientService Builder::NewNote.new(*a).recipient_users end - class Recipient - def self.notifiable_users(users, *args) - users.map { |u| new(u, *args) }.select(&:notifiable?).map(&:user) - end - - attr_reader :user, :type - def initialize(user, project, type, - custom_action: nil, target: nil, acting_user: nil, read_ability: nil) - @project = project - @custom_action = custom_action - @acting_user = acting_user - @read_ability = read_ability - @target = target - @user = user - @type = type - end - - def notification_setting - @notification_setting ||= find_notification_setting - end - - def raw_notification_level - notification_setting&.level&.to_sym - end - - def notification_level - # custom is treated the same as watch if it's enabled - otherwise it's - # as :disabled. - @notification_level ||= - case raw_notification_level - when :custom - if @custom_action && notification_setting.event_enabled?(@custom_action) - :watch - else - :custom - end - else - raw_notification_level - end - end - - def notifiable? - return false unless has_access? - return false if own_activity? - - return true if @type == :subscription - - return false if notification_level.nil? || notification_level == :disabled - - return %i[participating mention].include?(@type) if notification_level == :custom - - return false if %i[watch participating].include?(notification_level) && excluded_watcher_action? - - return false unless NotificationSetting.levels[notification_level] <= NotificationSetting.levels[type] - - return false if unsubscribed? - - true - end - - def unsubscribed? - return false unless @target - return false unless @target.respond_to?(:subscriptions) - - subscription = @target.subscriptions.find_by_user_id(@user.id) - subscription && !subscription.subscribed - end - - def own_activity? - return false unless @acting_user - return false if @acting_user.notified_of_own_activity? - - user == @acting_user - end - - def has_access? - return false unless user.can?(:receive_notifications) - return true unless @read_ability - - DeclarativePolicy.subject_scope do - user.can?(@read_ability, @target) - end - end - - def excluded_watcher_action? - return false unless @custom_action - return false if raw_notification_level == :custom - - NotificationSetting::EXCLUDED_WATCHER_EVENTS.include?(@custom_action) - end - - private - - def find_notification_setting - project_setting = project && user.notification_settings_for(project) - - return project_setting unless project_setting.nil? || project_setting.global? - - group_setting = project&.group && user.notification_settings_for(project.group) - - return group_setting unless group_setting.nil? || group_setting.global? - - user.global_notification_setting - end - end - module Builder class Base def initialize(*) @@ -158,7 +56,7 @@ module NotificationRecipientService end def make_recipient(user, type) - Recipient.new(user, project, type, + NotificationRecipient.new(user, project, type, custom_action: custom_action, target: target, acting_user: acting_user, From 651f50ac00bdf14ae660af0fea3d463d07d8d25f Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Wed, 26 Jul 2017 09:32:37 -0700 Subject: [PATCH 077/177] make sure #custom_action is always defined --- app/services/notification_recipient_service.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 5d8c3a39af1..b286cc373bd 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -85,6 +85,10 @@ module NotificationRecipientService end end + def custom_action + nil + end + protected def add_participants(user) From 46d0bfdcb982d76b8595921a956b088df1573905 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Wed, 26 Jul 2017 09:33:01 -0700 Subject: [PATCH 078/177] use intersection and diff operators instead of each --- .../notification_recipient_service.rb | 24 ++----------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index b286cc373bd..6b4e97aaab4 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -157,35 +157,15 @@ module NotificationRecipientService user_ids = user_ids_notifiable_on(project, :watch) # If project setting is global, add to watch list if global setting is watch - global_setting.each do |user_id| - if user_ids_global_level_watch.include?(user_id) - user_ids << user_id - end - end - - user_ids + user_ids + (global_setting & user_ids_global_level_watch) end # Build a list of user_ids based on group notification settings def select_group_members_ids(group, project_members, global_setting, user_ids_global_level_watch) uids = user_ids_notifiable_on(group, :watch) - # Group setting is watch, add to user_ids list if user is not project member - user_ids = [] - uids.each do |user_id| - if project_members.exclude?(user_id) - user_ids << user_id - end - end - # Group setting is global, add to user_ids list if global setting is watch - global_setting.each do |user_id| - if project_members.exclude?(user_id) && user_ids_global_level_watch.include?(user_id) - user_ids << user_id - end - end - - user_ids + uids + (global_setting & user_ids_global_level_watch) - project_members end def user_ids_with_global_level_watch(ids) From d45b4065d8e0b6cc893ccde66e0c37f459ca901b Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Wed, 26 Jul 2017 09:33:23 -0700 Subject: [PATCH 079/177] make sure users have to be able to read_pipeline to get pipeline failed notifications --- app/services/notification_service.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 675b4536a26..c330d62a2ce 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -308,7 +308,8 @@ class NotificationService recipients ||= NotificationRecipientService.notifiable_users( [pipeline.user], pipeline.project, :watch, - custom_action: :"#{pipeline.status}_pipeline" + custom_action: :"#{pipeline.status}_pipeline", + read_ability: :read_pipeline, ).map(&:notification_email) if recipients.any? From 3829d7245a446fe80745f5e7c082e005fc013365 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Fri, 28 Jul 2017 11:38:35 -0700 Subject: [PATCH 080/177] require that the user be able to :read_build to get a pipeline_failed email --- app/services/notification_service.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index c330d62a2ce..e9a67cac4d6 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -309,7 +309,8 @@ class NotificationService recipients ||= NotificationRecipientService.notifiable_users( [pipeline.user], pipeline.project, :watch, custom_action: :"#{pipeline.status}_pipeline", - read_ability: :read_pipeline, + read_ability: :read_build, + target: pipeline ).map(&:notification_email) if recipients.any? From 19309b970556797027e57c212d9b9aa053c36892 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Mon, 31 Jul 2017 09:30:35 -0700 Subject: [PATCH 081/177] default the project to target.project --- app/models/notification_recipient.rb | 12 +++++++++--- app/services/notification_recipient_service.rb | 3 ++- app/services/notification_service.rb | 4 ++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/app/models/notification_recipient.rb b/app/models/notification_recipient.rb index 0b2eee56ff8..96e8e32c644 100644 --- a/app/models/notification_recipient.rb +++ b/app/models/notification_recipient.rb @@ -1,14 +1,20 @@ class NotificationRecipient attr_reader :user, :project, :type - def initialize(user, project, type, - custom_action: nil, target: nil, acting_user: nil, read_ability: nil) - @project = project + def initialize(user, type, + custom_action: nil, + target: nil, + acting_user: nil, + read_ability: nil, + project: nil) @custom_action = custom_action @acting_user = acting_user @read_ability = read_ability @target = target + @project = project || @target&.project @user = user @type = type + + raise ArgumentError, "Project is missing" if @project.nil? end def notification_setting diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 6b4e97aaab4..0627cca9214 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -56,7 +56,8 @@ module NotificationRecipientService end def make_recipient(user, type) - NotificationRecipient.new(user, project, type, + NotificationRecipient.new(user, type, + project: project, custom_action: custom_action, target: target, acting_user: acting_user, diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index e9a67cac4d6..f5366b9ceab 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -272,7 +272,7 @@ class NotificationService end def project_was_moved(project, old_path_with_namespace) - recipients = NotificationRecipientService.notifiable_users(project.team.members, project, :mention) + recipients = NotificationRecipientService.notifiable_users(project.team.members, :mention, project: project) recipients.each do |recipient| mailer.project_was_moved_email( @@ -307,7 +307,7 @@ class NotificationService return unless mailer.respond_to?(email_template) recipients ||= NotificationRecipientService.notifiable_users( - [pipeline.user], pipeline.project, :watch, + [pipeline.user], :watch, custom_action: :"#{pipeline.status}_pipeline", read_ability: :read_build, target: pipeline From 8386d69f8f4a75a45e0226f4ad89b7d200c6d84d Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Tue, 1 Aug 2017 12:51:14 -0700 Subject: [PATCH 082/177] .notifiable_users: compact the passed-in users --- app/services/notification_recipient_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 0627cca9214..d412e5414b3 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -3,7 +3,7 @@ # module NotificationRecipientService def self.notifiable_users(users, *args) - users.map { |u| NotificationRecipient.new(u, *args) }.select(&:notifiable?).map(&:user) + users.compact.map { |u| NotificationRecipient.new(u, *args) }.select(&:notifiable?).map(&:user) end def self.notifiable?(user, *args) From e7d136ebdabf3f784412b859bf3ad7427c88e7f6 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Mon, 31 Jul 2017 11:32:17 -0700 Subject: [PATCH 083/177] don't require project it's not there in the case of personal snippets, f. ex., and we've already guarded against its being missing in #find_notification_setting --- app/models/notification_recipient.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/models/notification_recipient.rb b/app/models/notification_recipient.rb index 96e8e32c644..1856dfe5734 100644 --- a/app/models/notification_recipient.rb +++ b/app/models/notification_recipient.rb @@ -1,5 +1,5 @@ class NotificationRecipient - attr_reader :user, :project, :type + attr_reader :user, :type def initialize(user, type, custom_action: nil, target: nil, @@ -13,8 +13,6 @@ class NotificationRecipient @project = project || @target&.project @user = user @type = type - - raise ArgumentError, "Project is missing" if @project.nil? end def notification_setting From 18288fe21e12bb524757a97472008eabfca5a352 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Mon, 31 Jul 2017 15:04:42 -0700 Subject: [PATCH 084/177] style fixes --- app/models/notification_recipient.rb | 15 ++++++++------- app/services/notification_recipient_service.rb | 3 ++- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/app/models/notification_recipient.rb b/app/models/notification_recipient.rb index 1856dfe5734..28ac22da6e2 100644 --- a/app/models/notification_recipient.rb +++ b/app/models/notification_recipient.rb @@ -1,11 +1,13 @@ class NotificationRecipient attr_reader :user, :type - def initialize(user, type, - custom_action: nil, - target: nil, - acting_user: nil, - read_ability: nil, - project: nil) + def initialize( + user, type, + custom_action: nil, + target: nil, + acting_user: nil, + read_ability: nil, + project: nil + ) @custom_action = custom_action @acting_user = acting_user @read_ability = read_ability @@ -103,4 +105,3 @@ class NotificationRecipient user.global_notification_setting end end - diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index d412e5414b3..083b5f2d229 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -56,7 +56,8 @@ module NotificationRecipientService end def make_recipient(user, type) - NotificationRecipient.new(user, type, + NotificationRecipient.new( + user, type, project: project, custom_action: custom_action, target: target, From 3c56e41402301f26bf70afe13d2565e74e4427eb Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Mon, 31 Jul 2017 17:09:01 -0700 Subject: [PATCH 085/177] use a simple pluck, since equivalent filtering happens later --- app/services/notification_recipient_service.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 083b5f2d229..7c9bb54f020 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -175,9 +175,7 @@ module NotificationRecipientService end def user_ids_with_global_level_custom(ids, action) - settings = settings_with_global_level_of(:custom, ids) - settings = settings.select { |setting| setting.event_enabled?(action) } - settings.map(&:user_id) + settings_with_global_level_of(:custom, ids).pluck(:user_id) end def settings_with_global_level_of(level, ids) From 488e8e79dd85e973e1b562fe0320f69b2bedec06 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Mon, 31 Jul 2017 18:56:56 -0700 Subject: [PATCH 086/177] force queries to include notification settings --- app/services/notification_recipient_service.rb | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 7c9bb54f020..1ce92c8cbdc 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -50,11 +50,20 @@ module NotificationRecipientService def <<(arg) users, type = arg + + if users.is_a?(ActiveRecord::Relation) + users = users.includes(:notification_settings) + end + users = Array(users) users.compact! recipients.concat(users.map { |u| make_recipient(u, type) }) end + def user_scope + User.includes(:notification_settings) + end + def make_recipient(user, type) NotificationRecipient.new( user, type, @@ -114,7 +123,7 @@ module NotificationRecipientService global_users_ids = user_ids_with_project_level_global.concat(user_ids_with_group_level_global) user_ids += user_ids_with_global_level_custom(global_users_ids, custom_action) - self << [User.find(user_ids), :watch] + self << [user_scope.where(id: user_ids), :watch] end def add_project_watchers @@ -133,7 +142,7 @@ module NotificationRecipientService user_ids_with_project_setting = select_project_members_ids(project, user_ids_with_project_global, user_ids) user_ids_with_group_setting = select_group_members_ids(project.group, project_members_ids, user_ids_with_group_global, user_ids) - User.where(id: user_ids_with_project_setting.concat(user_ids_with_group_setting).uniq).to_a + user_scope.where(id: user_ids_with_project_setting.concat(user_ids_with_group_setting).uniq) end def add_subscribed_users From c2dd4239c939e003dfe569196ec2d39e2478606e Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Tue, 1 Aug 2017 10:42:54 -0700 Subject: [PATCH 087/177] short-circuit if there is no policy, and add :read_project check --- app/models/notification_recipient.rb | 9 ++++++--- app/services/notification_recipient_service.rb | 6 +----- lib/declarative_policy.rb | 13 +++++++++---- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/app/models/notification_recipient.rb b/app/models/notification_recipient.rb index 28ac22da6e2..837b62ec0cb 100644 --- a/app/models/notification_recipient.rb +++ b/app/models/notification_recipient.rb @@ -76,10 +76,13 @@ class NotificationRecipient end def has_access? - return false unless user.can?(:receive_notifications) - return true unless @read_ability - DeclarativePolicy.subject_scope do + return false unless user.can?(:receive_notifications) + return false if @project && !user.can?(:read_project, @project) + + return true unless @read_ability + return true unless DeclarativePolicy.has_policy?(@target) + user.can?(@read_ability, @target) end end diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 1ce92c8cbdc..540e568fed2 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -308,11 +308,7 @@ module NotificationRecipientService end def read_ability - @read_ability ||= - case target - when Commit then nil - else :"read_#{target.class.model_name.name.underscore}" - end + @read_ability ||= :"read_#{target.class.model_name.name.underscore}" end def subject diff --git a/lib/declarative_policy.rb b/lib/declarative_policy.rb index b1eb1a6cef1..4936669a73a 100644 --- a/lib/declarative_policy.rb +++ b/lib/declarative_policy.rb @@ -28,7 +28,12 @@ module DeclarativePolicy subject = find_delegate(subject) - class_for_class(subject.class) + class_for_class(subject.class) \ + or raise "no policy for #{subject.class.name}" + end + + def has_policy?(subject) + !class_for_class(subject.class).nil? end private @@ -51,9 +56,7 @@ module DeclarativePolicy end end - policy_class = subject_class.instance_variable_get(CLASS_CACHE_IVAR) - raise "no policy for #{subject.class.name}" if policy_class.nil? - policy_class + subject_class.instance_variable_get(CLASS_CACHE_IVAR) end def compute_class_for_class(subject_class) @@ -71,6 +74,8 @@ module DeclarativePolicy nil end end + + nil end def find_delegate(subject) From 444c8584491ce0efe2314747326da6ab7d17490c Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Tue, 1 Aug 2017 11:42:24 -0700 Subject: [PATCH 088/177] use safe navigation on notification_setting --- app/models/notification_recipient.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/notification_recipient.rb b/app/models/notification_recipient.rb index 837b62ec0cb..a14254178e1 100644 --- a/app/models/notification_recipient.rb +++ b/app/models/notification_recipient.rb @@ -31,7 +31,7 @@ class NotificationRecipient @notification_level ||= case raw_notification_level when :custom - if @custom_action && notification_setting.event_enabled?(@custom_action) + if @custom_action && notification_setting&.event_enabled?(@custom_action) :watch else :custom From 4af2c647132bee8b2ef87d0d190936449759071c Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Tue, 1 Aug 2017 11:42:46 -0700 Subject: [PATCH 089/177] fix comment --- app/models/notification_recipient.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/notification_recipient.rb b/app/models/notification_recipient.rb index a14254178e1..6a8287c88b8 100644 --- a/app/models/notification_recipient.rb +++ b/app/models/notification_recipient.rb @@ -27,7 +27,8 @@ class NotificationRecipient def notification_level # custom is treated the same as watch if it's enabled - otherwise it's - # as :disabled. + # set to :custom, meaning to send exactly when our type is :participating + # or :mention. @notification_level ||= case raw_notification_level when :custom From e5496e1e8ef3fa82e6cefcababcb9ad3b55a11c3 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Tue, 1 Aug 2017 11:42:59 -0700 Subject: [PATCH 090/177] use the accessor for `type` --- app/models/notification_recipient.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/notification_recipient.rb b/app/models/notification_recipient.rb index 6a8287c88b8..c307f0ad5b6 100644 --- a/app/models/notification_recipient.rb +++ b/app/models/notification_recipient.rb @@ -54,7 +54,7 @@ class NotificationRecipient return false if %i[watch participating].include?(notification_level) && excluded_watcher_action? - return false unless NotificationSetting.levels[notification_level] <= NotificationSetting.levels[type] + return false unless NotificationSetting.levels[notification_level] <= NotificationSetting.levels[@type] return false if unsubscribed? From 9d53418acb736476e4ede216c1ba9d08a5e3554a Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Tue, 1 Aug 2017 11:43:24 -0700 Subject: [PATCH 091/177] clearer argument name --- app/services/notification_recipient_service.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 540e568fed2..cfc1fab210a 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -48,8 +48,8 @@ module NotificationRecipientService @recipients ||= [] end - def <<(arg) - users, type = arg + def <<(pair) + users, type = pair if users.is_a?(ActiveRecord::Relation) users = users.includes(:notification_settings) From 934305ffa3eb1662a367761058ae8ded210d3336 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Tue, 1 Aug 2017 11:51:01 -0700 Subject: [PATCH 092/177] rm unused NewNote#subject its functionality is swept into the project permission check in NotificationRecipient#has_access? now --- app/services/notification_recipient_service.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index cfc1fab210a..b2d805e9f27 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -311,10 +311,6 @@ module NotificationRecipientService @read_ability ||= :"read_#{target.class.model_name.name.underscore}" end - def subject - note.for_personal_snippet? ? note.noteable : note.project - end - def build! # Add all users participating in the thread (author, assignee, comment authors) add_participants(note.author) From 246951bba7965f4257aa50377a981f3c85c67f1e Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Tue, 1 Aug 2017 11:52:43 -0700 Subject: [PATCH 093/177] unmemoize read_ability since it's only called once now in make_recipient --- app/services/notification_recipient_service.rb | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index b2d805e9f27..97ff1f99f02 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -87,13 +87,12 @@ module NotificationRecipientService end def read_ability - @read_ability ||= - case target - when Issuable - :"read_#{target.to_ability_name}" - when Ci::Pipeline - :read_build # We have build trace in pipeline emails - end + case target + when Issuable + :"read_#{target.to_ability_name}" + when Ci::Pipeline + :read_build # We have build trace in pipeline emails + end end def custom_action @@ -308,7 +307,9 @@ module NotificationRecipientService end def read_ability - @read_ability ||= :"read_#{target.class.model_name.name.underscore}" + return nil if target.nil? + + :"read_#{target.class.model_name.name.underscore}" end def build! From 0487009d3707c8180211bfc4b3c5a8a9daec50b8 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Tue, 1 Aug 2017 11:53:43 -0700 Subject: [PATCH 094/177] deparameterize `project` since 99% of the time it's `target.project` anyways. --- .../notification_recipient_service.rb | 30 +++++++----- app/services/notification_service.rb | 48 ++++++++----------- 2 files changed, 37 insertions(+), 41 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 97ff1f99f02..b36bc90c884 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -44,6 +44,10 @@ module NotificationRecipientService raise 'abstract' end + def project + target.project + end + def recipients @recipients ||= [] end @@ -138,7 +142,7 @@ module NotificationRecipientService user_ids = user_ids_with_global_level_watch((user_ids_with_project_global + user_ids_with_group_global).uniq) - user_ids_with_project_setting = select_project_members_ids(project, user_ids_with_project_global, user_ids) + user_ids_with_project_setting = select_project_members_ids(user_ids_with_project_global, user_ids) user_ids_with_group_setting = select_group_members_ids(project.group, project_members_ids, user_ids_with_group_global, user_ids) user_scope.where(id: user_ids_with_project_setting.concat(user_ids_with_group_setting).uniq) @@ -163,7 +167,7 @@ module NotificationRecipientService end # Build a list of user_ids based on project notification settings - def select_project_members_ids(project, global_setting, user_ids_global_level_watch) + def select_project_members_ids(global_setting, user_ids_global_level_watch) user_ids = user_ids_notifiable_on(project, :watch) # If project setting is global, add to watch list if global setting is watch @@ -230,14 +234,12 @@ module NotificationRecipientService end class Default < Base - attr_reader :project attr_reader :target attr_reader :current_user attr_reader :action attr_reader :previous_assignee attr_reader :skip_current_user - def initialize(project, target, current_user, action:, previous_assignee: nil, skip_current_user: true) - @project = project + def initialize(target, current_user, action:, previous_assignee: nil, skip_current_user: true) @target = target @current_user = current_user @action = action @@ -280,12 +282,10 @@ module NotificationRecipientService end class Relabeled < Base - attr_reader :project attr_reader :target attr_reader :current_user attr_reader :labels - def initialize(project, target, current_user, labels:) - @project = project + def initialize(target, current_user, labels:) @target = target @current_user = current_user @labels = labels @@ -297,13 +297,17 @@ module NotificationRecipientService end class NewNote < Base - attr_reader :project attr_reader :note - attr_reader :target - def initialize(project, note) - @project = project + def initialize(note) @note = note - @target = note.noteable + end + + def target + note.noteable + end + + def project + note.project end def read_ability diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index f5366b9ceab..c93f82999dc 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -42,7 +42,7 @@ class NotificationService # * users with custom level checked with "new issue" # def new_issue(issue, current_user) - new_resource_email(issue, issue.project, :new_issue_email) + new_resource_email(issue, :new_issue_email) end # When issue text is updated, we should send an email to: @@ -52,7 +52,6 @@ class NotificationService def new_mentions_in_issue(issue, new_mentioned_users, current_user) new_mentions_in_resource_email( issue, - issue.project, new_mentioned_users, current_user, :new_mention_in_issue_email @@ -67,7 +66,7 @@ class NotificationService # * users with custom level checked with "close issue" # def close_issue(issue, current_user) - close_resource_email(issue, issue.project, current_user, :closed_issue_email) + close_resource_email(issue, current_user, :closed_issue_email) end # When we reassign an issue we should send an email to: @@ -78,7 +77,6 @@ class NotificationService # def reassigned_issue(issue, current_user, previous_assignees = []) recipients = NotificationRecipientService.build_recipients( - issue.project, issue, current_user, action: "reassign", @@ -103,7 +101,7 @@ class NotificationService # * watchers of the issue's labels # def relabeled_issue(issue, added_labels, current_user) - relabeled_resource_email(issue, issue.project, added_labels, current_user, :relabeled_issue_email) + relabeled_resource_email(issue, added_labels, current_user, :relabeled_issue_email) end # When create a merge request we should send an email to: @@ -114,7 +112,7 @@ class NotificationService # * users with custom level checked with "new merge request" # def new_merge_request(merge_request, current_user) - new_resource_email(merge_request, merge_request.target_project, :new_merge_request_email) + new_resource_email(merge_request, :new_merge_request_email) end # When merge request text is updated, we should send an email to: @@ -124,7 +122,6 @@ class NotificationService def new_mentions_in_merge_request(merge_request, new_mentioned_users, current_user) new_mentions_in_resource_email( merge_request, - merge_request.target_project, new_mentioned_users, current_user, :new_mention_in_merge_request_email @@ -138,7 +135,7 @@ class NotificationService # * users with custom level checked with "reassign merge request" # def reassigned_merge_request(merge_request, current_user) - reassign_resource_email(merge_request, merge_request.target_project, current_user, :reassigned_merge_request_email) + reassign_resource_email(merge_request, current_user, :reassigned_merge_request_email) end # When we add labels to a merge request we should send an email to: @@ -146,21 +143,20 @@ class NotificationService # * watchers of the mr's labels # def relabeled_merge_request(merge_request, added_labels, current_user) - relabeled_resource_email(merge_request, merge_request.target_project, added_labels, current_user, :relabeled_merge_request_email) + relabeled_resource_email(merge_request, added_labels, current_user, :relabeled_merge_request_email) end def close_mr(merge_request, current_user) - close_resource_email(merge_request, merge_request.target_project, current_user, :closed_merge_request_email) + close_resource_email(merge_request, current_user, :closed_merge_request_email) end def reopen_issue(issue, current_user) - reopen_resource_email(issue, issue.project, current_user, :issue_status_changed_email, 'reopened') + reopen_resource_email(issue, current_user, :issue_status_changed_email, 'reopened') end def merge_mr(merge_request, current_user) close_resource_email( merge_request, - merge_request.target_project, current_user, :merged_merge_request_email, skip_current_user: !merge_request.merge_when_pipeline_succeeds? @@ -170,7 +166,6 @@ class NotificationService def reopen_mr(merge_request, current_user) reopen_resource_email( merge_request, - merge_request.target_project, current_user, :merge_request_status_email, 'reopened' @@ -179,7 +174,6 @@ class NotificationService def resolve_all_discussions(merge_request, current_user) recipients = NotificationRecipientService.build_recipients( - merge_request.target_project, merge_request, current_user, action: "resolve_all_discussions") @@ -204,7 +198,7 @@ class NotificationService notify_method = "note_#{note.to_ability_name}_email".to_sym - recipients = NotificationRecipientService.build_new_note_recipients(note.project, note) + recipients = NotificationRecipientService.build_new_note_recipients(note) recipients.each do |recipient| mailer.send(notify_method, recipient.id, note.id).deliver_later end @@ -284,7 +278,7 @@ class NotificationService end def issue_moved(issue, new_issue, current_user) - recipients = NotificationRecipientService.build_recipients(issue.project, issue, current_user, action: 'moved') + recipients = NotificationRecipientService.build_recipients(issue, current_user, action: 'moved') recipients.map do |recipient| email = mailer.issue_moved_email(recipient, issue, new_issue, current_user) @@ -320,16 +314,16 @@ class NotificationService protected - def new_resource_email(target, project, method) - recipients = NotificationRecipientService.build_recipients(project, target, target.author, action: "new") + def new_resource_email(target, method) + recipients = NotificationRecipientService.build_recipients(target, target.author, action: "new") recipients.each do |recipient| mailer.send(method, recipient.id, target.id).deliver_later end end - def new_mentions_in_resource_email(target, project, new_mentioned_users, current_user, method) - recipients = NotificationRecipientService.build_recipients(project, target, current_user, action: "new") + def new_mentions_in_resource_email(target, new_mentioned_users, current_user, method) + recipients = NotificationRecipientService.build_recipients(target, current_user, action: "new") recipients = recipients & new_mentioned_users recipients.each do |recipient| @@ -337,11 +331,10 @@ class NotificationService end end - def close_resource_email(target, project, current_user, method, skip_current_user: true) + def close_resource_email(target, current_user, method, skip_current_user: true) action = method == :merged_merge_request_email ? "merge" : "close" recipients = NotificationRecipientService.build_recipients( - project, target, current_user, action: action, @@ -353,12 +346,11 @@ class NotificationService end end - def reassign_resource_email(target, project, current_user, method) + def reassign_resource_email(target, current_user, method) previous_assignee_id = previous_record(target, 'assignee_id') previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id recipients = NotificationRecipientService.build_recipients( - project, target, current_user, action: "reassign", @@ -376,8 +368,8 @@ class NotificationService end end - def relabeled_resource_email(target, project, labels, current_user, method) - recipients = NotificationRecipientService.build_relabeled_recipients(project, target, current_user, labels: labels) + def relabeled_resource_email(target, labels, current_user, method) + recipients = NotificationRecipientService.build_relabeled_recipients(target, current_user, labels: labels) label_names = labels.map(&:name) recipients.each do |recipient| @@ -385,8 +377,8 @@ class NotificationService end end - def reopen_resource_email(target, project, current_user, method, status) - recipients = NotificationRecipientService.build_recipients(project, target, current_user, action: "reopen") + def reopen_resource_email(target, current_user, method, status) + recipients = NotificationRecipientService.build_recipients(target, current_user, action: "reopen") recipients.each do |recipient| mailer.send(method, recipient.id, target.id, status, current_user.id).deliver_later From 4dfda5f2662afe32fcaa95b851fe6bdff9e20c08 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Tue, 1 Aug 2017 11:58:44 -0700 Subject: [PATCH 095/177] declarative_policy rubocop fix --- lib/declarative_policy.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/declarative_policy.rb b/lib/declarative_policy.rb index 4936669a73a..ae65653645b 100644 --- a/lib/declarative_policy.rb +++ b/lib/declarative_policy.rb @@ -28,8 +28,9 @@ module DeclarativePolicy subject = find_delegate(subject) - class_for_class(subject.class) \ - or raise "no policy for #{subject.class.name}" + policy_class = class_for_class(subject.class) + raise "no policy for #{subject.class.name}" if policy_class.nil? + policy_class end def has_policy?(subject) From 1ccdd99fbd82c082a992ea344938dca17c337140 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Tue, 1 Aug 2017 13:18:51 -0700 Subject: [PATCH 096/177] disable the delegate cop --- app/services/notification_recipient_service.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index b36bc90c884..0e1527c1a7a 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -44,6 +44,7 @@ module NotificationRecipientService raise 'abstract' end + # rubocop:disable Rails/Delegate def project target.project end From 56a40a2b6548d57c2c2a32b34a76c157ae5fdeab Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Tue, 1 Aug 2017 13:26:55 -0700 Subject: [PATCH 097/177] rm unused methods --- .../notification_recipient_service.rb | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 0e1527c1a7a..5d394f67631 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -199,32 +199,6 @@ module NotificationRecipientService ) end - def reject_unsubscribed_users - return unless target.respond_to? :subscriptions - - recipients.reject! do |recipient| - user = recipient.user - subscription = target.subscriptions.find_by_user_id(user.id) - subscription && !subscription.subscribed - end - end - - def reject_users_without_access - recipients.select! { |r| r.user.can?(:receive_notifications) } - - return unless read_ability - - DeclarativePolicy.subject_scope do - recipients.select! do |recipient| - recipient.user.can?(read_ability, target) - end - end - end - - def reject_user(user) - recipients.reject! { |r| r.user == user } - end - def add_labels_subscribers(labels: nil) return unless target.respond_to? :labels From eaa503d679e3c2a1396091efebda49a91637cb02 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Wed, 2 Aug 2017 14:14:53 -0700 Subject: [PATCH 098/177] move the read_ability logic into NotificationRecipient --- app/models/notification_recipient.rb | 22 +++++++++++++++---- .../notification_recipient_service.rb | 16 -------------- app/services/notification_service.rb | 1 - 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/app/models/notification_recipient.rb b/app/models/notification_recipient.rb index c307f0ad5b6..418b42d8f1d 100644 --- a/app/models/notification_recipient.rb +++ b/app/models/notification_recipient.rb @@ -5,12 +5,10 @@ class NotificationRecipient custom_action: nil, target: nil, acting_user: nil, - read_ability: nil, project: nil ) @custom_action = custom_action @acting_user = acting_user - @read_ability = read_ability @target = target @project = project || @target&.project @user = user @@ -81,10 +79,10 @@ class NotificationRecipient return false unless user.can?(:receive_notifications) return false if @project && !user.can?(:read_project, @project) - return true unless @read_ability + return true unless read_ability return true unless DeclarativePolicy.has_policy?(@target) - user.can?(@read_ability, @target) + user.can?(read_ability, @target) end end @@ -97,6 +95,22 @@ class NotificationRecipient private + def read_ability + return @read_ability if instance_variable_defined?(:@read_ability) + + @read_ability = + case @target + when Issuable + :"read_#{@target.to_ability_name}" + when Ci::Pipeline + :read_build # We have build trace in pipeline emails + when ActiveRecord::Base + :"read_#{@target.class.model_name.name.underscore}" + else + nil + end + end + def find_notification_setting project_setting = @project && user.notification_settings_for(@project) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 5d394f67631..7d4f8110f84 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -76,7 +76,6 @@ module NotificationRecipientService custom_action: custom_action, target: target, acting_user: acting_user, - read_ability: read_ability ) end @@ -91,15 +90,6 @@ module NotificationRecipientService end end - def read_ability - case target - when Issuable - :"read_#{target.to_ability_name}" - when Ci::Pipeline - :read_build # We have build trace in pipeline emails - end - end - def custom_action nil end @@ -285,12 +275,6 @@ module NotificationRecipientService note.project end - def read_ability - return nil if target.nil? - - :"read_#{target.class.model_name.name.underscore}" - end - def build! # Add all users participating in the thread (author, assignee, comment authors) add_participants(note.author) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index c93f82999dc..2e52296f048 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -303,7 +303,6 @@ class NotificationService recipients ||= NotificationRecipientService.notifiable_users( [pipeline.user], :watch, custom_action: :"#{pipeline.status}_pipeline", - read_ability: :read_build, target: pipeline ).map(&:notification_email) From 273cd9c3c9d94e1d40249073ec23e4eba820f260 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Wed, 2 Aug 2017 14:16:00 -0700 Subject: [PATCH 099/177] remove build_relabeled_recipients --- .../notification_recipient_service.rb | 19 ------------------- app/services/notification_service.rb | 8 +++++++- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 7d4f8110f84..8c7a36d4cb0 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -14,10 +14,6 @@ module NotificationRecipientService Builder::Default.new(*a).recipient_users end - def self.build_relabeled_recipients(*a) - Builder::Relabeled.new(*a).recipient_users - end - def self.build_new_note_recipients(*a) Builder::NewNote.new(*a).recipient_users end @@ -246,21 +242,6 @@ module NotificationRecipientService end end - class Relabeled < Base - attr_reader :target - attr_reader :current_user - attr_reader :labels - def initialize(target, current_user, labels:) - @target = target - @current_user = current_user - @labels = labels - end - - def build! - add_labels_subscribers(labels: labels) - end - end - class NewNote < Base attr_reader :note def initialize(note) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 2e52296f048..a62085dffd4 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -368,7 +368,13 @@ class NotificationService end def relabeled_resource_email(target, labels, current_user, method) - recipients = NotificationRecipientService.build_relabeled_recipients(target, current_user, labels: labels) + recipients = labels.flat_map { |l| l.subscribers(target.project) } + recipients = NotificationRecipientService.notifiable_users( + recipients, :subscription, + target: target, + acting_user: current_user, + ) + label_names = labels.map(&:name) recipients.each do |recipient| From e4789cdfdcc2cebb080c96b5165733043db0ce5e Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Wed, 2 Aug 2017 14:21:31 -0700 Subject: [PATCH 100/177] add a comment warning that note.project may be nil --- app/services/notification_recipient_service.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 8c7a36d4cb0..0382ecd4abb 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -252,6 +252,10 @@ module NotificationRecipientService note.noteable end + # NOTE: may be nil, in the case of a PersonalSnippet + # + # (this is okay because NotificationRecipient is written + # to handle nil projects) def project note.project end From 17147f2027896c557cb52dbb5344b87e7d4db1ea Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Wed, 2 Aug 2017 18:54:18 -0700 Subject: [PATCH 101/177] rubocop style fix --- app/services/notification_recipient_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb index 0382ecd4abb..21c9c314a2a 100644 --- a/app/services/notification_recipient_service.rb +++ b/app/services/notification_recipient_service.rb @@ -71,7 +71,7 @@ module NotificationRecipientService project: project, custom_action: custom_action, target: target, - acting_user: acting_user, + acting_user: acting_user ) end From ae96e6a3a6944d743eea2eb6334d6f48d6f12320 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 3 Aug 2017 17:17:22 +0100 Subject: [PATCH 102/177] use new dropdown styling --- app/assets/stylesheets/pages/diff.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index cfc801859a7..da77346d8b2 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -561,6 +561,7 @@ .diff-files-changed { .commit-stat-summary { + @include new-style-dropdown; z-index: -1; @media (min-width: $screen-sm-min) { From ae99f05b059f613296c39dfa45c37dbcab40f4cd Mon Sep 17 00:00:00 2001 From: haseeb Date: Thu, 3 Aug 2017 16:39:10 +0000 Subject: [PATCH 103/177] fix #35133 strip new lines from ssh keys --- app/models/key.rb | 3 +-- spec/models/key_spec.rb | 14 ++++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/app/models/key.rb b/app/models/key.rb index cb8f10f6d55..49bc26122fa 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -16,8 +16,6 @@ class Key < ActiveRecord::Base presence: true, length: { maximum: 5000 }, format: { with: /\A(ssh|ecdsa)-.*\Z/ } - validates :key, - format: { without: /\n|\r/, message: 'should be a single line' } validates :fingerprint, uniqueness: true, presence: { message: 'cannot be generated' } @@ -31,6 +29,7 @@ class Key < ActiveRecord::Base after_destroy :post_destroy_hook def key=(value) + value&.delete!("\n\r") value.strip! unless value.blank? write_attribute(:key, value) end diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb index d41717d0223..251d0cfd08c 100644 --- a/spec/models/key_spec.rb +++ b/spec/models/key_spec.rb @@ -94,15 +94,17 @@ describe Key do expect(key).not_to be_valid end + it 'accepts a key with newline charecters after stripping them' do + key = build(:key) + key.key = key.key.insert(100, "\n") + key.key = key.key.insert(40, "\r\n") + expect(key).to be_valid + end + it 'rejects the unfingerprintable key (not a key)' do expect(build(:key, key: 'ssh-rsa an-invalid-key==')).not_to be_valid end - - it 'rejects the multiple line key' do - key = build(:key) - key.key.tr!(' ', "\n") - expect(key).not_to be_valid - end + end context 'callbacks' do From 4974f1ef86f697fa410093720f51414791f210c6 Mon Sep 17 00:00:00 2001 From: haseeb Date: Thu, 3 Aug 2017 16:44:48 +0000 Subject: [PATCH 104/177] fix #3686 make tarball download url to end with extension --- .../unreleased/3686_make_tarball_download_url.yml | 4 ++++ config/routes/repository.rb | 2 +- .../projects/repositories_controller_spec.rb | 2 +- spec/routing/project_routing_spec.rb | 10 +++++++--- 4 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 changelogs/unreleased/3686_make_tarball_download_url.yml diff --git a/changelogs/unreleased/3686_make_tarball_download_url.yml b/changelogs/unreleased/3686_make_tarball_download_url.yml new file mode 100644 index 00000000000..4e75e52e3ac --- /dev/null +++ b/changelogs/unreleased/3686_make_tarball_download_url.yml @@ -0,0 +1,4 @@ +--- +title: repository archive download url now ends with selected file extension +merge_request: 13178 +author: haseebeqx diff --git a/config/routes/repository.rb b/config/routes/repository.rb index edcf3ddf57b..2ba16035ece 100644 --- a/config/routes/repository.rb +++ b/config/routes/repository.rb @@ -2,7 +2,7 @@ resource :repository, only: [:create] do member do - get 'archive', constraints: { format: Gitlab::PathRegex.archive_formats_regex } + get ':ref/archive', constraints: { format: Gitlab::PathRegex.archive_formats_regex, ref: /.+/ }, action: 'archive', as: 'archive' end end diff --git a/spec/controllers/projects/repositories_controller_spec.rb b/spec/controllers/projects/repositories_controller_spec.rb index 9c55d159fa0..f712d1e0d63 100644 --- a/spec/controllers/projects/repositories_controller_spec.rb +++ b/spec/controllers/projects/repositories_controller_spec.rb @@ -6,7 +6,7 @@ describe Projects::RepositoriesController do describe "GET archive" do context 'as a guest' do it 'responds with redirect in correct format' do - get :archive, namespace_id: project.namespace, project_id: project, format: "zip" + get :archive, namespace_id: project.namespace, project_id: project, format: "zip", ref: 'master' expect(response.header["Content-Type"]).to start_with('text/html') expect(response).to be_redirect diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb index c02409b2e0b..39d44245c3f 100644 --- a/spec/routing/project_routing_spec.rb +++ b/spec/routing/project_routing_spec.rb @@ -165,15 +165,19 @@ describe 'project routing' do # edit_project_repository GET /:project_id/repository/edit(.:format) projects/repositories#edit describe Projects::RepositoriesController, 'routing' do it 'to #archive' do - expect(get('/gitlab/gitlabhq/repository/archive')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq') + expect(get('/gitlab/gitlabhq/repository/master/archive')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', ref: 'master') end it 'to #archive format:zip' do - expect(get('/gitlab/gitlabhq/repository/archive.zip')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', format: 'zip') + expect(get('/gitlab/gitlabhq/repository/master/archive.zip')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', format: 'zip', ref: 'master') end it 'to #archive format:tar.bz2' do - expect(get('/gitlab/gitlabhq/repository/archive.tar.bz2')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', format: 'tar.bz2') + expect(get('/gitlab/gitlabhq/repository/master/archive.tar.bz2')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', format: 'tar.bz2', ref: 'master') + end + + it 'to #archive with "/" in route' do + expect(get('/gitlab/gitlabhq/repository/improve/awesome/archive')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', ref: 'improve/awesome') end end From 03440eed20cc36a2f9836dc078d2101849e11319 Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Fri, 28 Jul 2017 14:16:26 +0200 Subject: [PATCH 105/177] Migrate blame loading to Gitaly Closes gitaly#421 --- GITALY_SERVER_VERSION | 2 +- Gemfile | 2 +- Gemfile.lock | 4 +- lib/gitlab/git/blame.rb | 24 +++-- lib/gitlab/git/repository.rb | 16 +-- lib/gitlab/gitaly_client/commit_service.rb | 11 ++ spec/lib/gitlab/git/blame_spec.rb | 116 +++++++++++---------- 7 files changed, 104 insertions(+), 71 deletions(-) diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 4e8f395fa5e..1b58cc10180 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -0.26.0 +0.27.0 diff --git a/Gemfile b/Gemfile index 403b104a9d6..34f231a04b8 100644 --- a/Gemfile +++ b/Gemfile @@ -391,7 +391,7 @@ gem 'vmstat', '~> 2.3.0' gem 'sys-filesystem', '~> 1.1.6' # Gitaly GRPC client -gem 'gitaly', '~> 0.23.0' +gem 'gitaly', '~> 0.24.0' gem 'toml-rb', '~> 0.3.15', require: false diff --git a/Gemfile.lock b/Gemfile.lock index 9f90965a567..a17aa3ee1ed 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -269,7 +269,7 @@ GEM po_to_json (>= 1.0.0) rails (>= 3.2.0) gherkin-ruby (0.3.2) - gitaly (0.23.0) + gitaly (0.24.0) google-protobuf (~> 3.1) grpc (~> 1.0) github-linguist (4.7.6) @@ -978,7 +978,7 @@ DEPENDENCIES gettext (~> 3.2.2) gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails_js (~> 1.2.0) - gitaly (~> 0.23.0) + gitaly (~> 0.24.0) github-linguist (~> 4.7.0) gitlab-flowdock-git-hook (~> 1.0.1) gitlab-markup (~> 1.5.1) diff --git a/lib/gitlab/git/blame.rb b/lib/gitlab/git/blame.rb index 0deaab01b5b..8dbe25e55f6 100644 --- a/lib/gitlab/git/blame.rb +++ b/lib/gitlab/git/blame.rb @@ -1,5 +1,3 @@ -# Gitaly note: JV: needs 1 RPC for #load_blame. - module Gitlab module Git class Blame @@ -26,15 +24,29 @@ module Gitlab private - # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/376 def load_blame - cmd = %W(#{Gitlab.config.git.bin_path} --git-dir=#{@repo.path} blame -p #{@sha} -- #{@path}) - # Read in binary mode to ensure ASCII-8BIT - raw_output = IO.popen(cmd, 'rb') {|io| io.read } + raw_output = @repo.gitaly_migrate(:blame) do |is_enabled| + if is_enabled + load_blame_by_gitaly + else + load_blame_by_shelling_out + end + end + output = encode_utf8(raw_output) process_raw_blame output end + def load_blame_by_gitaly + @repo.gitaly_commit_client.raw_blame(@sha, @path) + end + + def load_blame_by_shelling_out + cmd = %W(#{Gitlab.config.git.bin_path} --git-dir=#{@repo.path} blame -p #{@sha} -- #{@path}) + # Read in binary mode to ensure ASCII-8BIT + IO.popen(cmd, 'rb') {|io| io.read } + end + def process_raw_blame(output) lines, final = [], [] info, commits = {}, {} diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index ffe2c8b91bb..1c3beb5e834 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -683,6 +683,14 @@ module Gitlab @gitaly_repository_client ||= Gitlab::GitalyClient::RepositoryService.new(self) end + def gitaly_migrate(method, &block) + Gitlab::GitalyClient.migrate(method, &block) + rescue GRPC::NotFound => e + raise NoRepository.new(e) + rescue GRPC::BadStatus => e + raise CommandError.new(e) + end + private # Gitaly note: JV: Trying to get rid of the 'filter' option so we can implement this with 'git'. @@ -1017,14 +1025,6 @@ module Gitlab raw_output.to_i end - - def gitaly_migrate(method, &block) - Gitlab::GitalyClient.migrate(method, &block) - rescue GRPC::NotFound => e - raise NoRepository.new(e) - rescue GRPC::BadStatus => e - raise CommandError.new(e) - end end end end diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb index b1424a458e9..1ae13677b42 100644 --- a/lib/gitlab/gitaly_client/commit_service.rb +++ b/lib/gitlab/gitaly_client/commit_service.rb @@ -128,6 +128,17 @@ module Gitlab response.languages.map { |l| { value: l.share.round(2), label: l.name, color: l.color, highlight: l.color } } end + def raw_blame(revision, path) + request = Gitaly::RawBlameRequest.new( + repository: @gitaly_repo, + revision: revision, + path: path + ) + + response = GitalyClient.call(@repository.storage, :commit_service, :raw_blame, request) + response.reduce("") { |memo, msg| memo << msg.data } + end + private def commit_diff_request_params(commit, options = {}) diff --git a/spec/lib/gitlab/git/blame_spec.rb b/spec/lib/gitlab/git/blame_spec.rb index 66c016d14b3..800c245b130 100644 --- a/spec/lib/gitlab/git/blame_spec.rb +++ b/spec/lib/gitlab/git/blame_spec.rb @@ -7,63 +7,73 @@ describe Gitlab::Git::Blame, seed_helper: true do Gitlab::Git::Blame.new(repository, SeedRepo::Commit::ID, "CONTRIBUTING.md") end - context "each count" do - it do - data = [] - blame.each do |commit, line| - data << { - commit: commit, - line: line - } - end - - expect(data.size).to eq(95) - expect(data.first[:commit]).to be_kind_of(Gitlab::Git::Commit) - expect(data.first[:line]).to eq("# Contribute to GitLab") - expect(data.first[:line]).to be_utf8 - end - end - - context "ISO-8859 encoding" do - let(:blame) do - Gitlab::Git::Blame.new(repository, SeedRepo::EncodingCommit::ID, "encoding/iso8859.txt") - end - - it 'converts to UTF-8' do - data = [] - blame.each do |commit, line| - data << { - commit: commit, - line: line - } - end - - expect(data.size).to eq(1) - expect(data.first[:commit]).to be_kind_of(Gitlab::Git::Commit) - expect(data.first[:line]).to eq("Ä ü") - expect(data.first[:line]).to be_utf8 - end - end - - context "unknown encoding" do - let(:blame) do - Gitlab::Git::Blame.new(repository, SeedRepo::EncodingCommit::ID, "encoding/iso8859.txt") - end - - it 'converts to UTF-8' do - expect(CharlockHolmes::EncodingDetector).to receive(:detect).and_return(nil) - data = [] - blame.each do |commit, line| - data << { + shared_examples 'blaming a file' do + context "each count" do + it do + data = [] + blame.each do |commit, line| + data << { commit: commit, line: line - } + } + end + + expect(data.size).to eq(95) + expect(data.first[:commit]).to be_kind_of(Gitlab::Git::Commit) + expect(data.first[:line]).to eq("# Contribute to GitLab") + expect(data.first[:line]).to be_utf8 + end + end + + context "ISO-8859 encoding" do + let(:blame) do + Gitlab::Git::Blame.new(repository, SeedRepo::EncodingCommit::ID, "encoding/iso8859.txt") end - expect(data.size).to eq(1) - expect(data.first[:commit]).to be_kind_of(Gitlab::Git::Commit) - expect(data.first[:line]).to eq(" ") - expect(data.first[:line]).to be_utf8 + it 'converts to UTF-8' do + data = [] + blame.each do |commit, line| + data << { + commit: commit, + line: line + } + end + + expect(data.size).to eq(1) + expect(data.first[:commit]).to be_kind_of(Gitlab::Git::Commit) + expect(data.first[:line]).to eq("Ä ü") + expect(data.first[:line]).to be_utf8 + end + end + + context "unknown encoding" do + let(:blame) do + Gitlab::Git::Blame.new(repository, SeedRepo::EncodingCommit::ID, "encoding/iso8859.txt") + end + + it 'converts to UTF-8' do + expect(CharlockHolmes::EncodingDetector).to receive(:detect).and_return(nil) + data = [] + blame.each do |commit, line| + data << { + commit: commit, + line: line + } + end + + expect(data.size).to eq(1) + expect(data.first[:commit]).to be_kind_of(Gitlab::Git::Commit) + expect(data.first[:line]).to eq(" ") + expect(data.first[:line]).to be_utf8 + end end end + + context 'when Gitaly blame feature is enabled' do + it_behaves_like 'blaming a file' + end + + context 'when Gitaly blame feature is disabled', skip_gitaly_mock: true do + it_behaves_like 'blaming a file' + end end From f81c07eacc6c37092b13559dcaf479805138eb45 Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Mon, 31 Jul 2017 19:38:36 +0200 Subject: [PATCH 106/177] Migrate Repository#last_commit_for_path to Gitaly Closes gitaly#433 --- GITALY_SERVER_VERSION | 2 +- Gemfile | 2 +- Gemfile.lock | 4 +-- app/models/repository.rb | 34 +++++++++++++++--- lib/gitlab/git/repository.rb | 21 +++++++----- lib/gitlab/gitaly_client/commit_service.rb | 14 ++++++++ spec/models/repository_spec.rb | 40 ++++++++++++++++------ 7 files changed, 90 insertions(+), 27 deletions(-) diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 4e8f395fa5e..1b58cc10180 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -0.26.0 +0.27.0 diff --git a/Gemfile b/Gemfile index 403b104a9d6..34f231a04b8 100644 --- a/Gemfile +++ b/Gemfile @@ -391,7 +391,7 @@ gem 'vmstat', '~> 2.3.0' gem 'sys-filesystem', '~> 1.1.6' # Gitaly GRPC client -gem 'gitaly', '~> 0.23.0' +gem 'gitaly', '~> 0.24.0' gem 'toml-rb', '~> 0.3.15', require: false diff --git a/Gemfile.lock b/Gemfile.lock index 9f90965a567..a17aa3ee1ed 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -269,7 +269,7 @@ GEM po_to_json (>= 1.0.0) rails (>= 3.2.0) gherkin-ruby (0.3.2) - gitaly (0.23.0) + gitaly (0.24.0) google-protobuf (~> 3.1) grpc (~> 1.0) github-linguist (4.7.6) @@ -978,7 +978,7 @@ DEPENDENCIES gettext (~> 3.2.2) gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails_js (~> 1.2.0) - gitaly (~> 0.23.0) + gitaly (~> 0.24.0) github-linguist (~> 4.7.0) gitlab-flowdock-git-hook (~> 1.0.1) gitlab-markup (~> 1.5.1) diff --git a/app/models/repository.rb b/app/models/repository.rb index 4e9fe759fdc..2dd48290e58 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -613,17 +613,26 @@ class Repository end def last_commit_for_path(sha, path) - sha = last_commit_id_for_path(sha, path) - commit(sha) + raw_repository.gitaly_migrate(:last_commit_for_path) do |is_enabled| + if is_enabled + last_commit_for_path_by_gitaly(sha, path) + else + last_commit_for_path_by_rugged(sha, path) + end + end end - # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/383 def last_commit_id_for_path(sha, path) key = path.blank? ? "last_commit_id_for_path:#{sha}" : "last_commit_id_for_path:#{sha}:#{Digest::SHA1.hexdigest(path)}" cache.fetch(key) do - args = %W(#{Gitlab.config.git.bin_path} rev-list --max-count=1 #{sha} -- #{path}) - Gitlab::Popen.popen(args, path_to_repo).first.strip + raw_repository.gitaly_migrate(:last_commit_for_path) do |is_enabled| + if is_enabled + last_commit_for_path_by_gitaly(sha, path).id + else + last_commit_id_for_path_by_shelling_out(sha, path) + end + end end end @@ -1138,6 +1147,21 @@ class Repository Rugged::Commit.create(rugged, params) end + def last_commit_for_path_by_gitaly(sha, path) + c = raw_repository.gitaly_commit_client.last_commit_for_path(sha, path) + commit(c) + end + + def last_commit_for_path_by_rugged(sha, path) + sha = last_commit_id_for_path_by_shelling_out(sha, path) + commit(sha) + end + + def last_commit_id_for_path_by_shelling_out(sha, path) + args = %W(#{Gitlab.config.git.bin_path} rev-list --max-count=1 #{sha} -- #{path}) + Gitlab::Popen.popen(args, path_to_repo).first.strip + end + def repository_storage_path @project.repository_storage_path end diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index ffe2c8b91bb..734aed8fbc1 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -683,6 +683,14 @@ module Gitlab @gitaly_repository_client ||= Gitlab::GitalyClient::RepositoryService.new(self) end + def gitaly_migrate(method, &block) + Gitlab::GitalyClient.migrate(method, &block) + rescue GRPC::NotFound => e + raise NoRepository.new(e) + rescue GRPC::BadStatus => e + raise CommandError.new(e) + end + private # Gitaly note: JV: Trying to get rid of the 'filter' option so we can implement this with 'git'. @@ -998,6 +1006,11 @@ module Gitlab end.sort_by(&:name) end + def last_commit_for_path_by_rugged(sha, path) + sha = last_commit_id_for_path(sha, path) + commit(sha) + end + def tags_from_gitaly gitaly_ref_client.tags end @@ -1017,14 +1030,6 @@ module Gitlab raw_output.to_i end - - def gitaly_migrate(method, &block) - Gitlab::GitalyClient.migrate(method, &block) - rescue GRPC::NotFound => e - raise NoRepository.new(e) - rescue GRPC::BadStatus => e - raise CommandError.new(e) - end end end end diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb index b1424a458e9..3f6c2c09418 100644 --- a/lib/gitlab/gitaly_client/commit_service.rb +++ b/lib/gitlab/gitaly_client/commit_service.rb @@ -97,6 +97,20 @@ module Gitlab GitalyClient.call(@repository.storage, :commit_service, :count_commits, request).count end + def last_commit_for_path(revision, path) + request = Gitaly::LastCommitForPathRequest.new( + repository: @gitaly_repo, + revision: revision.force_encoding(Encoding::ASCII_8BIT), + path: path.to_s.force_encoding(Encoding::ASCII_8BIT) + ) + + gitaly_commit = GitalyClient.call(@repository.storage, :commit_service, :last_commit_for_path, request).commit + return unless gitaly_commit + + commit = GitalyClient::Commit.new(@repository, gitaly_commit) + Gitlab::Git::Commit.new(commit) + end + def between(from, to) request = Gitaly::CommitsBetweenRequest.new( repository: @gitaly_repo, diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 764f548be45..f876baaa805 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -139,24 +139,44 @@ describe Repository do end describe '#last_commit_for_path' do - subject { repository.last_commit_for_path(sample_commit.id, '.gitignore').id } + shared_examples 'getting last commit for path' do + subject { repository.last_commit_for_path(sample_commit.id, '.gitignore').id } - it { is_expected.to eq('c1acaa58bbcbc3eafe538cb8274ba387047b69f8') } + it { is_expected.to eq('c1acaa58bbcbc3eafe538cb8274ba387047b69f8') } + end + + context 'when Gitaly feature last_commit_for_path is enabled' do + it_behaves_like 'getting last commit for path' + end + + context 'when Gitaly feature last_commit_for_path is disabled', skip_gitaly_mock: true do + it_behaves_like 'getting last commit for path' + end end describe '#last_commit_id_for_path' do - subject { repository.last_commit_id_for_path(sample_commit.id, '.gitignore') } + shared_examples 'getting last commit ID for path' do + subject { repository.last_commit_id_for_path(sample_commit.id, '.gitignore') } - it "returns last commit id for a given path" do - is_expected.to eq('c1acaa58bbcbc3eafe538cb8274ba387047b69f8') + it "returns last commit id for a given path" do + is_expected.to eq('c1acaa58bbcbc3eafe538cb8274ba387047b69f8') + end + + it "caches last commit id for a given path" do + cache = repository.send(:cache) + key = "last_commit_id_for_path:#{sample_commit.id}:#{Digest::SHA1.hexdigest('.gitignore')}" + + expect(cache).to receive(:fetch).with(key).and_return('c1acaa5') + is_expected.to eq('c1acaa5') + end end - it "caches last commit id for a given path" do - cache = repository.send(:cache) - key = "last_commit_id_for_path:#{sample_commit.id}:#{Digest::SHA1.hexdigest('.gitignore')}" + context 'when Gitaly feature last_commit_for_path is enabled' do + it_behaves_like 'getting last commit ID for path' + end - expect(cache).to receive(:fetch).with(key).and_return('c1acaa5') - is_expected.to eq('c1acaa5') + context 'when Gitaly feature last_commit_for_path is disabled', skip_gitaly_mock: true do + it_behaves_like 'getting last commit ID for path' end end From 8b7f4a6a2cc2e4d68b0e55f4110b848b408ccae9 Mon Sep 17 00:00:00 2001 From: Winnie Hellmann Date: Thu, 3 Aug 2017 17:54:12 +0000 Subject: [PATCH 107/177] Use mixin for new dropdown style --- .../stylesheets/framework/dropdowns.scss | 7 +++++- app/assets/stylesheets/framework/header.scss | 21 ++-------------- .../stylesheets/pages/cycle_analytics.scss | 24 ++----------------- app/assets/stylesheets/pages/tree.scss | 23 +----------------- 4 files changed, 11 insertions(+), 64 deletions(-) diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index 572203bce34..89dd99831e4 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -725,7 +725,8 @@ // TODO: change global style and remove mixin @mixin new-style-dropdown { - .dropdown-menu { + .dropdown-menu, + .dropdown-menu-nav { li { padding: 0 1px; @@ -766,4 +767,8 @@ } } } + + .dropdown-menu-align-right { + margin-top: 2px; + } } diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 1c4238bc564..555e444a062 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -4,6 +4,8 @@ */ header { + @include new-style-dropdown; + transition: padding $sidebar-transition-duration; &.navbar-empty { @@ -313,25 +315,6 @@ header { .impersonation i { color: $red-500; } - - // TODO: fallback to global style - .dropdown-menu, - .dropdown-menu-nav { - li { - padding: 0 1px; - - a { - border-radius: 0; - padding: 8px 16px; - - &:hover, - &:active, - &:focus { - background-color: $gray-darker; - } - } - } - } } .with-performance-bar header.navbar-gitlab { diff --git a/app/assets/stylesheets/pages/cycle_analytics.scss b/app/assets/stylesheets/pages/cycle_analytics.scss index 87b50c7687e..6753eb08285 100644 --- a/app/assets/stylesheets/pages/cycle_analytics.scss +++ b/app/assets/stylesheets/pages/cycle_analytics.scss @@ -1,4 +1,6 @@ #cycle-analytics { + @include new-style-dropdown; + max-width: 1000px; margin: 24px auto 0; position: relative; @@ -110,10 +112,6 @@ .js-ca-dropdown { top: $gl-padding-top; - - .dropdown-menu-align-right { - margin-top: 2px; - } } .content-list { @@ -446,24 +444,6 @@ margin-bottom: 20px; } } - - // TODO: fallback to global style - .dropdown-menu { - li { - padding: 0 1px; - - a { - border-radius: 0; - padding: 8px 16px; - - &:hover, - &:active, - &:focus { - background-color: $gray-darker; - } - } - } - } } .cycle-analytics-overview { diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss index e0f46172769..44ab07a4367 100644 --- a/app/assets/stylesheets/pages/tree.scss +++ b/app/assets/stylesheets/pages/tree.scss @@ -1,4 +1,5 @@ .tree-holder { + @include new-style-dropdown; .nav-block { margin: 10px 0; @@ -202,28 +203,6 @@ } } } - - // TODO: fallback to global style - .dropdown-menu:not(.dropdown-menu-selectable) { - li { - padding: 0 1px; - - &.dropdown-header { - padding: 8px 16px; - } - - a { - border-radius: 0; - padding: 8px 16px; - - &:hover, - &:active, - &:focus { - background-color: $gray-darker; - } - } - } - } } .blob-commit-info { From 120fd3b3aea9cda81384c6488a1136c176ab3965 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Thu, 3 Aug 2017 11:52:53 -0700 Subject: [PATCH 108/177] another rubocop style fix --- app/services/notification_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index a62085dffd4..df04b1a4fe3 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -372,7 +372,7 @@ class NotificationService recipients = NotificationRecipientService.notifiable_users( recipients, :subscription, target: target, - acting_user: current_user, + acting_user: current_user ) label_names = labels.map(&:name) From b9075d22d7315bd9f408e0ec460b8b3c7273891d Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 3 Aug 2017 19:21:43 +0000 Subject: [PATCH 109/177] Revert "Merge branch 'rs-warm-capybara-only-in-ci' into 'master'" This reverts merge request !12761 --- spec/support/test_env.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index bed78928f14..c1298ed9cae 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -229,7 +229,6 @@ module TestEnv # Otherwise they'd be created by the first test, often timing out and # causing a transient test failure def eager_load_driver_server - return unless ENV['CI'] return unless defined?(Capybara) puts "Starting the Capybara driver server..." From dab08be606878139ce3fe3d8e197ef73badf8e88 Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Thu, 3 Aug 2017 20:31:53 +0000 Subject: [PATCH 110/177] Resolve "Specific Async Script Loading by using a Page Variable" --- app/assets/javascripts/awards_handler.js | 2 +- app/assets/javascripts/behaviors/requires_input.js | 9 ++++++--- .../javascripts/behaviors/toggler_behavior.js | 1 - app/assets/javascripts/boards/boards_bundle.js | 1 + .../boards/components/board_blank_state.js | 1 + .../boards/components/new_list_dropdown.js | 1 + .../javascripts/boards/stores/boards_store.js | 2 +- app/assets/javascripts/commons/index.js | 1 + app/assets/javascripts/copy_as_gfm.js | 2 +- app/assets/javascripts/dispatcher.js | 8 ++++---- app/assets/javascripts/dropzone_input.js | 3 +-- app/assets/javascripts/emoji/index.js | 1 + app/assets/javascripts/filterable_list.js | 2 ++ .../javascripts/filtered_search/dropdown_utils.js | 1 + app/assets/javascripts/gfm_auto_complete.js | 1 + app/assets/javascripts/gl_dropdown.js | 1 + .../javascripts/graphs/stat_graph_contributors.js | 1 + .../graphs/stat_graph_contributors_graph.js | 2 +- .../graphs/stat_graph_contributors_util.js | 1 + .../javascripts/issuable_bulk_update_actions.js | 1 + app/assets/javascripts/issuable_index.js | 2 +- app/assets/javascripts/labels_select.js | 2 +- app/assets/javascripts/lib/utils/pretty_time.js | 2 ++ app/assets/javascripts/main.js | 11 +++++++---- app/assets/javascripts/milestone_select.js | 1 + app/assets/javascripts/notes.js | 1 + .../components/interval_pattern_input.vue | 2 ++ app/assets/javascripts/profile/gl_crop.js | 1 + app/assets/javascripts/project_edit.js | 2 +- .../protected_branches/protected_branch_dropdown.js | 2 ++ .../protected_tags/protected_tag_dropdown.js | 2 ++ app/assets/javascripts/right_sidebar.js | 1 + app/assets/javascripts/shortcuts_issuable.js | 3 ++- .../time_tracking/sidebar_time_tracking.js | 2 ++ app/assets/javascripts/sidebar_height_manager.js | 3 ++- app/assets/javascripts/todos.js | 3 +++ app/assets/javascripts/u2f/authenticate.js | 2 ++ app/assets/javascripts/u2f/register.js | 2 ++ app/assets/javascripts/username_validator.js | 2 ++ app/assets/javascripts/users/activity_calendar.js | 1 + app/assets/javascripts/users_select.js | 1 + app/helpers/defer_script_tag_helper.rb | 6 ++++++ app/views/layouts/_bootlint.haml | 7 ++++--- app/views/layouts/_init_auto_complete.html.haml | 1 + app/views/projects/merge_requests/show.html.haml | 1 + spec/helpers/defer_script_tag_helper_spec.rb | 13 +++++++++++++ 46 files changed, 92 insertions(+), 26 deletions(-) create mode 100644 app/helpers/defer_script_tag_helper.rb create mode 100644 spec/helpers/defer_script_tag_helper_spec.rb diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js index 18cd04b176a..097f79a250a 100644 --- a/app/assets/javascripts/awards_handler.js +++ b/app/assets/javascripts/awards_handler.js @@ -1,6 +1,6 @@ /* eslint-disable class-methods-use-this */ /* global Flash */ - +import _ from 'underscore'; import Cookies from 'js-cookie'; const animationEndEventString = 'animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd'; diff --git a/app/assets/javascripts/behaviors/requires_input.js b/app/assets/javascripts/behaviors/requires_input.js index b20d108aa25..035a7e5c431 100644 --- a/app/assets/javascripts/behaviors/requires_input.js +++ b/app/assets/javascripts/behaviors/requires_input.js @@ -1,3 +1,4 @@ +import _ from 'underscore'; import '../commons/bootstrap'; // Requires Input behavior @@ -48,7 +49,9 @@ function hideOrShowHelpBlock(form) { $(() => { const $form = $('form.js-requires-input'); - $form.requiresInput(); - hideOrShowHelpBlock($form); - $('.select2.js-select-namespace').change(() => hideOrShowHelpBlock($form)); + if ($form) { + $form.requiresInput(); + hideOrShowHelpBlock($form); + $('.select2.js-select-namespace').change(() => hideOrShowHelpBlock($form)); + } }); diff --git a/app/assets/javascripts/behaviors/toggler_behavior.js b/app/assets/javascripts/behaviors/toggler_behavior.js index 77e92ff8caf..b70b0a9bbf8 100644 --- a/app/assets/javascripts/behaviors/toggler_behavior.js +++ b/app/assets/javascripts/behaviors/toggler_behavior.js @@ -1,4 +1,3 @@ - // Toggle button. Show/hide content inside parent container. // Button does not change visibility. If button has icon - it changes chevron style. // diff --git a/app/assets/javascripts/boards/boards_bundle.js b/app/assets/javascripts/boards/boards_bundle.js index 88b054b76e6..89c14180149 100644 --- a/app/assets/javascripts/boards/boards_bundle.js +++ b/app/assets/javascripts/boards/boards_bundle.js @@ -2,6 +2,7 @@ /* global BoardService */ /* global Flash */ +import _ from 'underscore'; import Vue from 'vue'; import VueResource from 'vue-resource'; import FilteredSearchBoards from './filtered_search_boards'; diff --git a/app/assets/javascripts/boards/components/board_blank_state.js b/app/assets/javascripts/boards/components/board_blank_state.js index e7f16899362..edfe7c326db 100644 --- a/app/assets/javascripts/boards/components/board_blank_state.js +++ b/app/assets/javascripts/boards/components/board_blank_state.js @@ -1,5 +1,6 @@ /* global ListLabel */ +import _ from 'underscore'; import Cookies from 'js-cookie'; const Store = gl.issueBoards.BoardsStore; diff --git a/app/assets/javascripts/boards/components/new_list_dropdown.js b/app/assets/javascripts/boards/components/new_list_dropdown.js index f29b6caa1ac..72bb9e10fbc 100644 --- a/app/assets/javascripts/boards/components/new_list_dropdown.js +++ b/app/assets/javascripts/boards/components/new_list_dropdown.js @@ -1,5 +1,6 @@ /* eslint-disable comma-dangle, func-names, no-new, space-before-function-paren, one-var, promise/catch-or-return */ +import _ from 'underscore'; window.gl = window.gl || {}; window.gl.issueBoards = window.gl.issueBoards || {}; diff --git a/app/assets/javascripts/boards/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js index 1e12d4ca415..43928e602d6 100644 --- a/app/assets/javascripts/boards/stores/boards_store.js +++ b/app/assets/javascripts/boards/stores/boards_store.js @@ -1,6 +1,6 @@ /* eslint-disable comma-dangle, space-before-function-paren, one-var, no-shadow, dot-notation, max-len */ /* global List */ - +import _ from 'underscore'; import Cookies from 'js-cookie'; window.gl = window.gl || {}; diff --git a/app/assets/javascripts/commons/index.js b/app/assets/javascripts/commons/index.js index 7063f59d446..6db8b3afbef 100644 --- a/app/assets/javascripts/commons/index.js +++ b/app/assets/javascripts/commons/index.js @@ -1,3 +1,4 @@ +import 'underscore'; import './polyfills'; import './jquery'; import './bootstrap'; diff --git a/app/assets/javascripts/copy_as_gfm.js b/app/assets/javascripts/copy_as_gfm.js index 54257531284..13ba4a57293 100644 --- a/app/assets/javascripts/copy_as_gfm.js +++ b/app/assets/javascripts/copy_as_gfm.js @@ -1,5 +1,5 @@ /* eslint-disable class-methods-use-this, object-shorthand, no-unused-vars, no-use-before-define, no-new, max-len, no-restricted-syntax, guard-for-in, no-continue */ - +import _ from 'underscore'; import './lib/utils/common_utils'; import { placeholderImage } from './lazy_loader'; diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index 178e72a1127..070d0a01c0f 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -79,10 +79,6 @@ import GpgBadges from './gpg_badges'; (function() { var Dispatcher; - $(function() { - return new Dispatcher(); - }); - Dispatcher = (function() { function Dispatcher() { this.initSearch(); @@ -637,4 +633,8 @@ import GpgBadges from './gpg_badges'; return Dispatcher; })(); + + $(function() { + new Dispatcher(); + }); }).call(window); diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js index 9ebbb22e807..bd1864b8321 100644 --- a/app/assets/javascripts/dropzone_input.js +++ b/app/assets/javascripts/dropzone_input.js @@ -1,11 +1,10 @@ /* eslint-disable func-names, space-before-function-paren, wrap-iife, max-len, one-var, no-var, one-var-declaration-per-line, no-unused-vars, camelcase, quotes, no-useless-concat, prefer-template, quote-props, comma-dangle, object-shorthand, consistent-return, prefer-arrow-callback */ /* global Dropzone */ - +import _ from 'underscore'; import './preview_markdown'; window.DropzoneInput = (function() { function DropzoneInput(form) { - Dropzone.autoDiscover = false; const divHover = '
'; const iconPaperclip = ''; const $attachButton = form.find('.button-attach-file'); diff --git a/app/assets/javascripts/emoji/index.js b/app/assets/javascripts/emoji/index.js index cac35d6eed5..dc7672560ea 100644 --- a/app/assets/javascripts/emoji/index.js +++ b/app/assets/javascripts/emoji/index.js @@ -1,3 +1,4 @@ +import _ from 'underscore'; import emojiMap from 'emojis/digests.json'; import emojiAliases from 'emojis/aliases.json'; diff --git a/app/assets/javascripts/filterable_list.js b/app/assets/javascripts/filterable_list.js index 139206cc185..6d516a253bb 100644 --- a/app/assets/javascripts/filterable_list.js +++ b/app/assets/javascripts/filterable_list.js @@ -1,3 +1,5 @@ +import _ from 'underscore'; + /** * Makes search request for content when user types a value in the search input. * Updates the html content of the page with the received one. diff --git a/app/assets/javascripts/filtered_search/dropdown_utils.js b/app/assets/javascripts/filtered_search/dropdown_utils.js index 9c7a4d9f6ad..db5560fa753 100644 --- a/app/assets/javascripts/filtered_search/dropdown_utils.js +++ b/app/assets/javascripts/filtered_search/dropdown_utils.js @@ -1,3 +1,4 @@ +import _ from 'underscore'; import FilteredSearchContainer from './container'; class DropdownUtils { diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js index 6cb9cfe1382..5c624b79d45 100644 --- a/app/assets/javascripts/gfm_auto_complete.js +++ b/app/assets/javascripts/gfm_auto_complete.js @@ -1,3 +1,4 @@ +import _ from 'underscore'; import glRegexp from './lib/utils/regexp'; import AjaxCache from './lib/utils/ajax_cache'; diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index 9475498e176..a17680794cc 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -1,5 +1,6 @@ /* eslint-disable func-names, space-before-function-paren, no-var, one-var, one-var-declaration-per-line, prefer-rest-params, max-len, vars-on-top, wrap-iife, no-unused-vars, quotes, no-shadow, no-cond-assign, prefer-arrow-callback, no-return-assign, no-else-return, camelcase, comma-dangle, no-lonely-if, guard-for-in, no-restricted-syntax, consistent-return, prefer-template, no-param-reassign, no-loop-func, no-mixed-operators */ /* global fuzzaldrinPlus */ +import _ from 'underscore'; import { isObject } from './lib/utils/type_utility'; var GitLabDropdown, GitLabDropdownFilter, GitLabDropdownRemote; diff --git a/app/assets/javascripts/graphs/stat_graph_contributors.js b/app/assets/javascripts/graphs/stat_graph_contributors.js index c6be4c9e8fe..cdc4fcf6573 100644 --- a/app/assets/javascripts/graphs/stat_graph_contributors.js +++ b/app/assets/javascripts/graphs/stat_graph_contributors.js @@ -1,5 +1,6 @@ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, one-var, camelcase, one-var-declaration-per-line, quotes, no-param-reassign, quote-props, comma-dangle, prefer-template, max-len, no-return-assign, no-shadow */ +import _ from 'underscore'; import d3 from 'd3'; import { ContributorsGraph, ContributorsAuthorGraph, ContributorsMasterGraph } from './stat_graph_contributors_graph'; import ContributorsStatGraphUtil from './stat_graph_contributors_util'; diff --git a/app/assets/javascripts/graphs/stat_graph_contributors_graph.js b/app/assets/javascripts/graphs/stat_graph_contributors_graph.js index 0deb27e522b..f64b4638485 100644 --- a/app/assets/javascripts/graphs/stat_graph_contributors_graph.js +++ b/app/assets/javascripts/graphs/stat_graph_contributors_graph.js @@ -1,5 +1,5 @@ /* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, max-len, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, comma-dangle, no-return-assign, prefer-arrow-callback, quotes, prefer-template, newline-per-chained-call, no-else-return, no-shadow */ - +import _ from 'underscore'; import d3 from 'd3'; const extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; diff --git a/app/assets/javascripts/graphs/stat_graph_contributors_util.js b/app/assets/javascripts/graphs/stat_graph_contributors_util.js index c583757f3f2..77135ad1f0e 100644 --- a/app/assets/javascripts/graphs/stat_graph_contributors_util.js +++ b/app/assets/javascripts/graphs/stat_graph_contributors_util.js @@ -1,4 +1,5 @@ /* eslint-disable func-names, space-before-function-paren, object-shorthand, no-var, one-var, camelcase, one-var-declaration-per-line, comma-dangle, no-param-reassign, no-return-assign, quotes, prefer-arrow-callback, wrap-iife, consistent-return, no-unused-vars, max-len, no-cond-assign, no-else-return, max-len */ +import _ from 'underscore'; export default { parse_log: function(log) { diff --git a/app/assets/javascripts/issuable_bulk_update_actions.js b/app/assets/javascripts/issuable_bulk_update_actions.js index e46c0e90255..c39ffdb2e0f 100644 --- a/app/assets/javascripts/issuable_bulk_update_actions.js +++ b/app/assets/javascripts/issuable_bulk_update_actions.js @@ -1,6 +1,7 @@ /* eslint-disable comma-dangle, quotes, consistent-return, func-names, array-callback-return, space-before-function-paren, prefer-arrow-callback, max-len, no-unused-expressions, no-sequences, no-underscore-dangle, no-unused-vars, no-param-reassign */ /* global IssuableIndex */ /* global Flash */ +import _ from 'underscore'; export default { init({ container, form, issues, prefixId } = {}) { diff --git a/app/assets/javascripts/issuable_index.js b/app/assets/javascripts/issuable_index.js index 5c96646def8..ece0220c927 100644 --- a/app/assets/javascripts/issuable_index.js +++ b/app/assets/javascripts/issuable_index.js @@ -1,6 +1,6 @@ /* eslint-disable no-param-reassign, func-names, no-var, camelcase, no-unused-vars, object-shorthand, space-before-function-paren, no-return-assign, comma-dangle, consistent-return, one-var, one-var-declaration-per-line, quotes, prefer-template, prefer-arrow-callback, wrap-iife, max-len */ /* global IssuableIndex */ - +import _ from 'underscore'; import IssuableBulkUpdateSidebar from './issuable_bulk_update_sidebar'; import IssuableBulkUpdateActions from './issuable_bulk_update_actions'; diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js index f0e02ca0fb2..7d7f91227f9 100644 --- a/app/assets/javascripts/labels_select.js +++ b/app/assets/javascripts/labels_select.js @@ -1,7 +1,7 @@ /* eslint-disable no-useless-return, func-names, space-before-function-paren, wrap-iife, no-var, no-underscore-dangle, prefer-arrow-callback, max-len, one-var, no-unused-vars, one-var-declaration-per-line, prefer-template, no-new, consistent-return, object-shorthand, comma-dangle, no-shadow, no-param-reassign, brace-style, vars-on-top, quotes, no-lonely-if, no-else-return, dot-notation, no-empty, no-return-assign, camelcase, prefer-spread */ /* global Issuable */ /* global ListLabel */ - +import _ from 'underscore'; import IssuableBulkUpdateActions from './issuable_bulk_update_actions'; import DropdownUtils from './filtered_search/dropdown_utils'; diff --git a/app/assets/javascripts/lib/utils/pretty_time.js b/app/assets/javascripts/lib/utils/pretty_time.js index ae397212e55..716aefbfcb7 100644 --- a/app/assets/javascripts/lib/utils/pretty_time.js +++ b/app/assets/javascripts/lib/utils/pretty_time.js @@ -1,3 +1,5 @@ +import _ from 'underscore'; + (() => { /* * TODO: Make these methods more configurable (e.g. parseSeconds timePeriodContstraints, diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index cd45091c211..a807ce326a6 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -36,9 +36,6 @@ import './shortcuts_find_file'; import './shortcuts_issuable'; import './shortcuts_network'; -// behaviors -import './behaviors/'; - // templates import './templates/issuable_template_selector'; import './templates/issuable_template_selectors'; @@ -56,6 +53,9 @@ import './lib/utils/pretty_time'; import './lib/utils/text_utility'; import './lib/utils/url_utility'; +// behaviors +import './behaviors/'; + // u2f import './u2f/authenticate'; import './u2f/error'; @@ -86,7 +86,6 @@ import './copy_as_gfm'; import './copy_to_clipboard'; import './create_label'; import './diff'; -import './dispatcher'; import './dropzone_input'; import './due_date_select'; import './files_comment_button'; @@ -150,9 +149,13 @@ import './subscription'; import './subscription_select'; import './syntax_highlight'; +import './dispatcher'; + // eslint-disable-next-line global-require, import/no-commonjs if (process.env.NODE_ENV !== 'production') require('./test_utils/'); +Dropzone.autoDiscover = false; + document.addEventListener('beforeunload', function () { // Unbind scroll events $(document).off('scroll'); diff --git a/app/assets/javascripts/milestone_select.js b/app/assets/javascripts/milestone_select.js index 6756ab0b3aa..04579058688 100644 --- a/app/assets/javascripts/milestone_select.js +++ b/app/assets/javascripts/milestone_select.js @@ -1,6 +1,7 @@ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-underscore-dangle, prefer-arrow-callback, max-len, one-var, one-var-declaration-per-line, no-unused-vars, object-shorthand, comma-dangle, no-else-return, no-self-compare, consistent-return, no-param-reassign, no-shadow */ /* global Issuable */ /* global ListMilestone */ +import _ from 'underscore'; (function() { this.MilestoneSelect = (function() { diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index dfa07a2def4..b38a6abc8d1 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -11,6 +11,7 @@ newline-per-chained-call, no-useless-escape, class-methods-use-this */ /* global mrRefreshWidgetUrl */ import $ from 'jquery'; +import _ from 'underscore'; import Cookies from 'js-cookie'; import autosize from 'vendor/autosize'; import Dropzone from 'dropzone'; diff --git a/app/assets/javascripts/pipeline_schedules/components/interval_pattern_input.vue b/app/assets/javascripts/pipeline_schedules/components/interval_pattern_input.vue index ce46b3fa3fa..b5d85299cf8 100644 --- a/app/assets/javascripts/pipeline_schedules/components/interval_pattern_input.vue +++ b/app/assets/javascripts/pipeline_schedules/components/interval_pattern_input.vue @@ -1,4 +1,6 @@ " + end + end +end From e18aef5f11365a3dae7639146a4e2d5412749df4 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 3 Aug 2017 16:38:29 -0400 Subject: [PATCH 111/177] Bump rspec to 3.6.0 --- Gemfile | 4 ++-- Gemfile.lock | 48 ++++++++++++++++++++++-------------------------- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/Gemfile b/Gemfile index 403b104a9d6..8e4a90094a8 100644 --- a/Gemfile +++ b/Gemfile @@ -314,11 +314,11 @@ group :development, :test do gem 'pry-rails', '~> 0.3.4' gem 'awesome_print', '~> 1.2.0', require: false - gem 'fuubar', '~> 2.0.0' + gem 'fuubar', '~> 2.2.0' gem 'database_cleaner', '~> 1.5.0' gem 'factory_girl_rails', '~> 4.7.0' - gem 'rspec-rails', '~> 3.5.0' + gem 'rspec-rails', '~> 3.6.0' gem 'rspec-retry', '~> 0.4.5' gem 'spinach-rails', '~> 0.2.1' gem 'spinach-rerun-reporter', '~> 0.0.2' diff --git a/Gemfile.lock b/Gemfile.lock index 9f90965a567..73f45f3ccb6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -156,7 +156,7 @@ GEM devise (~> 4.0) railties rotp (~> 2.0) - diff-lcs (1.2.5) + diff-lcs (1.3) diffy (3.1.0) docile (1.1.5) domain_name (0.5.20161021) @@ -250,8 +250,8 @@ GEM foreman (0.78.0) thor (~> 0.19.1) formatador (0.2.5) - fuubar (2.0.0) - rspec (~> 3.0) + fuubar (2.2.0) + rspec-core (~> 3.0) ruby-progressbar (~> 1.4) gemnasium-gitlab-service (0.2.6) rugged (~> 0.21) @@ -393,7 +393,7 @@ GEM json (~> 1.8) multi_xml (>= 0.5.2) httpclient (2.8.2) - i18n (0.8.1) + i18n (0.8.6) ice_nine (0.11.2) influxdb (0.2.3) cause @@ -610,7 +610,7 @@ GEM pry-rails (0.3.5) pry (>= 0.9.10) pyu-ruby-sasl (0.0.3.3) - rack (1.6.5) + rack (1.6.8) rack-accept (0.4.5) rack (>= 0.4) rack-attack (4.4.1) @@ -658,7 +658,7 @@ GEM rainbow (2.2.2) rake raindrops (0.18.0) - rake (10.5.0) + rake (12.0.0) rblineprof (0.3.6) debugger-ruby_core_source (~> 1.3) rdoc (4.2.2) @@ -702,30 +702,26 @@ GEM chunky_png rqrcode-rails3 (0.1.7) rqrcode (>= 0.4.2) - rspec (3.5.0) - rspec-core (~> 3.5.0) - rspec-expectations (~> 3.5.0) - rspec-mocks (~> 3.5.0) - rspec-core (3.5.0) - rspec-support (~> 3.5.0) - rspec-expectations (3.5.0) + rspec-core (3.6.0) + rspec-support (~> 3.6.0) + rspec-expectations (3.6.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.5.0) - rspec-mocks (3.5.0) + rspec-support (~> 3.6.0) + rspec-mocks (3.6.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.5.0) - rspec-rails (3.5.0) + rspec-support (~> 3.6.0) + rspec-rails (3.6.0) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 3.5.0) - rspec-expectations (~> 3.5.0) - rspec-mocks (~> 3.5.0) - rspec-support (~> 3.5.0) + rspec-core (~> 3.6.0) + rspec-expectations (~> 3.6.0) + rspec-mocks (~> 3.6.0) + rspec-support (~> 3.6.0) rspec-retry (0.4.5) rspec-core rspec-set (0.1.3) - rspec-support (3.5.0) + rspec-support (3.6.0) rspec_profiling (0.0.5) activerecord pg @@ -860,7 +856,7 @@ GEM truncato (0.7.8) htmlentities (~> 4.3.1) nokogiri (~> 1.6.1) - tzinfo (1.2.2) + tzinfo (1.2.3) thread_safe (~> 0.1) u2f (0.2.1) uglifier (2.7.2) @@ -972,7 +968,7 @@ DEPENDENCIES fog-rackspace (~> 0.1.1) font-awesome-rails (~> 4.7) foreman (~> 0.78.0) - fuubar (~> 2.0.0) + fuubar (~> 2.2.0) gemnasium-gitlab-service (~> 0.2) gemojione (~> 3.0) gettext (~> 3.2.2) @@ -1076,7 +1072,7 @@ DEPENDENCIES responders (~> 2.0) rouge (~> 2.0) rqrcode-rails3 (~> 0.1.7) - rspec-rails (~> 3.5.0) + rspec-rails (~> 3.6.0) rspec-retry (~> 0.4.5) rspec-set (~> 0.1.3) rspec_profiling (~> 0.0.5) @@ -1130,4 +1126,4 @@ DEPENDENCIES wikicloth (= 0.8.1) BUNDLED WITH - 1.15.1 + 1.15.3 From 9ca7abfbdc3c81470e643c617b30866122ec5e95 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Thu, 3 Aug 2017 17:32:59 -0500 Subject: [PATCH 112/177] Add active state for pipelines settings on old nav --- app/views/layouts/nav/_group.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml index 8605380848d..261445ecd2b 100644 --- a/app/views/layouts/nav/_group.html.haml +++ b/app/views/layouts/nav/_group.html.haml @@ -25,7 +25,7 @@ %span Members - if current_user && can?(current_user, :admin_group, @group) - = nav_link(path: %w[groups#projects groups#edit]) do + = nav_link(path: %w[groups#projects groups#edit ci_cd#show]) do = link_to edit_group_path(@group), title: 'Settings' do %span Settings From 01dc8e6d66598c42edb58e35c7da79c3b4cad425 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 3 Aug 2017 21:00:20 -0400 Subject: [PATCH 113/177] Don't bother going through an entire Banzai pipeline for empty text This bails out of `cacheless_render` immediately unless the provided text is present, since there's no point. This is a slight improvement in our test performance. Across the creation of 1,000 `Namespace` records, which caches the `description` field and which is blank by default in its factory, this saves about four seconds, which... sure. Why not. --- lib/banzai/renderer.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/banzai/renderer.rb b/lib/banzai/renderer.rb index c7801cb5baf..ad08c0905e2 100644 --- a/lib/banzai/renderer.rb +++ b/lib/banzai/renderer.rb @@ -132,6 +132,8 @@ module Banzai end def self.cacheless_render(text, context = {}) + return text.to_s unless text.present? + Gitlab::Metrics.measure(:banzai_cacheless_render) do result = render_result(text, context) From e9b079d023df7df1b4aca051a1e347b1a8ad810a Mon Sep 17 00:00:00 2001 From: tauriedavis Date: Tue, 1 Aug 2017 15:13:39 -0700 Subject: [PATCH 114/177] 35659 Rename Pipelines tab to CI / CD in new navigation --- app/views/layouts/nav/_new_group_sidebar.html.haml | 4 ++-- app/views/layouts/nav/_new_project_sidebar.html.haml | 8 ++++---- changelogs/unreleased/35659-rename-pipeline.yml | 4 ++++ 3 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 changelogs/unreleased/35659-rename-pipeline.yml diff --git a/app/views/layouts/nav/_new_group_sidebar.html.haml b/app/views/layouts/nav/_new_group_sidebar.html.haml index fdfd7e60732..33a83866cbf 100644 --- a/app/views/layouts/nav/_new_group_sidebar.html.haml +++ b/app/views/layouts/nav/_new_group_sidebar.html.haml @@ -85,6 +85,6 @@ Projects = nav_link(controller: :ci_cd) do - = link_to group_settings_ci_cd_path(@group), title: 'Pipelines' do + = link_to group_settings_ci_cd_path(@group), title: 'CI / CD' do %span - Pipelines + CI / CD diff --git a/app/views/layouts/nav/_new_project_sidebar.html.haml b/app/views/layouts/nav/_new_project_sidebar.html.haml index 9f1cb248c4e..8e246b6e91f 100644 --- a/app/views/layouts/nav/_new_project_sidebar.html.haml +++ b/app/views/layouts/nav/_new_project_sidebar.html.haml @@ -122,9 +122,9 @@ - if project_nav_tab? :pipelines = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :environments, :artifacts]) do - = link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do + = link_to project_pipelines_path(@project), title: 'CI / CD', class: 'shortcuts-pipelines' do .nav-icon-container - = custom_icon('pipeline') + = custom_icon('CI / CD') %span.nav-item-name Pipelines @@ -205,9 +205,9 @@ Repository - if @project.feature_available?(:builds, current_user) = nav_link(controller: :ci_cd) do - = link_to project_settings_ci_cd_path(@project), title: 'Pipelines' do + = link_to project_settings_ci_cd_path(@project), title: 'CI / CD' do %span - Pipelines + CI / CD - if Gitlab.config.pages.enabled = nav_link(controller: :pages) do = link_to project_pages_path(@project), title: 'Pages' do diff --git a/changelogs/unreleased/35659-rename-pipeline.yml b/changelogs/unreleased/35659-rename-pipeline.yml new file mode 100644 index 00000000000..0fe211868e4 --- /dev/null +++ b/changelogs/unreleased/35659-rename-pipeline.yml @@ -0,0 +1,4 @@ +--- +title: Rename Pipelines tab to CI / CD in new navigation +merge_request: +author: From 3ec93e79de20bdc61594daf63766df7e6cbd20aa Mon Sep 17 00:00:00 2001 From: Joshua Lambert Date: Fri, 4 Aug 2017 00:00:26 -0400 Subject: [PATCH 115/177] Openshift Getting Started --- doc/articles/index.md | 2 +- .../img/add-gitlab-to-project.png | Bin 0 -> 37386 bytes .../img/add-to-project.png | Bin 0 -> 21672 bytes .../img/create-project-ui.png | Bin 0 -> 22290 bytes .../openshift_and_gitlab/img/gitlab-logs.png | Bin 0 -> 70858 bytes .../img/gitlab-overview.png | Bin 0 -> 106432 bytes .../img/gitlab-running.png | Bin 0 -> 107993 bytes .../openshift_and_gitlab/img/gitlab-scale.png | Bin 0 -> 36628 bytes .../img/gitlab-settings.png | Bin 0 -> 111366 bytes .../openshift_and_gitlab/img/no-resources.png | Bin 0 -> 34669 bytes .../img/openshift-infra-project.png | Bin 0 -> 95725 bytes .../img/pods-overview.png | Bin 0 -> 106861 bytes .../openshift_and_gitlab/img/rc-name.png | Bin 0 -> 51390 bytes .../openshift_and_gitlab/img/running-pods.png | Bin 0 -> 29818 bytes .../img/storage-volumes.png | Bin 0 -> 49584 bytes .../openshift_and_gitlab/img/web-console.png | Bin 0 -> 34774 bytes doc/articles/openshift_and_gitlab/index.md | 534 ++++++++++++++++++ 17 files changed, 535 insertions(+), 1 deletion(-) create mode 100644 doc/articles/openshift_and_gitlab/img/add-gitlab-to-project.png create mode 100644 doc/articles/openshift_and_gitlab/img/add-to-project.png create mode 100644 doc/articles/openshift_and_gitlab/img/create-project-ui.png create mode 100644 doc/articles/openshift_and_gitlab/img/gitlab-logs.png create mode 100644 doc/articles/openshift_and_gitlab/img/gitlab-overview.png create mode 100644 doc/articles/openshift_and_gitlab/img/gitlab-running.png create mode 100644 doc/articles/openshift_and_gitlab/img/gitlab-scale.png create mode 100644 doc/articles/openshift_and_gitlab/img/gitlab-settings.png create mode 100644 doc/articles/openshift_and_gitlab/img/no-resources.png create mode 100644 doc/articles/openshift_and_gitlab/img/openshift-infra-project.png create mode 100644 doc/articles/openshift_and_gitlab/img/pods-overview.png create mode 100644 doc/articles/openshift_and_gitlab/img/rc-name.png create mode 100644 doc/articles/openshift_and_gitlab/img/running-pods.png create mode 100644 doc/articles/openshift_and_gitlab/img/storage-volumes.png create mode 100644 doc/articles/openshift_and_gitlab/img/web-console.png create mode 100644 doc/articles/openshift_and_gitlab/index.md diff --git a/doc/articles/index.md b/doc/articles/index.md index 9d2e5956029..335cb4f177b 100644 --- a/doc/articles/index.md +++ b/doc/articles/index.md @@ -80,7 +80,7 @@ Install, upgrade, integrate, migrate to GitLab: | :------------ | :------: | --------------: | | [Video Tutorial: Idea to Production on Google Container Engine (GKE)](https://about.gitlab.com/2017/01/23/video-tutorial-idea-to-production-on-google-container-engine-gke/) | Tutorial | 2017/01/23 | | [How to Setup a GitLab Instance on Microsoft Azure](https://about.gitlab.com/2016/07/13/how-to-setup-a-gitlab-instance-on-microsoft-azure/) | Tutorial | 2016/07/13 | -| [Get started with OpenShift Origin 3 and GitLab](https://about.gitlab.com/2016/06/28/get-started-with-openshift-origin-3-and-gitlab/) | Tutorial | 2016/06/28 | +| [Get started with OpenShift Origin 3 and GitLab](https://docs.gitlab.com/ee/articles/openshift_and_gitlab/) | Tutorial | 2016/06/28 | | [Getting started with GitLab and DigitalOcean](https://about.gitlab.com/2016/04/27/getting-started-with-gitlab-and-digitalocean/) | Tutorial | 2016/04/27 | ## Software development diff --git a/doc/articles/openshift_and_gitlab/img/add-gitlab-to-project.png b/doc/articles/openshift_and_gitlab/img/add-gitlab-to-project.png new file mode 100644 index 0000000000000000000000000000000000000000..fcad4e59ae37a7d4607528b77c44b735f7d73fc8 GIT binary patch literal 37386 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⪻W#Nc0fOM{=g8%1QrTU2!sxdC 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 BdCvd< literal 0 HcmV?d00001 diff --git a/doc/articles/openshift_and_gitlab/img/add-to-project.png b/doc/articles/openshift_and_gitlab/img/add-to-project.png new file mode 100644 index 0000000000000000000000000000000000000000..bd915a229f6af3bf9534e330b0405a2e664481be GIT binary patch literal 21672 zcmdSB1yEe!wl3JXJA~kx0D<7{1PciS3m)7Zg1ftg5ZocSySsaWH16Jw1{#-XlAL?) zxpS(fX5PIu@9ioIYVZBq@^7uR2~+qWje$yx3IG5wWZp_B0RV8=004|7G9vVjSb!}M z0H6fONQixOO*>e2`S{U1_vOvQn~5|5hutLylk_Ij^yJ%R0hcm?UDCw|{1>~hsM(_a zlthXOsOU*-1N~_V*zg}^;kyEfBFpN_UgxXU5{O5Hzx$fgj@SNUdE!1dt57aaJFqy% z^AorsK}DeL*xRM8RsK*R6N6|6K&+nW^S~#?>!#jHDj@+3_4;mYc#AuqF~OwmD-R73oFO4`Qx#KdZKX@S*aOf+Ne--=ws z)<+$_H}ZH+IqI8EhZF04Kx0j^m^gUBDw_2FWg|?>ZZ@BU(T3tCS=p>#y_65=%yvyP3B=`J7{>JP#XPEE!Nu26^v^L2`tvn#zEj!oky7>f0N&MxbO zXb?L}^7Mp7G5VAt?h8|9^z))(VPSjox5@MaS7GMJ4)&4?-5;%zgb+6SV;Zi!>2kWd zCcS8(bR6V_Qb})rT$w|3aO?e=@FdRDf<3KABgx*!_)(*5%chujlL z;t_PBet?)ne$BrUa#|4Xr{vk>cd8!JHF_;-bZl}VScwz%Kwgv{f5Q`Ycy>{2MT-Bj zk#H334wvvB&4ELTXSgqS)tSQLP=Ti&yJn*lU^-XZy|)xhF{j{$YP{IP|FRlB9%V4P zgD)o=*$_if6014;R~pZ{9TF~KxT2!Zk@6XVy}bZ*sI)(RXGr2@BiK~lLUvFUT4vyL zc==WNrT+Ky+`da891W58m$AJUFQ})WBG;vNBPohMw$7#Qjl$0*yNJX?WmbAv ziNURk=`Jzl>n>EL4yKLZ9bQlU(`pcpI=}p7qfn!_QOa7|*1nkL85>l< ze5xHO_#D6Et6kDwxbthc+w-EHi;3^aeel!>@kOaLMLr<%V*Kz}$2^s7#A)CDiaEE%UG(_b2v{u}+VZ z7^f$45JZz0pYre3+4F)(!(sgVK@mOJCuVkvDJoa4o-@ z`lWX$sQpHD{erIvczUtG8pah%V5@nB-np#iRP>yauQ)eIOz=zAOMOi@DP z`L*h`j{vY@HFO5dt*`U0ky6x%B0a`j16=8Th*-M(HDqS$4Gy~@7qEQQw~nN`O2`8z z*m=AK;+o*zR3=TR|7$o(z0JAJqP<(rj>6n)Q%$^-SrnaYKY%awB8il|`Cx&S;sZ@- z2~KJD87YU?YfK7(@akWvq2>MVn{T#jDb|s2q*Wz?*oghuv z3$Z{xQ_S3^6zB;(nckqCsjNmV<~H4jk{u!C00+|;N)DMTIOpihIiGX% z@wBq8CbUHR2Uk9mXtY{a0i0N4bP0-mb`yc{I4LT}dpB7}7d%;#bsiLi78hy(4-#(c zp{|W-Hh*6|EB8cuG+@@v1%lOFS`=4_ss11<61q!FPknmO;P|+hvksMWX>vBX=y~nt z0q*yT;r{$FttvhNECk8aHS^=|85u605pffC^*nUQKR4t>X!>+DIe{Lr9HQP_jK8s3 zNsBtTYf~4lYLS1KWIzX>xljrSAZgX_=r8B6@q-P^4&QHlTrMPl56EbDypRMf6p!DM zA5j;crQWV*OsVjETIJ1lXv)6G#U|OyyMI8|?M1@6<2mebiSCC8xSS(~c7Fr>1QT1V z3Yn1dD}@*LOwCj@WV{Mq96Xx%Zgl}8=1brD3&TKAd#0j*tf;H}Tn}PdvE`+{U*L}4 zZUTMi4u^N&EP{9O5CKmm@1ya$WtB@q#rHV~+xNxdjMk_@K;6qP4a{oNR6u&PV6;?1O?ym77FhipFtAX_0uQ`U6QI@75Wjem+r}( z_!DcI^AFCt-v?J)zFG(WXe*VsfVq&L5@MZG^Po_MYxXf67^fp6bpG(MgZbftIzjR} zxz>9OP<3&D0?+S!S(hw5-m|J$cTl_;f}OR=9+Ls70$#kZw^>&7dVgGCD2uP=WVRY1!<)pm6)MSiycbVH~n>JJApTXUI@Tx^tS5gG(xgR+GN!+6^WUwhe%i9vlVl970RAgTEGx%=AaM4%HoC}Ry znoOOM6G-^q_=9rbbB$|)?^pVYVI_8=+e1Q_JhG08FOzZ+#vUulb!NyqA(|YP^E^)FR1@8;&96=`^xa9h4 zZ0AvwDl?+nmKf3_Zk*lvz7ky)UI$ID`%60>K4zl<{69W_a*Nk<32}SG+jKF64Nfab4`ZE`#gm$4ycA6pZdSFU&Chry&}x1655(7I&KFC ztqB!U8pyP&9V%Z4AYH#8tgJX2iH!9wu@@9~m0Ej$3vd!;@FnehcbA0a%!^ z8=$WRbY3w_6X>s{2yqBw>TL74JUPshL)--ukM5AQh4-YICV63ld0wd5J3f3zyN)@L}sTd z$KCyBEhr5iw!2r`Zb?FYPe<$yw@kX~YM@?h@``9q$rT_Sqq4qN^@>!$nY4gqsV{jO z$A7zBKv>b1uVKm4cPQiNp{Rhz7XK*5K>0cD!Qd^64h42@dop4ZF{K2YK{BL}mjY zYnn8A5L>85%``2q+kF1C1U!=scJ?Z*@*3h4W0YT8Y4d1Q%DdlQzG_o>a+fq7b&umL zg5DUHN6X?f?>2d8TBKOIk04W!6)?w__DTo5CA2E4&f14jb4MIhF6K<~{lwr1LWhqP zAp+TZ=a{?}pB~6q4J%aOk>4LfsfDQFI~T`8mOCJ!f1X4y%goye(1)G>_Gx-XN7PM& z=pyl(z9mqQcM;`M#THJYcbNUt>-o@1z`6!S=FmVLZ10%i4V=V<3)YvTE`S&(_B7ST z1q#zJUr>S5ESqudc2Cb2{rg2}_kwTKESkj-@45Vl!IRGeU)Dd&`ItB8DNv?5R0>c& zPhIH=e@_SR)5(*@2VZ39vI-JnlYbP#Zm?jp{&*>beF4K^&s=dU<0J$Zm;|w8j`K31 zXocL#jh6F;D@HF|ik_Fo)YY*h?_7@mY;@M*>eNZ4^`r%#Tg>34v=?PCx~|fg$ANz3 zEv{1by6Jh#XIBJAp9FiZyOZ+YMy>tITd-xxF?;{)jaP5fi{J$}!?AJgxmt5P)iUiE zNr!&@&)e=0$6H^{t(|Ry=^&+=}QHjxA;~#EiJbOOHojO&4(9lCVi|7|rLJtng<{I4?69%OXSEG+? z38Lg?X=PT!16ok4^fzCklO6f$+x#44X6j8C(~3=3_B||thy)d7@uTf)XjR&es2bUh zNb7g;i|H0KiayusSYwd2sTyRa7j<^Vx$k7{K1Qu4n!fhvpn5m1C+XPs=gWjhEFv-D%|G!RBOm{eC>>-}Ta~wSp8e{L_T_#6Wgk3(ju?_r zu1a7q4Y)5{Dv18GD{uYXuy}&m)AJCd!ZwwN1+BV9FYvSCl41CcjvpMN=uV^oNLUq= zKQyk^!F;;ob+>cEuiqK+5$#xu1Y3idEp)q~KrQjYq)TfPzt!-E1Zk5KnuCAoE{P&F zI|URMCa_}%+)p};yw+i#--XtUre!yCi%S(m|!6@np1NiCfcM9EP#Xv^zg8gnI5f5`lo{O z-)ZwmhnVcFZOn}DI$SVCla2!UR_!ib4|rXl>FT!nf@-*Uoodmia_;nx8x$Eu4`NON zCa!{b?G89Uq?b!MjUlA*Ra5NWVIb$o0}J>&4<-QX9eQ~6gx~bQ(^=kHbc?eWje#F} zZ(6+?Ppr%IzG&YbO5*QYOT8&Hm$zh3)E__fKQS!+It09IdVWyKF6ybj>u2pTB8Q3n z!sCp!8@0lv#%Pz%;=w#k8zkm8;TNQO|IAFicggr_e^z-s zXr9LF20IW<2EMCm5La(7BbL%!f1xXJZeI1DG8F%RC8hqi$&UTM-ALyBz0V_=@Z+5W z_3ta-;i2OZGtmy0%o;Y!c zEnn1m-&^bYEH9w{RdGyf3WDjtG>oXK|8;!kl> z0@rXN5@))ZspN37SWTf~N_mmqBN8LmeUj97C7*6e>8&!!rOPeMa*xyTx-c+6K5H8c zjT4>@#XSgu?IlF(P)xVJvPijU^BFCh;$J+`xPD)D{opood3B%%_i)yY9x)s6cimVO z1Z2}9(vH{4%V#I4%OR{wBFG>7%&)-rEb!~=YA+h}j~RO&wa)`A+7-p@P}2fC=4ah< zo#wHw+NRx^jSc>uR9^+gz_ou?)0D_N&mPYyal%2Zvrhovvj{PINp^OhXg>6;0t*iQ zN#N#*OHi>p7$@89H4{5Bl8{Xw(F4xz>gfkIAo_o2GgN`u@DVt{?O0I`c#LO7c;s|T z9IwI3B(v%iL5S=h>{af*9LZR7DRN-tv}bs5KX$k)-U{vm_xzzkeSa}*Z^el2dWURs zmiPT-OQwa$u#?t{Ppxn#G3h+AB@?{(Mn#Dv!Vq?0Mj!pt8&*+l=*D8ps)_-pZu>D; zf(^(Q?d-gP#v5mo6bMx79eD*syJQKfRIODvolc%?{P^SERaYU0F()OHA^&`?2P(xy$X*)UNPf&Kwxw z0`N}E-Bc@(J9mqQ2zJN+WpdaIl*#+9cZR>-K!0*{QexIs&l#a;^GRlm-b3>;bJTy- zy_x_W`_FBO95&HEbioPh2mF;UT4Ff(KU|D8`(Jtycnm}BdGRbw$Oot3gWBfSJ~8x9 za>o4rWT#GV$hAyF2;$!jN!}AvN|_!ET!u7s4$vvwXOv7lx8jGu)zeBRTX&L^5}Kd> z=={s~LS4AtqTt0ZW`QBhHtmY8S5_iWo+~`m?#}y(esa}>B|HYWBFc;R%}>!YmPquS zM$A>&wYs+(VgdD~x)e!;oJplID_9#d@Z_-yS7#f>gIs(hvTR*6YCtJfPF9UKb$93Q zdm~Z*O8w*yTbOPdJJgjKW}twVn-|{qcE316Lf5OSNW<|CT)5piM-!PUtoS}!@P*0L}o ztNDC?G)4_!>ilVm=b8o5Yaa!{OvihX5p$XNVH-CN#jN;WqTQod|FZS_WQ8duvF+cS0Y6*HdYI;o1aeINt> zOq-qK9|6a7LG_*S$P>#pQ?%FGE3i+W3OVC5(e1|Vu`udCgzMe|tG6Weg=&{2WFB&*c8zza;gi4BucSgv)Um0U8P6$iW3+WyBV0vS5f8kQcY0WQ$dhiS5e!2 zo6DVzd}oLaGKuFj_t##4fF1JsDT@9Ad6o!N-7|FP;24qad=$f$-FW!TU&~|aE|0KF zoCzZ8E-35iiBw@I*f&oTXFI*yd}jwK8KKYoaUWP%-7LiGC{nQ64foehef54M3k~Jd zvd?cuRH6Hj3+mNKD=zOsjY`dIiCp!dXh7TYzZ4YD-&`w-D=g&op9~18d=yOvdSMs< zXg z>Y>EfTEWe-5s7}GgQ{K^*Snbkh#7e#DWQSHM>?Ge1j(UMk)mem&%33Ns1%<0pT_O# z-TL8~9q%o>PmsDVRBRs{Ly`@b;fN@8bW&p|-Qs_`vx=fKX&?T`MEuoAm(zYb+BZVM zSqZhirD3q~B>7^*>3)+S5;H4h=%(ip+UFH-E%uaPYB^EB7;ac;l^gZ4c>=id#sV=UYRI zQfIFnO_$A0V-u2Aa0ztm8rPSBmpBltr=TiFUdqxCLr~E0^o<=*j8yWLuQ?X75;FL{?wKy z{Uw_eo)!=jSy8b`6OC`%GmWzOaSC?>2ajc7C1L`8(X4bt;?sjR=Za8phlTxt~>4$*3!Tit4Ac#K2ss7{dy<``8A&B{YGjG3aa1 zJk}jX?*A%KG2;Z%Y{+)!1R7JDfs9)ly`R^-d`Zdu5|K?YHZ(LnFx`}#$O;_qm%)2h zud-W95j~7k(^T)FTi4dT5`~6MLR4lk5c*bDHzndYRTwqFLn+?>s@sEq_WCY|lr7bk z#JT}fXxkdP=jmY0)<)GZjW}Fv5|W6dB>G-j)2wr)HehQo@O8a#Gi=J-X1@4O|6Iuu zHY(M+sJSGwNV#vhAg73-Od9HH^gpETPd|7rQPyF6Q%y!uC9Dzbw4FE;kd4{r@vSse zY$*i|biH!_<;6|v)L1O8RcSLyP`}4<=5pV5$gxD(@pSf->qWMQLcA3j#y@%iW`BVM zXl3qB4@0;i9#Kxo$jNGfSN4o{6$8HN$IX&JmD4JiDSywZ(-X)MOim8L?j?)(s6T!H zOwMW7tG9-X@W)Q{n%FPo`k(tW0Yx>AHls|-P@U2_XUi(cq0^m&jY*6yeG;@dSfLwZ zv7y#})%8>Dwfo5Bc`v?1Inc{({42orliTWo#*PV7OuT`)J(nhax@j%{g8kvivn!X$1T+SLC-HfC1TUfaz!z!zSwR{^a2Z2 zD$G3xX+5sFI9rP=Lduy0oZAi(5(!;TKL31(7yD&bPDs>CmdjFiOlnmNtWW`bxlqX0 ztnxgvcX{S;nbNYu+rVk@U=ztpVQp3^_WsZvDbz4HFd#5+YMyjk%(K! zqPGUb@Vuq|mg(md-sfJM4#vW`IRF)ra<;=_R7|2+f=Qz%;ZCsLew3R3<@g6IDOKys zhU-54n@h395U^eRceINzhTn%QmDhertB-X4A?CA7pK=rj?+wuUotJxk08}+-Cy}%= z+h?_aE2NhaM&7@JwamyIJzFLpt2=ZF$t3uB$g-GWa|}s;KV4zP5D*`aNx5R`yPv!? zV=<~46*m*CL&rk6LqqK`3TtiqfLgTv*v5QP5<3na-3N(x?@)0E-oXb<_czPJ=j%*1 zwYED&lvxJHkl0){GV8Q0hd4wbhSI4NfwF#NyT&NUplb?zGqZI=4m;+Ac*ff+;kTLL zPRm&NB7Xx{c&znCAdbwQ=is;hT!yoj1Un3R(q+kQx<3@*@+?^c+pwTCq-8D#y`PrF zz`j|K+kGe>kyxX>KdZnz?~Dz8mJ8<26Bb$&JFw?i?zE@bfif1{`A2*kxq0AG`c_HO zD@=WpsO@{AUT!AFom;F;{S01AjMm?dgb&PP>V6$%IR_~_mU?gu93Sm>i6MbMz9jul z?2a4z`&cQx1gkDO36pV2bd+`NE$A_dBiSEc{Zwdy&E0jxvWVz^tMKy&tg$pncWV!P zfU`1eV0JSJ8uq(9T-_nsMxa~KL|n0B?+!AHM+%dDADK9ujj27%hDMaLFY7jn(vuZ= z3-sbkRx0XE5yc|)ST=B6&Yv#Wb?+tT>3Al805ttkuW(ATOWJ3i-9_J!Um!K7z!r5l(^~MQcZApy1ktMoHnv!_gO>%M5?Lhf@Les{g zE6unhxPe|S|MLd@gH1Mng4!Bma>yPayQ0(p>`q7btctIWzaaj_bp$bBRUOAq(#2aM zl2gYnVcqb|>k8gvU0()w%e0n4ytv863$hmj$Tqvhp?Xk;wnm^&UfpX>f#qcf_U4;? z98Xkr1gUG9ZTY=#?{NpWX83oPaY4(wfb~6M-$eeS0yhU!##V92>VF(&=QNuWUS7n? zE<@NSI@GN5H#qWATF@fb7i+~wNhYzs{?G=b5l1NvLqJA(UZ&-#O+h6??3-f|WjiCVaO!kz(Q7o0%LVYhbmj0jc`ap@f6?lu zFFc5uxb{n6Jy*&DD5EQMLnBHbUz}QGI)T}pB4Asa5A{BkuXMsCTgDwls)};SW@C)R ziRlNh%9ayd8HBkhRdGXU>R7l|JR)co*|DiEj~#r!M5jjVjlv3A929xmlWv#{CrA@rzuuY2FARP`$$YV?{f+bz?lzb!1e|B^nL}=^sxFH7m^Iue#G} zX#<0UXxLv7+n+)s9(mDUTl0e}D%tH@xe*(Na2KX5VxAJT1_lNnMSKY|1GlvTSDS(4 z>H&jakb4K{^d_e<_!}Op_AymQKZqAH0sO?MLPL=Uk_KIw#)PvVX!Fg$*_$221X&qT zbt6uL%?&o2NmWR=i-&M*^+-<63cwGk%LJO&rXmAjv-`Cchx!l@mHxwCjEAC_!~Mny|nS)u39 z(6D)FM2}-%A9XQ|%7lqs&C$* zpB_=1ilKQ%tl2Pkvv)_u7dsI3ba-o>$hq-r>TVir0v74I{$r&*i>VuBhczlW@~a2G z&`5(n`8T2V)#T7C&*e*I^@u0?D~ChDdt;fJA4p1F{rV3o{~nP;@R>q4H-@Z^^F8_w z378#6@X#`1Ha(OHn)rDF9*&J)Qp10YPCa7@VM{>9UbTu4n`}pVRw00+f%pfIn7@sR z5OXx5$7NS7u|23W*+Iufi^IdlBlAnDC2-YWQ=1MOtp8ui5iDe(V0XnO>Kz7;S%A5% zB>EeFK4T&LgTB1pABU$A@4-+YJ6Dhb;eH`gaW4l3?CPbqG*QLWIt3#aQ+O6T2@$Z+9!~ z`y1$8Mf)HBvJ5q?7feE#dXO=rT1n{@s!Vn+^i`C{Z%sn^#`;PhDG$;F*Po>X_xYQb zurdnu|I65JRcOoD@9f%7=l9vm8z{?KKEUp~=0IBrZw z(Sa(Tcyz*cYxOz-@uoy~;IQ3aPu{1Lekq{!@Omzx1rDL*f^vLOy3Qukevn}$s!Xea zrr-onJ&E*Sg$xHzR6V^)2F_@obr)gmgwqgdt#Q2$btD>vtCdk=cqK6MaAAYc?mcT! zZ++?H;kA66;`I0tHqa#fwq)$4`2*XbxY5`sIi-|)wAe$kmz|?x+lt2~yXs3sw4EV7 z7kEEnQ+n9^BZ;Adw{v`M-L?iV>VuJrf!o}~Trb|+QPIf=**;u(-_*g+>=6v+Dc%AWE=_`wa9$)dAvLn7!f zym+>4_1|vH9ZNz-5oJ6>Ao~175wzc@hK0K0a-JOgzG>5=bby48xhyC>j_yEcVEtD# z3Y6%9wEF<=5F~^9ptkg>4SOmcl#7fiUQLzIxu3c2r2-hU7jn3*bYUf(E67A}@EVan z0Y6W1Jk-WS-@c`nLPDZ)m8HHAQn_cd^l%}0Kef3=@jOybgBD2Mm|d4qCzhdpJ{IGD z$&Kh?&{dbH@G9QSy0q_CQ5fp;rK0?4B zZPf&QJc-SJvb%b?txIZMRtFCYV=r2JdEkxY({|6!65>)YY?YKptjHS-8&#ISdy$d3 z9Q|z$IWQdI_=kQm+e#}UOlYveQ`-Lg zJu*hxXp-rZ>k88xp*9?6)vem>14nIX75j557PtW&wfPd&vB1n4n!8*BY(m124MMp# zeoT{?&pcN|;K{{9$WqAdtIuDs`4GGOlmh9-y7LH^ZzV=|cM799u;n0JNg3F|oolQT zQgl=e?7FtTdlj2Yd+z9DJ};qq^f)^!y~h~Q&W%?(HFs*zEsXPRv3H_0`~LdMh#8mK zkj>i@wl$4(ee0E&fh69;%o62X8H#f-Q#y@9FQo#5Qt)a_wLL=70rmDJR_+=ARPG?e63_ggOt}CeG7Q~KjC*o~j))xhj0L1dypHXU(Oo)Tnh$U5Yb7c%g zCl}N)=w|gG0GXnX8>!d&p`Y&4^@PG>Y_Sh^!Yz+gd<2hnda14aKrxadsmgYr(Ii{? z`GvVxgK~3`R-7`V2stPB>7%%m$VU0Tjxiq^K4`^SOJJg4b<7Li6Ibi1chH$N?%T3lV>Ie4OiiV9*_ zRiBB&yg4|fcFsI!YGBCJ@NzOU=cP3pxkx~=bG*QT5YbK!P{UBaxMY8Z_|6Ft`N`W0 zd*F)^U%t31AS^!idor(!d#?+VG{VzDMIjzq6Xnt?MaECz2eR6_5JraLqGARqDs
X~^r~4*I8E1_!_{DtQRn}f-i0QnY<1YzU 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 literal 0 HcmV?d00001 diff --git a/doc/articles/openshift_and_gitlab/img/gitlab-logs.png b/doc/articles/openshift_and_gitlab/img/gitlab-logs.png new file mode 100644 index 0000000000000000000000000000000000000000..1e24080c7dff9eb921adcbb2d95c46eb27dff8e0 GIT binary patch literal 70858 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 Be60Wg literal 0 HcmV?d00001 diff --git a/doc/articles/openshift_and_gitlab/img/gitlab-overview.png b/doc/articles/openshift_and_gitlab/img/gitlab-overview.png new file mode 100644 index 0000000000000000000000000000000000000000..3c5df0ea1019200ecc32acd3677e27bec3e40333 GIT binary patch literal 106432 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 l#-IAtgBGv5gvEM=WX literal 0 HcmV?d00001 diff --git a/doc/articles/openshift_and_gitlab/img/gitlab-running.png b/doc/articles/openshift_and_gitlab/img/gitlab-running.png new file mode 100644 index 0000000000000000000000000000000000000000..c7db691cb301364b6d25a97189f7c7b3d6ba1630 GIT binary patch literal 107993 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

AWEp7zUB%^Z1E;LvL+w@6ZvtB;})byN0 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�U=InTc7ON*OMv+V_|Utvh{jC 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⪼J&CIYNleTe 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

$7`76%$$gqDpv?aO`YSN*lexrr{{~GUPfPX zT1rX2Ox~>%B>S*z!?EX+km!W8c5*lQ+C~7u*rZN!OivKidLJQAo^8~ICra}sqlJ-bpY}P2M0VG@qfjgGKsgOdl0_B1J31Z zt6F-SG-{(?qjYMCgBfBtiN!`4Eqbum18c6Ut>$2)UXn#~A_ude7mrlo^i{3iOBdGN zln zXut#=*1qfMcu(V>Y|e3%lGLAj_Db2hZeWrUx*0GO@*aRmuqC8<(CNEzUpPfa63P5Q zXeU01D8vlB8(!yT*zATubhj_8pKb@-U}Ws5w4~~-%pR|OXChA(c_kiY5Gh>B6o*&} z?`HkkBgjgXsYe^Z*LDIcoQzpZ)zPiD2-2=exBDPxh!qGT2b*ikI{g2r8^+~Y|qII$m|Hon2c5- zoYkoH>difpD6TVNR>JsJT{(v{Tzk;(ux9TPd8&=ZaCTXj{3Kj9t!+PgZ{tU_HF={k z`?05#Z6&4uX{F|1pmNrnh#!(Ggn%#zPF;5yy|=#BD5fl-Zjn+}F+;O;X-jU(U;HNi z3NW{<{NFNERhSi%F*Zd#(nvAm7-cXWR>m0YDO(DQx-!wqL-B9(cvZe8k!WTHU*L}= zwkC?Y(jI3k=vUiXI8zp#rPz53&}cU}QDGB(8N4Qzmv!NY^wMYU%*I7eG8TkLJHCh{7# zE=!d1OBdXW&gdXf;~Jt0iEy9uqB_CL#JVWAx0!Mi!3D(!_=6gBuWY{5!{`3&xEQGu zgIj>d{I}-#6x0FTCUTGC7glQ<;P|O^(Z#)++35e^$>sTz|FRQ5^4$0SEC77~?R*Z1 z5oBuzDvcp_Cw4&5txo}%9%%pQuv6;z|ExAN<$q%L_7F$h_8Ug!e=LCIF{OX)?2*vF zbY{B#g56nC`?G)U47fgn1EodvIWwMbtm2PlLj@>Q?;N=mV2|z{`xt)U_qf=BQ(J*E zb=VyXe8NB_0y?*`fkEc{ycYmpdTSaOSOd!98k?8^UoL^_M;3>cjHcFrrZo=KWIBvz z?H?M}zpHUy9Lw8WDvLnrayCLnQPIVcnHiVN$sByGxn;!h*fa@@h5QP zg}&4F(Yb(#IIHT2I7D=-2nO$Jr%JC!URhy-Q8fd7>*o8(g(J5h*vzopZ2sp>efQUS zcBFe>;K}C=dX7ABLRc(-qXXJgNX`FCQJ!qp``-kD{{KttI5&h}e#`a1SNS@ysiAR8 L_a^$f-IIR5fKGI^|c-m(LYK= zL^m|=+$Pklc@B9Ke%-cKS9wizb^VpuR1im~x$CKF;zLA4_VD`W22o1dV?rf~FF;d? zWbrmFnY7qfqutL$L{EtTuU{DiOmENm2T+gQ{QbwHIuCf~*^)V%)V{?j z8Y(RN(}bPdB@XT+jh3Jo3~K(2mCx*m-6q<%pu*A;5m7(nNFk6!_yn*j-2YoxOt?eX z8Q~KKWTC$Cw`B2I=byiY0QUc9o%qCFbxD4A;B}KqdlomvlFDllX|!9n=+-x`YEGM8 z0zWA*-qe zUK)o_S!$}K-u;itcBZUPNo5`B1}3Q{Gv(?C72o$-$`?E{%^==!cBI+6d>#*Qmrc3a z-I+>jhw|QW)j1swP5CEUKwnqZgo--5@-tqW0aLdZ?!YPOXmCP{iU6J3bffN+;U>4( za1KWn+O)}Cl!Ee_Hm>SBN{t!@>7FRi&R25oVx#c<0j%iy%Y9VwZN$t`&#nPL??`-t z+i`&0E=^h|gcmvf*)0Xi<^X77pzjvpe5J`KbBtMwZ^UZO_;IuIs~4T-4^3Xr9A+J@ z^NZ{(5tW}GZOs-3_}oCl^8+0_#l!9)3kgd9L_Zy{aRe6OtYIt6YEdfMu3OD>0Sx_d zHXUaLl;=&Yfa((^7{96C`pd!+)%PqGtxPrgMdQC|jd#6*w62y;(hLK}yTbt&lJ27d z4ZI$@|DNv>8~yFRsP=SKAS!1eHqx2gnU>cKkzMT3}XFp6L`0~rSG#F(o$Fm zs>JlMx7nVa`kG*!ZDGBCU~C2WuyJBBT?~gnpau=yfqLc7)mSM>2_O62VYM0Y`jbsQ zsWkVxaw_M(-?FA#3mW_>_C4sXWJj=yJ(AL()~N5+aHZAGZM%9p^_$nza%B)W+&aNa zY9YPcEtk(sxo+tfuWjE=F*&az5b2;u<3$^~* z;9sAu5IbCD>a-Z$x60Z;qkW;);-;NTBKWMOFvZzGO05VekS~0_mRamuUQ3kKJ1ma` z$5ZGlgG%IhVIIv+J-VbVRs3>9u+r6|`%#(prJc)G{fQ>EInT@fC|kFM?*KGmRt}9qLtTNzo7_o$B9H}wTZ<6!- zuE3`}U!I7XLCoh41^M(plg10yv+T<0SFKXekD{#HpTgRNdYz}6;6dj4pDh}DZ`y=! zVG1@as&}rpxmZey95oRn-{E6!%MIo2cYHm9KiC9OV1jf&d9oCYvz1 z<=km!bU9r(B|lREr+fy2En(=^Ky$YCe1OG({6*z_@Re-S`O&|Ir|Kix%rQeMkujY@ z#hdufxkK@YJ;~llu7#iSTd4cUHGQ1G?Lb@CmZeZi!;l#3ij>pGnHfOfi#?=a2|DZ5 zgm}Fz;#*Cp+H?U*Mk{0YrheFMa7>mJ(W0e6S%;&nG3Pc+PT9C==}}@-h>gzYX=b9< zRa&OtBehOCdIlrc zQ~s?dr$0P59`w;%P$BUvJ5KFbW9~$sh{qh3RZVp*ra-c$MYn7Q-%%lX%TO%ddrDS= z0q38~d}&w;4aJ@=9;UC@NPBu&svl7h;XY8ku5fp$QyzB#0b=mJ&61NXChi+4a(&`9 z`UlC1n{&W?T%0nm-^DGWS{(g?sUob>VH2q4vz~h=nz!B;7tr{i29NYFaMy9{YYu`0 zh@QWf(2IPUnwXorh4G-;sJb*XxERL{hks~yZ^5a7N2-3vDJ3pU=cHNSPJVKjMelk> z)~h7PCnlg;Kb248=4eeJvjTuaenV~l`C;ReQ4J~CaF{wFKrBoe#u^>J8h0Nx%10!YiV=~h;{)l>_D(9Tf}PMgVhTS@tOJDnVGS#Z5jOV zRz0L4s&N(|QwaegwJy)2=7j+9h`!A>*= zG4NfUqui!BuTZ| zEq_brlkkVW)I@2|a=qoH3UIl5n=i6yUR6}`jl}}j7=~V+&iYk}=!>izK31Dex%#ye zvRWX9p4U&$cINSJ-SM8La$J&Bw>sW5F@S10SX#+=?qe@1w5GF}!YX;~3Dv2Dl%+2i*I_ zp7H>mEI-OUr}(8kW~1mVZNFW3pQ{MycE8?*@-!I+&eZ_VR*vZmu73^s?9N1`a)p`zQD zdUa;J$2%s7^-djg>oQE%4K7E2@$QSmT4VCrd&4mwk1yjH!OVk+8tZg|Zz<`=@Lzv7 ziBWyMu4bO3^QO*8yMN5ucC{Erw>h*#m}mMVlkj^sbt9gL0iT z=A&Ow3S7Pp_K{alqYL&{cnF$O*gB?&8EeXs-r6d&Ii7iQ)F`-yhd<7XXpkSNFRif{ z#(UfE4#j!!jf1Fa_;qMn?BC9t_#D37@^*kTsV@3)IK7i{*!;)k-%!K(7orQNzuJ1% z)W)D|;mYJG%>ONo3CN$ywL|7r2?stEy&hw~M$7_>hd3tuhTj>6{tOlDw&Am^loq@f zn_K+L9BZppjveiW-Zjt}lMdRQgJW*q2dK$30!rm%%q8)qwCTi|`&7K}$I&6@!ebO= zkC>Rq12m|7BY1Q#T*-<{zXa!V&F$#=VeR{xkTEwk^JmMIk@W{1jjgQf@7;gX&15v- zW@Bbl%RmLI#56GK(+*lv^i=WSF(Z1bYHBjjO-SmUc& z3)5f)`<4i`g^Cwf!A;AbazCX#tjEN|Bd1DX!+wIi`+)L}hvpkt0hN$9b{~DEGrjE@ zaWlst9I})1x!Suu=aib>?{sR(9CWO zjB>*h%TrW7?t{8&h=QrhYgeSQR(c|BE;(XB^0We9i(|nbLLnd)?-rBGU;)Dh+9Dk` zudSO+72r1-<9b1BLk(9(j1T4UQ9btk<(qNDL0eg%DqMS)bbJaXTqn!Qe-75HqZn5% z&~5W;)D5xgmQtvfoF>%s^%+Pf&`Rmb4GW5O(nrGSb59b3p;Z+4e>+Bl;p$_o z?`HE&yXw|kq{R=o_?M0e>~-vd1%R8f8m&nxNGo*6M zl9SWcxE%MkIg`pcEnhcIz>=WJLw1%u5P!1s^>7x3W)o~ubjwj1oEx9+=7?(SB71Ux8;a6h@An{xKyl{+f%z@<|n!D?y3Nc&k z&_4C*p^i=we(BLHuAJ(}1gr+BO*U9i$%}4f+lE%T2dT0mpNwxk?ARK~DfplnGnSK`($PIt^Bn%@U0^cv{KP@U z<>DVzP*Jov+#nF11QzNsT)8A7Y8?4NXUV-&-$89wmV}i&Q+(L}ZI30_)hU7dVJ4Bb zXS17{_(snBqnoRKd0QB|kAfRySeK-8dj}4mFjK#s5-k*{d%-tIBFZmEna8(X1b>L( z+j$XqDKApMoRS-NdOR}M7iT-*$G!Xuj@`AjpHHfeSuiP;AvpyGndYatbA#6nb_PiK zXhMU_X7CZDN@gZr(@nvpY+c))YAn=s_rkef;yoxwLQmxo%e3di)NLz8oE}KTAN;&t zIWKgs*)EhcEf)J;h35Fs=oYjB(%GBeMr5WVB$C;5bh50SQ2X*VtfZyQ5-w-pxrA<7 zfaZ~qOpG?xNNl77$DKR(U#V&LNtpoVFB49t-yLe%_nSZxmGn~>c$fOqTkeijg?@hd`HxX}caG3N;oL}TRu5|SD*Fm9qmtF${ zqvr2O)RHOdX5H)3r?7ULH4y`TF0&g5`hbC_-2D0?$*a$Wfy?>KJm2NrZ~7DMOZWH6 z202ap$wJln!Od6P>`fQt5L2ibtkUI=LLcd=zWvYn#$#3n-;s@r8Fg5-RlX>#WA zf>D;23dJTg2N_O-V{$zp1CIDj6nSm=Vev^G;#OD@yR_w7gF9Lizx?I9TReBsby6Z< zN`^?7OS>$au>tcj1@2|R-Teow7`(gow;bAsq$R;8eoX%1%8eB}mTo{Y!6ewg66jS` z$QPcuo??ro=%JP&5OzeKK(Ii{z_>AZ|Xd@TIz= zyRF2xSzTDkcb?k|#$KGYe=7SRFrc-N8@$kcE`{%84#K3%AC`V!^8N1Fd??BYI!RE5 z$J*46oNUCMo|;X@iJKhH)WjWw?zb1Xqf$NOFBR}pP7Oz0Bn=UK7ia0_>vPORVgA#Y zEfBW;@bR&mnR3mS$2mbg4o=wZg(|zXnC{PtCem6E1Kb%Qw&PwFegP>mhpvW#xg$ats zECaB&aeM6U(>d$R8(BkpSH;V9ZTYu)#wKjEYbJg>?Z+crjjn@^C{)ElhH!1 zAssgL1^TNkCnlz4$;#2fTUj0Qx)G7`FW_WZs&^f#l{R9_+N!Wc6X2~#k_7PPBlmBQ z46Cx3AZx_!R1MlLBcvA9Oa0P?1)Q#ftfkGl#l8(9aW!Z(Eyp9{Jxqt?(BK8hW?P2Q z6r+HYsJ8R?1hb=pf3(N2 zO>%M$wQk3+P7xlqm+CTU$p=Ar)Im9Ig`>yBI0bTM-+5{$3Hr_d+&$+wb74Kmar%uy z&z9U#eh^;Tbihq}X^e;nxDhP7VM)~b0Wwv|#m4vg*&9f=hPtk`bwpZwz%F;&zM=8A zg@yTfJ8eVn@HmM4M{6m)U(3~7Ig%Fg>(VlE!InAb7R+JHL6S{OPUqp_5M(-OBQxt7 zR*4T`Du6xI;*t788d%TN@ZiCn6+!lgnmXl-Sa37Xyx&LX_-=W{vaTnYEI^i4_pYmm(%$qq{4M-{fav~zhYkPFnM7D}dV(J;Ej!-*OXQ+q)EY`A&@o)y zWd^<#A0Uzu{e`z5|3TGU_TTjX-vQJAbMgOei2Hwgrk+O_4T`w8 z?-Z%;-Fuo^o{*A}l^btRC+o}dciU%M5uscU3{H5&U365&kOq3SEmD@rqO5=h|GlB# zV3#V4v2@daoD(oEqfpXVds?+IY>0AJ=@KFbz<7DJB>U{AZJntcjV~p~3>*Jlyi|uz@qPs=D(IvIFxKXJ zp2)d_GY3(&t4B;Up3!VFGCl=}kRue**XW;^E5~v4>ZG+P4bWs8Y(LfvL3qWkhId^> zOvbz?MA(%V(4Yo)Zs|wY^X}I?BEUC7=bQDACIfaMMIT677Mpr*$=Y zf|W~U9hLa04O{8f8h)D`8E^YVXQG7P7u2GK{dd-ND%mxcs6yPpt~2!I2pdoi_ zL;HI2R(btx0@T@TC^$xOs(bjQ&a}y<#m~(IVRGOHfVJ181)VZy{;2T>zIIQGYqTjb za$6`(2N}7n#rmFyPYk-DtT(0}bnj@4ctpkw{e6JKpv8pPMtG`wW9|2SSZ>&18EFlp zenehn%6sezXdody`*Z=X2i|4McH#YntQ-(#PgX;C?QX<&{+=k>KGddO{}&S5VxuuJ zt`@Sy&@{w>>;!))4N;JkbsK|84XpBGYIjVZuRheogR`m`KgG4}>z_Lx`{GgW#!7wW zZi1s67xdDbQ%kGS498s#`jxh09E`Hbd~w>DJmapJ8F=N5M59NC-pb~dxN5Vq8%6-V&G}Vqz$`UCs6xq$GtTaWOcybsnopmayE9!0`*GGsn5O zGV`m`<!5>;j$P^Vv&#ONgjQJN}Ig_8EMoUu3k#(gV`Q8QSm?_iP6zFqJ&aKW&*W zqB$Mq`aa*hH*cU5eIJ>~pe7|s@LlP=u-1Q|q!eYi?#eNnD#c?oiOi^r@4FDYJo*S*BBR zn#zyA5}dpEGJDzx9d~VH3Vm)>Gu=ER;L+7Z!Q6ePgnoI5{qg2|IoizWr8>}bqd!-@EpfZBKrZ0@;QIXEC-Nc_;V@8Yco)z+v zLVAbLu6Z$+2*`ZA&wA|pzK^-2;+SsNH^+w00zOjOVGAKmI)Sq$N4qAya`$;Gn{mV_ z22*?sa?>?ufGXeF^E|V06|K@d>a9Y|Urd)+vpt!eQw}#SrDTK%l*?)R)tkLJCgr0l zeG>4+!3x&?wfyquPJ+7llPoXo$)lBbl1|R9oX5N1occ;PE@<43|BhBW3yeRo1XrXX zLDglu%tJ53W1+TTJ@-p3CDNN8x!~YF)Du}L-P7LVqBCk+C(jgD6Ky5Pr9`TS8?N44 zjkHO|PmFk!j4Vo;uJc=*j*BI1NtiY}yeB_d_WLj%U}o7gzcOo>f+OR@h+5*lXZyui zrHro{@#CCQ@?)SzrC)?c>(){90sbC_cfJqSTr-XcKrjPSo=?reF5xtHUb6x0EziG^ zPx+`&JmzqDBRCpvwK1CLbWt}g`uQ4Vfx8?aZg6ejcj?&|#+-h96G`yq0#JkIi2icR;Bmq`wAuBtttKN%xSl1* zjE-&c)RSD9dNG4SxF*e&koZU{rrXadJR<``z%$X?jSr(l8J3# zay?4S^{grAsQGeJr_?ugE3bop0!dBM6nuXcyMQ%4#_|D%-%0|JyZD+%+evHwoo)-L z(;9Y*#Pt;$k(GX5{OV51tg!0Iue$D&!P4sm!mRzyquBVb)>)e~0a>a+$KX1h_SmIx&-kw81nr^%7H{BY|_u~IRjP1-w z%vB7ocJ9JW9nu{(hAR`}mhp~33uE*bXCv6WHjuL=r)hsLb)M-@>W7QENpfvtC=k$G zzXjPH&t0S=ulV`kW97-I3HB_~q&{%_^vRuTW)L(6U!Zcfea^ z=su!+mI(l}I@F(dMOD;*r|5hB6=LGI*;dnB;P7`qtCaa@j{}whi5z+e86bPj*0tO} zx;-#&P-Ml(4!G5EBDhb@#5AK1v!y7^eWSQHnqD)9eB)0wq#3QYjuQ7Z@DZ=gD&3_E z_!v&^=-VIU4$ah`AI{!vTtk$RiloouPjVJ?Vmucb7hL8rjoEHy=6{{*mjLjPa>Tb# z9%TP#sq>q$`m?)YeMgmgVQ9|2v_}Z{KXNI_U)ceqTr-N}XmvI~6LW(h=67@cEfWEN zUJa)*w>{=DW50KgWMf0g^ht``d@Ktf!g(yKGpOIdAYBF$F`{XQ7rRug*GRkvmO9Vr zoy$4G0E5{9C?3~QPD)9Y|FnsHREdGq>VTU!*i1Qg_48eKC1XwLla7C?cFd(b0(Y9r zu)d*hi*Hno;Ua?Dj~718{dwFMNyk&crN{ryZQATa8U=5AjrzM}ye%z1wU^z_#M&^ct+)jDMKP}OfLjnZja{gv}ggw~K?q|b}(Ow*Dz>DmJwFE^qB*679?-Lv4 zI6lKuQFAkp8CC%CvpeCxZbJSK%`vnHZ1ol~`tE?4IxKUsoFKU9l$F&!7 zcYu-xn8Aevi_TfDzZ=P1sV%Ho(VRYfH(yaX^gVdjsCtCG>ubC7aQOM2(?OP~d&ia+ z`ht;Pto1TsEu#$o3%G_{F!xtYp7O4n^LCIC$9!b=Woh_yS39y$h1S?%?X%@0{E=#t z)RJ#zxhGh5&W(8>_P;0Su7jB4c*L{&Nt0_}-WAX1j{m7j#Qlewe`z6Vyr1=7)xO&M z|Kh1u-un^%wUxf+`fC7)8etzeYF|(?%W1IwZPAIk7h%RBEG#VcUwiwVq=EnIkO%*F z=KcStlWi8ke6go@EOQTCI6S_cPEH80{QGl?jfy_n*B(8gB#9;>N*Y2u&CMlY31r@= z`*G(6VL-N`1o;_Cb!?XFuYiVBn!%9dX zW2b-hqwct+8X=KySG4@=JP2ihxc2hqfjztMHIQU2PTv%V;TNMP3`F+DqS+Q=*b?97cm+( z_-QtUv=I@D2OHSP{2mk{Brm^1@KR;G}FCzk|ny_=m~i&IBk4Nr^g3LVEuk*6v`JFrP)> z;EySOp%>i0t27rhW=d!FHUu2j-0eU)kF2}8hABPfv%X1>33mHDZ`g(E#f%tPyjkNt z{X*sxti_dSrb(%>Xx-HDNLX)W`A=J=kW|rNIf?w4jvJ^(&mN^y%H*`9YJz~Uu5V(2 zYX}HY0YTj|SN@Qbc-y-t{n5AZKiMY;qZ4lw!LU`K|G4bE;f$4KP6yiAY8 zJSl(R-$P@TGdYU!kgns@v~qj@94+@Gpv8=kDa0Vl!-em>*bL~n&u=M|_>N$*;~&3g(XpSsG4+;ATk?xwa?Wv{ zG(s;vzMLQMYV2nM#4+7|z>>E{+;}8^NB`ft@y*%d$`vn146}M=phshxz{j^Xn+Q-t zxQKcL=qy@d+^Jwt6Y4mV6_BtutFn`g!!U8$fnYe^$tus^+7a3S!~CB7ApQoVZr)RN zSKKSn6Y*h2NrM-RPh8JTDwdI3)dJ_YzQ(%&NRdn&0B<|SiMQ}I?n+&tIO>7L3PxQ{ z1wR3tL7d`&c;61lC91E-@+Bb@&A z#VYi&!~i94ZPa#nnN&45Oxc3+A5Z@ZUGaCG!v+VYajW@MuZIyH)b}i0Ca{_Up6{l{ zS#~5b_DGH8)-?F?c7*GL!m!0~M`3$`{q`}UHG8}W6K|nvYzKwb401VQLkUp)ocx4nfOj$Y@KUFd6xyVmiOwHX9 zE(`NkAgjUT+Lvk?eVi$JWU6hT50!$QIIWcy88+Eyk3}5GtYcifzF<+@7b|`R>kv^d zXY>*)a?N3=%r%K1l)P;duHfWE8!)`jK+nr3^m44U&H`3> zs#-6i)jznI%O_4h4ixWB7&in@JHFHi^BXWVUGdrHA5j*R9W{!BL$xAL^1603hR(`z zDjSwG>BnluKkT%%zj*ciJ;J&@;`}l}5EyZbV0+`aqNoo}1j%;!cFG!jds-W)L&jHf z`+Lp3jkBqpg}ajLL_JsxYFM=Z8AJ*4He!lPzX`}aVlQ7ywkb5xpe(91Ejf7QyK<3{ z=bxna&qe)tXC5FnFAJztl9s<|B>qeMjl7FG`*EsDgGf5E1aIp5R3~)iHMOaBqN{18 zYx;IIJrAv8Q|7uu`5CoIOVf?WhOYy@GQ@b;$h!ky);UsYWPUr0B$Z>NKl^6)csxxV z&DOQw6=(?tOrbB>07VuMHUIVI&N<447Z8;J6R2Zfe-Qc^`k>6FlKXd-O@jNd4<3Xo zdW9Y$W=6-ccZlH-4hG#n7YJ$dL|J##?m4VUbQzVre9ChDf;i;h@009uo|Z7dVPfpR zGgt7Ik44uvdwaeK8jjh9@z-uNAZ*!p6Q^hr2o7q7<{|G0+ukYt4~ZQOug)^-WF&Z- zomv0S@!9)v{nCuF%#}CwR1Mh@s@8Gfq%Bn~nnKdobxh1zyh{Q~<&J0Q}l*`KKKN^1nFnSY-4$0xt zN}`omTH3ZFo{%EA<&zJ(mSfvnvU8*B{eH1xwb3IizEflDb~Ii+xJ zXamyu>5XN8&64dtJ5eJ07-F4Mqn5ND(5S6DS_ zP#LIM6?K=ZJmc$hg01jHkxkFxw1_{#8{RJkU#Q!ZOjca=lBx8ygGrmkiN0+sErt_L zgeUy;-Npu*-gA9dBTTa0-SE%)ulXv|fJw`A?~fC->FnRZ{`fc2?LlvXs%hlm>XG~qlaX!p1(vA2+;5()rT6-VIO4sx?2n2>MJ zB}J||1^4$G$F)7H>}3CLKXp^;$rtEq*?NC^QMKDlw{w-nkXt}VpD(|fOX0j5k45b9 zEiO|(ziJwO(_F1|Y4brWX01=Z;|n7hzl=D#uxC~8x>3-gn9w0WNk#xvt$_m75PatZ zf(LE&SR^XDBc(SG9JY(!I1T9uQDE4tsIx>U)t0iw>^hsNxM;jN6s7ZK<0zcp!iZ<7 z5L22Gq-yPXP9D)znUg9W9H}%{it-mfZ(|@$bF0u^8 zo?LtHCEui!^lUCRJU@u&%~$#e5W8O}ullu*M6$<2rzAETJMe{w$xTPG>kXR;XLUB)yT!Zr$=89L&x8|Z zj`^GJ5RRa9JTub(KYpBhSTWuEwe#}^(aSEM_V+Biycg(OM3?MQ*B5JE>i)0O%Wwk! z)WnppBhySSpaz%Tnrh<-@Kb!$EE!x@;CydJl`2EU(Xo&quGfSRX#D5Tp8^4MUl?U9 z27|(_xSl^Z<^`4AoQq9r~Obn$r&%`AQhflQ8CPe#s1qyHUZ~Q>$vapB32QCRA zKp2KMG3!&0kS)NhLi1*;4+nJwlIp{!!BVlQq^WlX;?hC+ zKJky582|QoX%#Ux=irQ&Q}1AD(-z!+{;1sP9UG#1*b>afaTrx)PC6^64WpLW10^7U z>bs&G3pI=&jXlB!2?P<&Q5pu~4Q4}c|NV36qtyTI?JzPz%7fc%ZR|CmaP2*nm6g%v zF%d$1ogyQC`oF-A4vXtt{c-jfxJxni3tU@gN4#YnXZ?-(-ji%|%y0CJVF$Xa=hyPV z;D6vw+A8cL3zO7QKM6d|;$LI2{Wkwcb(eCCJ$@sEP@M2twDdX`gdaSwa&1zn!t+Zf zZV%e*RgYxbjg4^(^ToKNTZH=8xjqvY4{>y;)87$sg&b;57bbNG#)I@4B;|+eKkgaA zcpZ+~z~i`r>Wht!YJuy|s_OjE*YLM)v>A zt*B`vNoB@AFwz)I>REdJ;4d}%B1y8;!WW5#G4;Vmen>^wiY1oDaN#W8Vk+%hP5*Zw z)_D`31MZ9!g|X$2dCD$$HDsjuzfR?3)V=yf)a3J2lf$LfU0Tj0AJpyAO(MevNG~cG zR>^7_TZ!qy?v>jRGeH-5--+R~3Mwad3D+nNryG!!e(z7F%-O5s>O%gLVU zqt@@wg8rSnhu?$7pqFcy1~-9n2JZ9Efa6x0FIexD5liYXN5@@fMN2oXgnpPE*Mr4> z4=hhP;o$_3mWrzubqEfXhs&}7Xcmg78!r8);%K@?ijp>!NLGRc##_Uk{R6Bm2#y{` zUM62A=jQ)nL8#XKIQG|}8G*WP3jxNFFh+0blXa*9#4w>8Q**Ow`)K8#X9OqO)ZC#k z*Uj16!7238vp(D5SD|8|=9Z27*dg;m+(<_LN0rOMk}EVyEB11_0_UK4wH#J_DZau$ zk0J@L>MWXa73KCy{LK1St%wADrUc<$GI7T}4j1D2_JuTf-F-^2{$57XlKWhJQa*?* z=ifgX7uJf43c7FPjmo$o?dxQvUwD*fY}4fBn(C&Ug#>BI(y1KvOf0jt6&v9#M(4Z+ zoUE5D*xgML{se>uskL@U_gBiKSYWv7=#H+E`bjR0>6)quYE^tshuG3*zPym;lqc}8 zym5g_%Q7pgkHn>|HZAb=6GTxJqEFnJK~BX7X=IoY$+XL=(#<^WdCbq_ zVrToG%Fpk@VyLCW3p%;&nW1^Ep&PfU-&n1S~o>B9`K2X$zFkVt}u z1`=h&FsTq2o5Pxg?C?6%4tH>Re#qI&&rVxZ?wi@%2g#da&Jh{td+9Z}#o|Akr<+#% zDOa~h-X$@f>U;0KurE93M(Xi{cY<56;6jCE>LH^9_e-6JOoef!+XFRNm&wY|!^n-C zsRgQ>GQzGdZxF1OXI9d{tTa{$-09bo3|5ViI|%1F4OM7MT?-K|UGmV~$ovCE$fead ztQ-Wa_~mUxTb;T@R+TjeIMjwvATH!xU1GfI_XNTI>3d}w5^*%mxKHjb2YEafDcY#s zvXwmC&(aa~9BE$Oo%e~5t2c7N?%%T+`gAUInD>H7o)5Tmloq#q=?$>#|FhTQnl{Y^ z+UtE$Ty7<&wkA$EzS)ntAMsSXeKH)$)s;-g2Oupp07f$;_3-YEAewp^=f`t9wpQ^> znEhMjS{KSLeoRT0uZfSJVB?F6VY*lu5(rbrnZFqN$K>8L3rqztD{qp{t~9K0s%ybev4hAi;Y{n{kEjWg=YF{24C>bVqg;ZKmyXgx`v z*|?Jb(4-#jEj}D(O>T3>d1)5S)3tI=MmJX_O)`#m5oWBhHYuF0m&X9zZRZ`pXXrsw zj`ZMf0$VqQKG4|re|LWI97DV%K$0)5Jv=_268kbrnKd>mMymPzF;CSk&BIzYkjMD6 zYA33WZ^|e9cFuaa6W&|-so(|Kp8@_3*g*jrBzyRu++% zo_yJ~wb{As|CheS@;%?~RN)+6kvcA8?_JJaD31N=^(I32Kpz>;|EdldO*fbSwY}b7 za6VQmx(K6nIUA1@C!&o`>7ac#Y-djN+woQ)gI22CCc$hz{ri6bay6|atD{mBGUq=% z2%dkbcF5+ov*URBhiaT~CZgDu?`G`Tn{i`gLU&Fx)wRjQh1E~%gAT$V1iJKu3T#qn zFq1Sr_2e$J^7G!UoI)w5$A&!#*+(Q*bmG-7vTB;wX2LpcXD+sOWjNArz;CPu9%61P zkSj+GQ5kzm5iLOM22(B4-rDo~C0g5{@hjbQj{=_LWDjPV-k?^>@*P?F=Bs@UbokoL zNfp?s$aMJi;|mM)UUwx+!N8}arL+an-MZghlnK)rW@QCog$7!}^3&0z^@A-po{JWX zYFZcQGUTx6nz=hnPfkfu|ANjH6mO4xM8CsLohLABIrsSVnv>cF3#TCbZntKJ$?7x3B)emzI+h8Q3j14k7Dy4-El? znpZ|Hs);eJT-;%PG<ApO|WEoppOa<3^ z(j{XhEGn#K3l15o#?an`EIQ}Dxt%foms1fpr+CSKw2yvKO1g=r6QfGkXP;j6UVGiR zTHM~x?I2%KcHXMcE7$4lQI$r?BQo z2r%P#c2BVVH|E!l`2umjKJ>SO^r~;*0k}#rpCWx6#bW18ZN1qT<220^RQeU=Ie6fIB( z+;%@&{`EbZdmyf|s^;yq00X;P{Nmhw(W#JplAPw}U26wm)OaetTdrfYL@#0}oFqwG z*y)#8eiX7b(W(6n#w?J&OJ!hYYbRCs7Q2>TSM_Psp#SLfHo3q~JB;07pS14v4+%1u z?}wG?#=6Onrh3HG=|oJUbyeDlyW#$xQHJ(fbY_>HxCvSOlKz!&t+T;v)xRuwPag3p ziYsp<(t^*!-C1wx6efVdfwuuqGr69xZm33Y&q#?wc@yNFlq~%DU&ZVlzSK_%pAub| zdl(;3<`Y~%Vd?w4>r)@Z6;bu>q+J#keH_W7=h-{|+5d^ZkMq(^=P2h${aFuYcs z^BoH}c#M-G&yd@RZ?$is>V-ew1V{;WEb-vrUn&y8wcObTVo$$bWxrtY7%}=M75vl#5CJgWa+td!usT)CeHux%Z2o2(X~C_jHlR3d`D+-#9Up_R^KaetLh=EJ+!wjLtSTknB&@-o1HUg zZf9mQ_{%PkdWaa9n<3v~Sf7JF?VQp?* z+h|)_Xeot-I}~?!3#C}`;_ebC!QERZZpGc*HMkbn;KAM9U3TbN>;3lo@9*S4*eAKJ zJb5zbm^SPlW6W=y!9XV9aD0XcZ5YN=IteU>>|+j>uuF$m$+i$ zE+PW5eRPM@KIM%!$2#aXIY<2VeJ@4vmgJ|inJ$V&2W3~>2HR}Zkb1BLabMp|bArRL zPX_{))c0p`a3VS17d+``KpFTa2GBz~pBVx}7 zs@HL!iThf_U=9CeMUIPs3Ol$zWg6UBlHKfDv)z)wBKVVaz#*9gNd|T1a^KhD|NY`T z;vKU^MfmIIfBj|k0T-k1wUK1ivqXBPBO+Sk^T$8(3HA{%_yu0{-!E??X!>^8622z` z$o_pqPQmtHKc@%$+YAXS1&;?M`mb@|zwZWQ8|D7Lf9A7@%d}zgjBx(DUs&g)QRR2( zk_>^LdG9vv6w4eQY;QyUZ7(8PTS+NeWQD=$>QMWg_kSJ-Xqj@LQ>&IHzZUwZoleb_ z)vjQ(*jO!7<^MFD5Q!A@pD(0}kwU0{2K)SBB*{um`X3^tCH{NB|23k2ruw;akz8^g z(toB5wo1`PUq$}Y{{MAn5&RTr58$J(81HF4L(yvJXse?#@*9zyYqtow8pYvnC?$?9*J^jt`(229i`WJ@E| z6z`{i7N|+)-aVYbC!#p6{AxrkM67!E0LC8;JzV?MC5l(}JQII!0B77oiUDSK9jc%$ zYtq#f+}&H`9P=JF4BHX4`(f`?xOX6ysE%OT43t)(R!Z$@t&O*YXS^&GJvaon3|o4^ zWAPy*#fMNV>NxVy^1JtHj)gD8TN8Ym5lPb)$!EvkeOF(AKg-_0KpwslD-y94+!od0 zBvv?^j3ulypU|2UOb+)i&OP~|Zx&mIp@?zMv<`$uzRds8BPgADkymsqz)TQzh)Nv3 z)Sv9*PrYR+*Vg4*jb~MD_UZM<-6B*y)wgk1p5*ptV(c;48IM`-P<0u)GoGl;nqcGm z>73Qa@qE~uSOt+y6P6Q6-BLwgEk|ducG-0ziE(e8<~F^*C)6*G4`WhPL~=kv%eXnHS8SSPD)gO`vB05ZWbw`uL3s_DvgN)T*hg7z`hjYzZ6tYHNq}8P~i0}Bp z9(1kK?7u>lCH^`rK>2jom5BCujGr{dzK|r+xjFt=V9IXSsRop^?MPy*0-_MAjeoCJ^+=~Nlpqv?m4dri_C`cYXiovnE#~F| z+aav>PRUFjLpX7hZn6C5P{mN3o=PY$quixsj7|9I*4-VdQs3HOmTt|8O1jMHJ6c{+ zP6n}!d7N4lDT9XdRk9)fxltmfFB7>CYodB&SmN?CuQ)O3AMqhgbva$Zy(5GCh1+}J zPoiK5dmj6)9vmR_7&l#Kjw)&hG_)^MpS&F&D0q$M-?Tps=IM*>$^R~nLmFo7sE3Sv%_uN%L7*hOdSMRee3$B+64Jpc_*4FR5C^nrxVAcXOml_ zKT0DhGzNWdELV}MKd$dbil#nR$xZ^uwOeW-5cyq4#TA+oE#~h0g7s;^4@xJMuZ=6S z6?{L;V^Lkr_$`g!O9^BBVIVXesemk-Ug0O%64Rvyo&!y;JjJa;XR{3uF>KS#ZTlRh zS3sn6!sCO37rC1wi%_SmZg!VfgwF_2aGP)V8>Zh;jJ|ZLBQowBEqbY(Ld>$Uto#B) z5y#CWjk)zOU|=3;qzlQkZaqs&p39yDo`8REtc~qOYl&bNk^;5Z;S+W$NL`0hSGkhg zdRy}AJ{@`wHlbV;4zZ4Bh>&gxa3_<3J{jPxV0k&!s^=~;oeGz48{VDswKRU7fBMsU zpqYrEGu9bgW`Lk9PqV?Hv?061e+D*$v9r|3_d+P{N&2`&GAHxX5LPwaek=%26KX*| z@=xUK@a58VgkrBiy6={ z-=?+g&S6&e zKBaFAGw)+^j@D@=`hbszEPje5EZZ1bjY#2ca*D1fI%)WAkD?3Q4k<$G$(}z`Z!xcU zpQ5_yp9K+DSfM+G6$P1bzR<$#3z2!RASd*+*J%fUQ}j1ge3VJuGw6A5xr~zyv>y); z?0FZ=)vvmOv1wo;yxJZnNwXOlxBIXY9qIS9!|9Q~N&8WIF7d^Wy3N`eDGF3Ay-Qy9 z>&s6cqilsJpQEPtiBCyD$*2DuD!|STz-A(8cmBu2`x`h_ znV{-tS@&D4*0WA{c#)!S^)EZbLXDEuQLpwoOo-(PU#WwC=KHsmE`+pYxoD<; z+`Smd1?4-6WVjq=r}W@feX94-5`9(?zV!0MaaF0fO8u>54LXw{h$`V>yH=b2l)PAl z|0y2Ju(8G5Jdyt_RA3#xB>_dQz>E4J?qqVd1q_m%_Brl4TqjiZm`E`H8T9i)?S{l=T=mC>xkWSF$VNhx@u05<;@!AS zl@zK-h37_p`_qCw@)h%t0pPvS3JB2s4EX)ESO7+Vdu7V5gLv+p>n*gjKjV8oyQXZm zmv)o%EtPksuDXl#EpQNLK0<8B-E7iKwxNea;7(dg-92gCu#?xUc;_n$6aJd&!eaKY zh-(iU#ZESmP?Ff?Z0&g!u;|rsuhg2pQQeB51I|}!(dZ2iQK@U!Fs;5z20L2cU)zKc zFF}q?W)jBA5J+sd$VtXFU&uJ6d0yb#Fn+v&oAM)2D* z#rVrvV)a=o$S$SF%W}x)ENN$aIIcT1X?d=YYEN!K_LA>q+|<{+g%I*qA$s0~L&{C#;;^OwWFr8Fm=mq9^IA>g%TQ)XKj+jl_4+a6vwWk}j zZ0B;WpY_AsBj-%?p|&TWFx05Fs!Uh|tm!dbrc|tiIgZ~VhhcS`{>4DG=1Bjl#fK%l zd8zy?52#?iT9T>2cPdncI=x41&G8xKJL5W2?uP@}wcHkVi}`4hC{)Hjw56>LE>02jOF7sX2Je^QLt1{xEPiY z#Dwn;U0Jfi8ue@wqn+qa$m9)wnqNg(4+yr$yP-%i0j(~#!|kha1erey@SKy6?OrwY zpRXF`MTG!tq5E5MtzOb$yHCPz@+WAM&XQ60_&wG47gBoX%85H%o6YTRceGn-+XuS2 z$-rDQ*fYaZ4do8?>orn=8=DwD(5DNrPQH@alI|VCeS-I0gw(BpcOnt2xR0NUZb!tm z9_}J0qMglg$>4Zup~PKTw8V9@aLjpgpFZ;qZ?xSb>IE4*VJ~b0a$nq;aJ-O~-e-aL z_Z;Av&SZy~k41OjH~kXKqJC3Ld3b~fwZOAcI-IPIw+gl__TA)#oA$2^;NgJbX5B|0D2+z+|J>3%Hlt_n4WO%9ccv-mOVA2Co8FcMxZ9;_8z zyLZv-&+pfH?jT0ssRl*ww8h3WtFxOSwKU46tDo`EJ-+)aP|USt&cUA8=pDwBjGp~) z+&CGc>k^+A;Y#{jM#(}j>_mXJ%Y(??L|}oFkb;^1wMFTvJEt95j2(BvP#)v8oJnZf zK*4|$3(Yr4_V})`h>cNy9sSMto#bYs5TDryjfEbTVu$+b@B#z9z2s4lfD>Vt(WeTC zS%S8xyPm@fJY@*TWvT8Q`T5{IzFIT{YJ2)cQ_m zigf8O0W-m>$h5cx$CvWbLx5BW-CcJ$V32mOJT!B{}Fb)!+HVM-zfL2W25_>4Tz_@G{Kdd`r! zCy6LMEazc{E+CI#r!!p0c0eOILSs$V5t^w|8y@(^vo$akANhoxpCHPd1YSB#bj_(! zZ9!JXObzbfzBz<(1vhRunUW(QzQX@xqjHu2+kBuIr2C~5qG=x0*F_;rquZw$A$|*} z)+jk`xIgJ34(fHT;VLUpIw>fcC{mR(8>!AY-MPN$@A_^kDvv=ydt9eb@XfAE&$Xfn zuxgcKAZkU?si%}ULT9ei zU^jsh7Y5^rOI?hpOlnHQ>`EtB&72wFQn%+fB|wp`_Q{+F&1MXVn)-K{P0yy zA*8$x+6_a(n+pN`#6m0{`!mGvqcwi+fH$ry^O-;wKgH(RLTEvlt} zpsyIB^1q3bRSK1gGv`BCI~kxxz3>zhIEtAAZi1>!_@VOBSgR}>S&99>KIFxiMrFo_ zp!P2SS#FXR8fs2=R0U~a4L6kUNkS5pW6BQwa$KZ^kA~&HvFoIZ^e_^ftoxyvGAD-m zFtF^;-?DAQxse2+H9AUdlsD;Qu@(y5^CBz6UP!C;ob3IMG~a8aw%F2|12fsV)XeLEj@V*nTP^@*&GgVIC;7y?2LlcdbB8hac|aG=-AvXI z742f^R{VpGElXAO@WYW9HQ<1=GY6f}U8O(^EUNV+lgwp)<1%9rSK{#qlPXvTB|;lP z{lxlAv$mb%Wif?dL5azlj}_~)nv%1kV)<2_cchvF@!Xz}wX{eNb=wWOCT$JYMY$Op zf$9CDN#Co_F;ACa3g5u-x!cm4Fd3AKLY_7pj5A$R490nQTpPl$XiY@Y%6i>(DEzd@ zC4FMa&o$HHXl_NEv(kg01M>Hlr6yJ}FZqeDIOSB#aAoV!?wVGcBcl;4CB{3fJm3}g zxrqo98?@0ILFV4*h5Z->$S4L5(xVD@DpwD81$Z^<@#Ptq2Clc7!uj=jjW$GgGA?ex zj5)NgCt{`(dAyJ$%a_E0P2S;lv})q^BkwK&mwFm|h!u*Bgl7Eqh$wP0WH23#&^hGj zb2H2o*d*oxQ@%gAAAH&)w7)?MQ{QX3MxguGB+U)4$2OO|?yypb@ya8Jp&`1HOR!_K z>ThgYLiMYI?1h5@&G)O%6^1C6QSCz%+a(~vVaR~K#~$_gg)V$I%=`)2^@~bzY}-V_ zE3JeXlFcQJ|1qq``E#Fb$hQK+Q)Jiy%rxA_bRquT_mEeb25JVC#F(dbFKLT5%BvT* z+YFPD0(E;1?Qt{@VroaXdzMD4mf-!0HATVG4K+?>eGM$3YJjHq40F|n%RetL%%TyL zF8jL0a{7Mzt5*|Lt-LDj1D9n#4QqtiN#2IcaFdUFj(KRZv{6~^{$q#d(3-@K^{G41 zGdjhdnX5@Z-COOk+Cp&&pYpw`2W2G!~zl1SZ zjA>}GMk0B^yo(8;Q#ly7#~s_4Bi)B6A5gurdICQqJDL)_Hw@qp3&h5L!zw2Dt1Xc0 zv!$C%lj=7_o@pDl{!bKH7wv7NSO{=la<_)t66}|jhc;ygFkc4I2IT6BEI+a*LA({z zQSvECY2yj{U_Rq`4*ZPy0dH9&`(@PWs=u&)o^zvej9;cK%Lbjj5wkXScXHIh%^@}@ z!SPLrl*B$dq1R3aQwEOD&PapuyjyoZbMn%-jh*_q1!T3 z4j{a;hP{b%D^^`R4|O$#-_e$RWdXq@)>QBeuV)X4P&3GvhejPs?}4i59rLHD=^wjW zK^%u2yWJkEI=YGDShbn;6;5>VAdu~hxpOgFv;Cdqphofsnr$`{l%J8f=}ddYGEfUq zfd9_}4SA%3poARz2}h!kqO{=pB&$>9v{m{g$EYyP{%mf+zAl=2i#RZ^v=xno)h2}n zw8rwi!uTS{0vk7D80{z+#9(-Tonz0J90@SmbEI+f7lU+FnJzdp1Mv>1R1tR>OI8yi zEfPxxa-q!*sC=Mpsa|Lmst zDy_et;PHx@p&cD}5zH*mnVMA^PkK$KASWfxSDn3}m);x)cRTV6yV1*nQ$@B|DoJ*M zT9*>R(b8AFIycWZ%_EixfMaWp>T}OjVFM)%a_u5ub}CCaesSm88GM?tU5{m!UY|wi zJ6F6c-L&*>^oRa7Sr|FB)nIr8nkm6)r6JUWP4%-}eD^>%Mq7!sv7c<=VES=mG0tMr zq*cF}U=!L{C>lZT019X@tYJj!8BdI+e?J16`9|w0_~WtJ#7=Jx zCwXv);Olwu(?7tT#*6NcyKg@>g2 zp5|tpTq*-gRjh1%yGPxOE9wfd@|t%p@}o&9`Y$bBraN&lTMvq6gXF|Z_;mRKG$bFK ztRuD1n39buaC5;}`iJI1Ua2M~*BRDaBV7}zV$cjD1$DT&OYF7Bm)gf*^_gzu)aF^| z+;yk#B?EGth7Dn;qU2{%^fhJBVlD>4!I?GwY@+lXod@Q^0_;C-a*%4TjhyOWwv79IX)4XY6ZFTg6z1cPGGxbZbiR4EZSYhcid@%m zL2a1WqeN_zko1z}iF~I1U#C>CO*x0(_eondjWQpgM-w{qq?oO&DRlG1I^7w;ixJXJc`nd_-;xf5ymN-r$E;A$< zoEU)xaOzWi{}c*FYvRfm6?j+Nd+f?F##Se6{;K11`M?E$4H_DHhpm5{h&h`}xgOOEM8(ddzqZFi^dgk0M27M=TfejF4A0;Nge>p?>2}*Eus*2m z82L+NR}KoX+;;rK``Ax7( zndqi(smY=p2W`95NcY9$66-9)ObB^}SqLm{B2=T{O`8@Le{~ zjbX3F`GgdPf$po6=+_RjZbnt`7gj`DbPT3No_H*EBQ+BwF1ud~FQs(P9LHM>#8n+l z^Q7)5>21j#)CeE%C2p^Z1^tN9#H#Xy>L2vjT<}M)8Vw}e7(MszF({!%vCqCV9>($PW<5>uV6jqd##=di|IQpt&u1u_5-!4Mj~~B ziFhRW`xYnWtgGsc-dtBSMa@f!G8(@Kxmv}t2MFgvBp2AmZ3c%DJLy0G-@4n0A~+E{ zI`k8~{nIto`Lt4S$DYO)W|4-&VAe55wHm2anMaFb)}H#<-W@j5A6~8MB6lzG3%=6j zO>P_l!ZHUgg_C*gC=XHXx*XwzQi)lu&R&MOyTvz~cb{zSLe%U8`P;8#{62bm{R(|o zkJ*e@|bR^z}jDOp}sEwa;2lxZVA= zrytkAaI~kuYHlQ)(nA`bU5lhE=9LE<Nb+klrqg! z5M&W{Ot&*O0*AkB7^oYLO}L&2$x^kvtMUXJ#LPyZB!;$m_RE%vZ5LqhDYHC%C(^=U zM-V=Wu~E&K@=ewkwl?0xYU)HQa3ope#k;#N=68MjJ-}s+hs~3na4LWF+XT)zJfgB` zzhtW|8a4i;iMW4IfTUyGLFBI`co;rhj2zSiea*C-M*cKhP@uDrMDRxYrE@-4 zWw{(Sme@}N+dk106%X9`&5obC^5)6nSS*5z%Mv(ko-^OohD3r7ZcP66u?y|dha=!KSc zeL&;`Fe{mWI)<^6u5y3<23o1JrL{PyvBSXP0cW@!-OK1K5LaQ9bxaj*Xd@3vb_oD1jtV7aUR*hDw8u1;2*V-*6 zC*Y-!(!t|7YK9X`d}cG(`7_Za_u$p&H+-1-mU?z8=l!h6LpYPr`%QCB2 zYGQG{Lk;v4?5k)cz0Ma0R_>9pP}3456WkmQglYw{e<}L%CQ3*M->vNIx(TsK95O7r zU3DY)g`GMxK2z-o8d#;?SZTH{Zln6}!L2;{NvmPB;WOil%e0J~r?&;{e}g1Hd)LP-zKRfEA}qNfWy$+45Ii23M7BrNWX;-u zW(h3C@n4#*bNy(F%RAm%@rW+lXzw1HTaA^u=LKvPw}_NC-n^%7?s&x*ks^4nE==cow_qjC9Zu&%_RM^o5Y#wRaq`|CBq0&>9rS}gn@i;R(7qqoJ2xu5c z)G3Ekd4$_%eauql+DduI5}eoGAv4OFE}V|KpX0e=*-@=`%V5bR_bpw0wy_?`v^~yt z9gmh14LA**Pd{v2ABGjPv(EL;jQ`rDHIDAF-ugP`>Ft()6U-k{hgk>-^=N&e7t+$h{zNuW z4E?z~lU#Q(#}fAV_(?;g*s0Nid}W@1BPlE`&<(7Ya#K_Tq!|m#!JkwA!r_T`c6|dJ z*khV=|A?PR zXI(X7M8-v#Hs+ExmFfCMJmo;(d0B9rMC(v$)U`ABm-4@Hye|m5s`ZtT4vQP73vbW$ zTkS5I#f+edx*p}cPTnCDo+)TY4$l4&Qk)gQC!x#KI*h9p+Q$QJOmtPRW(g8GH#5{# z@SbWb;0`X+VD=I0q4jps_%^<&z~*hELoCUV`PlGN<&Xo>Q#}XDuvM-cpDwJfinmo! zYO$b$CU5xPEQTi9l1-FgzGy6Ks4?E4to+;2w&e08)6K5@;00exvO_eZ0IzU1QC8ni z39IFiR000UB<`v^L9wg7?uBJ$PK$+@bq7h2C0m2}UjY7K)=Y&0X21KMhLRo|#s%-g zN&bL42nm`0P{xG$u zbHvzdtU*T>IROOYHxPzVajop}UZ#X{8+;f@K*GChMd@(Vmoau{7QGCMI2+zF*8a(X-| z4)+o53sH^m?!(Skl!DGSB$FUxHB>s3e}bdf%>lqJL7{yAi%qu@KQTMi5f*H)5nIO*S+s{mzki&lf!p{^BlDrl#bmUu2N$Y4>Dj*n86!4Zm1dD$tqdqK%%- zQzZW(ItBsf!f#1{?s^tbx?ve#>XS^lKvu(`JKSQp<(#YdBZUta47`Sm$kVB1 zaXqjm3rkUiQw0aLUWVrBUKO}IStrgk9u4kt##1rmSzEVoX;4Jo39*>bZ}a?W!(!uU z%166B#y>Y7^BqzS8(}F+;HN=6d!+9!&GC_cSt}=$qCTQ32fxLQ63wf~Y zMK1NF7cA(_5V71!1@8ADlip0hD}o0TDefdkj z2k{UN#dXAOm_XlCQaZsdYFOGJ0LkM;vBbxC%)ZXt%k0wk#z+ZP*B5yC)GQS^i~zL`kVllr$UnMev80MP^rzxfzcEt0qvT zYy9P_L#>TMfY&^04Ay}jOgW;?rS=pk|Ml|0_3PR>)M&Kn;i}t}gRK?mwTowO(~x2B zMj^%NsHiJ=XCSemXFI0n%@YwBvx9cq=+s7_r)@+_iJN@+s(zx8Q{}C?-%=}%_w|Di zCuQ-h3@Q^9>EV;e-INE-ie02%YFGi|^NLp|d(g08!6GrEZY>z+t=@Bu=4v7|R9lJW z)s$>cWDo*U^Jc7Jm$%XC5Nl7rAx#FPC%X-XvtAja;KsY;cc55qWVuiCE95;_4(O%m3qoMjRa}eZQztt2K3FEM}PEiga`{8Ks z*e!I;N?-^uf0IX~5MkoiMimB_YjRt-jM>;48;||6tJX~O-lTpWK-3VbZo|Eo=8bkgttUA|oETzF=Z&fi50B7=m ztjFUOzpd7T-x_rl6+Qkmju}lEDKjFN=Bsxhd0d$5CflMX6~uo*H@O#9%@a#g(n?k(Xb9uj`-D?TjM@$5H#Q=yHhuxH za%YPSoZ*D7l{^0B*Z%n?dqNgzagW+~kps&3RV9P!Vemv@TAoS!1>fpII$|5>RSCLCQy3r>u7K?Xw`jqorSNn~A|TO2 z<%il=778&_Wp~iZgKfx9T0HhP@E17BjjoBGzhzGv>Li8bsrW3#aH;;Z@yI2bUCqD{#Eu&QLN2Fs8Q8s4VC9#+7G)C5hZ?;kCMhu? zs-wKvWRJuvj>IVGzHhIPesPTYrU(BoXotxGoj}t)644%8 zm_kx`K|wr?a&rS04`Ku5E*mz_Ienyn%=?*Wl>ae<;Z*Nb@z%mzQgps?MuV@_3I$Q# zvn|v2%mfAsbT5w_xey7fEtFX_@fQwF3BL+T9iVD85Ek)NY26c=$TH-1o{%kP=--J7 z1{yw5(r(KIr{$0{o~S3ji96hYmu|S*M`34S@JE-IQ&fFk=&^m_A~u4k1PjyWMZ~_M z`jJp`wOl1>|G4@Qbb!aV>>9=ZskE(j=lm42V)z_+2Mfe@CMy8XsPR-VTJSn#xhD`z z*JGNDCZ?LiDeJq?di0ivBAvE&c54Sy?_%09Pd1zUhTGpmb#?Z%Koo_*mUM{lfO_8K z4RDo^N*uv2Bb?h?=cR?WQ1E}Sit&E5+>?25Irg5CH0nKOL0(Q4p@w7zieR!HpAhD_^g|z0?;mR{u=A;}<`giPUG_UXk zVUf+JguI4wl(0oYNSp{2IK#C1Jc(dmx-rkzY+71j% zKXK2UNSIDg$WQLwGZye76pz+#%ifU~;}BW+RANKc+I$fhj}0)B^9V%*`{3u$PUy|l zKqQLTfS^#DBAqK981JhWsmkEIcn3BUC@5%+&K)m=dbGR`P3xhrJ}VmT29Ve+ajBv} zz^4}!?CUi8yYue+mb{__9Ir)uGb`v~j(dIu(}_KxBdGw~5`I|QReXWi_JFWMKt#~+ z`IIfiVNt2Jg^3tG4wj0EypN84hWoZBKyHBG0b3ua15#uSgQ6{*+=7>e2pwiuZ;Sun zte&Aa9K`~dS_e1(Agx>-tYkfEFf$RB5O5;K*L08L(=sb3{vL|x!q^(+m*(k(Xc9Y) zuq0%d7S}|?GTvd8tdn4L`!Jfow*yY+gMnmmS277TP^R1YoshbUTI&+%%apg#AE(ab z-&;Gd3=h(%repRU)nsDM6BcC_wX<$_wpGFRO%n43tg<>~E#{QR2{JZdfyH-u(&gO?fHVJXRCg)A3`K@P5a=;a&3sq})s- zG#))jwcQ4-7 zJs_OxHGESXF~W1>$EjU(%)Qe=PtTF)78iMCE;@(*5l-Z4xE8+15*RT{`|)6yJh~bk;1H? z2ir}VRGF%aC}!LXZX-8;9VzV7u&kRW54ZmhKBKv{%t05=WkxAeD=lQftWa*CI5qeU z;|}hacI_@?)vOv%oUd17FiBl8STn?@gvEVWf#;MucB;r^tideg0$=8Vf|9?|C`%v8 zX?<~OZpuR2Fr?c*5U|6~t)lVWXSLA{cG(SOh`2Ax}g$tM>P%u8? z6qmn9lR|LqOO^r!4m^w4Qbj6CPbQ418>dcfc+fVQCD`o(?Dn>#ltY5J=T6p|-+r;a z!bOk!eNk->yGsX0904Hf2xIGNxw(&nL-&=jvPx}P#AhZouiDIz?HIJpeu!<5Lk5snjRuSj%Cg5SGV zGU)1tr2vKs6!W+}jRdojex7!1$7`xF@wosF9gB4~cq<;}(D&z>$t*vu-)wygMIhU> zTJMa2+n;WUDR|f&we2~nJ7N@Y4RG2!H|V%b+2^zVxnK_LTEK%6Ae3Dt)ES}ogb}QC z24>L{Dspaqgn)6#fF-NP5gh~qp59h9C7Gfs13PujPQZ>!?R`FH_C8)PqbM$qIS0b! zf#Fj-9DV9U8o_M*&@aUr75Dl(d}PAup48?$HGw-e#7@~fSpxs)PG-vmtbToq=3y6e zR;x8A0Z)1Of#%d$hQV*!BuzPkBgeVk8vUFo!C%T09xeOpF7EsWhl%Mn)Sa_YTQ~|7 z2rn=nxGJvp%4WQ*xvF~3Np<&&f36!uMRX1>yYy}kZH;z4$`ioY(4M^5Ici)z?q6(V zYd1(l+5s=!u3)_9ukP&#lzJxJ2n$0#9 z7Tc#*>!KStwSQ1g39J21mE@%9Brt*(CHv*8@(3Z6x<~fe+`0)ojo|ldxyNgvKo*J- zUu)+ss`=sBw@cG4PFGV5uRi3)1=$RO^2McjoH;H(9o>NPv5UJ{IW7=b*jgE%9w&0` zVbJVX4jUq1+LvGAb{Bu098*0u+^q^|w>fZny7(9jof#fok`USnZk#p889*c+o*QPX)=KjVQ2khJY2 zPPo^RFFny{g8Yxs{K>HB;@R($N$~0L(ziX;poPQ&@nMCfags?E&z@15nVGMB&yxwX z+>8VBKSu-npEz(R{&!|o6u*EZ`c&?y)+685<#f@FWr>SiGWC(nk1rmk27$Z11?+0L z-gv6JA2ej|rhfpX($s?+!QAReZ{nslkeg0<%!e1nJv`ZCrdoT`G+QzVmKIo)H)OS? z2d@gcvWg+ruLodr3kj>9_g|}GzpFgR?`Ow%O=VDAg&g+d{5i&tN*i=8bZCC(4mY*L zBRlqG#tYa?I@wx0^|mfzXfQh-y@zQ{whpgEEL6xU{j0AZ(o;2?`oZFUpC-(;(&YpV zGy=*s6|jWBg4$gPJva9&)XgFnD*zS=9uG8c%#pJX7A$Nas$o_X2U2Pnk9u!HUHR9~ zYthGALIoFOn=j3v-4ustQPGFOfLRZ3n5|k?O>hVMZ#;g_k7r)!fmGnh~r9@Et$(QWJUr!0ckEhcARVO8_GyC5_ml7=L z!ARksbj*(jK;d^0Xl37OR_w;PEaK8(w#u(Y$bS+LNbUZA%Hr&#GgwVa3oEx=ldnpH z*B0oWb!Z&&y1WvEr7;-3O{yjEqTrD|Xh2(sVzg_#H?E;UVLExZz6pT*<&ZY+k8(Wp z_~70Qq`C`x_!KSSlEYHTQTE4azw>u$X%m_k!D5&27Hd4;Ip@!%^=-kK<7&1lO$DUn zyBphisTj)lLrIg)6fUxp4QLxz;EG6;&}M|3X8e(Ab+*J>QyH_h53+(`?hY*d`7D33 zO>zyXNMKIO6WZv~OH@b3V@O#bfO&`8ZW-kp_;}+wHc6tz>7j>>KLBZU&Z@PGMN{;f zinYPsq22ku21*x3`|VJx0&Cijw^=`arBh3KsKxU=@r#X$qGdX-&ZQ$d(!Omuc~8Z( zC|aV>M#1#KgVq3uxZG$Zhn{N+(+Zqpiu|2WYq5KFa|6itXk#Fs>iWJIeR=Cb_t=`^ z_GD2Qvc~<$VJehQ0k@sNV6{D7D`>f0hN=3{e6LP1PMu@yO{!o^4 zUQF?oH}3*gitHn-NL*7qHbI)Eq#Di9l@3y0t#MqxwEx&byZm^y47R05QB6%v-_Whn zXvJLNjQc0!Tw!5>rGmBjbiiV(46?*RhH%5FQC1?N|M^3V&B2{snY8fk-u_6SuKA>b zwM2M-?RH9=f`kGnmhVfZVXLX}*-K^T@9hlRx_-(QI`ii%tA zePwphBIW&6Q@Y>~%r^CPa=H)`{VD$)F(Ci2mp4XGI>o=p)s>LO4tHnlWW4#-Z8@TU zPqTWb;4AsuBIlj$(J06~xqzv@6dP7a2v$vg*_XrhDae!am22%7-ag z>MyA|lTlZGjI=gIREfVZ8%w{qt5JnN{6eB#tuYE6n7b}S^#mYBmkYYm^ z-F@%#8x6B8{+0pqg$|1F|CaYoM=GjZ){`-@JyKQ_6^BV*ZQR$?+MwInQ*xV^>!4K!5@> z&P14i+lB*%3?{IgU;9h7`?u56Ra>(X9&AZMlARyDs! z$a)b*8Kg8@g~BO+Bts?O0=Vi1EHPck%75E7qSXX~(V1X?I!(2Y=tJck^#` z!F7tyf8V_1LdtZu6;6Eh@|8HMVPyFN%lf_rd1XmH=S1q<%(?k>S03GN{wK+xds?(Xic8+Uh^1v%$@x9o0RaI?1_K3*tO#~R zLqPlmAujwu$u)7m(M=Bh#y5Mhd3MKjYcV`&W-%^2c+u6=Yu{;N|7vIDg{F%cVlReJjG#3W<*138^G3vd+hUMD$h!!&y#CS>)D@ zBpD`mpzqd%JjsYR>DR>|Bc$O->&3inb0>0^3KtP{X7pI=k2`n${sT#>%xDGcoA4s& zV^EJTw*(bN)50{orj4!y@PUP7050ACn@4l@eCxdurt}`uGSzCF-p0_y&*g76Fr1(&i)d;RkQ)!hSz7=9C~qI*2Cg2=-Hk>3RIV5bZI3S&@F=-?~<76w&_x! zRjYa9h(+J|#u2_|Nb5@@KSTF^t)uf}lcGc}+vG)4vcnzl;7lcK<_WV8+C&Sz0l2Z` zc#Q7RuuUuu?Musb^uD)CPSjH}yIk+O^mi!Y9`#5NLCXm;UxsU##hX}hkn6p!c8 zJ!+?M_1D7?-?_WwqGv|Keb7GIqpD^A1R>#1EEJA8anZWC6rRs$xG84TW!KwLw2s_>{{z&>gjn=IZiO0^5StqMFCKVf;ZTnY{Pw8+X3AY>@!Td_WRyTxHHZ{?cmPPSiQr0kvLF4PCG)_ zDu*d2CcRczEqsjL*I(=N8JooquxD7bZInXqlA5moTcG=IwqQp|v_J*V1;`MCpzqGT z?~fNg*!TFyA4ys3&mHJc-5$#E)!YruKsHBKPTg=&W-2ZJ`&B0heDjbKmRSA%52z#t zXm)($I44Z<$NV+#;Jwc~f}-3RMY+iE6;iw0=WzW*yGf|I@RxKVxQHUNkS2ZW<%h~k z%w{z>un`LxMX56D>~aqOXmsq+lFj~Y8-tdRw|A37u})A+8|)<)QGOOK=U{8sVj!v= z3HHYaB!i8wR9r;k(`(;gL55p}LP}D!1_of1cX)x@ac1{CrVT^gnZZ0Y>CpB6^M2d-F%}{rq2H^r?K_e_E-PDidee1`= z(%dvFvin?Y(amCqNmqovn0Y+q@GlBnPJpj^cjT1zASF$1?I<G2<4`LNs3gG3BF27;6%tR<+ScpN`K)>tf4Xf}G)g8SIDp^(RAq z_q|tHalJ=c0eEwNy>~9{GL)-YSjw?Nh#pHl&^y@ce)tvEg2THUTgac<<&fq5HgQ|> z)r0$^UIFq`jG_e9LDA&C-ul)SSVaaw3PGA_paokIDdcBYI9{yp$)cEH7-Pi;rEX)n zv{@N0U1;UQ9wh>c1*n~VFVXvvD>*|x6}4rhg4k4(npBJ!TjU9jF(-GcJ?h4S?>sel zYIiO>Kd21O;Pfr6sIO{j?>;Sv>!xKo%ke=;?2LSpySyMBv|~1=N$b?~NOb8yM%on$ z@7tlc-nf@fYW6A9;JVmyI&M`bdZf#aR+w9yBw$C5P+xQ&{*?ra^(`hQ0=szj`*x*tKLDs z7A(=TnqD3w+TUzHnvvh1El1}5bkuDNPtoU(yUfzuZaQzXKU0ZSk92Do7zw?gdelrrZ1%n)%~)EyMzhD>h#gYRhM*M(Y@G0~^}InrOU6-4PDcXZ#&WiR>1qo(g4_dky4 ze2kazy?jI(Cpxzz-EMDP43al2{bb8H#!OGl`+!DoVnVWZO&`Ycqd1jjsV{@_q6%%g`PYYBRlZoLWbTg`(yDImf z9dja34o`K&S)==*zgCJHwZ*WumT9$6mqcD$V4HyxQ@k9$?b!RBDJz3mJMnX+qn6X- zoix=?4(vPkGx3k8%-yhr9`pvQW|Fn${2a7`0>`k|x3~IFt?k#2CuFrK+|N# zVPK`aYS1NrGcF4|L6^Lb5B|y7l-bRzo%+ltwvywoN3f_!_{aW7rHob@GnLDCLr$+R z@wt(7m)kj9dx+|%Wfki9ZtI?*0+RJRN8A3lafjZfCXt=>XxxXAKcJ^0SmZ@DioY+o za$F^jZG|&Bw4K`#F5|qf$Vm-A`xY?KTu6|toiHliJAVP@oG)ml_ zrNR@J;7>Xatel=v)yk3f)diSOVUDGEp^c%eA5c8F4cyyV*_Xu7N>WS&l{uDb#bXC-dc4+GcR@B9iwVGj>?lk45*WqF<*~(%SMSdw&kpIZDi^qLdVijVD+Hcj$u9XX{qTfLM`Mc z!@%CSLkrUChK7nCHP}_<-5XTgcNAR30;^V-hNe$CN%HBm6J~W0d0l#IXaV`H2~iHK z99kbWDH}GwDle5p!CD5ejoZ^7VKStqDaqo8c|F)}4Y$sWyn(`Wj9TT_w9ya{MHlVI zU#NK?WWX|TkEhQ+61kBK_Z(kae`K4XLuwHx+JNR*tv=HCFRwf|72>wl;u^hR|7+bH zip`z#+~TGz)g<;Bzw4LN!QB*vmS1}CdhPs=wbg?4^S#5p^x|i@vNLiyrQNIk9!Y}F zLk24e$YDk03g403B(uXAaT$WyU2Lhei=x2AJ$=%FSJy?u0;Jw0-N`ky9sBXTzxRGi zB>ZZUAeD9>!L5CwTGp&iT=dn4>S8R>3Uc&lSkJPhh0sdr$ega>^QPQq*j=D#~Q&iSC z6RHZu&?Ie^ii8ccYeOFbk%E$bz<-jmGbz0EjDn};kl|t0q*YvtFV7Wr%ua|VW2ryT zu=_(zuq1W}e3|~E?;7)gYNF8XVbPO7F<%3+kkG~6c*2G`%Y+#hg|Z=|J*<%ZD5MnA zG*3g=vKQ*f8TznOnvz)r;`Dco{dwx)hD$y>q|Ud~tKg#fgdW86Chw4Ca^YK| z&JRG4+xEcjCZQ*8ARUNsnE8_N^VGD)({!B{k%?FOsK{ytd!s~gwe~rMdQge&I6{tH zQSnrfoW&2EFFK5~s(Wuaiq6`0501BvU9J2+(!aj_*zQsW35VXfGwI z#H&;**cx}h_kJpv*Y9!<(MKA&Zm7kkqgvtX=iXN z7HPLb3pbH)C)(Z3(mzq{O3L!_sli+E{;TIzcO#rF+GqEEN@3Dzf8PpTfifU@i}4aK_Ui zp~W9TN9cr993)HVx@2si8C_E~r(g>qK3DtObsP8q5RdwK9otq>s~;>TDfv+_Zp}2z zSzI+LB_*gi z{E@68dZ+er*q;{LyWE`Pbo_9&n~&NN0@QL~FLeD+el#$8f5(b>n`n?TIx^EBSd$A6 zirf$y9L(^i-r{uyziKEXO9etc#1GaQ{*XFba|KMMXUsbz=2$bV6Hbb1V3dUTHE`g; z!M(iU5h&^gvsRtj)H!{2Yo^1>nDA!nKxDV8uV zsC7izL)I0r|9}(|Iqj8!W5QT+=brF3>Ntf^6yB73>y1!J8HScoJc?7RTe40R=RMan*ZW*YQ1Ism2IZA=A@;E4m z017E;{2p0|G$oM@Boq0X^BtW_D2#q)kJXRakqnkwg^n+{q2ya^Y9D?AdLBRBXu9Zi;PQlg zy|U+l{S4Tac<(ZN0ugAl!Ez(8_*_odfk=0TM_s`Z|A>EeyNXW&O~=M`^@>ybO3VJi z3-8mxY-D(|OA^SCdketzFhFV#}9{%xV=bKpT2X~ z&ZX_x1~b11 zRx_0aM_~u023I&*h-W(&r%HqQwBN%RfB8WpmopAYl@o+lF?ex#UJypyy7q=mzilSq zg>PQO0g~`;aNW}MUSDevb<|FRQG~ z4?RUG`oCSGy0FVHDbA_KoZ^3AzF{FZeH?%61&(&Hx?%%VdTRBOeifnSV$$_N=V4O9 z_{)VT6aZBHM!*F>#p2!B%hFr(jW&Se0{1sqWKi#UfSy9&t1A0zurI(D% zWelVuw4#Dx#dBAR^Qk85+eG#}qG2>RvEQg=+WlGNk53%@qT2ZYTI)jCYi4?{?F#}Z z!e_sG^fL^;#wwRy|N09pLN~~ZX%OkdL9g9Rhs9!}J1h|N^lIRId$C%`ToSUJXoE!2 zHe4;s$EP~5&K<`h08gWpfwpcsm4ak|h<|(4*+FP$WvGK3fs@J6nGZ>ViogOX(~I|o za^VV!U=6G-WJ&Cn?ZDRb@GK5A9qHln%)k(x=eksPbbM%_I+asl5DFi`mwQO-}9trXf?+kIQB2w=wqBS`t`q2 zKN7iBM*sgPfInzf+c?b3Mv@_$PXp8Rjyr52>3pV zV9z)I)BqF`R%{DwimpQ~jm;tzgK_hxO`Z<3FjC$ID>8Q8} zpy$8@$KvEa7`0HCUtWTj>GG zd+izP`)cVA*X+aQTtx5xQOsQ6i|)?ZCgNsgyPv8r(3*n1M=?xfbh@6BO0ky*=R$mf zT$eDc({xves_|PXJ+P7@Jt+O+BSog|oVvLN68DiTB^~49;@gMJc`%DLB7@fP%q+$) zV4x#JA`DAtiWR2Y|CpBVn?JiV&S7%Y@_VADR^ag6Bw{Q6HgtC6jf|f41U<^>d9rwXU6X8%XOf~&8Y z?SeekW|M2%P=S%1$nw)uMSJ>xO!mXqKjNgHK+tuOcDNi+A=)u~a?cQ0-T!5qmO?Xd zbp(9`PKb-Wmfcg?_2fOLn^0Qfg?Km4Bt}!b=eBuif*)stT&*1J%g^}7!f#*wk(zQ2 z6JGrrA0qPF_k%t#5#3@RRpTNwLwtB{r0B=)>DG|K_O*|jUlU1gIy(68)QDU&tP-%} zN4SR_b?*+7%iW?_e5%&~05Tr#u*_JaBypB4ST^FOJ*@ z2O?F~k>{}7v}I<0cX&QenxJn34tturk(QI#yc^~_1DK0jG>do(oA#a_fKdW*B!~v+ z63{X+T;f2i7>_B;$Q-M3`{ZO3V3J2m_}EzHwl#?i#g&;LmmOlJ?@AIhdFHi*SHKKZ zRJNR^Ph-TC&JCf#Zgi^cu7xG7ZpokS(k(T52Ymf1>xJw4Tu9hYDkpvo&PB}AKtC$c zQbmP*=V+?NX)Vtcb1(g4AKI}!)=Y%f-Z6sgrjNwZNJBrFCKYij`mhPVxTQ_$t z?OeJP;|PFHwEEmh{MX8gkAt@cQXZi$!Z2nF@;CZCesBbwo*+n+_#dc;{ zmpd9dnmHr8bJVfci6W`nnrR>3lA1jD`ykM?E|WO?k-QEConPidybk|S)DwbQ{k4RT z41iyWAft6R&&aIU@J&-<9v2j@U{p*_M>Dvo&Jr2T4VxAW^ABkC!S-q!j_xc0LmRyT z@l9bg)?Zk7To#VlRJmhj)diGvLd#jY489Dg^FWL!=)QUPj-|m2|CZf|;@N{oP5m$} z8m#HQotA!hjvw17fT{RkJ-mK$yW!axe!|x(xW-uYwr8xi?`rDr#-bY-;_|dk6 zuv+tA?~mI*vS6oD*rX8*SRd%w+9GReYSy?9wHCDqPnca>r=^7cu-gkgEpPc*Ix&j6 z#kGd;?9#=8x|zMI|MUV3R!3!CUyA(&c(ERjK3!8d?axrAr$vukCmr9+(o=S9zMsCU zU|zjVMuI1>8Sx|Ljoj8=Iz#H_M(r2Qbf^RAIBV;O7FFH#&3rm!|Jq3>)}H&-y5{kB z6cke>)zzxGNtHMS+LwKFmX%55-X2-Ed+i?oswO}45LGHnT8_*SbI7+*2fKMQ&&b^i zbwFxBj+TYjbkbFdSMIkv?~6_Kd}dTjHJNNjCg873U%S!X*WE$tzJVSs_>do*vH|mS zsu8YRe0*xGR4suy0HpX)z(ZtHWq}I@O}-ATJ+>!~`)tL<%}{URMy=f=K|`k(2hR(c zZtoa)RoK}0F}xZc-!!YA_mfWw*21(=FYhPkLT(NS)>=V1hpJ5>(aFtEP1yLT! zdA8=e{n*iT#l_&cT_gWWmt{$x%hK|e$L~eI*N<#`f5!G_@_Wo{v=nPfk-TIE$l;Yh zT-XC^kea#amq8brR}h1`g!=izv>dfH?Tdr(&}-zeec1;O7>0vVE3DQ~CWG<*J#f8^ z$jdsMUpo2S4aPEH?LIkl$9zi|Gw$!g*=e5FL}|Rjl8R$QB|HSL@)^?`^s`3t`+Z9d z)d33UdE5L3&f{g0Gkq)eB1`Z2;A2;O|SZk>h90&lMP*!IbDA3fQhjojRB zOXj@#`~dE5aon;F-zxTqg)lVSST1qWyT`uwPJay{XYWW*ppAaidCFxCJ5Z2yaZ5`m zEf}5!+(0%oMdWAgW7As2LO>7_{CYKw@ylU6p=rSn2-18N6|0LE$|VU-c`ghBFXnmc z$0j5#zK+i!)fkqwOB<(ABS{Jev2Gprrq~Pl6(urgQQgGy%YRRqRMjc}Y`*>WY;pm}Kz!>2e!;&8%9bqcRHQxN?@c)L z?&HrS-p6Wd!Fn+C4t`3{=GIg1qw#l(&nwqAutI45nBoqSkroQ4`1=rzg@p8&6g7(D ze!Sp<(sHqr8}7uy(#q|3MTK^q4RNN88hkI%cn5C|0px~9q2EU2B7fIKM3H64=yqz9 z`%a61$#78{qEBdW(XsW~dV`tv?Bq*iBr^Vh6gq>;?&T4~u;XgIJ*X=@$&c<4HpjSx zcs*a>NHBbMruKUJX79N8Z2D?+naQCbe`s20Sr8F|%=)~|tUI$tM2 ze`)AR!G{}F$!bvJ7vEZPLN9v%N`C?!5LF6;{!ctn?jq6LkPS+qaezvG_B;mg>(3d# zBCc;PdDYZvs2jmgKfcW#Umsw4JD2QV7@NF!U52e0%|r#Lxf|coao_74He4Bpu{t?* zJwc4z%CRg49yG~-)ZX?9HrachOVjHRd&6FIcF<4LLKnO}W*}X^wxSEk8;qdx_G0e)DDMNLzY}<5NlzgXIMJ8_YzjTSY4(Zg2DQ`P0+x-yZ52?ru*U>FEko~n#v8pTk-%wl9?@=Y3drPZiK zLhWVWD5_Kzxi}*QFj!k_wndW!o`8oY0kh#lsY4UizIB0~fdQN)_xpjkBVWkY?2|n4 z$0wn4iU~7jDCPdW1K?;o{dCwkIQo*SAAc5K<@=H+Zf07rdcQ=9F&`+JiMaW>)}pcyU2FkVZn*4|NA!-InrHfPi!&u@v!4=3Jl8WImy_}jg)Ezn9q~+sv0V7)jq&L*KDI1$;Y``^1!24=rKUzI702OdvMF+E zDo6fg=-h&n$eG~hH=Zy_zom6TwFAzJsiiMQ2k+N+)fKMrBDu*#KQ@rvaAtAVGXGsq zr**&7>0O`war5o_Pc|=8sIzU|6~2^Sf>$cf=r4QUM3u70l6d%%CHrA6wIi6a?^Hlm zr|8v{lf`5-xErQBoB26*BZJj_8uoXs zevbcwMzKre47v5OB!-GqI2YevA)0X3>sO4wMi24%!Pmrg$3zk4{H1c9$TjLQbiq+8 zR!3x)rLDe7H0LM%tHX(2r~~iK*E>SnSW@3o|5T z*~Nr8{gQ|w<+hdW5A$}w1UQfx&nrHw{Vx5kRKa`BRsx%T2GaZPFZIL!5*)seFJ&6S zKCgw&!sp7uH8AF7a?KN&)@}J&0|#00J?cB}`jD1i-~VFn@**XKW>BoPGENnpbuijG zF#mOCD0!T|7wH;JUTb7IaLs=*;sdKc>mm`8gAjwazDK#rgu&;U&(J!)TanocSZq)F zOzse=USBLY;C~hrE-hdr#Uqm(qEK@bM$sR2H}xLWUs00q8Ot`M-z(`_Y7}yTwFrA&9 zkS6l-sD%99VILz2pBK%|H6H=)RHvo@xd_7S0A2&A27&rTKS3l0rE0il$vkdfvt?7# zGBVx_C-d%=larIX-kwtd!z74o08~LlL>w!(sDOP@?h9APob!jU3km8pK*z#Lf1a7b z|Iyr>N~gi~ODu!#J?T}7`iRtO|+FJF!SbnDe zu!z2JFOo%-HWPcJYDdVFJ6YoQeuXI4CKW z?83;pF@EQwGAFN4_0IEIFgP49#jqXL_H7Rkxwfo61U?DI6< zfcV>6_jL+CgYHLg&DmpmTSfhyD){{UjYLCmq?_p7Vf8qaGGe+9Bp zgU6K&{RA0BqDWiqUQU5)Sk1U8s>^Md`>@tGc+k;O;}3X{v$Hequcl8_Q#Nx!8+?{0 z(?wvhewmK1>ioo9w`384U8|#a!_+DL&!>k3!lRJ%bVFLYtJZYd@pb-thRml!ILw0{ zuGPp$I_n35G^5(UhubSpX(4GM-N4kWBQrD$iK2|Z9;P%K`ou*vhG=TdQ*`+S12}NR zw|>|k*f2T#7?v~)tNUBuIL@h?E#A8OybhQc8?`f)S9-&T+zUr?iWi4am{JMBRF2-Q z5nj+GoNC)JIn{%GV+v#D=J#AdHfay9bBE z$8I!sL+#dG)8?2|mih&S%_s$hzM?o$zZ$lz?@HZucE{xxl3w1SnqUPftqLlj5h_oo zUV^>Ik|af}(~UF?g)lnA#l`yRghe(yqA_(o8W@l;!_!R4JbNZe+EETX;A(u0UWCip zk|}k8@pE%?gpHLR7DR$zku~MNR z3?c{)xze*55ltZ@)-LlIAU+S1$J*T+MK~>i10#tyJ?Skp=OD;^sv~c1R?iPq2}1Ka zJHHv$oE9M|N6L_r0bsl-WDhl{Mkn=C7$OFP{30!ms=CdauRnAyuDN)_QvfZVqg(Jb z_qEo-tLNkwfArF(d$zPsB8c$`3G#O*m}u|b$?MFIF!{WrPnH!l(a)UwTb%@eI`toU z*ZEx|B8mF!*^dYhH#hRHbo85r24{`o8J+F@77U3)xAbqzj9x6CdD-*sp!&COanbfL zufITEkHBv0f=ikGo^H+==``|~zMP=McirDw}2#wCY!bO>`Q(#QU;t;Lz# znEnpzhvP3SgrudV z!xcj5JN3E`+iTR6z9gM(wX{3Z(=X5fA0g^2OZsPTAxLTCe*PYrqD-Hz_$PKYF%f}b zxN49x<;JI3EO7ZUTZS1>^!4=>L|(meonD~!O0MId?!HG#l{N{u?IU}W=m`fw83fyr z>EdjbOVcshB1xUXkV-IoT10YkZl1{L2$c;MwBu3Yo1pX{knWPb4XBeFSGz(I4-R%c z-bGw$^mxx%LfiNyBLhCi!c6!8x>udWHp6s~l@u)4jRUgCdd@3AIXU5v8%f2&=r)8D z&fs+#$DA&kYH~S2w94nkmF4mNciBEH8+{UVBo)8GW?N?*qcKz#{p^?Z98$H$4LBVw z?r=mO8xgfGmX|{sH8HVPLJ?^B<60OP3rdg2&U0W!rypw>4=aKi%WC(+5{4te8L_mJ zjr}db*9J;jkpcsakruH47f;YF$dF#8%v{tpi~|Qi!o72sdtuP7;9&O}jTo1Y_#sVg z0YbN2XLl&sUz^Os8!75>pr|QP_QjDVm-7DJFMlLzQ1rKtPyq?o~xKi1_I18V*Q8 zH#-IVK2ILY!X{fwV7F2=imt^&KojB0$!50wy8L zSW>*@F@6J;_50j}t4&bIPSELf?{vsUR;)Hcd+Ep?b;@$>ebv-3O1D4pUzF(CBnDAW zr@ypv7E0a-!?p;*LA??j1O%Zyu3x*B~wg*!gz9W5?5WP23hl{ zv1>lNRW0^R5WJ%WwY7aykaMj8}<{E_`Qr?;3%!@Dv{WrXu@Q;^G;k%go0s~5+ zPSLyCY-twOM0zFX)zbAdntU5_mU)qQGqrT0DK|W{YS^! zAS@DDlI;%h1=_;V3pp{OKlLoSehv=DIn{*gyvAP}hQ39Cqqcr!gt~YaM}|yu`Uk(8 zk$m`}h+b}Fq5f3xFN^2p<$X{!OU=61Ad8W539PIHb9`F&hfDPXZxT~D3*!be|v;aycE-=6Xz zfZX3%xZe@>+c*Zqw*nWS{}m$w=)vnwg?{3Ea!BqB05G+3>kMgS*{YJA22#git&c8`zHSm?F?6a4;zah)q}NFZH3M6vMiq3nA`>1=)E! zyy5B+9`I>bk6&TmQM9#t@hoHyh*+sxM;a=#OJmw{OByAew1;5Ol$aeVxzatpyV5bz zZya`@J<~xLh8-ua(^|^Ex;^NZDu_FT)5OD5Vy!mkiK#oa0^aFC(^`1nYI*DVCK(bbdU(Gz9ege!kWx_M;@h3_V%vgnve*0LsqE$pKI*IiKhC zh$#&aw&dl%0Qfttpa6kEr$H}g2mYXNX5T!pv%c+Qy>U$)@{Z@AghJu;RaNaJ4(5y+ zNg233cRx_w`OG>&&sTYM*31HWZhlw(Qr-c!Pvt#Lr77ox>UvrZY1~BPV1R${TM0bP z%wk^qc20A>yq-k_%jpM+*mA=(I`7E(&`%J+1*g~?C&ro=HS%8J%nZO_Qx*%Xe9zfwi0qDP&6B1bc#?5ZYv zxfp01T=bB>eFm366%e9ED=ID?yd?G@@X+q{OrdDdR7w60CdfW!ATN8Eg7Jqu3MGFAG@ z39R;x4qRO$dg~LKA2-aAmnt=yaU^GsKUAj5@0_H&Xtj_2!=P7I_VX0E7w}rEssk5y zDA!ecw7<9P&sI6O%l8T`@&luyPc@}tv*uCA9iRr3 z*VSc+lN%SogJbyEHaLbB#b7D-zhKR^iS#B1Re=xEyC1X8C*5z4J+HJFy)|nQ`aL~Y zz+gydmUp$t!@bN`h~~Er@L8CLaQ!)Ss*krZ6kV<(_U%Ttn(+P!Z;MN-g^%mG3JXlH zcH+a-WBwcEZf$vFU$9%1PrJChHRg9?r%C15FhBK%l$6xd+E6}XN;#KpxO85{dr#de@``#ZdNYe@SrM7_1stf236?FGWmtKyw|hYH*+0kWMa`PF1<*3Ox6oQ7*pqqn4XRGT_sQ*pD? z;K&jJJG`QiGk3ZP<~xNe$_1fOtqby|bc=@(9`uXHi* zo8`EQkgulO`pn^Xxw|fCCEu_Zf^`CMAvhQZ3Hd)R?$+2!kbeIp(|MgjFP8m$f#@s} z#7coqR^(gRpCWN2&oZ)?YvC?yc$iUJ1Tk!EAau#cAazE!uV1j6-8+^bm)=|RQv`Xi zYb*d1kzUGq!vyiWu@GvNMtkE>KHY|MaT&aH@9q4kx#;2LInLF=ujtKUImYrIHc6nO zx>|BL&)mX7P)G=JcW+N#Rh4~Z3SdT3Q(plne5~9&z&$6|gUFvV8LV%t{|b*=vqmZz zvU#Qmd2JBXIaB@#H4#6FacT+4MiFau0J;}ZZKDZMe9$wT=&Z#2Mv8-jt8K`JHs-(; z0^-`0|FzE0C%csO;Pk~I4s*-Gwx-E){jF^{*<$nSGgmG&o`XAdpd3jt7@qUDb9U)= z#ZoPpaYeuw)ZWse#p6bjrGG09H0DmC{@5%Q8REuRzGZFsM?k=}q=~dcJBO-^)VW=E zo9@+`aW|somQ{io+O}mr_O+oXisQ!R3%YQ7XWjhR1SXgLgZjLiyt88U%{=w2RUxozncamgE z5YJK-CW?>3y(q0_u`0a7`fm>AjE7J^S>H#N_1ML)Bi1U&iq`SMCi zehUj)>zkWt01*hl&9R+l^^w`h|hLsJ7@CXBU~dt~fXIC24E6gETnB{#k^ z+&T(#k&=F9|MG$dus5#j=ZlCYwr5rT+3Td{^K*6afIioKEGvPLUP@tM5gKd)tjL)f zwajsuB!u>2cpfJ{Z=k96W!KQ60G{oc4glc$;3^Xgchy@Om8Z0oFF_o_em1IH)(@pH z!U0DUH`h4-NCW8Q{`(1^l0!bURP9J)=hmP18fv1D$R14pFTRLr(bY20_o`mDQ?SAj zX`o;qJ?jAzExg1KUf;x+;Y!Pp2HN!yL3AS5m$BTT1({11>z~ct(Ex{Ew-hQC91Qp@ zwli((;=ba-fE}-4=xU)h5u{@(#;K<9|+juGoNAXaEW4RsZiw7{h|Z z5R3u5VMv7_UAT&clMk59R6DRAN8ylE3N|*;|GMt|oS?M66Sgo3>ftooo;&3_&4#BL zN-}%JwmY^i$Q{FCq4BAuYjD2Qz8@(#q1qrK@ZIyOH7nCL<5l`m(;UE|+s6#49-|Yg z2rL`2f&QF-RDO^G)F2qOCotiC1Qi=JLRhI;t3s%K2^yf}r~BR?lto+6ZrTdi1Oe|- z^iFZP_WdKe1%t05ENW5ytk^I95`rxDpt0W@BclD=f0vC>9XX3#@;rx+l$l(y5zbCT# zrNDILUXP23iM9AfOczo$hC0HQ1_cLq|Th6m=`$&e2@{9x$MRap{73x^^V>x6J2Z^@z!I`JZi};1NV}XX@TwxW^YsUdcg1nAr+S zsG-m|=Zq`%};+;{*)P#6qp($K7(%;lHC4x<96c zO}F2wj`KSJ+N0p01#@8#arwR$K?xQP>TmE*>qd@3$9)qe=6AnK@w*UptL^JwXm14* zfBNptnsX4N5mTPi?#|7PE@_1K{C)>a;z+T_P-PhsB16kX0I83rqAYs^s{q^k;M}<0 z?)b@xk{+`uYG7jNYg+zEkc1Dl*V4_%U&5y7>5hm%E)o?pl9_gpeM^%lKdx|x`?K;p z^4=hb0TmtFFE55|=QJZ#bg(QT&k+UJ4KfK!xpG1|^+WI7%<{=rM*#7~7c#O+ke8r> z86zPjtYCbDjGz_QQVvJ`HsCb|<&T*?e3o|Dz}^nFV4P-G(!>^R7HPg6M*!Dg8($jY2YRk zuN!5ZZ>i#pqQolEB&niVyp|uQ?uAi~{P7oBFp9?o0WP1(2QoBbo+bgVr|}F$KtMIu zMM#K5%v@Rg(K5rT_L1>10SbvQA%a)jy%nrH-N7qnwf)+28hn2-GQN=}Ku$(RY)gtS zLLM%ZF19D(5WOu2`X!U#Q$M)QjbNA>0ifNunysm$_nX;*hem`6#(PzO$0`hGKwpZj z#$gKT&)pv1Gg4;D@kAa9gjy{cn3YrZ59V;os;~^W#0(N9si?R*xM0=B5^&DBxn7}d z150{%dMP){CV|~=Q{R;8Gg0P#cU$(r)|EXX8U?PBUx*Aq1h@Vpg3>oX)e>QlKA4&1 zbbQnEOYBqNvX%P{^X0u@CjYc*2r(c6`$JGuw8YT2;2~Giq(?q>LXs$$;K;m;al_(< zpE3;ZK2jrsq(Rjv_}=oX7YR+2K0F+9ej%GhEPBa33-{HPx%ltDre*Ncz=Lc<&g_^r zUelAkC*|bCS$+R{V=ZjId6KR^cNgTq5Nc1&1Ep%it57p*?bE%iLB2E=tr zCZp>Pyyx81AmdUeTkIYk)DvAK**3BS2UvAhRa0Yf*52zJB#dB@{TN4P`gk7oV_2xVgi?W)}JJ==mrZM|NT2c$!vZ(dzRIh05pFVGKk-msp#*& z)+KR{YUSE(b}3e-QV7#eu&OKy%Wb=P798Dv^RCiNl)tn!?vIJc&BbLOPHFqqfDFm? z7!$C?f$D(EyNH;{P&}S=I6mng-_-DY9-!swz}lGu&*3%aPek6Pro83sA^XK*3*ikR zrZ$7}k+GuL|K*vQqO(ZW?iKyJ`FW*;jVyB8z)7hT_flLo>n7ldV1XdvFRs^_ut2nN zaAg!u6UZ>xTI;Hmgn>g}6&Cxt-c?GMVoyz30w!du?P;X04Gcf^n5ZCSVSZzd+|R{F zS-mRRZA>){ZjZVwX)t8#Z4@Kv>>M+_L{~gb7mB*ikhpbRtap0z^aT8eCMVKaujPav zhAD|144kE4jw5_qajRyvV2q0}9^UjQca>gTH!}6_bed)4ZnTs;1yy>HQbm*6bFkd0WzFPjUVoR|4z9`M6`t6Min<@&~hXUp0E9jQjaFkYLGlM2i zd|L}F;Tnezi<%(4NoW@)EmYkRmrdwY1A;w% z&V4P8Kz*zC@EF3C8|#YUIh;0bKc_^fEnN4D7=D-QApfuxL#N8@XYl6VkfGq&XZpIA zR7}Z-2CDQGMhwRN`WMXe4+rX&_{4c!#r8aXqN%T}m0&vkzPTfrj;Kd`i-nS&8oaxx zO2{YHy?Puc?df5VJ{w@&y#w25vXg=v!wnkxx41Gd#yH4OU;LTv>3ebIdH~O z{7H`xl0?!@naJ4#!`cOI)^5;fzDJGGGA@?YUJV10ik$(Qeg08zzyEbee9uU4y?t#r zQs5#eX|iM8-dN1+&4uMaU!j(wQ^qM>*+7aU99ACGK$QV5tXet5l(bo_r)Ls<+w?;M zz2&vZi;GCusbu8-9_icymrq4xisGoyqR$WYsz6wp<(m;jo=w6%O1ZNpk&p_Eqpb0$E5Ij;;-+Ku=(@B&{>Du+=7R% z&U0%ct9IJoj~88qy_aC%|1;jaDAh$|F9M1$vz`Y@Yl*>e9`|CGRmBsoT``{5>5lnNcj3GDI=?KBcT4P+t2+IX+w5;! zJpXC?7T$9wQES(-BGROpy)o^$s@(R&&dqi8sUN2b^%4l38iT+Hyn?oiPdIeAZMRJg z_9y6BPs;py4?hrgnzQan?|ba>4o=OxjF+svi4-0$ON#C~rA^jue5!FsTF)b|Z_>-T zn%#DsJ+FYV|Gn%;huJACfmfEjf|+@n(lX>}TJzVP(mrqJD-P;pfP%T1r{L(RCm!bP z!m-g4!ROIAYCeDO{CG|I{CdQz$B)Ek9j1A_U||1Fyr$(5ula18`ki`3JGIcYw!6D8 zvEY98n>xX>Hw4Zkcc8E|_>_ICph>fkpDTU~Gk)C~@F0VqMa#~7-4nb`$@L2m>3I-& z^k^WF5WT>l!A5BYj`Xpr8s;qOR}?HlqcDXFFNb&h7Ixb&f*#^F(4W_i1J{eF+D_a0 zh(0sZoa$%@kW0bciu3n(M~}|$2QHx3l7XW$!DDLraD_i#rfVWZb)@-7E$i$A z_6sQ66T(G1wfEexw7O`d-zsFu`P<_=#Qt6xL|3iSLrp#eORV*)XQ?>~Uw@IvT(<4i zx5WfkJnD%GCC`1B@vUzOLcn2OX>0Osxb9NEUan6+#yRpP9`Wk`NaD5q@c#YT#L;RA zb6YUCPifcG=Tm$a3gn-+=c*yaP=1A3Jha zdd0tzJqMLN@9%%H!g5ycJ8ma+WLC3#AZ>llzoI{nBOGFm-;QJ}(_em``l?P42}v1l zPkbTUS4C|?;Br5C^d>L)bl4pqiO84U=dopg z=sMF}2)b?K?JBR_(gU=Rjde#;wwsK{;hMsl)6&_BCy6^mjNp}N&HVyNrlt2tMG+pz zs*SR#0$mXbBwq%vs3$_#idfbvH}BIhh7{=eeOW-L6*ekKyy{0h`k%e(W{-L;KCOxD zKpbjY*D+g3br=!!-OyIA*u#^`+)WeXmDi;|nf`>zo$Si!muyWsGOW48L_T(JqIbo( z9GsjvXHvItUq|;zcM0Vu90+xyFi@{w)b!}-w2g;dUaGn6;0jNipi+#CWx~6Ie z=jZ13Lh7jWOR1Nlavys)8b1O!&OFJn3tYdlizhDD^NR(M`Y~OhG|*J=1@+B2EE%I> zf(+8HwH=${ZFpzvcx&GL=nag$(Q2VeS4R^YR0dai&#dr{i{)}_o!S5iBvDj}gN8z< ziRR1ObT{3c?xhD+7i4^1#k1+^>>krv*ou}*Sf;1fK_qRb>Z@NBaG3Nu$rS`*vi5Y{ zUKL&q9yQO02DizhICvb6=mlkst(4U-cJA4I{j74|GW~P2())>a`fU6olparcnfNj} z3kz2tSWa!i*}oR+3H(;@+3vkq74;8^nKY&+r|tZSWFLhco@`kU)gG`E*?N%jrAACq z`7yO~!?8nEJ!ErO$a;M!pZYk&;#oP3w4~HH)DmrN6r=dQ0Pi#qZqn8+{dw$7w``MM z-~oB6@=E1cnVQDwX`Kb`i`27;$R>+_#);>HqWF$iSQ&52)^|GQa3;J^??a{JeUGci!Ly6@v+`C*pSQRpcwUr(q&lf=C4(O0O~9u;7& zmQe<564;+BC9Q|zPMVN`kB|>BcujJo>43G<+gpomVt0G#xA}On+VOd6(11?bx?+f-~W>qT5-c2^Xi=pB}b!MTw|D<2rtDwV>^ zJ?qI00%^xjt<*T#H|khe5D&ag;5x76=-7Mj2R>xtO|>sJ26q@X=-RsB&)d7tI&dfT z^D5k~#uEV55Ksl1HyBfi5^|=I4jzd6-2)^khUB;sr5ftrJpFWRSEP&e0UN!KoD!=X2a`#1ZSelA6k**xmHwFZvl8`IQ?^|kgb^hg4 zIFVHBvQilM6^LPiEui+ip9Y4GAiZo9VplBaPJix zNC?HC%mXJa{W}bL64M7}?j7~^-)oI=5K-4RHy- zDB&JlfQ>5Kjkr3jomS-an6HdZJa9Rs3WDF+)puC4wXYu=@R?^78C}pO=`+DNoI)bf zQ6BbG*U{mnej1!oDc9|vES%?D$Rr9F816W5@mHkHQQBL!z@?kn?6qn7T5h=5?@Zmu zeMb91L8e?iRbZeyVOra7$uwxpI%q*LCa2gitcZ4!c#G(HHT*t0Nki}abnKF~2t9>) z>~aeRIzR9Hf>Z*LQlJURUcK9`W3eF8mLs8{V4Yd>YosL2+A^H@R-+Im*nynHm&18s zcE)J|@1aS7lJw2}Qxa>~158n(k=f^nvIac|H=B9Peh;aAMh- zQDZ292<0k(RkwGnJ;Q{8qKTqKr-92@>e85^lbS*pHmLKXZ76D3Qb zMwoo12=bU^!wKB^k=EA*t8d@EFJ0Yo%!LFsN83Y578^mfx=QZn@wv|FdoS z%j@q7<59?^Y858sA7p5yZqv|;FIL(uAhl7WtE2mEM}o> zlu{YmSoX#zrX*J{UyuwIRQeDVRm2+<^SQ74jUZGM#+-`km$1LW>7mxD;*D_Pk@9yn zz6vFVrrq<^&9GgIN<(W|6PJ9YQAA?d6LSNbqUK091&s2-n{q?O!y)p1U9ilaGE>32 zA&4$YPHD-lK^>EGGz(Zy+^Ug4i?X9N~%+4&iBAX7k&520=jq z?a81cGnktZ(d#GKiPO3*0!J|Ys^wSyv%q(>n5q%@pzX??QMRg-OxI18NSo9~TaceZ zDS5)#tJc4QYRc0!MjYuzV7;r;*^x2|c&J6IMPspyS@PBu#nQLUa}w3y@nqKx zI;Y5~JyNC+a;Y9lW^_7lPFyEWbk7P z542GDVgcXwIo0$&a?MgocSDq5QqjtqcEjvyu&5nqVAsI0ffX%Qm>Uld%AB*qfDLTK z3O+dME*~_hyg5mV$kXv&KOK++@X)E=6RwK7gZ>S5`H774MSypr@E9aAP{={v9U4lRY`UMqGB2 z)Hj!?*HAQA@Pj`F)1CgOzwQ{E&=4TkyWNfpIMe}WX0&Sxwchzrr|K)-s*v>SMZ(!AUJ!`?=Yu_;ZjmeR%F#f1 zzoIpNyYcrW6q{j+2lMQlYunUvZl(+o30(=IcYm7^6w6qzcKq%tpm0hRPXYo6`-7Qt`l zW|N^05uFo->-l7JoBpo=DmF8e4SP4Z(LH|~h>Q<=A;_4{9GTh&(kRX-*CX)%3co_V z`>;4c%cDi8W%iFjD%R?1yT^St&TfF$VjkgwrrfKZn1invfl~-XIILT-CJZLlIog--^dx95=bP7w z4&Abjyy!f%?^wIYY4Md%n^>=2<<2vv*80|>k!g0zNAclxy*9h8^YzMw$8wEBLnC@$ zpE)X%y5Rf;Q-d}f>K4MBDUEaevPTB=A7SNLZ%Yg3eajXoF%A2W{j$+_ zSVK@AOXQ%>#s-o3p?TW{t@YhR7g(IdBY&W4Ga_yJ5Nq37nMSI-Xhstk)_AA9LGR?) zrop4<(~oM-yR(^FND-w^OKS2HG>Q17z3w0py6=!gbI_pW-w_j`$w#Gsg-ix6`PjiL zbYEjWt#|t_)or7OQjr~_(Ii-w_Kc5H;30`w?Z55C)Q13bg|~bbQpsHY4J6evz5k=5abVf^Qk5 zUw1y~;#f9Opni(}&2`MM=axO@oHm(Pk&s_Kf5D0GUg3ZX9u72dk9LV03QjwWIVgq) z>KaKMHEDYc%E)x1cTLeN&x!bHCU$u1AR4r|lGW=jG`yk>I=VzOsD>HG=89=X$?3w=0FLbT1;6a^a};ga>s-VzkEjUoKh-A9<5&|AK0>Wb*U1kfM#yto0KS~7h@2zgeUlZyJW?UsI z+e?WwRqg5!g+7{!0pqSv_BtsW4)#{}5=kMSe6fX8XP>KcRXcH-k6tGfT|RMnAoN*4 zW%xvNWZcV|eRJ_fexiAdH7aIlSm-)Kb|N9>X}ekf{Zg0RcQt!{tsMnL$kv0*t|O%2 zZ>c{`PTU}KGDZ>;o{;W%9(!e>8yVZ0NF=psR3}*{C$99<0^GD=u0SKyC!#-jTDh=9 zl}f*ZmNHFswo~X)IrC>Lr8I`sW8z zW+(T4&ej)iB;^``9dcLLU-|W8$Nl{)pGM6`va;DzUrF|0Fq@>hqip_$suPNAcude>$_yS9w(YI0 zfNG@0v*YGiHW4xSbVwlgnrX9=vkMiiFhd|u!kUijFL4rZ@GF4)hhV(#3*@M;rA2SL zliR;B{)ikFb1PTXn|R@X$e}eRtbKpvTMQVg92LMe5izW_7fiE<_lnBU@JJv2k2#(} zW?VJ5K5eVp-)CCG@!pW^?G!_eSs3n*C*kcm$!xJ6iRN3PXeE|0^zk8Xb6~t17v?AE z$`hYCs}qm7MtOt+iEItI-zJ^#kotZ=`^NetVr`*CShE2bJuSjO-=12=A5iE_W5l!Vy_S7zFp=79IP~o+Ut1W z9TsG-BxomnUQxCi<525l`ZM_NeJaL zFHv{Erpw7A%oCH~r+;Sw1S)zqKex;>F`&v+A(ENgj23 zoyzAC*O6UWX3=qh(_uoErw&kQNyD^$;f&;+NqFOit& z-#(9X?Il#CEYliwg0V#m)?xyo&_HK2Y@z)}|psV%}nF;o`mVsJhQ=8{_G=qBFD5rMwrd+>v&4u%=F$Nak zDY|_+X0e1ek+=eju{jnNQBV)V{_crvu^#me^G*vG;ac@cS7#~F2V!#|Uc-yzDVa?0 z(Z|~u=Bbi1y_deu!2;PG1nCo%Ds@P%>d~6vuCqVi)pd{W)6@D2PmEGsjp+;_Us5jr z1jj1gZ54IIGcfL4&5UL$;ydd+Lv@W<{)RakO9N&n&OQ5eZ7}8eKxm0lZ$?e4$co^x z_IG|r>GxFgJolK%a-tTzG^AFa$f#LZ zFW=E@!=|tt7W&hZeCC~i_O&gJwJLENTci=pW*y%QBCwm1-%s|iw#6ZzzM&zQlOG0{ zcd?B3O?*3}1%N4fWUQx^kJMNqXy>nZvsILeF#IO??S|vsrmUi(vfO>I=C3=rB!~MU zy%UGmlXdz+#?>X)cy}J%y%S$sZ*n*13Ro58H!u*fk-g&vuD<*peu0K(KbBNc8P7O_ z7)tegd-eq^T8aI&2WPL)J`n83*QL*M3hqq>NDR${{Pw4c&nX2HWtOQql-Z9W`L@wv6))Mc-E?NlU_0pJA4oSZ3lcAa z;$IGIc%Ih%&JnKa*)K}S(S45w1T2lDpy)}kC#Rr;>;EcR7=BQG(uEzJ>!4;K5`jaH zX+mOI+k9%Ddh2yvbzp44tp+*GHhH#Go8j%-2=Jtvpk8#N#Z7c ze(2=Pz_|m+JSDOGUmatlnF@PpVWL}U&a^jsX0SvhvEj3wpOsc^1+3@+?Y&P&hFB`< zVS&^O83Q*Mje1-t*Q9BiLnCE7q<2p;unGC{7MtOantmyJPL218$z>s;TWLQ{=2W0V zFn+}0XrOBm@}7x4(u{sT+5=Gz=`A%*j9u?kS zhjW%Ne9(2SDPcB>iT-$eAGF>9y|M&kga$(3GSBlV-c+L-)XZEFzD;8y%;YB=g_1wji!je9{-;OXtEjaw6Knq-0#m$L8BK97z% za>in*FU^ZhOZHXmoCh-nw&Ewt;GuqTa>foDE>X=bx6JYmn8V zv;=oASbUfNql;nHbUZebl&&RR^I~cH$rxj)d(cl|Cx+q={|cCVB^cRX8*w31SGv&1 zWD#W(*F12LjKSGm?pds{UjE)Ti@L?!k$2IX_H*}V(K(3%Zb1_8=Q&a|&K54BH0klv zu$ZIvAqy7tg2v`U>ZkRv!bLcl!gOLOMT{t^`OnIq07Ke}{YyNQFI`p};JW1I$FuZLmc zI+rAw@HCk<;pifWar7O>CpO|*xwQaxzxtVilgsa<^NKmErx;=4_wH7xZI)^6%qa!O zTyq>g3qpayMAK3#+Iu3jW6@_#$G(OU6MXVkozr_rgyBBYkFS8YwCd zwMaZmYF!U2Ksw%p<3-|ZGW}&37f2R%(2x98 ztXoN!YF+5}Tk;E)Nabls1ZCMX5}zE4Ga; zec7e;Zwfn(eR5YHZftb+zb8lJClnQT3p#Z<9KCIP2n$40oanlO`>ewHZN}QDD&^e1 zuB^Wf#=-8tMJRW4&c1C~Q52Zx1T~Bx#&wsO=uxQ18^yfD=80ahhj;A6)+Ajg(mF`?Yr&7z#pAi zBOPtVOh4~)(c!|3T5mrg~ktdrMuZG8>3`}D6IE7$dZ-rp;D zjF|8q0$cJ~>pM5wG$yRamy27m6XYV&lEUs@QRoA+)Ui7q&jVV}boBjtPuC9MLHsRt zKg*bumVWCi_Sh|3R`9edC@UQ_{Uv zTK3kPqg0(}PyHUSD94nh0ZXc3t;2S9%8>TOdxU3%XB){tlSmeso9fkj_wGvk8n}|| z_;?|f&`=+hFV8bKGD3$3IWOmnX3W0~M+9hy*Iu))C#uZyvm762g znc%Qb0MFika!V(`ZReStQv4FkW+$4HP8k?Gn0=7-uw2`sT@a)Hz#M_wWd%`UI$*zsB`jEU&Gl3sH;{ zyIYJWc8q(HyF*7c6=2WpMNJP1Ztjx8z9O72e=7^`F_O*PX+8OLWfCU zwwY*l`)qpGnUngNQ~!*&E{K~+o+r`jF^n!4>TNSJ>pIB)-BO07h0eCRQj=lfu8~Sn z22;JFsb9ZN>>AIZbMhsI9M+0p|08kzLCQiyk}?-e@6*w9H?vu1$i&m41e(MG1|ef(-hNUK6^Nf(ue|1Txtk0mD7GCJ|TXE%d&WVb)|LVpU-MHRNQ zW?aVc4l2oJU}9Qcx^wMvH<7J#&{S03zxRsvn4pMfy$`m94-Bg*nwi&2K;ty7%B70s zVW9he`3aUj%c)&W6(JO76NE2!k7A?FPgOwoLYrSN0nTyiFr`&{23?DSVA7biaag3L z6^|tWAp1%<#|eu6Mxdg;NCMvhByTmx~Jo!a2_#Jhi5mFxUH zOhOKp45mI7!uZs$ZK*Ot9H1>mzcHfN+$5fU?z;Kx1oY2chQjjSebM`#oom)I0?{+? zYI&m$7sFJ6z@$I&fV{5b*ap+}z$A5s+9>~&gwJ@GahT&Qh;m|fPV*1P$ysj_%^L3b< zG0l50K-#PCp40bo-syR~RVU_;@(F4G8F0bt9e^qb+;B<3H%H5|3COomd?Y0cn-la& z(O^uVLqarz;J|| zjAD!ODfEXHJuraN--#m^@I>|1>9wR?K|;~6nfUPeur2jHtbEQebU~28x7w?Xmidr$ zwRkf5@R#2`oEKk`2^<89<@h~V-kNd)0Tb}@*C=Hcc{sihY`r{EkQjtQuj;w(K|t>$ zGDK0)J^9B8p>up}*F0KK`^v(e0mICS9>6a=2UjioZ(ZtxME9mGsRAjeJPBFqp}QV{ zTt;5-h0NvkpMVSG=hlD|xx=Tl+DIm0I@_v3ykU$vYBc)U#z^oXEXHuu1{FpkpY;z^ zfrfvF@Q!{m7x7O}Xz%>1Ly5YkU@^SEqON>WFK^)u3gY4Z6L+x%DqR%POR{u*EkMVv zo+=POd#zP|d_vTKha}Z`l2)?<9t4bn{$u}Cf5AxGc^{8H+f7Q5a&ze^D6R%3(!#vm*z(WbL_%WVmua zc%kwN_{e>;wO8^v3HmH~x#9BK<(h4TBhf`+BZ9xgtC3$?#=au8UxSy`!U9G@MT;GF zt8+U2N+jpqkAg(E+gdJ0-RS^AC_QrEe{Bz_N6V)G`~y|~gm>$UYF*-fKRzkI~!j|?YLhEp}TTDd_;b6W2Tq>52PbX8wjo>G_CjK61T z&W~_%9R^Z4MREbi!c<|{Q zBbL6ujE(%3uINqTFV*r=nes7-7Kov9E-B);P?VnQM7RhxzV3uSES% zL9O!-_1{`sncheF;C4gOP7Ll?2&(A| z%iw1jr6*LBeHy>_C#iODhTC3>m=j3>SG;lr4+oq=hV)fAP~|zjd!I=&Ww_a3bIszk zDLEwlwD|#d2>bbwrSjT~(Q7_p{moK8uaQs&Ab{M5NvCvN56v9&NJ$Hfvw?e?Y0)?y zF=vc{OMvGmQ|uRP1AC1tPzo!PkF5(;&m!ak2j;#VUCa_}ODTeYzIL{xndGCvgh%{n zRJHZY74AAK5bK*W-`7B@*KTE_f;!6>VLU=(q#awGSI7)6n4y};p}p}}4r zTh25I2*o#uu}zGlxaFj&m6(6P7Ob!|#|?GusWlz)7jNvfka}hrEK*)zCAe}(%Qfq{D4fQcZ=y!tM9046kp3s+UR`v^ zl8}pe6VZBL(cuE{2vJ(IKdHX+LJu4H$>e{ODGM5!3@skiAp@#HJnoT3+3{%->9!Ho zoX^ceXt8iO+ke^XnjI2Ue5n_ETTD-4=>hO3|kwo8xAsla6}LZ>hIUlLT~ z)>mSMr;YzLdLWIxO7Y?e1O5uz#+$^5_!zqt%LoG476^utz`m6p2@1`4F0T|`r`%ve zBqOB~Js_7T{J8g|?ii`#k)-DR?C$;cOy}8$60C#P@aD?Vd?&hhwkjs+sKi`3>`FcX2L6%p8W8}b$`^6h* zkArU?$}+W59R)=WrT_W39)QK)AFW_yKU(v7?@|g}tk3K+{!_W)Hch5@wj4LDFY-1J z136k;SC=RQnR?d44vS$;_bree=mo2&zZy!#;oKtoXP^9Ck?}io|Ib>=haCuch9L;Hz}K@m>lsEHp)X!W zqBwWFcMWjjGpOgY_cqj@AEM^^toXh%a~%R?bMe8RFY{Y!?I>>PjvJ4|8`BMs207aC1{8F$>Esco75z=SQ$y50|D zc=~psZl-WRw%Q+X7f1906S)x1KPb;Q#WjtxuuTbINkw!Agp~moMCEV5_ixqEefcifWwQFL-PTFKYRM)FZ)`9rcdz34J9va>j{{K%g`1K{$>G!Hy0h& z@3Fq_HWh2&ZN2y1}g<-Lh`GSLQjnVY)- zfRD#YRjrY4LqA@oUog6ewq8&;+DPS<<$C$ia1p`>?rO&zMY{lXJM1~3?;l{K6y9mU zlJu%3zXT7!t-4dAadsazS(^7H**?bG< z)&QLCZL^p!=D|OgJ088b&p$w|aslZxx?!y(Rrv|fjFr;+#zHd7FAk*vW80LFxhi@} zisZiD7_o{hN$DUz6K8C`xfe;=jN1!u5Q=K$3DS~~9s8FZe%guJiO?ZLGh2o)x#mBT z^ldZ%-S!2QKB#q!b=M_F)X#gXPs2ib@kLE*7dm@KB&RDl3M0R804CD``Q;FD?(m8P zQE$g24}^b=h&f*O1g9{eJhkm1^*4V07s(~WhaNcdWl*8!K86~*HqXvOVF!%s91F;x zpaO~xD-gIU#d&cW(l2+*?qA^2msep`zqzG_v#PkG0wvQQ-Al$MEF?qyC;4g!vudxF zKfO;TYv93|x5e2NAkv5_ zgg-3>IQGAz^t7~yv_C~6ao&yMMu!q{FkAZ!h&UO_Uo-xoOI5uf5ieKN$PHM~=aH^u zwM`tB&ovXF066^tvks1=4FPG6!N=vBJg8l+9>V75j{e;G@3p6?#;X|bDM!b6^+h~; zy}WvT5fwcpEhX_lH7+|DpzG9%F(u_r_6ERTC&`&WIWM{Am779s^@H+lU_hg$qXvv; z3AR6rP#d)10zIof->-$IDP8FnKS?|CKDIC}t2H4c1#``(YWATC0uvMsOc3=Htf+j< z<-1aA@3)Ec2nv8pHB9gf5$uUxTU_UTB2Fq%VQnCuA0n)N8J~|6HhA@G)(<1A?_7w? zb-F|{M1YsZTdfBaU=K#`ry*LBLLYL$+|~@hc=y);hLU^qUTA zjy~_d>@Ft;CsQ&)2KYs08G<%%+hBr6rE8;({p4g$V>JpvW&bb)TUCeJeava;2(%sP zgCickD|kN}=W0@Ff`@Hx%D{+0L*ZCbLhgjeN>ixMI1qT=5=% z_YP|VPA_8#^4S*rGek!oq@u3FoS-a(NN0i;r^&Oj1Ub^1sQY=EiOr zFYZJpaUmZetYCi|NKlv91Ix|kxHR>zvF&d;c}G;g#47J|!#9(88ejtVkUz@K%{pU$ z0RhkyWhI24BshU6Ne4ihpdl#8UAI&7p@A@{-SE^Wv`4N^2pGVio@YKdWpZ7NVDBn>s^f;ZMC<$)e?l}MrdYHtHn}EoKXm~hb3^9$xRHch_R5?C9{YUOx!}O zd?oT30H89Iu{cLs&TUxmkrv&~7@HppAmQ`jN1FF`sn}lb%1-zVdl{{Cy5a@mf+iym%=a4Hu5=-M{sEBB7}j z2-G=lJv8{MP=2gvGRqPR@^P)JW6ynG3n{*dzILC;mp;&Fniy|dk(qBNcDQ)(@6^^!Bv zfjaATWM?|g9yK;FcDzF=^HAU8w)3Jps>Bd(VXw&Ix3egNcU2x+??rP99OdOE1a1#w za`R4(jzHtu$#3aQi zPl^bX5@E>%$&9}xZ;MRVBj+oqK6~ZN-Du$IShSX5f9F}5IrWyI4e6gb<^S*Et`~8T z;kL{;c8zyTuI{$!nc`Q=UnCf?O6(}7DnQSNKhsQFGjd^O;J}8M_?d=3@cVM??Qxl! zpqOyr3gf}YdW8Q&V_~$VW8dN%Zq8dAEzo!ffl8yC&8coLaxZ{Tr(iMQS`5RMM%825 znv1m&f2#^E;l`FuO{(}Bg4p&K^jzY83{q^ZkUbL)z5sE9E^(xt6y*lyNQ`tys{dq1 zPWdoQb{j%T>d_L=2HRwUELd)xESLGHF_X@lFS&c$mX7|Wn%f$J&FWL*bH)U~-#aYW zz$P3yC;gvzaL_<*&iI20Iw2!lfpZ&vEjdJ1Iqo%gUdJBz2Gu+)xbys%Cy5DdEWDqx zbY^u?(!qg!jE!VYL4XTK+BH_Boae;(irC4R|3#iu$V}k=(vi+{Mpz`jQe}d^M91sD z!I(y`{kqk)^zBmz7Th70^!)}d7j>=zN7JNm?#g;l+W>st417}_vA8l=vJFRGNuCL7 z0qVac*7Mr*KkUtqW~fM$R!>Km{x?UJaTgSd%B+P{mc*Wi0}ZFY-gaO8Z{_^4;&c6Z z_Cxkki0?P3r{i6M>pS&Uz2h68r1o9ymzQs3FL?lS7rNz+%W1u!nZv!o4uBI8 z!q;73*Ux4;y+W;Vr;G>6xg5M2yC2o0Bp@Xvko=l-xl+>Ax{PnHR$s`~1ys63w3q-+ zn49ygv&D8}(824S6;13xxE@bI*?Wb*tt&vp;WJ9pP|1TEwA>&9ogMlqiLoxDd(VhJ@+QOVPtqoAr2!hR`0C&+^J4@uaHmV{hgEVN+re94OpB|jc*PfLd16R z=-+2_?woB@i*Md|uImDT_iW+rmfeQ7fQyjxP-=k?H7Tx- zGnhq6k@JqGORs2>Q2+f+;N48}v5MDAx+vAUtZs=Rpk}3%oQC*kax4M2j>olap{M=U z$TP(miE`Qge%$}8*4X1hq;Al16$-?hhpqmhq@YZx@+QEl;g@Yti#p%Ok~p@A?)2xq zkfay0EwA3);z!R&o!o!ap@T;LN0P0V0#4~YPucP;pulu3ff~aHzwIf%t!IOzmInFz#bq}h+@;*aDet_PWVrFUK-t@2Q z7G6$F(jSMRJgQ+`{BvW*MAl*wRRf`|YzVyXi7@im1*_XUF~{A5g{|esiZYa@zMttI zpYPNF#7YiptCdT^n*;oOu?(Ima1m?f*(-d2;w@(7KZg>7hYu1v9oODD>7^BZ7C?0y zUPHdqnJBH*?(X~MBq>MN3R|rf69hK#FY0@VOV9zJGWe1E*oy-jtJ;4G>J|qrZGdvR z)@k)gwL7SHUvc|JC7(;_v|Th-9Qp^N)DJx|)&Z5dwa_rxm*{Jw=@{HP6aA-Sr>V)5pGZe0NOa2MX^+Sm z)_}S;G?qbsqeYK}gnj;b86zF01qo6Wz^r0~g#0Sdi6Up0rD9Y?AB`9%0k#3#*M z*Si}Ln#S=~2%}-8EZ`u2H6rLX$4p>aXz()7VS`X#PMh+#ENZ$nR9rVW?-marIviYY z@J{S2N{e{k@HVP=py&)FnutMqB%+@g#o*g0DmsmOmd<*hcQ+OeIJIqoWhT5&$ldlE zne#S|9*edefB*xyIG|Ygnt1jc{=Oo)Eu`(H2WMlz>;Aphp{J175qTl|8`i%;omBy+ zED0pi&)_dXzRtX7=)=a$KY#9|1qS(YR5!buJt8YByG(+C5Tlp2%@L?haP@}Byzofz z63_Mefdizm*SXrqOn{hU!uYNA*lGD(Qm%Fb;Qi>N;F3%`SP)Bfpvq$gU%86P z^D2USrwqr6BoyOABRfsmMf21G$5>frbsBuk@f;Jv6_)e1ZN3J|+XW0AirhtMM$Sze zKNn900T2=H`IE4x9r3SU-dlInHsf42=2?v`u4a6$W*$vLnfxPzc3jOXZeUh<>kuCK zRf^$R=Zvo5ajy42Wec=3IPjPqRvF}9Q9NHT=GTsE;!=&r%)nIwVT_pKjrQ4FaO>et zT+Bi^4iz?RWY2y0>~pnuJ$cU2+ohu|dVh@!`1dYCe1ZW)!0*>H_fDJirWsBYeKjOf zpyU5Gvqea9NbILWh3}#H=e!aKcTGo=FA=djRl67<+#an@ly4-Z3J8-4$*pvL>i=NJ zw&vB83Nax@nTq20-a`^WW%-M$HHgri@R>5B1O9==(#iI$A zBKJR@6^*W!VP*Bcff5k7Id||pKQZBY>_o712>o(U2peo{1s*L zv%ee)Fb##yHy?SgP~~1yTT>neIF6j17Kg;qh5B_9jq9D<-Y~KM4^veS0|*SEo5CES zg#KSraX}U?Eil@rDO``M2*h_QFwtJ;1kn$xNuRUOUf>r1fe~eR`7ot@&-Y>tCZhj& zaTpBl7un-~uxWl$9Zw*SRZ*$@oe7 zk_Ld*uIl#YDX>$RJ~l@rZQHKA-L@a-wjWskXu!>%KlGxlmz-pPgbVKd9^^OL*VR+q zX!boGt(Azd#Z3kU!u2ej@M!thifcPA@S8;Gv|q*by1z^V!t`=$ z=Z;JaXJ0cByzoxw<9e|{nnYpgK{`ZcP)W7#lf(1uTIVg=XmNnT-6fQ)_OdBC9t+jQ zZm+hk_4PCMx~k{usm+$(dM4TZ`>xo;gL})9{E}dsFH{Rq_D@9mk*75?I$TDhSL)+) zeTg7O9oih6VJw(sS9+rfB*o7g3mduyp=wp(XyV_!BpMjlsDXANv2>;z zcf{8s1k%H6n-r<*5g$S*Q7#D2;tRaWj#c_L&m);!{@MbTo_Yv*O*O+O5N?Z?R#af{ z2hUp1RHep1dUH>!<+o&g)4?BFCd!0=OhX}A;E5Mlz4*0Ijv5AY%R&TYyiE$NbV##i zY?IP-UE3Q9>G_$!2}Eu-cB5EHHhCwb0k`2i0-+DuG~?`SaY*XxRhmn=uCr*#_7O24c5!wX9I9eX{nQUZbBSQ2ZSA6Uh}S8`ZCJiQZ__qurVh~5eJ$P&0lg$nUi%qk;>XvgXW!zSnxXR9AByGQ zDyZ8M+G}tU-f;-*(-Q*A{TV9?{H1;{kvb|(SW_j2GijOz*h|*@6Cbbto6kiGY({~A zN!2hNn;`!667ayZnj2CkIz`T+RjWEq8B^td?{}+Ic^CR2M7qWlo?H@Fw{H+aSK%#2 zUW>zmH=TiqL0h2Gq$I#+bv_5bX&$9~-AWnyec^1_DXTnh{$@SXx*C&ioX3Q4iVY(? z9bVTVQO&9vDS^lBZTRPdWf_7qj#Dv_@1-LYDeSSudgbEh4JtyZsxUgs%H35KhkUr9 zF!BRZtZQtDJvwP4dpw~9c&tV7<+lX*1k*>}a;2|Ds>WzE!5X#~EA0;=Rx`b{27Zzd zC8yuc?n@3a3nak~(^m_1r|Cqa4nL9@;ME-ml+DR4O3At04+i2&^jc*MLHq= z{7J`hcQaDWr7 z5x!S#ELae_pi4jI0bdhyPNnvl$FXo}!>OncOxK|ZI$R{XxiR63lw^yn0Pdr7DMHROmTP}x z2w#o;A1%gK{P8!G1Dp2SGzo)uYRh zFdBzim?niDikQPT90NV@g(%8k2U3UDB?8Sht6A+n~;j zew%V#v@i_udO|r?viI!cL9WYK4Nni6bYgKkFHaFNat>lGvnvtuUl>vnK7jW%{}BGA zXT^QgzY@Ov0MGr0cylDgOf4Q4bJk3Jac-0-3S?_kZ)#en-0vbgiQP4+gs@D-KsDFx#5vpN05?2rB5zUYgw>65dUaO4m;!Zq7t(>_= zTWDYxAt<<6joVcajF=QGu$m{TWn_+=jM|$-rgxZ)Y;(_^ZP^|$Kr@VfRFWU(+}L4Z z|1~_zJ70IIoLIk<5hJ57|9&$R4eKL!Hx3A?3|OeQ={#Fi!;wbB>`ZxvIZQ}%cr^Ei zR~zBdFq?G*4PJg(weow<*11#}q0rX>*rf@Bqr!x|Ms)P@%^sG?=@Jeb6r_)!+$wXal3idnz^4-a<&%ZH z*~sSevmXCp_>7WYto)W-R_eWZDSi-WJ=#6Bt7+U*a-14HLWyEzRH8`W+&-Az9QV_V zX1`Y$p^s7h9&gS-q6p=PuXM8CeLTX?mS8sJ{<>pHn-hW_$Z(uQy8A;qy=QHVpxw`LkfO zRaC<4e0kU7CBgkS58R{k-zljcMQQ;$&R~6?JLF5wvg!&u%qM&A`()|%Tk9#>0xI_% zO9sXRnP+PVl+%}a25cB!{|$9cge(kL&A;iHOept!?N^fusoq+H(cVuN8;m7IF-HRY z0Oxd8_G{&S}!wMs2HLTgjN2X5$**({0VK z@_nXt(mQ1GQFsWoURVc#@GmJL%73!WE1**7Ki~NDyg^d_IPc~v%(U;y{RyGw6AYiGQLTj(?AM&zYEWbq7p~TOYSB|e>pr?*ZXmu?J%7sUHj2Oh&h$hPU z3`r%fJ}WV67(;Npos=sVaw|MS8!XMKE;;>ohW~QTU*5d2SSTUUkp6&Sw@x4hDd&uw zh>>0%C#p;%J^^k5E*ue)OyKK!xJXVyjTaN7|6AtbAp1`a7+j_!Q(f3m~E3` zh1!Kn{ruXR;!M^MKFVDWAYjx;P0eN!f4*yaAkYWC{c~kp5FAkiBT8nEKg1ZPMXOk_HC(>DA<$z1?Yk{IaJote*CD zl=H90!t!i9rorAdj4B4$l>mMd#G5`G(=9 zP+US(`LLxX@vq-#tnQkXjKax$MBLom1B%!=Uv2sh?3-d^@=%lJ+x++tJ~`qhW)F(V z%A#%%(4l{10~+%L5Q~vQ_|`}Z4aoTozR&v^bf0s`@51-yO@EWhr8(cF$@?rXLaT1~ zQFB`vmuRRs2zR{PJ$f)>T1jJh9hVMT%1~_bJikwr6RwCtmKtF>&~PvfIa5g-0zy!1 zHK~m@ z9colkpfI)kXM+3grkb4nN744=!t|S*AJTAQ2P&x~D&1@}CYssFU5?mVhy9uj)5eOq zd{j7$ZxhaLGrnumDo(I&jAOVQXhQqm-kQ-8zF8bssoN0N&J4RpwK>81)B5leY32df zi7b!~adh){00yY-ly5OPWP$$7epNahJIIV+^p-ENcQNjlD5^*OW{ zp^&L*kK&iZ3NuP=J!Hu#oCzsGEp9!~QtgyT(WBP*T=T8(_hQDK(_5*TgsnA($?qud zC4sYbGXK8~iOL*UxPX)5qE$FuDvhJJS0*g8~?;m=E zK0ZXfaHzJ0+z~z)z0&crw#bA!YbtSjYS>?wGvtg7OHDDKC#z{Oi*%LW!Q?g$A3R#; z1+Oo4h7v*yd|2%ssIE?vAjd4cL1r0YH22(|%d-iPbcTHn#VJ*m!gJXO_6iT!EWRs7 z=Lu&@5h7P64#>}}Ga+^1fjXzYTJXDK?r^_K4A%IJW~W*^GxvDuu=(!%(l}Qdheu)` zhNSzCzUlCQ`=Uh4=At>ox*Ua4BkBRxLfFNmN={?jttumfxPbZ%uUOO* zANzpxhk!I#W1h3PWqzdmJz~SnZU|rVF!X%mzBF-glcwb9kCt&XwMm%IDb^P&!a3XI zwuB7n^rz&!TG5yL-AsA?%a0v5D21*3yGjMQ`h7hbOG3N1fzRO5*uNimGJ=q*o6=TA3kRKavh~L1HkyofjC#DzE zN+sX`A|rVHFlum^M|0c?9aa2uXefY^m!#y>TsqB40DRWchc$x%@;hCqkbIxt7r8a8 zd`@JgOF%W=3v?}5E=!4wRV{u5pnA)kB&wV`fP5#4Zs8JlkzRO0=rxY18`gdA3Pn2pi`g44yTB2 zX!oocOf^hAG3s|dA1bge^299+PVkbbgu{S7VJg@}MsZ_v>VMiW7e2~At^aw|i(s$I zjwVb#7*O@A6gc$+mVB&w$WqGQ;+cV9SyVv&Aj}SjH2x4yI9=$M${ffrPnyHU`x&lH zXbqdPO*E?A!$HPNznpzQcBH2u$YZJspn%YW_x54sH3|HvD+b)GB!rX}FaR(mTXaEvvD;7jH!p~Tas**TRPVl4t?&oGCoNF8#wWttWEKOX<3;lI zsg|*dOM)W9*W-$@(f1KE3x!3)4~vSa(eYbfMoUCEC%*Hi9-rTvqR)(iI&xIA!ZRYV z+w;U1^F_tYvOkmlmir*TV4|ZpkX?M@bfl|4S?n=L!MIo5uFJU7{CnMHFX0Wqh@}Us z8ZZZ%6~($a8wxBgiAW-i+d6lxut$|#VoFBLXI9Ohj?23k2w0B{M>$9iS)io0%kPa> zkb15h0gD^XVEV_@W*s6y_}#z!N~7((<&A6T2F1lTY6@-W`Sp8R}hv4-k5*J zq~qiVv7K>vX7ozq_~H}8<^yb3K2mG^hnaOzo$Pr;|FMs>d4=!eg54|WIwEWtYwlkT z-KAn9IX{D|;0Un3>UQCi3%$Ykz`)?2742-Y%OY;D+HMb{OTeFQ9v(-RK*jrpXl`z9 zbhB_f+Q?`dpv99*DEKC~X*BFF^3M3GEJq}67`EpX(r5*0$1qD9JAFAzdHC#7dKNphIWVa3yiLbD zR8)UE{sC-uo!_q(P8UuYV9g1CEC}d4B)v<$JbTvK0ro^|?)V-jHfuMix#88f(=U%; zB1^GKY2-F?*l_kb(;VT2LRuaX8eLjyfuDfVz_Id>lT#FMAN$CX1K)QL$-VF;zZ z6`M*DZdk9(>nkM@nM&g;K!imv2#r%y4ioOb3i^GHeeBAY@r8{C%#4fFxqf1+V&ex4 zQ1T7Us!j~O=$HcggS>qk*6&W-jluDbZ6xv`#=e}Pfn?oN=AZ51eS;zeUte|L73Qs2 zCY(KWZ6v)7z5cm!;yP;8vB8g7AVe(`(~0OS{8{sO_F6Qqxnhe!} zxHP%|(Rja7`uAs7A93_^%1DDgzD7Ki6VB4|t)xqs;fE0FlIu%#YvWV(dJ|Z3M&*E{ z7=*vm66oJ0k}(Pvn=VmYm~5VmF@|{UmL>@v5LLaT<8ab(zH8rP&Ys!-NWS&v{o1wl z%$}<@{uwo(6O$ZgkEIytx`}43;=B7XZJaLTq(D0Ul_0iI%C4~Vr%9^cnIgtp{B3;;4)~b<_rhX~=JbdeY`nz#LGHkIxkw3i!wb{Z; z_ift>VLVCEpcF{Yk&#BC^p9Pg37}_re*svP$cLoQpT5N-?X>*%m(Jxsg3`mSbaY(P z55oq28Sg3aL>_oA1ihTH{QU0it2S;01JxN} z>ef*1B!emNwIph=!hy+TGFj1@?J{eJMsr1e=HbvQU=JYyn$m?sPpy%UN=nna`Xw=kfMB?|_ z(V2JjhP2IPlt&hAya%o2+F*bm8X34(M?xw>l6m@J8{?)n##*IFYSl8Con+K> z!$thj7q>GS)V2=L`cqJl4eyJ73hqvPFHl^SUBBJ#?oB-a+b@|d1nh32Q6n6_-?0hO zJ%aTRR$W>|;vo2=@9;ulOeaUBpuV`Fd+HT}_xMQkGdS>Q-4U7uwm94v1?mqsC((^gd5cW|azvi23y%kUK7$I;NGEFLaEn;JE zGEeFxe{k-3hYXARatfw>JuNz7n?&rXhbT%J=Ou+fDW-VflvM~8@E6wx?Jd09h$Um> zLE?Bgqq5{{XcDS+#-Os-wn=4x0@lIpu5ijaX2ZE5&RNaumf>(o+2ytQ`=qqXG5Q2? z?5~J%!+6{hwyuSsJuWrwa%f#L4ZuakQgWNfG4I?*WL{0iWIzJL7;k!J22z?s{1@Um z-klV8I7G{<6e{u+^W#@ceeZ8)x4^k&MzhdnZn%2|sRa)S!ao5uOE@}0F$g%sbd;Bb z$ZKvn59e7pVF9tyF5Tzh-|p0BVu0fwm7$S&FMIQf@1%KJLK{LTb-24Rrk6PQEqms~ zYDBMyBUhmutOGEGe?B3@1Z#i%XAapdjE*n9>5Yy)>8M1-7ij38bK?4t_LOS6B%!>Q z0U~?AHuK`uF+mIlfed2Eb^R^_iZ$p~pROP}`+nL3zPW&oC-d%;mOlbG%J;*NRp0e> z<2>gZvMup~VJFX`bnMF#`MUMdb%(q@4y|?kRW`E3B_{y%QAgpw+?9fLiZ+uz>s;br zUmOlgXCIxV2ExPH`yWdaDaB2+brFPME~CoE@N{ncTEY}W>Va0i&H7~y2LvbuNaf(0 znm2AtGagIyvBhzS*P|*(kR9bsJFiJb!OfAydW@3mZvX%{VColioBSbe<8pbWLpWij zr>c}wQKkl%Xe+fIdo?7Ik zvSu+B2*{|-&wzxZ#;*;9;MrlTJ}F8gM;Lhh&iTC`(@L1_5R34fP*7j$i7y^I$DwNN z;H~U;oTrnFxLdenoz{?q`5B$cif5ZUP0DU8ARdJPt4|T1pd_!g99c$k(70d=iGy=? z1xPp778EsGxb1RrbA`2e44!L+j0WdADOZKa5I0jgd*ey-@vi7TI` zJi+2PqSz$N7at~ti3-Wu7{0f>AyRneW7|{=otoQOHIW8=VwT90Mih5lf%8rOV8_0_ zf3ah|=iW4k<{{fq``>mL65Kw7ocq&khbzAy`B+e(#sy}U#mYPVU9kT38CaH8=uQID zvtcC8Y^kNg_ob%5>1b=Q!_})O!7Ae1F^(aafT-Rl#Jmvzlz9O(fWtFI z4Yj%XS2}BZ1Jph?gxn5~f+*(|MC@_pV_3QY`X*nDe#J?LG69W?{9;D#D2_PvpFced zKC;b*T1+1fcnwo=X(&y}hdJa(F*WC20!PqtVc#SjfN zh0gyMq(+sR#P8>g%}xqaDngQ1SNFXg-Paz^{TCmhW-mcwF=S1XfO;I+a1f_)a&8~U z_ug>)3uEpfHpu!fpgLxA)k~-B<%jHl%0P7VL{OED1+5yv8yncn7(GtFvW^rT>3T*~ zX-Y*=kaBFt@h5j8sk{hNiznI{0N{6NAH^D5`DY?s@oE-QkP%~b^||Lu96%lVTEU_0 z1e+vIxBfE%X-r6l6xPBUEJ!+AghwI^Q}+n+pZgmEagCcVVTDSbxPcLX2!+?yJ{_Fu znVNEpd;`GclM4I8MiDg4tWW1TU6Dp`QBx*%_01UU0{&&skSGiWA+>qeoA^9&hgO1= zQ8kLF>_|i5W-$3TQPZBi9rQl70Cs(fbQ3d#gUwgZ@VUZkb4N~Gmt=dFOEk?)zi3h5 zDkcWcNo)iG5KGV5D5U2}V8rS{jf%Eh44nTcM@=()%LD)3rq9f%=y{%CT6IqXy&d6|t zGPMk>EDYZ2?0s{=KbYi%52%_SM0AHI1YSp#m8WToX#C}4gc|<~A<7e<1b|N+`t__! z$8tF&B)4>`N^glka6T%lKAkZf5vbfJvGDeB$|sz7d9~V4$ns^7|)A zsPiJg7SUl1RmUeJicrC$;hI0aIMl$$<0_?zEhuUJ6@7`MG9><-XMElk2>u0(7Ndg* z=_7nfiMIbNJgqhd7xFVY0Pb=5yqJ6bba^y}S+d#g10i&`zY#Jpfas^m*ch-l$3(_>K7XXVIYZG}{9F_3b7_mRF z_uI#U^df*WUv8Ev_O{VVe!hh5^|4;n!9d)4>;|pfR|^Ol#MS4bVGL0J8goc{l7+#x zMQ3QPWO^`okz?8!~i3R6*tLrmI}aLsa6Yt;YVMUY;j=@x zI7I;u<8UzX>$ix7^131OXmUyjwb|D3Ym31laGs0(N&Bx5dUF9T%$9<*d4B>G2mO9= zOIgfd4MKg?O4QYeurRIzF7LD92uV+IL|llW>ePc#iPpZWJrgGz0pAC1FTL#{(4u5U z!z@fGl3KEqcZ&aKpnbqYovYIo4WE0<;I5xT!{(Q8gdMn&bewvrea7*wk#n|R{YC3UuEZKG0qx>Gi{ zXW)_Do7``fO2jR*?3{5~D6I#)d4g3nG8~<=K<4(lbUyZEj7WNzxTP__3IT?ez5Ma^>fS z^>)plB1}7b^=&5s3sA8ca7@h}KEPyL8tuKb!^7#w0wT zL(?fdvs42WDjqz7^vYrHI4c2>GErN~cLW<_9Y~}Ot}%ZTPAkz>(VgrcQovFviAaJ8 zOJA`&aFsj1U^M+?A3`}IWypMTrPivCl%0#zGB+nQ&BHd!f z{nzYl=;fs|&`dqAqy(Y1wpQvv+Fj4c@5f-{dfGYD85#?dx;Q+$#FM{~9X z0T&Clx=_uD&)oCpa&Lhnh0|dI^t!U(r{B%ph?2u>aE=XiIX-*SKijLtM&PsG8?hK{ zxYH-j=@VZN>p5)Dj@yU-@-`sG%}3Pnw&h?@NWgA~W5zLF-IhBNzfZ4g+_}@lTvT0<{8+3*beVvqaM=O z$ko%^t2edh3UN7Rb+zw^CzeNjc|TTr`wlzU*a`me`pl%p zKn>IRU^Yk%?e+UjHj-1JF89d|Z+~cbw6&XTfv8q+t6y`?4Qj5K1I|&)DR%vlq{w(> zD_7Rynzz;C2V&3N*DZ}t+CN#(wm`s$g{py! zClslVz#OAbhSN#_G{U|@<{hiH_l?mXpG$>5UXSlg53BloT2C=iNnJ@}{&*9&4C;;E zGIQV3XFGMOFr8V_FFnlFHg0Em#8!ha;A1oqW>vMp303=$k*X&r_gFEy;HB$7e&#=h?M%N0b!Tjj5n#)6pmA&ao?`E`^mKi7= zm~v*Y38=#(bKi@AmPD{%o{%!|gFAEneS)-qE6iGtqTD}%1Zs_8lwlHmZr7n1CIrXg{IY?|V4L0?=Nc(&bru3g)#aj4Bz zi;D?JNW_$su)cq)I0ITB5%+8krE~_*v1&6+swUUI_wo4oD;$AZ^Xc{}WZvcpv5#S_ zqEJTKmfkIh=YsB&#=v9|m4qC5Q865}5?tz3zG?AW|6?S`QROKEWvgHXQ0Q-cSXnNA z6ks<|?LQJykRmI5W4-e3%1TsIlQ@f4Bl2XIfWz{E6e9r^$Ne0g-1k<&8cVm)L1n5?<-B zh|~>Qrkk)s;dhfG!5Kd0jE&e(`GcB*%25C8x4ZY*H%Q9xZO=giTD#h+r`GYQZ24j} z9>4ot3g|$Fd+psrj~k!-!(C~F&?c0xi;GPkxCg{i>wLpgzy@zgFXzc4z^?rtE`Syq zMDPjH4q=1K?L|H)REH!+AYtUF75eM$k@mvH$V$`!(Xnc!7AgxT$o1~%0uz*VfkoSz z0JI;NYc)sSX!pIlq|dx!1!wjC{z2xqwC?k#ZjyWx#zNR5=oP{hUzBzX&d%gRdv~GM zo5jl#9_{yC0U81}y(&7DVDp?So|!u~d7idc%}n|k08LtTk(`Dk(>}r(!ru_mm>9DK zFk@qtn6rgBqAAG_%r0%HTaC;LN{m>!#cmLs5V{reM3xzDCCRT^#p@fFYQ|dMu14sW|d3lQnmKERfvi+V9tCMs%YS*SrL82GyCx(O?@4pK$Bq|9BPm z$DjW*WHhAE3nqAp%43iv-X;|*$^59(o_^-B#H43<-XCRRZcqFWG%`P0sj%oa1c;8w4wV#xkhpj!xHmCD?=I-* zyiw|(4BI9a-3^)7*49|o)G>xiZ6tt|h&mm8+ej1v>>ukjXuJ>*dymVMOiZXawU;`M zlh7gPcz7X$8tjhwKSLuTx@~xrN6VzLBzp=o$>4{p%nG3_rUiE{hgzn7MNO5x6EXO5 z)bl2$+4+*-k9IqpiOC2{Sy>H@z|RAu>CNTC&Lsn@Q42S!vzc@dUXAku>D}_4gXF?B zL{IO9cIF)P=e3iQl@|1OW&0U3BP3{Ilc`gn(B<<;_Uz8&yBM{_?6M}us8Xng(bkdK zh$)MP+hLs?p5vg_wrwAcmbeRI%xr;u&k;5_z;|?ZRA*cq$xU9N=*rwf+h!8*%->a}6rYr53+;~Rv0v&d-K%bU z-0l7Jnmr3~ud)b;!$N!gn!?V3Zw-sozdCPdzp->5PjZ&gVSZa`2`0e@Y%;a%;dSVm zb7hp{=qa4nCtDsyD2J$3*a-yprsK`d3+e-bp63Ks!em$2AXNi0fO}~x;bjMwBL9cZ z8nEB))yESAKm@~#rWyd#bnJB%=Nb96$f0ZK<9Nko=>GO_MDBbA6(%6A)=hPqHJl|CaQ8ZQ!Jm&-C-e8umNv#i(ssFmzAv=hBxukB*|d8xfmHf= zk*qXse=i?bfr$o0Ak3DWl$MsxX>TX<^71mZwiY)@3{9_ni)CWsZP8sI$4(NV>9)OW z2M8gf=V)4T$8tUov;4G8;ye#cVe-M0b^sH74*sF4_gK{b#uwVOw z-yu$M+rhzO;pevVbwy@{bqztkafi)GhxwCF7q1|2ncwuhU!_u2qqP?S{fb;Zn2UUR zYai2DNa{-T#o6o7`*3O|_Bdx@oBi3d``md{-IWr7uZ*fMuw}J+*lK9Z#haP)|436H zCViw$`WSli(>hZIyizPyBC;K0+DQ!9H^3(jT>BP#26Tr>1+^W~NpI;bunDfMrAujB zZRs7u5@cMgGcQ`a%!=N5ETR%?am|dMaSrZUIUK|**WvOC2{s*=Ce6bI!*Py{#F*>n z7^-crJI?}z7N2jvMxAdt8o>4CIb?aRTy{L4LJ5l>G|vvI9-4lK?rU7QST$ad%JSb1 zfrqD*VzcZpG@oh6V7ia@Nmdl#$lB3vSDys{QZFZ0Sa0^R-b?5++M581o_x!=O=RsN zal8zhHruZ1uNfU{e?o10P=f~!>`3BPMkneK;k8zq`3*FwM~YaL#U;bnP=M#{`}v*E zaUsLc%orVH^6g}`W<3^9b+vHt)y0ZRM!cuBpqwK1q?cECdP4vfXd?6I*~cCwf1g*= zH?V5-xG-;s9!}c8t8u>&w_Io>@W^r}aAUm0;AoCx#sEC@0|3jvheH33od(X-Sf}aEZoH`*J$Tm`RJSV;#8*|vdO)NkaiSCX2xp2w4ALT zEmht%J=ve_3Z~v#ILku&*`$> zuT31%3#I`Z!{uSCHB}dn+@V84SLfF9na0JH_7&euR?JN^%Gazdz*oLW7L797!i33# zDn>qQ|GDkv$O-=8i5pNy4xp6YDH!aU{jCy{npd|@f~hUaQi}KCgkNgF78}q8Y3GEj zzp#>vPqHi9z4n#}Uy0gdzfIy&(hfmLQOUn2sU@`W&5nomA=}O}gX38?f8m((8mrF0 zVk6`6iBC$xdYbTlLg7a*c&j&EFP!Q;z0KeF+eToyZGKseKx>{h)dVDe7p(N`MceNI z0;Hx9(p8$>v>5(T%x8qKbey;5TaP6mPR_iqUyU^2u^w~ehUU_IY7C6Uq`larx7J6i z7NTXcwY2ui8SnwJ62Lhgt>c}qBR1ZjZgK~6puNzs-U<{0O6)*CY zNF>mMn#% z&?$Y9$Ge!dM;&aQmtdL%9%fXOgtt#8x4VtK)%pQ*LPsNtrL8%H? zKHF_;!?W|-Eb}}Bg5A2FA1C$Wq}yRe-_hHf*>j3lKORL0&KgY4+Sqg@5WOScu7E#o z$yR~$`We>bu_M8pYhWwDRi)uX5<8-vMS!gHJ;a}s;wO8UNp zx$??Arx~Rr3u?0WBQ;=--sRXpirnG0*U^XSnlJ0K343eKPi_&XVvXHMEzCc5N73{V zwd2@;B7i$f1umU{-9)=`KvZ7)i``KB{=-WOX6x0$VQ42nrMYxtTFIvpWM7YrT0>N8 zZoAYdpho4*CaTMqGw+r2T zl}#1#^kER4WSJ%)ewb65t#$@+Qvc~Wa!ulTP|mBR>Yg<|S(U@gEaUHe26alOTsM_G zh>_1Mc~PIt1?#OM`}aU6jW*y3E)5W3A75k$7SI>mrDfd+!dGl2fXe0`-kIk0>LUs7 z$?1`x3#u0EpUm2fd*4ih`wD%ztn z_1NI$4(5XHoM~1&;p30V+Ihku$slF<{~E0_GDFrl*J(sTzsi{tw(eza78!>@1(uWSYM2w{FLQ{A>AZhI&|GFCAXHNly){DMRrRik2OZUqjz!m~m#BkR0S$25&{oi z>5BPkgMQRMp2r9+%`+j?zlkTTl zc=QP`DP&PC1t!Ibf>;xy{JdN|wN3qoQR5H?5IHNGSNUF#(}G(6lsUfGS4Bv>PlSp} zy|m>7K!^$emm2ZPhK7T7AJ!LZOorcP(2s<0bhnj8ef!pFwV5tN;+8x{k=EbsL?)%| z@O6LxQOhVzatnz9GmQKr4%NOgt2+smDin#quo9PAI@*VH7=6391#>q$lXr*L4w*Lp zB`dkbLHB37&{^r zy)W$5a(?VccEy%quEN)pk{JryKJF>%mFM-oG%6S8*!&~0meAI2i6P1%bae5RB3Tp# z4_3gxGuWQ*6N?2=EM-aLKx-dUhX0x(nsoFk27^Jbq=djYb}M8IqYFo?SnP%qAVcn= zOyB2EKO=n+)-qTq7#OOzjQ`~4-vY_5JGdikOg2 z_r`qtli7iEqe+hl2bif{1ECYW;sRCFWhvlU>6>oEXb!L$n4N7S(kJ!!uSW6`!)}?6 zw_Ut(d>XD?<)t{qvGVlzP3B1(o7vXTDyS9m+q5Hf?l&+jBXxkKH%(zT)9t#>PYQQ0 zT@#8u>2@YA_$lCB)^bRHwkxKb-~-1ce;b+&366nzPexu{upY` zxg+W~9K?;SEy_2%@S9E}zt}B142F{I#c-)H=}Id_k0h^5%dfcexQ{xY8_kYAVjhMVMa1f0u)d*~VxFxxMtQ2eND|68x6rvKwh?k(a)>^Ssk5{4*$ zD-%CbA>SNh{cgDtT5$Hl!_>f56rs1+?nRCQ^FLCC&+pR6?+ICds^}fSL={|24<_?m zN4;NpoF)DMJ^Olr`A5_11sl_;H!qZi%YUWlfR92$NZd6R^%FPpK);WC6}5Zmcz;af zvJ!$u9IgR;dL50QO!Ph%?asjA)0a0diL+4Cf9VB`=OPGqL;Y&mpA7doIHq?}2q#Ds z?~f~akMkFgdX!lhbO3P#sf~hNeTC;_^`u7Y>;EO+XvAzjSSX#5dE-G;#6q-LmN=|A z(h+mi3@x~HW<4BS#R-QGwPv` zU(W{IPgNpnCvk7SJWYCn?Yvb(P|G6A?_{2RJp+C9h0(Ffh9uIAh{Lj9>jOUpx2!FCp%(b4yqFR-=~2?6&H{cjLwxXXK^q&sfMA`X0X`T z?+Rv2g>3>e52zyW0_jG^K5 zj0402u1S7afP4!JF&n8`oPHLk!upNcjaAl3Z}yKsR2w-X$|A?dO!8#nXZlBSYq6gC zifMLotx|i19owFoH)4`04hWE+BcLqM3wX^|!Tt~_cy9=B88-3A{8D_pI&ZjZ45)zP z>obVtwEs>IoB&V3q;qW&WL8L6lBR{!+;2JpuGZ^@yE-@o&3gK> z0ZCIYu9A!=D6+#E?!6^Xh&zYdiLbU{N2| zxGk4kFkJfksqAL7?;nxws){twXml5oVJsJ$aS%S&>n)$PiwKtu((?mR10L2^t45X*BB=K(Tad|a0#yMB^p79xI<@gPhDh5SR6wc|K6+l|>Gd2p1dJ_Add^eE%3 z%Rm?jQO(KHmF?yrj%F!c?;Z0(gi6^=uBEZw(ARe@t?&pQr+AKNI?AneM0e~5*+xgN zt-8LGZthH@N)AF#9iCG%Yu?E@M!CjQhvyIOV!;-?7}9n?2=SmyDT}&~`$?+- zS?6ZNl@p^14=vcUO7gp%T<4qFx-+*>f#3T|lMEr8s7aq0%_-*!MJ+Kb^7@R4B>--0 zk3OqnuNf`hJM(3m|4EibfJ-^bhW&r#|4++q`MJ1=HRxUE3_!7M$DIm!t)D^Vp5CG( zmNr?V3;DFFN$q2k z+N9w$3#4X20EH`F|Sx;Iahy`fywo{d3tPG;O~~Xg7ud~{i7kf*qM+$6ban83j;eDJT;oJJ-7C5~9`In)Bl}`demFDxsF|g9+s1R! zzSsuIOn2{7-|W10z%pCy4q|Fr2&pTnq4Gvy;<-#Be!!`((26>UIp|iBdCB!$q; zvg-XI=z)8+;DCl%PqVgyaTgl>oYYLXLqH|w3*Gj)WTN_~P8$JFj4)0(2o(nkIAqTA(CkY(^W^5J&QBD) zw^DzW9>_^0o5?<)2_oIZjy`$A;DUylWWr{trbT7yqyzJ|AZHqM-oV+zXR!sMq{ z(do-^wCd&tXby(v|ybO^oIfC_?&fPnNSy%Sm}2}MQe5K16G2)%^>p@mNJHs^cvocp`)-Eqfz zlz)G`cY^&4jDK~zXgoS|HSiF@ zx?m+`Pv-Aep;>1z2*r4OOEfS3kS$GBf{4CSX3-@oQDIr`^snZWTr!t9w zG*P!qE1N5e)^}Q)-QFjUPGrn#Pfd)*J!I_uUcTo@?;VgFBq>AJbMa!$ zl}KP~2(5>H+jk;4BttFQB4nG;ih9PF5ZDY zaN{|fjR|2g=uA|QCGl`=_JEw z{gVDBM!liuegtIH+0}ang*y}MwPaB;d4Rxr5*;R|K*`fMT*`*9D{c3^FGAFp3Rir^ zfjpf*9iya->E9W|P06D7gri-~@z-Ki$?O>#@^j6UJ24Y?ypZHVg^520%c)(A=J}d| z=EaC&y=*nE2K}hVY)Ci$q1uAy%c8?{(3fhGGNGfck!G9J)(#&gkEy~6p0_$Gf9C{B zDN9()4$gK1JKn6Vh1&w~$=6^2MO+$-_* zX~Gy^`rT_(f9H{^vRB^Q@J!r~3mdYpIn(Vu9DL#JB!c!G;A`xX!`8=$8lQ)5%71;) zu{DC&{eYE5saM+V+#CMRv)_$*#lNA*>FF3mjl{sdK9|wDcsk8Fx$sLei5{UuO`xDA z(%RZw`*tbxpPcK*h*7ec$BcJAWjj7({loQ&>ASQMrPS}PsjaWB#(ex!u`c=dD}V53 z=KMZJ1w1^H4qM5Mt-NQ4v40-#_&lD2YZHo%DeaPIh$%TVQu6O^Xbvi=9vhk%dwQ<} zwm7@t`%)JvStZG)ayZbv^5+}t?nJh|-GvTcVbb7cAI3RHj1;rIQd+f5Xl;5+co46H zeW;(KDa=w+fwakB>TOg=!qRmyRx6lQcjfM7S_?U8scH<~Mb{nD@$pwZJldRSPsrz| zWE+I;>hmj_7IuDa;eoEnm+IFGtb2BYA(s*=2ZTH-FkE1N!Y;4yuHqEpT}X20gD@vi z9d^Bq_?|H%{eo}bWUb2dIY%sR>lReZRGhjdBTJiUtsKItG&Ui9b+_j@rB-q%X)2Q= zp@pC5mm(xkFDrl~;G8iUY<@#pht7U&{zQ6Y4|ekCHph}@asJLEDRNhUX5S=Z3v+$3 z0M9Ep;LX*f60|iDMd%MYlpCr4{dTZdRCJ%21I*jxdD}z7%qbqc@sX|FIAK>z-lVsL1%uySH@T|On^O4gL2cAd9yuX=VR?V- zJ6%sTgza4TRmklw(X~dGKby(@S_q4;D#Z?SKWhP=HSQ%FAGc6epCALc(W<$Q@9}mL zZ&-;hJVz$DW9HaOhTg|n>d^Xir7HK^pXf`+i)Jp9w1_RlJaYO>$>Q@^39@$|xu0Of_tHS8Yrq zqi){Vd2le!_!UgeG=sdXL3zBt8qDh8y~OW)sMv1m4u-a!_D9zl3@=j}X1QboUwG+& z88y1lu}6eEM@?l3yR^jkSqjgxOBz$Hp_gjlfKkm%i6E^9*JyI9)VWFIQX?+#fzl z^2@t((4oWN%P?6!?}|e>*tc8B)H^yYae~sGAOeSD-clC8;?8*{g+$r_M^*v;2G>xp zwvp`HV2cicFB?DWnMRL2G+#;Qu)uhK-(~6^7EEh2ONg?X7o}rjg52&G<(yt^ zE|`>d4dYZUe(USo0EXPgivHLJrO8HELTrY48Pi{$uokTm)gjE4S1aTwd#CgL_)KH_LSz zBOaXw>@z;8(l((`6h&$;8VAUz25xE>|4!uS)@(BywnBn--Rx%MO(x|5sOe_UxMBt zz03nB&Tl`Go?12nx%;uxP(CPAU=O3QJU9tHq6Sxf-#%1@O1yHX?U9KYyY3L0ucF{h z)OK~Ph}0J0fgUcrzsV~gFx-m+5T5!6YnPnbd-FG}Nt{sUexsg70?VqDpL{+YBY};^ zhOppI5neZlWP-RQ;Ih~jrAweZsHOF<5RxQ@ulPl6XYsO*si!h(LPCXxYmB>PFbjrj z)}JKz6qX-edkQ~zfFtYpkIcg+WK2<#NB;7cJU`*P#Co)M*4er?0$^K5D3Ei9y;&E_ zWxQIz)|%;ZXp;Ax()G7~VWwTDjn#^rfZoOA_LRN!gADuOQdFo>e1&Ct(^GwBk9V2O zYstmLGRe89x;%{tcs5Ux@%CKjmvqlCq2}EBa58v79Aa)vi9=0h*$i`Vl6UPC_htP5 z^pAO+}lhF0+JuLe(O3 z*Y>_?!jnd$_gsH#Por$a9Ea_2nJiLB52h>4D4udS(bj2dSFj>Z>m27CD%J?)=Xq_cX(rY;R> z@uC&oywe6$P*Qn@3%%$Fcc*>})KNmGpZuhvJPimO=LN;D?I*h)tKtra;LFIw!gC4Z zWl0!RA8pkFKHN0uQJX}lWgQy{wPl0PqEZ~y)`a=R4-!g>e zKM^iNsz13*o{_lxQ_VL1Oi?p6@Jm>$bFWxyw5e#?TtVr`%!T{aUzI_t<^jgW5%DIu zYkJ^SL?u_zK;JsowrWdpUS&XOT;*0wI)lK)R!#kwMJ9&0x5*+nYWVkg+&KGbQ2B*nI=;7Y)sNL8VQXAi5KX#ixEGX&&IZwuRZB-_H-AdiM&|%hRB+uvOWymwV z=!8N?W`u&^{l+5R9-ZE`xm`Ny`|!(<^B`d6w|!`PBnOywd&vIYAhk}7ONbLoHWtq( zg1(kFQB`$!t;W!$S`B8I%>*{#LP3021_kPH{JJHr{k!eLrGjlbwPYND!OM3@% zn!1E3OU6t}ULQ_p(lrW_LUay-C}d`k2>U>B73c6EHjM$%-60U?$WD*F>dY;xwk!oD zjWu=TNg<7a%8-xzs638bo)+m<+ArG*Co88=(<1rVBf<;WFjRxVWWweJyHc;*&=c#+ z=eePABS0rw3p*B?l`eO4dLG{T7PQ!6p*FaGEjkZ$kag_$}Jf8ic4UQiZ!k?3c73cErHY7}4B8~v1!^r9r` zQndUHG!<2zs4UPM7~7_idxsmq$EGplM0_Y6wv$N#%wS7yq`6d9W|iobFnGSZpTwo5QHiPhhdUr)|6 zA+jsmB9A(}@|UTh&LfD32vF?x0YzZUU(oWv@Cm=4D60f|dtdcf<@I9G{>X$%YViW? zz@jk8`$FoUdqp?$n*#E*8lBg@Sl)qRZ~fnVSMga`Tc0GuL;6ktg88K3dJ(B_rG&*E-|T~Whiu?)Yu12In{ zuEzG|3#R*{vT9m(@ti>~Dwy~YTH!>0Z9H=M^dy^uOvz$1LiGd)CD#HqVT|(Rv*KGR z;Uc?{3CE_1Cac{CaLy(o9e*7(+R60j?D3cv?}}*dWV3=Pd}ukvTL9f7Hd&J5-1Phe z0o|Pt;_IHrA1SHw#*50^GlNmfH7Sdbo$e$9AB@oP(k>6TQvGf(CSq%W5O3(zf8*}UYPov!Z_w&R&o<2}U20YUI>de&h$_7Jn(%DBxhs5zx6nL>T6Zp^{* z&N5cTY2Y+0l@_`B#+b0ZDkwM@le-J)h`EJW+96&}Xt$qnbH-MnlCB0J!4)oiAl{Nb+iBitqQx~D ztAEdb%PU`<T2j!A70B9eG7^+fOZu+pb`?A>A~fxTg95wYW7fld^r>z#w#s zwkCa`MXYCNVYtuz7(LRQe~YqX{s;P6y6Ew8g1z?ObaQ&~#z!Vp!&5^^g-LF<33VL! z&{~H!BvAWsRjl{Czufrq8hJ5PDok(He@NU?Q3&0ynKzJZqC^(kqWI+*$5^rkOCa!8 z#xev>(uaK_c|AyQ@HC8FV|sMcKU+?1B7tcc-b()1H4LuQL^&X@ZFz0fIO=?*ER{)e z=^ell-n>bU4{jdj-vz@MXu)Q?Y(&rlmKw*L#d{N8d{{W2OLLp4evzO6?5%H*bI691 z|BEaDi@r#Nu*&vSp9jTI&eTjwW8&7$#I_=jLr?IGxn?>Vp;n#4;T|bXb(Zlh@iGX>^;pep=I}hSDy)7?(gY8etY*h-o1@ES! zyeCT*1wS<5o3#(XxSfKVD}K=v-IVnj@qLHt)k8%S@K)n6BAYu@d7yDK(qIkxlV@l7<4=RNbpx& zs?kF$0MBbV?Ns)}o2Os!p?uH80`vva6jL&~yWGBRx{AY*4pwWK?8wiMC-bA`-N@v2 z99el1qSwc8w_r+%I4JTW>%ko4IRglNZA~5r_AgT>`JYNS4#Z0x9~l7=(V_LkV30D# z#J`kvykFxn$C34fSYIJ-R0h5BM&r%*5b4F@WX~?)>$Qg+F)1WilK-6Ot-)&_t6KOw z`gWZ&vKPftX{A~xWxV`nGOZ_6`Jt{U@=V62n_4}_+W}LAgtfGM;vy%TbdI&=iEAI8 zfn{<#6vR_W(@j@f~qhu#3Mcz7@?D?g8ZB!}Z`Px? z(r#^NuDCr|bM7|lFSA>G;!ME1ifeECq<;cH+^@1Byiu~XaMEVE*edOU48~c|NgMZ4 zBbD>cxaGwYZe&jZI!~hl-zJ~i9?CaC$A5#_lA&jpA5y9p1Uu;Joz~e%SJlib8RM(EHQV@3b(_cFei>Pp3I5)-tc+d@rgbaUTKu?3!D<%M~ zvBV~g$^Cw34}`D>DkA(z6d~Tq@RTXNClO5&W)3TD(X@#!%kYhAc$DCcIkI_{Y3=L2 z&So#CVr>jd!#UA<#w{H@-wl0CP5hfA8#y>}4mG-fXLI!5_*zxlI{;%lyiwNn))p%| zGNL&Pd0xySys-QPd)-&HV}0k&Dj|G(sq=ju>|IB>WA0Ms!ccfNDgl|VE!J(ox_JzA z+yAAgfDiPyqA~)CDy5J2xW!Ii#_P5$Q{?{^q_n)1bYP~V@eH+Oq0>gL)pidKzRz!1p`dzn-cS=&-Y88Ims?Wt zEk5&t`j3a8o+M!f_l55M83mQolYG}0T+@?fRO}LrT6Q^_x&hlZh@Wn}nVu@9^~S=9 zYqjS3D1|DTLTxcSqsvP(oBup(?jr4>UR#wZ?0!dxo@dedEh=IA@&zi zbjCs4gV)eSL|lHG$;7oQc9wqI?P>sz<2|R*_s)Ye*10F6(B^$sh7>4TY>U>A6I0q% zL*2x=d~bkM6(0ii>(yM;#oa$_`sleVU9{Wem3(kMvIfbWEdN zsIhFz%wOk2BQaxKRBR@NMC4B_HI?vh5s2co1;it{ZTDGLthYhs^dlQ8Vv*mYt+kF1 z`^ky-00AAPMnIinFM#@MzK$GbRAV{Iul-tgU79!dQF_9Mnln6gjeyGxwC{c0*P3zJ zSH<~ffeRNsd$0GZFrad1KrK4oT)gk>&MSxnjRsNE8T*pR`+gJClXB(-*{Y^Zc6pUI z8(c3eKSFNqD`znWiqEwyp*d0u(5Uq%gDS5 zB`+?U8>dM$UfxlCSK+8|LbFyMRA9G|w?BR<6&r+`q97ksDY6kuV+v@{cuVOrDLGZa>Qc+LOh#4A2UD(5cO_i( z#JwBeEoneu&09}!RhIA8Oscg}P1VnsgXx~Q?xqgVXatzl@*CtxGVu@c)#u-sP;e>0 zKRm2Hp?raK(@jgK=gGOWrcG+7HM>ZJ0AQz8p5fNm!N((~5x%_+J?S77nzaTE*ot%X zr;!xj7HsAlvCzQfLCrST<2JFT0z+m2^wB=eHYq{Od4p7Unj9ypHh6t4lh)c^j=<)H)R-G%#JI$m8{$eH=ZqbykH^rbCR zvxPb!4?^8=&<0J2@#CCC7Aw&POS4EtxT@7?y64`3Zb*aIJ2!Hi#ronIu0YIvPdxn9 z5A3cbpSG4958_*z^PdC_a*6EjaB1ub@l1K8L-?$Q&hq^A@Mgh|HJ8m8aQgA&3}xX*3OtGFY7F#s|^kXcxmDhM4pBzL9XJswR8hTDoz_0dRFkY|}n{c$x?W$OP)%E6A*a9tx z=B~Y-wzjpzAsG`+tH&r#YEM!p9d`3M!F~s#48Z(_=f_Igtt-w+j1r;`mHh{v{aKJ? zaNDrp>)iL6wz!a=rz(331g^oMg>pEj8kS4G~T$&TqQo}7w z!WdB2j0BNo#VEtz$H_T>_^Gs5e!>CpC{OtqsXT4`=CWX{)Fp_ellVYh=%dN%<3xO5 zMq%iqj0G+`Hq6%61VAvl`L;+;T-*37e*WhSPc!8=xu|u7r-shON_|~#Z*W)0HYp{> zcG;+>Y{7igf^znCj3?{p=#c>0(68F*uD%ppu?UR51_bdhcz-!vd;(}iGQ*`^A6lG; zPk?{q2}+0UirDY}2&83Q_ylGS$KD6oCLYZG2!z_A_Pz}Pfg>)UP7Q1_`(82%=$Ksp z=Tt&y#hAMk6Yi)qHL_*B#V+@A{7OQXO{b&LnnK*Q+UxZJdAbh|W64XK6cF9` z2(Yha{m(#f;XN(rCZL7v{J{rXF&iA4!a_vsP!0vrSIktKsUCG5#f@$J?wGi|eGTHu zb};(Jq|q6(*E=XIdIX16rUTk*{#jFDtKb8)t;#L zfX9ova-;ZzxHYw>X zvYboP$a=rK%j-Nd6;Q&&eg<|Gw4~NSxCg?%g7tR26K7an?KSGkZ0lpz^nY7dt%i*`R)5WD- zG7-EGX|W0{+ov+GsHv#9U;Ui^^Pt)LQ^G?cbAt?4#(s;D@4yP(k5L(`w&>V-V>i0} zhfnWQQC(yH$!c9k=X^#j%HY?NZzouDLehj5D}1%0wW{dhyv4qMo^HwD1eEK($xk?w zE2wyh5*Z?Zh87-dL!cQ>4@V^MbP;|)fDL?m$eC~mr~!I*UMrP~>LutOp;$bC*%bx( z2*yQ}2Kz0k=1W)S?^k|Lq9@u7-?Wj?>60i3%m`|1_|8H__2R)lV^h7KfI@#XD;l)0 zRl$BHHx?0t_apEOlPF(&O zv~RGlY9ZFX0AJfd_arNck7|N@NDzO2Twht z0x^BC2>#$P%)IXGM-7v~pr%wO*mXf;K;8{s|G78e4j9hmRQ~6JfEK;{ z^wYG_0w5jhb!b*6Q47;C86 zwUc*JFED}kaVH$)U;lFdlCV{n=IIxR6E^v;|1i5|-AR{8{l(*i-u=&c?stCz2)>v2 zP=GW3&uPpO?@9va9;5|W*uO7!U&{*^SRNa|1pa+3v%D2xN>#-Gg68LlR7ZhXO>_ci zf?orw{67QwC83mid>KD$0RYkeZ;@7y2t7z4ij!9LA3aiSKUtcrA<2Aqfcya!6~ixR z1`htUZh@nJmOQY+|Fvj=gMZfh$@2aODu9E3Eq37GADjSS;a?B~9Q@B+?1E&_XMKXZ zn^jkrR+(cgYiK}BPHHt{<*37}QJq1_g-xmXImdw{`2=pe#buEp`bn?H$2Fc~ffa%- zNUFi?%@(9p7reu%OKa^wilc-WUT;K2b^Dp#^9nb2_tUXe(poHpE^ei?xG>8q@#=mv zt^QZ%Q)D?+O4bZ+TeI|OP>=d^)}vnu&axUIXI^TTzWpce`aUO zxx8+RjP`luP+odQJDr7{@_E(WMX6y64aT1c%KaVZ{g_2uVNUqilxiO-ACG+wml)NeD)mZro6SOTWmyjmcN*v2=mjw%q3A`LW=<-q1eLDq zDencgJJ-D+YSx+5p+V_sf(H2mHD7ZCx%&Ou^RhylzF@#ZDV8#0OqDB-gVgCfwR!oW z!QFQ^M|dFhF&=J)Wjm>M+6E!|57IK+@9zAUG3qDP^V|#+j0W848XZ0n+r-WKGy}Mw z!qn!gVX#50DT|k63$CPE$ICbSDD=d77&+xV_&lzP91j&4sgWaii=Jx|L&FsaHK5zj z{dKUtyLG%#>k|FfivB-FGh%)1$Qdo~)@eQ4XfHABj_^3u$IPv|tK><_mLyJ~>aP+i z@*{sb3Rf(bE#JwFrg$wmcv`dz-m##6Bth7u7U1d+!haa3+C9@GT`geDc$!SmnTPeK z55M|&7@L#1hKY-2fa)#TcAce~iWqaw&ow=SoYE}p6bAS$2J+ojDy>% zz1-E>D_iA*9|x*OE|th|Zn{6@^hVtk--+*F$YxhXTSW21%~M~St}sW)EdF+x6Uq3~ z%H6(O=9M40#y_x3dIKR{i!moYoppI=i83tykcxwNN2Mp^3j0|Ga88%fq zYzsz9yHl5Bd`7dWsa$+nc)N{Cy@p@KM z3?hr>73`d(7X+%bbe-q9VVaVu6RVs-1`B!1*+C?+JtH<0`JAvKiDtKQ9(w1uvXO%r z|9tM+6~3~NMJd}yfEh`gJK>E(t~u$oyAHRLMZt;yJH8`Hoj~FsM#p7Cf#~>fqQ z4O-P+n^-8Heu-gvxzgd|7h+9uR_rZ5%BYo@f z&!mEytWm^aTx@K%QHrsbVfy=>G`jsAZ~p(5&+P$2M3i+s&D%yK&*Gs_CiuDqHEXqX^uXqENlwb zbbs+3mtB*T6?wbs?sh|U&VtKfvarO_lL29*WL7bw?Av?m4R}W%HAN!rv*l|JA?>An^YaigTA_7e5L@=AvFF0KL#A2_4%bWoOcGy>`a| z8oO=hsNQz3SKAFGL(LLWnm9Qo8+G>g_uWR^t4phmtYda@o`E9riJ>ZXNmwl-L;GJ- z@a?u%_aA6g$3d{A>R)HM2Pt@PpfidVcH>Vgw_4VONp47rHjXt6U-k$(@iSiHKLAdO z(un1ImXPE^M?}~MJb91m1p=XOP}1|}4e!XDCOL98=IE*AP;#S0oqd9`vX^a@MX>rq z<5$?~_&8oMROaiRH@xB=66OUg#TB+`US4#e#uLWws&q)X{e3#eJ0pcmwHh(n&=>i- zC5o8gQbRaF@zAAUH1DQlc(t$lD+h6}G+U3eIMh>dcDA_Y{>-D97B@C>TXZy3p7AjJ zlT8&~A9HK#I)&<(_;lXq-6b%@9B^pix44raOZ3d$z=ls32Z&J1^~SKsABYNt;louwVL zzV16Eg{lChM1&WPwcLd;Cjb)1PVM5=cJxag{M5tSW*o+}2YtiR;wi{&)Y+kfl2T>N zoX#@j@a%Dxmu)v(tyCJ9h1|6F2+lSTdsswDqJ{gBvUpq~Fe<#&>#}=J&4%xJJxH8- zBlAzNyxX=ZV&wv6&LL`YGQ3hS9^Rv%%%ZZU&jj@l3S2pcRbY5IS?=`pDE@8o42;sg zS_YObh};q2pU}_MSkzgD>FKqC*TzL?OTnW#;yb+1R^43GSkd-fh0@A%3W1MQ9rm4e zKL?fiH+2>A*jD? zvDq}kMAG9aX0!-oAqSU^)hp$R^zLHwNc&#HNcF<}T9LS?<}IWNCLQcweM?v^{{SpR zo1klbmD;$cwE9D7OwQMxRRC|V?Zu;3KX5=kTwg_@1|Hb#5ygX7e_Y?ar8H`Xe>Hix zH8eSnB}HyctX!Srhq56-)66XMB2WtItCfCn2fpVVn=a$Wpb=g(H*dT6iUG2we7yLJ zK=^CH5-Y@(l4qFGxLBcsW0S;z)#5JruvLiBq)C6a#O@M_+URt0oU8g_s32j8j z?RxD4HMtBE=p#y9p6ETVd)@c+aOm!t#M8hhjZ{Vzl= z9r2`Bnhb8ziBp<`x;ZN|d7qs@3iO~n!?250o}UqXGqvX=V`xB6F@;cM-t7rgr?72P`?(b8QN#$(+7V}(FZbe1vkmFPI1SSv1@CIf zH*5X3HY-D3e|?KUP(y7E=S&A;jL8avov&ZZTD~*l>7T!~#rjY$@DZh4a?|~Q?XbRF zGj?U`q1RtRD(1B(^~a>I^C?RNG#F%zV7T@qlG^n2FrSNeLrpOvv`~RYqs7o&F%2uj z->9Aq>NGv|J!inJbm9Wo@y&#?W*lY>2-kLjkA(9UWnJeqEfAhQU49%z@5oz|>t42w zeVH1k`P)9(NnYL~kLlQ-4io-izyp+Lc5h3;X(Jv7${kA!uZV_vdkC_^2n|ARofgtE z8$V-xwQmv#*6p>__8>?6iq~@Rn+-VyD74f%l{JC~HXlb&Xw3GfakwJ|BYN*^>*?id zta3q58*6D5qd3?ajR9$s%i1Y_gDf!3fGHw&I)%H2yELQtG4%ee zwPD{!<`?6&A-!Ze_~W;~cl<52Jx{OtzyW68%%P!ae>C@@RHSjOZH&PpsUI`C>Vr67r>JsT0fSb|Z@7Q<%~+*pE$`04cOW@}4)8;* zcZ7%)`vleN+Qfz8yfO6w{H7HKz%#gBxjNMU?$ww+HrwevSNuY&iT&&?gowz&q3rQ1 zeghkno|2vYxaV>qSU|xkot+NpAc~CKMYK50LZtsdwq&ZEJ=^JhwV;8Yj6&=Gw;=pw zq5VO2asE@H;Q3>dCl(3mV>&S36aib4uV--$_}5PDeDv>lhK86=J!%z!9_Y)*g>w5g z${mDvBfgLZRu{Lo$o<~16EycxYF5wiUgq!W(iXbf#3oymc{`d!T!QqSyBH&Bw-VDW z#1Y}r6kBoSd6OmY;p13oWYaVHmBySN{%GlC;b;Q)h7Usk?Y+p2hi%f68|iJ|)5F_i zo-ZPWIz4W*j$WN?oGFnHv{GN#;P1FMm@le*uD60g3R5BpYeOomfhru&Qhl-f#V}n6 zhhsWM#2Rwj2&9TE6^W5m+WLtRAECLm!HiN@n}?Lk-=`?%k-o@umU{-;nE zm(}vp4*~FV?b0Y`M1kDpZ#pG}oCBZSb<7t>78}poowFaVLb7nqHwa9GeRb~|{F%xY*S>Rx>c!@-tXIgbgHT|BH42tW%}lfLMCpaS3AIYH z;@wTIWK6|0dq=I!_)p80O8a|gLd(34heG@0QcjkGiNE1gPBEKGvBxU8&mC=4(D=Js zop!kvPf>PgvgL4)6c^#RYsKwY!Fk)lFa}C)+b<)=2d3tatXW-6#8nJ(X5E^Z!203fmsaAa|s-QJ9t=3$8RXfBjt?kL@Qlk5l0sgs=Xq~|Ce=Glo%SA7WJ*7K*u^bTup zk!8`hD#5=|)iwOH5;_{DkNv#r(+gOk3CkyK`hDVqeZohZ`GGK73SQg<3&+U&aE$enY(Gtdu`$pYz8CQ%c z8zHQNBHKEK_3<2pXEy6??)3Gixn$DYH-VsDcW9?ra!EQs8YV=KS%~WFfggnpB#jyRDg}WS zX6s{p18!miI->icEXCC16jI5FiAwC0`a(IpVwi?_x7;ZFAo z^yI7bz>NvOY^CI7?!u&sxfJ%ebC#D48o^6B-!_JG3oD)kB@r$)bgV6}^jE6s9E3Ie z$4?p&TspMzADZxeU|pc(aol!N!SnbaLrxtkkpC>BLI=N`stom$E8RTT6OusOxU^*d z1Ad@CEDrsnSXOUQdzs6lA-~zwKU~A?5kgRBcGkj-T)V@aHf2;<2j(SUsIW z8QFvfmtf=@NMn{m0?E!Wj$Dk=e4-X!=8d*pYlZaOZOSQ|eqC8wZ9;R=-m@zY(lgP| ztMzQ>Rk&Z*d%!Tk)lH>^?kGKV=DPO~tvCQG?k)1%^J4_@BfgrHitmGxpSnCfha)p` zx$P2A7}0Z1vm`ovntkfCi-hQ3?h7ExI&)7iNfKa>!_KmV>N%S{&0B=vVz{GhG=oxb zIZe|ARl6>63mIH7-1`mLxr=ctZl!G72~m_36OKBm;nm=?VXTX}UX6T6*S($7ex}x? z0<2_7V5h-;|5e8r^RVQNGKGH!vQzJeMpx1P<{`Fd|p20G`p+%j+XlN70c##TW5YE%(A4)wG5gO6Wsvbko`c(Y1+-P7K`QCfe5 z*{d-$)DK!$And}KRFb;+HuLt_Y8&flb}NBnAYX{r13gO*a^#@BEUWhXyXNf1rN^|O zcmMT%cDi0~B}2>k=A=N!);Oe!!Jm_HiHwx!n6XHkm-BpJ_ z&<#ODzNF*|XBpk~OpPHO+5>DU2N~;sjzsP@5DyF2R8c7=4-E4vZSG6?+4x1sOBZ+I zJwij0H%k7CB(1NR99wFnNv9hZ236|d2Yq$?3Q^~2fZ8u(Y!RD#u}5RJ0cNC#^bB@A z%H~h+QC<<`XWj4`iMaY&q2D2*Tm?guqk>DO%IC5s0!u1*7y@}~jZk8TGFiyH8Xb3b zP;zadJcijw8{cR9qC-X-##VzSOdB(kMqbe!TWJ=sp!~Rle=>3Z(^T#MfKdQG`v1ra zyPtiNoSghC)9~>mqXcB|^fU|VjR;@<&TTLNxrqPei41{51#zMOBwVzDPAnEJkS37_ zfj|j|p63A^xcjRz8~E_w|??%?12_=&6ZFGeO55dXg^azO3>EyDk8c{CMS zHTAKJqYk2@4!)fo*c{=Avh$N$sIugVFY{hVV=w=7x0N@%&Yb7#)vD*uByz@aP4F9* zsR5*$8)gyz0%|&i4b9iF^#_KYTM; zvFnba>D>e~pw0{ly@f{~T;d?I;iw}dE8%`}Kb9ODaLOuCpdFKO(`&3+0csqNGP_Qjhq>&oSW;cxGc)}W3-aU zpWweIpZ6d~dU6S-$&t_AIofElZ_vN4=4Gg$xlchgi2If7>BBR zUOHQ5Vc7U+=L6i0x^X&!31VKFuhaE@H?h?z_Hn#qx+Vj0vx0D0?FLYiw6iKT+ZW1^ z?P}Jwe9zIOQDA+XzNWbheiokDb$@(pv3 zL!gc*>4T99k3*6Knh^i#s9EiV@}mM^2T0;e0aYuGLlQBz}L-3eebgEN{%5KcBOrp0$=>s}gdgP3R@Wq+ekvU(>eIhZ)?_&LWF|C6znFzOB7wGT;a$rSc(yU8Gjz6b z?OVoatv4)ouNpngWhR!oIJ&Tl@v35()QO=8NF+oqU5#zUOS~pE)~@c;Km6h232SUYw_vk*b|0J$2@b4W3nci;3eAi zzI2QZ0@@v!gBPBBYR&Q-8^up<2}K8`nDgHpI3OCQlp((MKMbsRXeh~QEY!d;_I#=@ zPb~$=a$(Y^!Medu5HcNo8^$T{+yecxJ0OD!x3rqoBGy2Y$PP2_J2I1*v}YxUW_I4- zY$|^`=B=BWga66DgaiogeN3zpa2|1#AVh`XZV$VKB24w<)t`JPD8?WU3kIs96l3Tt za|v_nreAVKo>~<6*9vWY%b;(8Dgo5+Dbq!(F>WQEO^mHVE(PWoEvr^Ss&;$6A*;47 zs^n2$$a!$pPBN@PR5gmXcj)nWvE>RBK%G*9CaK>cS?cGou)9N+VKB$x zr^f83G1dNR$;n|sDkvqx%pxdT^=(SP$YvWG#Jq9M{8;RY!x79;i${gMbD~<#rkE{Q zR-?Mh0_NO+G0s{1Jlte(%UI5p%eiD;-tu?IOFTdd+!3z&6MQpFCYjvgmH<=4d>vbx zCj8B=2Gu6hW3^o-C}82ea?Hvlz}yEd;NPA}kM2qcoNn!_5Spb)rI6} zzV`GAU6Vn|IIQ=cHf0@ApB%+I$jQIN^D9vXAO~HT+)e|KtsE`g`P|(7-OqyP@^EgX z{1MiRLzAFsUK<^1A*a60)d_m@e9UM*$bD2N9p?GO^A+(q17tH)&{{*Q|jU@ay&uB*VvJ?w&M;y%;(7wWR`U&R$(6;{3}*tH888AJ*;{#1j4Srh zmIVvwM{z5D#{N4i{qfz^Uz*jvp7?d=u(f=WwxiOu!d?XrLaSwDRN7K4dij}VC-X+S z-Zqc{4&7d;RyigVL3g)!{WWDQoyoDItH1X&4|*IV;`Q_?5j7a}%%0uGicY3hoMm)V ziPb@n?zxy!r@Bg%zrLH)&oIFP&k6cFoyN3H{a{pV=iPYgq8G#pAs4MK2RZPItG}T( z>Pu#rUzoSD|IrD0CAMEd4}~yIJMa9g1<*E-HyeRQg74YRsg-bh#ybuszm7%dmy6y* ze>c$JOJF2Ch&Vwi%(7g@jYiR|cZ`r3=gCu}8X|T*%cZZd@$*(iS$6rA;cPAO(`$vA z*4D55g2~DV>mfw>JWNF;sy=XIm~U*W&$Z!BIYu)9qlkxdl#t%4MGB`q6^!yW-7xVs zL%qUl1^O*K+LdICUQMrCNBzZ-pAthn>{{79Of-va_&=tsx zqbc!4#DK0d`XDX4`Hx++gRbsZ$f`rcQHS}eP53AHs>2jPIC6-$@&18|FXj!@VD%w~ z`|(VvUdif%VILE0D3)>4NH^Zn-q3ivYqspi?+#su%jbkMI+ViRsRfpC8? za@tAP&w6?(^Ksr~Cdeg?aG}91G}FlJux2w#TW?=}p2K#-bY}IL$=G{9v+eatY1x;r zt^)fkJ;}9kqEChW7s}RcU@I|9`iZH035jdv;pbEgo0TD$b%mC=gtGn*IV%^>NFcjm znC$KW#nJFbVbZkK>{@xNkLTJF&-{$JlU~MNNa5}2>C3d%oAU3Mt`Q$To?lp?&g1^( zsM?Zi;a_71^@`jCoV~8D!42uCof0*@p7o05o8w@cPfcqtbM~HE%mun{IaFd-D@SQO zAbURhmouHsZ^4S?i{k~Ou0gU&^W(bS2MJC0ImWcRSvUsUCbUiVW)sZnQa+^vk#+2a zHf&SOoT4eq!&l`%H~ejW%Iy1(jUufAv)>osW6#C?OhUkh9G&n{_*W;bz^8>0tt+=g zcf{Y;npD)Z>CgH)B3XC&cz6`*MUg8tQjDvT{IJ4;zx|P^sKwq6xIL$=(9u~{|C z!#9B6J^1W!Ke%#!Y~JNzwVmN}eW39cU~=8&7CNTOyR54SJ}|@3d^JPI(N4iT==f5k zPK6lHy0g|l)GivU@@xwaZs9q=mCPK^8>H#5)&v?aZo&h8K<4M>&a_s{e_LXlIl^9b zWT_Z775bEsl$(lCpo~oYxBRc;eM|9vBC4;~6K{}Vg9)XjV`N&@9b9j22E*Ipi0yh` z^8&;#Dtp+yjlFRCi=`}3#-)GduP_23EY2dqHccSf2T z`tJYV1wZSQ5#;WA!SZR!>jXRfr*Nq2NxuDSQ_ACVI+g?5v; zc`R@5H>BI7=OoN3lv?s62zz_Ta@H;x-8sy~l7WgSpJNZ4=qWOQ( z_11AwcH8?fNJ&d~2nYz$4APw)>(L%cWVJm>NG zp7VQW{$M_QX6_wp?-kd+)?N>9DQVzk-wpg_pa~~`c+&wd8-jgS(E#nK$r%CF9RKRU5E89| zc!&`$i;qONKsizN@`R~HB5DbV?Qu2}>+z?&-&@J*8_q~8&W5lI?wem$0(VZ|Fr+x9 zO*9ixOAmIP4Q#`}&H~uM$Qu+uw|t)bqvsRKynJ}XYLZcEohjz1!huaV9Yd8z**oJL% zjzQjz4`^!g5f(^V`oy^S;f)^5Jhz#B)w~@1Lw#zWTAA9d*tz|=iq^Vr9Ll@&$5})& zz%RP~AuA;WKuDiaS+BFoy>q(q^CXof%I}-V^{lHTIjW|g;Nc|({^Rk-T`yh%4Y$72 zz86<^c4-%Jkq^tJWP^OVB0>maI%PcqgzNR|Ln{FhTC@Ae^BzpC9aT#rW1}iyd~`Jb zkmI^+@a-$*1(w)L9U&$Bo849nhK%yAUfc7_##%(C9kyalOwMS0>HdJPpLLQb^K{OF zZ@)p663ArGi7XJW+=>14=7Y2_cN3lJWs?Wq`?lP!L}Fwo?SM%bIA+%^nYs*QAcjoHDD;lf6Sr{AU`v(sm`BCVQU+=X&B! z+(5t@Qi%Y1PDk>OIj}Z+!r-T4(FwyDaP=8ezxtf&sf+emCrBqLr#cFE&*oJwvXvd( zU~VXPO^~O<1&>V!B_}lgOQ&O$|gVlh@8i4EcY4j{@8t2YAP?{ z?T-p>NmBx$Yx;-1k7oRzg{zc;1p?Mn^f;=Uqj|<EPn)0onwr%&J zE}0#*phoyx*x6IDv5UPaa_*F6_BJjssW6RIz*!nL-c^~6*v&LOYu*%LbWLN%1?g6%p z{^LKLlrHANz<;C5CCRYk2KvfIH>mHHr5D2to~O&5DcK=*Y`NRCA+-fY*8KSIRp@rD zY6^_3aqL9En$fT{LgK^dlzIrmT*GQ<*m=1i_Rk;MfKr~^{v%KI2YDJRC`iSub(==K zoz=Hr6J~Wd3l61vTS#m;d=p1O?w|;04dr-nc%-~276=QJ$u~)gg0A}$o2?lcmf$+z ztZBRYTu5{a1-*!u_=dT`yn3U?*T+Hq;a9PLe#JehExnTNgGnt)==b_EWu2(ezN%}n zzj9|%(?YFVDFnNN-vIBd{&pD5oiX*!_;>v?I=Y>tzc=&5b19|Fw{~jsUf0skSlH<7 z@TDXa2pC&GXcf}u@mIY`|c30gVhbdpB- z)`^AM6CY`ldj~uS02#mfBV!G4p~QzHhidjMr=!65&v}C{ILB*0(kd`>pI?e_NaXB5Y=E_EdsDY7qh*9i1OPmP3MD&e=Jj z?Hibs%o;6=TFtHm7-yQ4S8yCNb8}<(be(q1HY@P)DXT9Nf_SZ_=@5x6*n{G@)_;gZ zqRn$+9e7OqLbXZe!tIyYtR@OAjqsrKF7GC#i!wMqYLWV8Yq@Ke)~++SYv)qO-Hd|o zfY~M>PALSm>*4c43cr@W)}EqbCJh0>ux#i;JK$oTWAv=P;fN*%MG72f zJl;3|}l_tP&&?}mqmWj#Fjxa%$HV3S0tGBY!9cx!v|u0rq7 zgn)L-s%p?CV3JM$-j+q^AWgMyopR8Yw>7m;S+{rjXV>xCM4cojS<|jO2?Ok%L@5@% zNgZQz%2QQ0FN$v}dLaeQ6Y{xpcy$;T4t?)2pIHf(5e?c<&NWk`*wn0_>ri;o`rcY3 z2~b4}(dZ!sU0gVrWtTeZR5Tkg)o=QT>4#;lGR?v+h&VD18*C0uhUWKzQd)5tC%tqx zn^}db*G*jYW;>iQFB}$kX0rN7D(7c@gyInkI?w>Hl57c%!K&augSEKc(acF(v@QJm$?N%i8G6y4fC4E$=pEM zo00X-WewME^IrMsLJ=$Gen=mcB_#|62ZWDfryYagPd07Gzjt!S4rc81MI*35ptap6 z;f%sZRuq^npW8b3eZoKKWoTKtiZN~9@))7&OLTPr+&qbDIsB9RMe18;pu)xCj1Zet z@AnLQe(wPgajobiasyjtLx>PC+`xz7c7?|(Qjc7?2j-mHU)?2FIo^^(tf=m@XJ9T% zbL20A%m6)xf%Ip85I*R@%Lyg>(IV&z4(p&Su(&3mi*sABB@RQZXLiYKGg3j2>Hy!w z1jtF%(}`15iUIj1og&sC=&!| z?9hB1Vd~ixFBGcXF(8OE(8@TGO$#G_)MK=;PWsvg_Dn5Csf)HRz9Q=>S*-!|Ru-Q_(Vm z;Yw)z{&!k=Ql|>O;@hK9Ft^^cP8Uzk-e8)r-R!}w7;gwJ=t~?-%V?n4zW7@-qLk8c zJKL=9Kme^lpgl?bMiM`@D>mp3x&Vz#%M|jY6LRI5b{vr^mpQr?hRrm(Qmd^yX2yJb zxt1{;tY}y+7o`xykXGg0;}FTmHtq1kSx5HnGyWd5mRc)QnFi?{jm;zb0i*hmjzftY zpkxWS9&1zim(jWwT-BcFcKPtI?OjdBp_zRrmy&Do@wqpWKPoOTI^*|$kItCJCN?;< zcw$Q8`+KHS@1IJ(6X^I^KX4BSYwzJoM0q;&U2noUX7)oHO5UQxVAxI{o;E^nCyNS0 zY!QlCg(H=G*;ntfhD3quj<%{+V?eXX*4a7yJgyY&moA^^BfT&|?aM-=B`Ue))L(Wx zB;!Cw&*pE#(!_Vm+S<_ONCv8{*AXGMm^?3Yif@?fsWiP`^yIR2hhzKZxL#8`yla^< zz0#d2J8cQ*a!`cr=d^!VCk1IZ65IyhK4R<9IiGv6*ZOAj^iKS6YVDQ{eYS4cz4v3o zgBTAMx`9zLzu^3j`@&cz6{nN*LB|@41w+`c7%Rn1bCy3ePk)YKC1X1J5Lv)bNwy%- z6$QjHTSL~OyyPYzQm`FJvbPkQp$MZa!a&~;gqwA{59LW@;8q~wG1XVfO;6VW1HYIS zwG(lhF{i4y^C!Srt}`_Lp;df*vD`JNme=Nvtcyc9ANZlH(Rn|41h{q%^e}ik9wO7B zzK-?Myx&6uY|AlhzIc|lFMIMvv?e7-_nMHXER?8R&_V<2#uX}TSIWwlkM(bBXd;w2_1 z>u~?@WKlW$2@}usx?31xZUN=)w4DtAU%j6uL-448k8{1}M2JjwDZ9JDOi?307-($t zvbu!=j0POnt$r$5G!5tP{$O_0_S; zAMRmhW=;>7U;#tJaHZf8I8wPIC%k3*WO0G#TVmirxT5ySxp&B1AT{7hbU*srzv>3O z7#Z}_!>!7w!AxX%6^EGf-~lLJ##Bo{)VRMRq# zj49QLWRCZ~j8;VvK3DA${}qTmFiii}ljsAgrufhNwDA`Ua^RVzt5#_^xg-o{0_p^l z0oT6_kT(DIef9tIeZprqf*eQIAgD-Lw}|@60HQj)$&~QO=?MYmJzqy~kr?0whduuz zO#KJ1e(r5o=9|-#DZ!M1gYl4}8U<3<0`}tDy3%>%dLYiuJ$i`4{}q3yRbc{Nvt)0{ zP7XUn-x}zWs;UEVaI>CgrTUbxQe0#tGuGd36XTxbkWvU+@fcYi$BcK|8Hb3MV0vgG z%1+M3f_(_v5yemOk7ZS_ZUO)ox&I%kgvbUfIJAFe2Z?$Q$UBj$KJKDCQg;f*wwrLY zn!m+R&8?%}Jc(bkS{9hp{qCVp49u}s=bs*8fB;`m48>XD0Pt>eYMg7OnaAcB&O|6K zF;vCGG?y#10`b|-`BPG29txBlt@ivdF9RmthUd?$ye$?`vqZPi=({6Vm#buHN<`SJ z;6tgqZ=cehH>Z+T6d4wjN!!qNB|cA%j{~{8yT?-iooM{yuFr<1p-OZsY9SelY{@mT zq$4BI;LHWpJSoCZm`+Bfm~*yCcXs{h(dc`2To8v!UcQ%&XZU{QKKe zwkI^dfYkfo&|`_-dPB;}51@LKXkPFW+XugvIpfcC+es=ViZ=FJRq|>J`Mm8m_NgQGVgU|7nrzl*`VcozOeq3;D1_vAsN@lNXH(@idqL*WMrrW#y%jCahK#( zfttpr*Tkxt&lQc&Fhqa|1J&%lX#^Do9y!X1~i$DOg57g8To_Y z&&~vlEjMyjcA>8_8E<`jTQ4_?oIO!UTG56w>qd#S0`NeL>cT0o?6=&#X>-cOCZYji zw%%YAOkoF1687(fW&Vv`d4v{s(STTl{>C7bv_sRdS)@8cuEjFSB&C@6_e*{)P+d;s zZ;q`)vwKwn&q%57mT`|xp*LtBvonJSZ$8Ewi0A+=UB`Vh_loG!8wa~%-;{uLk;cnt zUZtDwY3tCW`rqrQ1$AJH8OwpzJ~G1wTrCUQn?S{GNH71hi_#E^ZKij&$6b?Zr2PCS zJz2Vo!?v=San(LTKCsNGvC=W)cPA~=A2;6|{h7@Za3AxlRG&7{6^Yw?+jGuP=VGp@ zEXc3-f#MAgOGognuGHH*7rWWCsLU@5ReMW1s-ow(Tg$gX@?UP>%2nE=Z=;}B5~3~_ z0sHNp-xmjUC9ZgCf$?1ViC*0@0heFQ(KMaU-OI5-io~ci)@cr1v0rtv2t#I*K;<{Q zlMJJXtEEvu?xuCrkJ z*z;**3hOj}2)S>*^;L1!w3U6aPO}x+bl|nI>U)d1&Gah2G0E^WH0Du66bi$>Nf>2uQ;pHo|Wb5#;I_{Ss@Os_|3YPh6~;L#bu6iUaH`Y>8ykg z!T|e@O%X<5^YduC52@Iy>fSS~`Wr%?iO;Gc2iz&(6;11BZ#;Yib$7(Ri>R*Uo#gwa z{YX`U!TPONe~Eu0OloK-y}{{VQ9!TFhbV=^uEXqgw5v8GgF13P~KbF|#_eQjuH~U)|)A&x=cLT>5q`Kat=3m()x<2P>>R0IF z$1yj*3HmsX2IDv_#{nsdhRs_^TQ+wv50*xF#aeQS+QD>gdQGx!>$Ut@>_}iaQm2LX`3BY zECsUIBuj(N3vM{#Hn2hK_ii7pk4HQ;A4OnD@FIdc*rr1pj)S;hz_q4RT2Wj1Zn4xN z&74RdM?*28 ztZ(*g^JrYr6pw=Jy}Y?_R%X?_`RyYIBo4+txu=d0jMrbdQPvGf-=Coeb`^XSzVY5M zd!5FQ*rT5PeG{UA*bq3J`^BI^CTGNaOs~(kvMs3HA5JIw6z>zU!C6bCaJ$N~0dCIP zB}wYhqEmiBfr&e1G&QA!1>BNVmkKt#Q5aaU$5IeYU;o`VW z7%vY$_qZsJrB#R)_1<^s{BU$lf-6-^6%#?#a6aZuUXU(DUoEq8nMzbo>_DBv0za;Z zFK)zX_LVJ7Lif=X%2D6ph0A@#^_4#EneVov!0@{kHbK_EjIZ06s=Aum`_s*lJTSQH z*t{|DUX)$05kUc?JTQ(o=8Y=Bh|Pl2^Gzq0jktSR*a0qhoP4>adwSuK3NvsOGuHGI zxM+P!ea3aI)0m4H)ekxAay(*tlwoSIAW&(0@7=nkD!8sQzdeBft){xw`P(WG*gZDK z$01yl(LblUF*m{@#6amQ7mobe?2|E+fdiD^A%eMIjHox_*xm=ABp$-l_dJpBFvm1LYkU!g_lXyBe7d%J zoLc=oK-^-AWW8XP+0Ge*UFyDh0WbG!yFVINNHPKf`OoB>ksPANJiHF?U2RbfvLpL7T32nnj|?fy4xj=vXNKj@Un zY*%P;I^Bpu;M%-$V*p8)bTJn;bS}|{-XC4swEG0=i50z6AzsAxB}TNLRsTSpWLW%W z6syva$jVnBQ0w-#0`0o(tbx)oc$qkp@-I)J86Zmf!}%)onu1HUD%ZNhFdLoM!v|6% zJ~Cv81yVDrTV+BGP4FL4kKXe)v`(eC;Jj?;h?W7&s1x{UtK1VE8FaCq*na)z-`HKO zx2F?|uSn6jXG~XvQM9X!o=%(ZNv$r~Ac)&e+9S61VP6P95_+>h%mw)eNxu&@_vb4orp(zW&9LDT=zr^s4w-)X7D0gaZ>`Ux{})W z$p5D+n9PMjf`5Qpb}UkvsVhw`>rKaPt2gw77v) z)%Eq`K7PbsZ1W{aVb||I=R^lF?ILB<5jcNs9?(mJueAh9!y?+zlu}1}a;gx=yuph~>-+14umhia?S zG1go(gAw*1=J^jTZpc2e1rkj1#jI(FfFddut&WVVgXYrHKl#krb9lY;mUXNJYL@`d zqw`t$)89KrwUm9+Fl7f{WPvSCspiWIcjx?Ts*Ft8oVl*s4) zeq3`f+@O7Nu}eD3fqklJA*6hYan_t1o>t15_5BBKx*Q=2yb0Fi?*NG;x5Y+1kB7Wu z@l{pxzeU6!*YegE3(Wql+{YRjA1~|X#`~r(^X&SjWp4e0@X$6P{@9~1NyJQAl*PMt z$+*gq0uETaKEfgVr~mD3+uh9pC{@HBpHV3@xBFnG)RAc30`OmD0*biv3bA0>$$X0?|k2e?R9wf~{>qI!BxTOf8Ia9822cRCL8dAotskWg1x zTJ!GV!wzoCD6M*hz<}6BPp5}t#$FLXgono!85Jcnzx8}p$B0HEkK-N-Pz9$W(9l-} zE{iNI>2kAPrel;+`7V+E-f?!}6x8&J$;msE35vOhQEhY|imE&HvSSRm@>X^$BjLaD z4$wT}&36vhKWU+v45sDg7;JJ(w$6z4ft2MnTSw)h)|HRBXGit}K5Y9L&aGal_F+Tv zOFnVg51SAQ>g)I4uDndOU)iqqHzg8SOVAY>2drG)$_)=1f38}>I8I6e2V@0U~U zYYW!h*|0y8q!~FsI$s`!q4{tGE-d6PCuFrnG}&=1wLPN-Ci=XqLI`0}UpMHo7Bret zDd%?YDNK#_j+*JfB0*}6bcR(-$E|3z#_h{E(CJ0Yb`HMD9 zkCl#F0Ed<&m6Iro4cSm!zk-zEoH{V-hn(gB)O4-6%9~m~9yCvz*H7%}26yl&e;On_ zM3y}&FV{3y{gL6i11umfUa$WQAnvaz1u;udzVIbwA^ACqtx^cDmU zH0sVZWNM$tk!VAQYR$$MFS}!B znF2H-8-)7>sJ|}qogUo=BV=W$yl9_G3O}d06xLFy=N;&8-}OQomc5yp-^zdJdbT%) z1fOEeKHT382t53~f7;~Wh{uEPyPoNP;hn`$jYv_5eL`XLh|O^dy5~AM3tf)gG|f!} zSw3dGZ2Xziz(00I9UeWw+zJ&IsFd-iI1TSJdF2rW`KF1L0LjR_P&2V`e`>Io*UQHN zg(TZmig)bZ)!WC^f6BHWBl-)^D8!5)&m0c$J^;v$8k(BjCg^SIucZ+jq2s8+se!l6 zs2l8@azpU3j!w_OOS$3~t71Ms7+$4%=o2_Whgqjls7ShXcBPc)`=fJRAyqzeCNH!b zAE)!|7fGJkAaMkt?8F=+}<0 zuo{EDoFqalW%AJHj)BoErMpuJ-#p5@XU~k~6?P(cVWpxVLgUr4%5!%k%d-CNty(iI%A{bh)SIJ|K^f+A?yeH}?jnsRE@&rsNS@|NLQ?JOrE~!# zo&;`c(Y{G3-sR^I2p|Z$){&8WakI19z29L{*NtTSE{2E4trs|;yZR1z{o@VSFHu}@on}Gn>XCcQ*k}#ha0sdHP1Zc)y*YY>!Q%}usRXPLe`T<9+84C49 zscAchB^dXmg15w&QLIOV6B0ZrffaDWq0)PbK6ZI}>;gIExOEf+z(T6(!A#2xs{ma4 zW35zPMr?HS+Yd=ep%PNrJ!pmpwv+=f&@a-i;k z3-tvH{qXv&wEt}O?^1EfMN-br&T@gc{@-484(4{Eod&iQoC}z>*EAkElQ(-F#?M9k z6!dv(_Vm%^=};%0gGVB&{%Wv+Jq{>NI-Qs#{;;cvro0#GIwDCB3>3mn<$QwF7Z_#J z=8r=(X4Cn;Nea9-(Vmi-O)p-pWAuE}*w4_;oZw6qxq1EW}o&Z(H3wUA+SCYoaw7SUBI$e1w8|G+zz zj0ZI@iz-YYhA*c+=Jl|0CPCng5bEEsnxxgY-~Z`I3Mvr1^g2Ym5(4VMIOX4;a(MZS-16?E$`q&R`_bG$IHcO6R0$e zz=!U|8rdIuKiPj#&hcR535WkVVX}{o9Gq9wNYpE5dL|WuWtXOgymrPSjwe5OXY!3B zTujU}qB*}?@H5Ct2LRPye*o2dDeNbUp*0+OCA)-0Xj4QEUFr!Uv4KkdB;m@G)(ANg zA2>H&>390K7)*IHMSJuC7_{{2AG*R*8k-Bv^heZ#Mfw_21RGktk#qe9quG6T zdToK~)96^~vJD^l<$>|rPJi7ABK9lf2hm|T{^czJRIRHAg!qv1B#;xzR)qCd|5s3Z z4ZwRsgl*GDbPILXApY_+>a&Q_|?tK&o)U)5oe*?LFv6q$Z{1?31 z(l>R?T>D4jzof7c_R28)q7DqHDuYTe^`_@_8pFvyF|U$9kg|vCi<);S{eA$+!+W}Q zSlNfoOB?3^^a&K{eell>)cikO+%VYjk6&~UZCneN-S5bzFXz$SgQVr;T9$p}=sb>W zfEpziSR1h_a?oCBEJ|SvRv73W&Ciy`*5%*8D2Y1iGdey#;_B+^$gMG?F@F;(v6Qs^ zPku9oBi~!M*GI+pP}@GgVqh#<-+xPjh(IQ_KE}#UjgF2UnXnt7MqptwVqOP1k&eNr zWW?#6vEe}wSFgpibX#>zD}rBtt@Miu#iQvYUr}-Q-8V(BVitIBUE4u303k!$#`_JH3F;u^dkl%Q;QbR(FLMMR>9g+D>uIXjd;)M~^0f(%x^0nG z0Z}HR^^R}%Z0XtKXpZIvp~#&Y`a#wHCRGjdvxN|VH8W-Gbf~?^J+GH6lA{$WCtSk1 z7^-b9tZ9}lo~eUOE9qbPgek@yVGr%NQojTRK|U9K(}P3WZ1Tg#?ex}Quv@IQPuH>Q z#+G!MM%ajT*7CIHE@qV1`pPYFM+znU@*n6fxs9YTO~Yge4#?#|eMj$)q5=*<0DRW` z2|cGKbcQ|&ZHnRMQtf6zQI`sBKt_k)sK-!b_wwp=_=qMyy)*rRYKb97yF3(5!Mq>H`-LK|X!hpxWL-wIrjN;>P8bEYE;GSUgu z@ri=R)-4EQ!9$qP-keZU>5J&T&Zl`*ZZMI@$-eS2G2O0?*%*x#nmy*da<~$o--gP3 ziU0zLo-6Ikc}O0oUw}j@jqMw67ryI+h3#rTN3`R>eVVxbx%T^dL7Lu$sL1%pPU|9A zA~M^@q(uHHFGB$O+?wHebSoF%y)~9sUGNhDp~{MVy=}%o9NO-Wm;E790dt>T@Bv8; zgvh1xTjMjf@}h39TdbND;I$+Bw9Dv5!VCiu75bmcE5GWi^)3Z_TvPCHDMv+*=cS(P z(e{4tGnu#{Gni?(+c1%a-KPWbk8Hd@7Q&9AubK^^lWh-aCAcsT#>GHU&*no=QX<90 zV9xm_%NucF;H>>H0*I@A!jl96Li1lF=1`g9v3Ulp7D6xOPpc`D#kgJkV+^a11QUaj zQ)Uvx`|H`BSvA|>YDP?4v5VS)8#>L~XToQhG`Y)+UD|EfxMJ5y14k$G-N*5&rf&{= zMglJhiS38N*h4Fm0FndOnaN5&SdOq5jJfLnykR<&d`vS&CWhGfcW%k-Y(B~|&le!N5$&i;w z^~>x0LCNK-fkrnLv`^RPvNuO4@iRrt^msh^xLN79Prt$TWWimirkUiY*K+ji?wB^V zw&02eaaXt_fD37V@g##O#yE2`5eU4MjhrTbP5vc(J6jLEvBFZ6G~P004!5`Nnd=yn zcfr8=PB&R3P1@KFB(3aKOi%7^794U*yZn^{I2Y&?i8(Ca_j|%Yy8EGFzj7<{vRTo{ zidpx4ap+4u1DM0TRl*q7VL{(o9rjg~d=LYlh~SN_6UH;ccDk7WM^ z%VPC2?p+%pzp5LH_O z#lKdv#han1J#k`f#YCl8UQGt(bacHr?zV5}o z>RtCI!HIPiIPX`jMilWm>n!f@3$AGp**ttK%}JCOs3BbOGJZqtF9dGHTF}c8ur5Yp z8&Y$YW$WT|U*Hn0)gDZAbn7=2o_(WU%mmj@xw!C62Wz= z!KTu2U>hFltGh#eS?Nir&(f}0x8}b6VATCHy5)|^`0T>p4Cu4^R9+@q4g%(?4bB1N zV_!qQw*E%DQ=0tEvPHc@Dd1w51%J0uqDfTiYjPoy`3^I36XY-ZH|{r> zwxP~Ut}y^sWv)7E_Ya6CG-nv!@ELAdrM5xHVfMsiOdx*@h^sbbbHz>R=+s_MUjU;d z@Tcod8Jj+2}zSMbNoOqCEhW2FK_Pi_O}*W>Bj2WFj{yKk3M2#Cgz zQYhrqUdO7NWH0RcQ%!OxM0aJhbPa)@&4_wzuuX>k6rEnWA|6-{phAKd7%%^{+oA}B z`7J>SZMv=h@AN+~oVzEOSdge!aND#ol_Imafoy5H330!98XNRV(;d4N>ZD1a`b83ok}h7&Th$giwL|a)sh--wxeNv~AXj zt#m+zPlH5toPfNH5DsL~{cW-KiqLlKy!XH7%n9COuDb-LzcWV(>u8}+0b8`CQ8msb(5 zOs&4W9w*8WaHqKbR#|1PLS3=MBC}ooXmF1rte30h>ATXSpGSnRbq!XIsg)e;{m_y6 zEPWR{OuU3Q_G%MiIZH8*O=zCggQ&IZH>#T{VxFWlkDCf8wNmwJ{bG|)`7K^H=Q+(a z^Rc>}vcYywYY1b5)*Gyf93iGvH)@}keY=)5ujvn>es+l}{f zP!)-1EprlaDFhx1$;EYSa!`Es3%szA1oGdZM$jMS%_y3%5OP(#JI` zRjRsKCK0M8NsR6&IG#S0jWQTR_u7uTmjTybiH~a)k1Y@OZFL<-MrxRBT@G0_b|B`x zK@%q=iJsm!XyZ^qqzmqbP>y^0_F>YeHU9q6thx@2eF5|3-gM?0xJYF}GYi zP#6rdAR&y9^vfP{mLf~b*Zk5)P6iCkG1k6TA_`i;S(8a8k7~=Pc#JHrUq!Z!w3hgh zk20G#z@z5+(H-BFH$V!J_VW{aofb$IbW1B_JHryIL=&ErA0UtEHdTZ$(y-$Qz-}pA z%+F9lKA{@_T*%J-x#JT?3rxA=ZYkT{C?1ovEfJm1nYeQ1ra5%M^glBm2ht(UOpbjY z@`lq*9>XB3>2U#Yig_!(qDt@z@Z?_p@#NkS99Tps7m>P>;9 z;?$Ck#Go1|i=G`qWAzhRuR-7WeSSqIXsaKby8jlX8%m^?Q(FucP=CidDTy5x{^>N_ zxcALSQ$R2m;CmvucLjRtUf)d5i&lsg9@HlM7)=QbPenYeg>wT}2wynUE*729{t0Ev zBmtW0QHQ6SMBGn)fX&vV5Y}P?6qi}?$`mNRt^ehKH1AWGSUs;&*0f4y`_u6^rkPyfk+SUziTz42i7k~DMPf*Y zw(Ewhz)!~v^eB0x2S85E>mU5NFmi-Tz8^^U?UuG?B1c8Zwoe$>Q1I?*#YP#~bZe zIi@eOK5cZ#KJ+0nvYX=1#^IhM4P9X@+)q{ycid%r>Wxxd(aEU5uSTP%0S|;~bd4&j z4Q*Kluc}7!BK!;X_=oV#AJ~*+pZjtibp~dYg(l|N2!^VCIC5lS37J<3tmKxkgDep; zPrI4rBR-6lx%H2@UPxgZ(Y!r%`+#SpqkzOj9MB0Q(4a^dfOnxC6?P3{yu*Iq)8ga* zw@v$pHhoK#B*KCqIHjsn)3&1OF+dJqyC?tAR8#Zsq*c{&vTh_nks*=kP|5#o*bZn| ztZt)21@)zt(!9($5?P(Z#h7xJ!I#|xXgze1x1INUnrhVlHtb%E_iUw%ud&~z1!!c# z*JoI3Vi=$)5*1wMT*v|Wl0Y_CF8ziNpY2!G0xq#j6!-&4^Pd2jF_jGhT#wnBB!r^v z_{UQs_Ltf;v(|j?Jc|Sn5QsPxq$M=;<7gEc^J~^trMkjuEHNjojQEi{RS6Clful}C z`<<<+9AcaP0D|(mOQRiTEXs^v;}JH8O%OeX*dO!?4qO`anHW!uAAix0xkE^;KPqfN z0mwirxmjWKx{J^wvMJAaS*%bTmUi+oo@^KXase z`}!Wx96S*p+Gdrq_02am2nfX;Sux%d5OAO!mJjP^`Pa&jg;MrM2;AX)d0KkH`1trw zXl8Kp7zcZ^25b_3M-dYlC{adMPT5oFpXW%${hLS^pFO43F5Ml8YlOX~lHTEuiGcl# ziIc4kSN28Q&hfkuq~2scW?No~B6@OCW6?1K&YF5CEqAC3vqwcV~AGXYvZHfmjBU} zzew!9x5xn}!7Ff|4YRo4;d_3AG8BZ=sh6Bg1soSz3!A53{ugd>ugG58o0Gpi6_zW; zD+gUV^)nKd?vL;kE7Qx&VWRD%;eM3Sr9y?pe`m`Z`rU?l7JbA|Tk-#g#+?3NH0Fub zQo!NJ3wcN+kosL!w+G~u_ETm?er9PK@Ygkz@1;OHg!}8~`1{(9$jMXlBJL&^_=cu^ zRUi1kX@|qUJmJ&om~$x2yr=89@M1K8RoG+jxSeF9aP?|RCIEUUVYT1RWb+3W-6jO1 zRzcFJp_*t^7{p8VLBoBjv}l=1-Dna9(JcU6=9Bq#Lr=m%^7*8d;szbNInax@MTNBX z2PoRS-dl6N{289mx&%4n%bSfcuJC9n`By$v1z+ul=xtgr{hVHGELw|hRSFAG+(P!x zys{cXt~xFf`hM9#16wk1H}<8a<)l|?C*bnI#0o#YsjOuP4<8$d_&nfHBjFCGx~fAi3l0Sp$w+~Vn$ zdQS6ZlCgTzd)NHh#9>Atb@b_${Ar#Z5evDBV~z!w(B?(jdgP7>p(Vxr)N=0g?@a2S zo@6Iu+xP38DHv>@__?nFkrckvFMaT%((Uz0#KhL|keABSPj8 z!&oGD9ZFDS1FE#?aC~X}NaIccVpl}kzpw}CiCjfjsNCyuO327*MBi$8>}g!lWNOuJ z2%h{G_tD?y|KVo&O|{(SiO9YMB+Z3~*Jx7JO%e#7o*O!^0QXriOIN0H@i*K`weosk zjYlMOW)v(K6BYzP(P?=v${XzY0N>%)bK4xey#dz0C}G~M)*V^dJcOpx&@*_zfuuE* zpzeJcm5po0khP_j<4nXcKA{@1!;;m2PxvWbsZ59u-;O%0adg+ z3w55SR_(N|v&Zn!{1i1cK0cXp5=(tKeE=L$WkAnINXc={CB+y3Mb)`toO*oWqF3Qc z)#NN@`3Qd;CKSMD8&CJ<%UU(g1`r;xM09#1WEEa65r?Hs5e=hF)4j=~bJj3@-y}+s zs3xUP7c!(B8W~BtMShq8obf%dmq^;_x(3_TvTF1ia-$sD-HzfHkwyedZ%C2x#TUsN*Q0i{Ek-Z!SDDQE+i#gDk;FFY zz|io)+<4`^SB0@zr`Z=m%pHY4Y*X%a=Hx`5`e2Q(2HYvTen}OFk$Y+p7n%Opa~(}? z4-xIpZWbUw&9HnJ0b^w^7=ulD791WRbh*@f5q-StOhCj0y}Gu ze9pGspU}$bU%L37YGe6r=dW7=oS(CUmkaCOK2yL4Sn_~>_*XW7f07xi^@NHlZfnab zKUQel%Pv8;*IPss!m3;lNo z=_fTRLbx4r2V83lPVt1i>Y#_nPsriKM^rW$4dpVPsEI!bQy?MOpw-61s9%44L1hxa z!cRrq?V7y>XyHI=IgrvQ@QqO(i1gdZ3EF3ZaUEMZV;$dxagDaY{|5i;_yRDeiYPXwapi2!g?U3Dz&w}Xk} zign(7b-j5Jh01UdEuPi)C}x9{?z5C$vNg}*5$W62yXC|4gkzs7(H29;7tbfW7Y{#8 zw7YLO?|iC$+?LeOP7pK$O^a!KN^ujwBxw$PwA}CoUT?2Zd|ZdS2o*Dfi6jpGSt8G+ z;+PQ&7!kz;-ch^B17~hT-&o>eL5QTt5BcmscHmLsMv>frngubf^Taiw3%IcQRU|Qp zo47sb^30Q}sG^LNIzd2apPpfGN3wNRF3R2jhcZ)cQr-kf)L#T;LUY4MxbmQnuD77# ztg#~suo=;<&$db^BSG+C$r=8uum6r(Q%rC+jQ$g~`fWA!b9uS$TEihJ$i)Xch>@vZ zW+@K$S`IE>>=rRJFi$cl-Hbb*=S)x((lKsx#CyL=j(^=rp*zAmtZvd*fh%itbk-IC z_4T)*WISYbZc@Rg7-iyqWJ$5NuoIwwzGG(~TX;FwptJ~_uG#sOi1k$pk9+N?Q;7xu zgk`S{^>v>t(UKuCso~Hl;EEQv}tI4OA0`y*RnT$6L2=B{RFawN!v7Z|qx;czTcgbW&1D%h_d_6FAudf3M`3w(~>> z-2p(~ns_EGlD=qv{n~U#87`0Me`Og-cBI_G!IMOWQ5lu3w3dr?-9=1ZHdveOC+~?e$mrJ9~uGrdhfeagW~i z&P{z`ZDq9WSc5r}wrgHyIP6Cx53e`YP?IXKabR`kz!+c+5Vd~pbx+<7XylcdS4+@ zY#Bz4+tY`7*gs!O7Ey2k*?)^X=#gT&6JPgFfSh4Jk8B_}p7_68Z~B-0mQ*e$gNotb z6trYIK4b%CJ6eOQqejE79#dq}N|+KH7p1=wb}4pWSVxo7;D2Kqp6ELMa94%G-+|Ni zN5H>LC~KNG`o8W>R31&B^nMMv%b~d3WHzn}$N{w}r?XfbtrgUEA9&v5c*5eO?`WD2 zWYX<)|Iv5mz?Pq7faf{2>Xwrz`YhKr zE2~5ghAn1-QM3OVy8)Bb=k%H<6S%tHn-$mrXW5jPz#9bB!AA(qaszG<)CC?EVI6q$ z*@TP0#tgr_*5L)8w??csTCk^ZN$)MKMSI!jdk8Jq)|DXuIuGaCl$R5M?&9BG^eN^0 zZQvMnp>KY3=W;91ks`|QOlEM!LQwVhi&@v#UEls|RlvSH|EJ-PrXH$#v)T|C-icG+ zO#bnTg)=Gpx_HAmwViwJ&&v{46S?;IqW?=bd0o5lu;%yiJ4G&YRviN_bodark*_-2$721~N81jzd3D=9Fqs>v z;_+>@acGpw9kUw+aoI=jNeSQ6zV>kE>CzV;b4~vlZr^kF+SmVe!L8c7*EY;Hm=|&hXJC$u)mJ zso2#Sb!-1`RD3pn*Qd{MHJ?(%?(c~?Qe%7UW56LBW`-+9R~Ue6j3lynOgr0x&biNi zAFuy-^WDQ0|0mfy)Vw|T`o_(<$N7Jsp0WP;k6I1G9S>L-R1jLCgOnbn1Se?-?$>Gm z@$IUTUAtV2^0!#z+>W9 zNsMx66b6QK{Zu_CEm;Lj*_ObAclb>wsdxsRm&|Io2MT-;XY(kB-eF)RpQSeWWaZ_T zA;1W@zopr05S<8BLDyZ literal 0 HcmV?d00001 diff --git a/doc/articles/openshift_and_gitlab/img/pods-overview.png b/doc/articles/openshift_and_gitlab/img/pods-overview.png new file mode 100644 index 0000000000000000000000000000000000000000..e1cf08bd217d13f4521af0ba1bf8df6d5535ce71 GIT binary patch literal 106861 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%0Dk*;@C^i?i~$?T(9p>4 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%0A>Ry4CA?eQ6{EVlJ_KiP1m9F^nE0#@ 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

^^JcOni5rQ5(C}|Rly)WPpgFOGfegU9tUQ7 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 literal 0 HcmV?d00001 diff --git a/doc/articles/openshift_and_gitlab/img/storage-volumes.png b/doc/articles/openshift_and_gitlab/img/storage-volumes.png new file mode 100644 index 0000000000000000000000000000000000000000..ae1e5381faaae5845d4b3faa36612b4327b1635c GIT binary patch literal 49584 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 **Article [Type](../../development/writing_documentation.html#types-of-technical-articles):** tutorial || +> **Level:** intermediary || +> **Author:** [Achilleas Pipinellis](https://gitlab.com/axil) || +> **Publication date:** 2016/06/28 + + +## Introduction + +[OpenShift Origin][openshift] is an open source container application +platform created by [RedHat], based on [kubernetes] and [Docker]. That means +you can host your own PaaS for free and almost with no hassle. + +In this tutorial, we will see how to deploy GitLab in OpenShift using GitLab's +official Docker image while getting familiar with the web interface and CLI +tools that will help us achieve our goal. + +--- + +### What's on this page? +{: .no_toc} + +- TOC +{:toc} + +--- + +## Prerequisites + +OpenShift 3 is not yet deployed on RedHat's offered Online platform ([openshift.com]), +so in order to test it, we will use an [all-in-one Virtualbox image][vm] that is +offered by the OpenShift developers and managed by Vagrant. If you haven't done +already, go ahead and install the following components as they are essential to +test OpenShift easily: + +- [VirtualBox] +- [Vagrant] +- [OpenShift Client][oc] (`oc` for short) + +It is also important to mention that for the purposes of this tutorial, the +latest Origin release is used: + +- **oc** `v1.3.0` (must be [installed][oc-gh] locally on your computer) +- **openshift** `v1.3.0` (is pre-installed in the [VM image][vm-new]) +- **kubernetes** `v1.3.0` (is pre-installed in the [VM image][vm-new]) + +

+**Note** +{: .panel-heading} +
+If you intend to deploy GitLab on a production OpenShift cluster, there are some +limitations to bare in mind. Read on the [limitations](#current-limitations) +section for more information and follow the linked links for the relevant +discussions. +
+
+ +Now that you have all batteries, let's see how easy it is to test OpenShift +on your computer. + +## Getting familiar with OpenShift Origin + +The environment we are about to use is based on CentOS 7 which comes with all +the tools needed pre-installed: Docker, kubernetes, OpenShift, etcd. + +### Test OpenShift using Vagrant + +As of this writing, the all-in-one VM is at version 1.3, and that's +what we will use in this tutorial. + +In short: + +1. Open a terminal and in a new directory run: + ```sh + vagrant init openshift/origin-all-in-one + ``` +1. This will generate a Vagrantfile based on the all-in-one VM image +1. In the same directory where you generated the Vagrantfile + enter: + + ```sh + vagrant up + ``` + +This will download the VirtualBox image and fire up the VM with some preconfigured +values as you can see in the Vagrantfile. As you may have noticed, you need +plenty of RAM (5GB in our example), so make sure you have enough. + +Now that OpenShift is setup, let's see how the web console looks like. + +### Explore the OpenShift web console + +Once Vagrant finishes its thing with the VM, you will be presented with a +message which has some important information. One of them is the IP address +of the deployed OpenShift platform and in particular . +Open this link with your browser and accept the self-signed certificate in +order to proceed. + +Let's login as admin with username/password `admin/admin`. This is what the +landing page looks like: + +![openshift web console](img/web-console.png) + +You can see that a number of [projects] are already created for testing purposes. + +If you head over the `openshift-infra` project, a number of services with their +respective pods are there to explore. + +![openshift web console](img/openshift-infra-project.png) + +We are not going to explore the whole interface, but if you want to learn about +the key concepts of OpenShift, read the [core concepts reference][core] in the +official documentation. + +### Explore the OpenShift CLI + +OpenShift Client (`oc`), is a powerful CLI tool that talks to the OpenShift API +and performs pretty much everything you can do from the web UI and much more. + +Assuming you have [installed][oc] it, let's explore some of its main +functionalities. + +Let's first see the version of `oc`: + +```sh +$ oc version + +oc v1.3.0 +kubernetes v1.3.0+52492b4 +``` + +With `oc help` you can see the top level arguments you can run with `oc` and +interact with your cluster, kubernetes, run applications, create projects and +much more. + +Let's login to the all-in-one VM and see how to achieve the same results like +when we visited the web console earlier. The username/password for the +administrator user is `admin/admin`. There is also a test user with username/ +password `user/user`, with limited access. Let's login as admin for the moment: + +```sh +$ oc login https://10.2.2.2:8443 + +Authentication required for https://10.2.2.2:8443 (openshift) +Username: admin +Password: +Login successful. + +You have access to the following projects and can switch between them with 'oc project ': + + * cockpit + * default (current) + * delete + * openshift + * openshift-infra + * sample + +Using project "default". +``` + +Switch to the `openshift-infra` project with: + +```sh +oc project openshift-infra +``` + +And finally, see its status: + +```sh +oc status +``` + +The last command should spit a bunch of information about the statuses of the +pods and the services, which if you look closely is what we encountered in the +second image when we explored the web console. + +You can always read more about `oc` in the [OpenShift CLI documentation][oc]. + +### Troubleshooting the all-in-one VM + +Using the all-in-one VM gives you the ability to test OpenShift whenever you +want. That means you get to play with it, shutdown the VM, and pick up where +you left off. + +Sometimes though, you may encounter some issues, like OpenShift not running +when booting up the VM. The web UI may not responding or you may see issues +when trying to login with `oc`, like: + +``` +The connection to the server 10.2.2.2:8443 was refused - did you specify the right host or port? +``` + +In that case, the OpenShift service might not be running, so in order to fix it: + +1. SSH into the VM by going to the directory where the Vagrantfile is and then + run: + + ```sh + vagrant ssh + ``` + +1. Run `systemctl` and verify by the output that the `openshift` service is not + running (it will be in red color). If that's the case start the service with: + + ```sh + sudo systemctl start openshift + ``` + +1. Verify the service is up with: + + ```sh + systemctl status openshift -l + ``` + +Now you will be able to login using `oc` (like we did before) and visit the web +console. + +## Deploy GitLab + +Now that you got a taste of what OpenShift looks like, let's deploy GitLab! + +### Create a new project + +First, we will create a new project to host our application. You can do this +either by running the CLI client: + +```bash +$ oc new-project gitlab +``` + +or by using the web interface: + +![Create a new project from the UI](img/create-project-ui.png) + +If you used the command line, `oc` automatically uses the new project and you +can see its status with: + +```sh +$ oc status + +In project gitlab on server https://10.2.2.2:8443 + +You have no services, deployment configs, or build configs. +Run 'oc new-app' to create an application. +``` + +If you visit the web console, you can now see `gitlab` listed in the projects list. + +The next step is to import the OpenShift template for GitLab. + +### Import the template + +The [template][templates] is basically a JSON file which describes a set of +related object definitions to be created together, as well as a set of +parameters for those objects. + +The template for GitLab resides in the Omnibus GitLab repository under the +docker directory. Let's download it locally with `wget`: + +```bash +wget https://gitlab.com/gitlab-org/omnibus-gitlab/raw/master/docker/openshift-template.json +``` + +And then let's import it in OpenShift: + +```bash +oc create -f openshift-template.json -n openshift +``` + +
+**Note** +{: .panel-heading} +
+The `-n openshift` namespace flag is a trick to make the template available to all +projects. If you recall from when we created the `gitlab` project, `oc` switched +to it automatically, and that can be verified by the `oc status` command. If +you omit the namespace flag, the application will be available only to the +current project, in our case `gitlab`. The `openshift` namespace is a global +one that the administrators should use if they want the application to be +available to all users. +
+
+ +We are now ready to finally deploy GitLab! + +### Create a new application + +The next step is to use the template we previously imported. Head over to the +`gitlab` project and hit the **Add to Project** button. + +![Add to project](img/add-to-project.png) + +This will bring you to the catalog where you can find all the pre-defined +applications ready to deploy with the click of a button. Search for `gitlab` +and you will see the previously imported template: + +![Add GitLab to project](img/add-gitlab-to-project.png) + +Select it, and in the following screen you will be presented with the predefined +values used with the GitLab template: + +![GitLab settings](img/gitlab-settings.png) + +Notice at the top that there are three resources to be created with this +template: + +- `gitlab-ce` +- `gitlab-ce-redis` +- `gitlab-ce-postgresql` + +While PostgreSQL and Redis are bundled in Omnibus GitLab, the template is using +separate images as you can see from [this line][line] in the template. + +The predefined values have been calculated for the purposes of testing out +GitLab in the all-in-one VM. You don't need to change anything here, hit +**Create** to start the deployment. + +If you are deploying to production you will want to change the **GitLab instance +hostname** and use greater values for the volume sizes. If you don't provide a +password for PostgreSQL, it will be created automatically. + +
+**Note** +{: .panel-heading} +
+The `gitlab.apps.10.2.2.2.xip.io` hostname that is used by default will +resolve to the host with IP `10.2.2.2` which is the IP our VM uses. It is a +trick to have distinct FQDNs pointing to services that are on our local network. +Read more on how this works in . +
+
+ +Now that we configured this, let's see how to manage and scale GitLab. + +## Manage and scale GitLab + +Setting up GitLab for the first time might take a while depending on your +internet connection and the resources you have attached to the all-in-one VM. +GitLab's docker image is quite big (~500MB), so you'll have to wait until +it's downloaded and configured before you use it. + +### Watch while GitLab gets deployed + +Navigate to the `gitlab` project at **Overview**. You can notice that the +deployment is in progress by the orange color. The Docker images are being +downloaded and soon they will be up and running. + +![GitLab overview](img/gitlab-overview.png) + +Switch to the **Browse > Pods** and you will eventually see all 3 pods in a +running status. Remember the 3 resources that were to be created when we first +created the GitLab app? This is where you can see them in action. + +![Running pods](img/running-pods.png) + +You can see GitLab being reconfigured by taking look at the logs in realtime. +Click on `gitlab-ce-2-j7ioe` (your ID will be different) and go to the **Logs** +tab. + +![GitLab logs](img/gitlab-logs.png) + +At a point you should see a _**gitlab Reconfigured!**_ message in the logs. +Navigate back to the **Overview** and hopefully all pods will be up and running. + +![GitLab running](img/gitlab-running.png) + +Congratulations! You can now navigate to your new shinny GitLab instance by +visiting where you will be asked to +change the root user password. Login using `root` as username and providing the +password you just set, and start using GitLab! + +### Scale GitLab with the push of a button + +If you reach to a point where your GitLab instance could benefit from a boost +of resources, you'd be happy to know that you can scale up with the push of a +button. + +In the **Overview** page just click the up arrow button in the pod where +GitLab is. The change is instant and you can see the number of [replicas] now +running scaled to 2. + +![GitLab scale](img/gitlab-scale.png) + +Upping the GitLab pods is actually like adding new application servers to your +cluster. You can see how that would work if you didn't use GitLab with +OpenShift by following the [HA documentation][ha] for the application servers. + +Bare in mind that you may need more resources (CPU, RAM, disk space) when you +scale up. If a pod is in pending state for too long, you can navigate to +**Browse > Events** and see the reason and message of the state. + +![No resources](img/no-resources.png) + +### Scale GitLab using the `oc` CLI + +Using `oc` is super easy to scale up the replicas of a pod. You may want to +skim through the [basic CLI operations][basic-cli] to get a taste how the CLI +commands are used. Pay extra attention to the object types as we will use some +of them and their abbreviated versions below. + +In order to scale up, we need to find out the name of the replication controller. +Let's see how to do that using the following steps. + +1. Make sure you are in the `gitlab` project: + + ```sh + oc project gitlab + ``` + +1. See what services are used for this project: + + ```sh + oc get svc + ``` + + The output will be similar to: + + ``` + NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE + gitlab-ce 172.30.243.177 22/TCP,80/TCP 5d + gitlab-ce-postgresql 172.30.116.75 5432/TCP 5d + gitlab-ce-redis 172.30.105.88 6379/TCP 5d + ``` + +1. We need to see the replication controllers of the `gitlab-ce` service. + Get a detailed view of the current ones: + + ```sh + oc describe rc gitlab-ce + ``` + + This will return a large detailed list of the current replication controllers. + Search for the name of the GitLab controller, usually `gitlab-ce-1` or if + that failed at some point and you spawned another one, it will be named + `gitlab-ce-2`. + +1. Scale GitLab using the previous information: + + ```sh + oc scale --replicas=2 replicationcontrollers gitlab-ce-2 + ``` + +1. Get the new replicas number to make sure scaling worked: + + ```sh + oc get rc gitlab-ce-2 + ``` + + which will return something like: + + ``` + NAME DESIRED CURRENT AGE + gitlab-ce-2 2 2 5d + ``` + +And that's it! We successfully scaled the replicas to 2 using the CLI. + +As always, you can find the name of the controller using the web console. Just +click on the service you are interested in and you will see the details in the +right sidebar. + +![Replication controller name](img/rc-name.png) + +### Autoscaling GitLab + +In case you were wondering whether there is an option to autoscale a pod based +on the resources of your server, the answer is yes, of course there is. + +We will not expand on this matter, but feel free to read the documentation on +OpenShift's website about [autoscaling]. + +## Current limitations + +As stated in the [all-in-one VM][vm] page: + +> By default, OpenShift will not allow a container to run as root or even a +non-random container assigned userid. Most Docker images in the Dockerhub do not +follow this best practice and instead run as root. + +The all-in-one VM we are using has this security turned off so it will not +bother us. In any case, it is something to keep in mind when deploying GitLab +on a production cluster. + +In order to deploy GitLab on a production cluster, you will need to assign the +GitLab service account to the `anyuid` Security Context. + +1. Edit the Security Context: + ```sh + oc edit scc anyuid + ``` + +1. Add `system:serviceaccount::gitlab-ce-user` to the `users` section. + If you changed the Application Name from the default the user will + will be `-user` instead of `gitlab-ce-user` + +1. Save and exit the editor + +## Conclusion + +By now, you should have an understanding of the basic OpenShift Origin concepts +and a sense of how things work using the web console or the CLI. + +GitLab was hard to install in previous versions of OpenShift, +but now that belongs to the past. Upload a template, create a project, add an +application and you are done. You are ready to login to your new GitLab instance. + +And remember that in this tutorial we just scratched the surface of what Origin +is capable of. As always, you can refer to the detailed +[documentation][openshift-docs] to learn more about deploying your own OpenShift +PaaS and managing your applications with the ease of containers. + +[RedHat]: https://www.redhat.com/en "RedHat website" +[openshift]: https://www.openshift.org "OpenShift Origin website" +[vm]: https://www.openshift.org/vm/ "OpenShift All-in-one VM" +[vm-new]: https://atlas.hashicorp.com/openshift/boxes/origin-all-in-one "Official OpenShift Vagrant box on Atlas" +[template]: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/docker/openshift-template.json "OpenShift template for GitLab" +[openshift.com]: https://openshift.com "OpenShift Online" +[kubernetes]: http://kubernetes.io/ "Kubernetes website" +[Docker]: https://www.docker.com "Docker website" +[oc]: https://docs.openshift.org/latest/cli_reference/get_started_cli.html "Documentation - oc CLI documentation" +[VirtualBox]: https://www.virtualbox.org/wiki/Downloads "VirtualBox downloads" +[Vagrant]: https://www.vagrantup.com/downloads.html "Vagrant downloads" +[projects]: https://docs.openshift.org/latest/dev_guide/projects.html "Documentation - Projects overview" +[core]: https://docs.openshift.org/latest/architecture/core_concepts/index.html "Documentation - Core concepts of OpenShift Origin" +[templates]: https://docs.openshift.org/latest/architecture/core_concepts/templates.html "Documentation - OpenShift templates" +[old-post]: https://blog.openshift.com/deploy-gitlab-openshift/ "Old post - Deploy GitLab on OpenShift" +[line]: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/658c065c8d022ce858dd63eaeeadb0b2ddc8deea/docker/openshift-template.json#L239 "GitLab - OpenShift template" +[oc-gh]: https://github.com/openshift/origin/releases/tag/v1.3.0 "Openshift 1.3.0 release on GitHub" +[ha]: http://docs.gitlab.com/ce/administration/high_availability/gitlab.html "Documentation - GitLab High Availability" +[replicas]: https://docs.openshift.org/latest/architecture/core_concepts/deployments.html#replication-controllers "Documentation - Replication controller" +[autoscaling]: https://docs.openshift.org/latest/dev_guide/pod_autoscaling.html "Documentation - Autoscale" +[basic-cli]: https://docs.openshift.org/latest/cli_reference/basic_cli_operations.html "Documentation - Basic CLI operations" +[openshift-docs]: https://docs.openshift.org "OpenShift documentation" From 1fcf3f3d94a157e2b57735ca9d0a306b91e75323 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 2 Aug 2017 22:11:32 +0900 Subject: [PATCH 116/177] essential --- app/services/merge_requests/create_service.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/services/merge_requests/create_service.rb b/app/services/merge_requests/create_service.rb index 19189e64acf..5414fa79def 100644 --- a/app/services/merge_requests/create_service.rb +++ b/app/services/merge_requests/create_service.rb @@ -12,7 +12,6 @@ module MergeRequests merge_request.source_project = source_project merge_request.source_branch = params[:source_branch] merge_request.merge_params['force_remove_source_branch'] = params.delete(:force_remove_source_branch) - merge_request.head_pipeline = head_pipeline_for(merge_request) create(merge_request) end @@ -22,10 +21,16 @@ module MergeRequests notification_service.new_merge_request(issuable, current_user) todo_service.new_merge_request(issuable, current_user) issuable.cache_merge_request_closes_issues!(current_user) + update_merge_requests_head_pipeline(issuable) end private + def update_merge_requests_head_pipeline(merge_request) + pipeline = head_pipeline_for(merge_request) + merge_request.update(head_pipeline_id: pipeline.id) if pipeline + end + def head_pipeline_for(merge_request) return unless merge_request.source_project From 28b442989b7d03432d300bedac89e5971d9a69b7 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Fri, 4 Aug 2017 14:15:38 +0900 Subject: [PATCH 117/177] Add changelog --- ...x-sm-34547-cannot-connect-to-ci-server-error-messages.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelogs/unreleased/fix-sm-34547-cannot-connect-to-ci-server-error-messages.yml diff --git a/changelogs/unreleased/fix-sm-34547-cannot-connect-to-ci-server-error-messages.yml b/changelogs/unreleased/fix-sm-34547-cannot-connect-to-ci-server-error-messages.yml new file mode 100644 index 00000000000..ddaec4f19f9 --- /dev/null +++ b/changelogs/unreleased/fix-sm-34547-cannot-connect-to-ci-server-error-messages.yml @@ -0,0 +1,5 @@ +--- +title: Fix an order of operations for CI connection error message in merge request + widget +merge_request: 13252 +author: From 7256626d6023869fac7ffdcfe3d291b76fb19e64 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Fri, 4 Aug 2017 08:07:05 +0000 Subject: [PATCH 118/177] Remove monkey-patched Array.prototype.first() and last() methods --- .../javascripts/ajax_loading_spinner.js | 2 +- .../cycle_analytics/cycle_analytics_bundle.js | 2 +- app/assets/javascripts/dispatcher.js | 2 +- app/assets/javascripts/dropzone_input.js | 2 +- app/assets/javascripts/extensions/array.js | 11 ---------- .../filtered_search/dropdown_utils.js | 4 ++-- .../filtered_search_dropdown_manager.js | 2 +- .../filtered_search_manager.js | 2 +- app/assets/javascripts/main.js | 3 --- spec/javascripts/abuse_reports_spec.js | 6 ++--- spec/javascripts/ajax_loading_spinner_spec.js | 1 - spec/javascripts/extensions/array_spec.js | 22 ------------------- .../filtered_search/dropdown_utils_spec.js | 1 - .../filtered_search_dropdown_manager_spec.js | 1 - .../filtered_search_token_keys_spec.js | 1 - .../filtered_search_tokenizer_spec.js | 1 - 16 files changed, 11 insertions(+), 52 deletions(-) delete mode 100644 app/assets/javascripts/extensions/array.js delete mode 100644 spec/javascripts/extensions/array_spec.js diff --git a/app/assets/javascripts/ajax_loading_spinner.js b/app/assets/javascripts/ajax_loading_spinner.js index 38a8317dbd7..8f5e2e545ec 100644 --- a/app/assets/javascripts/ajax_loading_spinner.js +++ b/app/assets/javascripts/ajax_loading_spinner.js @@ -10,7 +10,7 @@ class AjaxLoadingSpinner { e.target.setAttribute('disabled', ''); const iconElement = e.target.querySelector('i'); // get first fa- icon - const originalIcon = iconElement.className.match(/(fa-)([^\s]+)/g).first(); + const originalIcon = iconElement.className.match(/(fa-)([^\s]+)/g)[0]; iconElement.dataset.icon = originalIcon; AjaxLoadingSpinner.toggleLoadingIcon(iconElement); $(e.target).off('ajax:beforeSend', AjaxLoadingSpinner.ajaxBeforeSend); diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js index 44791a93936..6583e471a48 100644 --- a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js +++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js @@ -92,7 +92,7 @@ $(() => { }); }, selectDefaultStage() { - const stage = this.state.stages.first(); + const stage = this.state.stages[0]; this.selectStage(stage); }, selectStage(stage) { diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index 070d0a01c0f..ad5ff19ec58 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -504,7 +504,7 @@ import GpgBadges from './gpg_badges'; new gl.DueDateSelectors(); break; } - switch (path.first()) { + switch (path[0]) { case 'sessions': case 'omniauth_callbacks': if (!gon.u2f) break; diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js index bd1864b8321..6d19a6d9b3a 100644 --- a/app/assets/javascripts/dropzone_input.js +++ b/app/assets/javascripts/dropzone_input.js @@ -217,7 +217,7 @@ window.DropzoneInput = (function() { value = e.clipboardData.getData('text/plain'); } value = value.split("\r"); - return value.first(); + return value[0]; }; const showSpinner = function(e) { diff --git a/app/assets/javascripts/extensions/array.js b/app/assets/javascripts/extensions/array.js deleted file mode 100644 index 027222f804d..00000000000 --- a/app/assets/javascripts/extensions/array.js +++ /dev/null @@ -1,11 +0,0 @@ -// TODO: remove this - -// eslint-disable-next-line no-extend-native -Array.prototype.first = function first() { - return this[0]; -}; - -// eslint-disable-next-line no-extend-native -Array.prototype.last = function last() { - return this[this.length - 1]; -}; diff --git a/app/assets/javascripts/filtered_search/dropdown_utils.js b/app/assets/javascripts/filtered_search/dropdown_utils.js index db5560fa753..8d711e3213c 100644 --- a/app/assets/javascripts/filtered_search/dropdown_utils.js +++ b/app/assets/javascripts/filtered_search/dropdown_utils.js @@ -123,11 +123,11 @@ class DropdownUtils { if (!allowMultiple && itemInExistingTokens) { updatedItem.droplab_hidden = true; - } else if (!lastKey || searchInput.split('').last() === ' ') { + } else if (!lastKey || _.last(searchInput.split('')) === ' ') { updatedItem.droplab_hidden = false; } else if (lastKey) { const split = lastKey.split(':'); - const tokenName = split[0].split(' ').last(); + const tokenName = _.last(split[0].split(' ')); const match = updatedItem.hint.indexOf(tokenName.toLowerCase()) === -1; updatedItem.droplab_hidden = tokenName ? match : false; diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js index 47cecd5b5f7..dd1c067df87 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js +++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js @@ -167,7 +167,7 @@ class FilteredSearchDropdownManager { // Eg. token = 'label:' const split = lastToken.split(':'); - const dropdownName = split[0].split(' ').last(); + const dropdownName = _.last(split[0].split(' ')); this.loadDropdown(split.length > 1 ? dropdownName : ''); } else if (lastToken) { // Token has been initialized into an object because it has a value diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js index 3ce8b8607ad..a31be2b0bc7 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_manager.js +++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js @@ -367,7 +367,7 @@ class FilteredSearchManager { const fragments = searchToken.split(':'); if (fragments.length > 1) { const inputValues = fragments[0].split(' '); - const tokenKey = inputValues.last(); + const tokenKey = _.last(inputValues); if (inputValues.length > 1) { inputValues.pop(); diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index a807ce326a6..42092a34c2f 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -16,9 +16,6 @@ import 'mousetrap'; import 'mousetrap/plugins/pause/mousetrap-pause'; import 'vendor/fuzzaldrin-plus'; -// extensions -import './extensions/array'; - // expose common libraries as globals (TODO: remove these) window.jQuery = jQuery; window.$ = jQuery; diff --git a/spec/javascripts/abuse_reports_spec.js b/spec/javascripts/abuse_reports_spec.js index 069d857eab6..13cab81dd60 100644 --- a/spec/javascripts/abuse_reports_spec.js +++ b/spec/javascripts/abuse_reports_spec.js @@ -6,10 +6,10 @@ import '~/abuse_reports'; const FIXTURE = 'abuse_reports/abuse_reports_list.html.raw'; const MAX_MESSAGE_LENGTH = 500; - let messages; + let $messages; const assertMaxLength = $message => expect($message.text().length).toEqual(MAX_MESSAGE_LENGTH); - const findMessage = searchText => messages.filter( + const findMessage = searchText => $messages.filter( (index, element) => element.innerText.indexOf(searchText) > -1, ).first(); @@ -18,7 +18,7 @@ import '~/abuse_reports'; beforeEach(function () { loadFixtures(FIXTURE); this.abuseReports = new global.AbuseReports(); - messages = $('.abuse-reports .message'); + $messages = $('.abuse-reports .message'); }); it('should truncate long messages', () => { diff --git a/spec/javascripts/ajax_loading_spinner_spec.js b/spec/javascripts/ajax_loading_spinner_spec.js index 1518ae68b0d..46e072a8ebb 100644 --- a/spec/javascripts/ajax_loading_spinner_spec.js +++ b/spec/javascripts/ajax_loading_spinner_spec.js @@ -1,4 +1,3 @@ -import '~/extensions/array'; import 'jquery'; import 'jquery-ujs'; import '~/ajax_loading_spinner'; diff --git a/spec/javascripts/extensions/array_spec.js b/spec/javascripts/extensions/array_spec.js deleted file mode 100644 index b1b81b4efc2..00000000000 --- a/spec/javascripts/extensions/array_spec.js +++ /dev/null @@ -1,22 +0,0 @@ -/* eslint-disable space-before-function-paren, no-var */ - -import '~/extensions/array'; - -(function() { - describe('Array extensions', function() { - describe('first', function() { - return it('returns the first item', function() { - var arr; - arr = [0, 1, 2, 3, 4, 5]; - return expect(arr.first()).toBe(0); - }); - }); - describe('last', function() { - return it('returns the last item', function() { - var arr; - arr = [0, 1, 2, 3, 4, 5]; - return expect(arr.last()).toBe(5); - }); - }); - }); -}).call(window); diff --git a/spec/javascripts/filtered_search/dropdown_utils_spec.js b/spec/javascripts/filtered_search/dropdown_utils_spec.js index 244f170ab7a..b1b3d43f241 100644 --- a/spec/javascripts/filtered_search/dropdown_utils_spec.js +++ b/spec/javascripts/filtered_search/dropdown_utils_spec.js @@ -1,4 +1,3 @@ -import '~/extensions/array'; import '~/filtered_search/dropdown_utils'; import '~/filtered_search/filtered_search_tokenizer'; import '~/filtered_search/filtered_search_dropdown_manager'; diff --git a/spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js b/spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js index 9e2076dc383..5c7e9115aac 100644 --- a/spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js +++ b/spec/javascripts/filtered_search/filtered_search_dropdown_manager_spec.js @@ -1,4 +1,3 @@ -import '~/extensions/array'; import '~/filtered_search/filtered_search_visual_tokens'; import '~/filtered_search/filtered_search_tokenizer'; import '~/filtered_search/filtered_search_dropdown_manager'; diff --git a/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js b/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js index 1a7631994b4..69b424c3af5 100644 --- a/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js +++ b/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js @@ -1,4 +1,3 @@ -import '~/extensions/array'; import '~/filtered_search/filtered_search_token_keys'; describe('Filtered Search Token Keys', () => { diff --git a/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js b/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js index e4a15c83c23..585bea9b499 100644 --- a/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js +++ b/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js @@ -1,4 +1,3 @@ -import '~/extensions/array'; import '~/filtered_search/filtered_search_token_keys'; import '~/filtered_search/filtered_search_tokenizer'; From f2f1b9e3dd10f1f527660e131fb307c68214246a Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Fri, 4 Aug 2017 18:01:59 +0900 Subject: [PATCH 119/177] Add a spec for concurrent process --- .../features/merge_requests/pipelines_spec.rb | 97 +++++++++++++------ 1 file changed, 69 insertions(+), 28 deletions(-) diff --git a/spec/features/merge_requests/pipelines_spec.rb b/spec/features/merge_requests/pipelines_spec.rb index b3d6cf8deb4..2136f7d829c 100644 --- a/spec/features/merge_requests/pipelines_spec.rb +++ b/spec/features/merge_requests/pipelines_spec.rb @@ -1,45 +1,86 @@ require 'spec_helper' feature 'Pipelines for Merge Requests', js: true do - given(:user) { create(:user) } - given(:merge_request) { create(:merge_request) } - given(:project) { merge_request.target_project } - - before do - project.team << [user, :master] - sign_in user - end - - context 'with pipelines' do - let!(:pipeline) do - create(:ci_empty_pipeline, - project: merge_request.source_project, - ref: merge_request.source_branch, - sha: merge_request.diff_head_sha) - end + describe 'pipeline tab' do + given(:user) { create(:user) } + given(:merge_request) { create(:merge_request) } + given(:project) { merge_request.target_project } before do - visit project_merge_request_path(project, merge_request) + project.team << [user, :master] + sign_in user end - scenario 'user visits merge request pipelines tab' do - page.within('.merge-request-tabs') do - click_link('Pipelines') + context 'with pipelines' do + let!(:pipeline) do + create(:ci_empty_pipeline, + project: merge_request.source_project, + ref: merge_request.source_branch, + sha: merge_request.diff_head_sha) end - wait_for_requests - expect(page).to have_selector('.stage-cell') + before do + visit project_merge_request_path(project, merge_request) + end + + scenario 'user visits merge request pipelines tab' do + page.within('.merge-request-tabs') do + click_link('Pipelines') + end + wait_for_requests + + expect(page).to have_selector('.sssssssss') + end + end + + context 'without pipelines' do + before do + visit project_merge_request_path(project, merge_request) + end + + scenario 'user visits merge request page' do + page.within('.merge-request-tabs') do + expect(page).to have_no_link('Pipelines') + end + end end end - context 'without pipelines' do - before do - visit project_merge_request_path(project, merge_request) + describe 'race condition' do + given(:project) { create(:project, :repository) } + given(:user) { create(:user) } + given(:build_push_data) { { ref: 'feature', checkout_sha: TestEnv::BRANCH_SHA['feature'] } } + + given(:merge_request_params) do + { "source_branch" => "feature", "source_project_id" => project.id, + "target_branch" => "master", "target_project_id" => project.id, "title" => "A" } end - scenario 'user visits merge request page' do - page.within('.merge-request-tabs') do - expect(page).to have_no_link('Pipelines') + background do + project.add_master(user) + sign_in user + end + + context 'when pipeline and merge request were created simultaneously' do + background do + stub_ci_pipeline_to_return_yaml_file + + threads = [] + threads << Thread.new do + @merge_request = MergeRequests::CreateService.new(project, user, merge_request_params).execute + end + + threads << Thread.new do + @pipeline = Ci::CreatePipelineService.new(project, user, build_push_data).execute(:push) + end + + threads.each { |thr| thr.join } + end + + scenario 'user sees pipeline in merge request widget' do + visit project_merge_request_path(project, @merge_request) + expect(page.find(".ci-widget")).to have_content(TestEnv::BRANCH_SHA['feature']) + expect(page.find(".ci-widget")).to have_content("##{@pipeline.id}") end end end From 0c75e23fab61e34bb45343776e31cad4ea3e4ae6 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Fri, 4 Aug 2017 02:23:02 +0900 Subject: [PATCH 120/177] fix --- .../_pipeline_schedule.html.haml | 2 +- .../projects/pipeline_schedules_spec.rb | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml index 7343d6e039c..bd8c38292d6 100644 --- a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml +++ b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml @@ -15,7 +15,7 @@ - else = s_("PipelineSchedules|None") %td.next-run-cell - - if pipeline_schedule.active? + - if pipeline_schedule.active? && pipeline_schedule.next_run_at = time_ago_with_tooltip(pipeline_schedule.real_next_run) - else = s_("PipelineSchedules|Inactive") diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb index 605415d2af4..280c8a183e6 100644 --- a/spec/features/projects/pipeline_schedules_spec.rb +++ b/spec/features/projects/pipeline_schedules_spec.rb @@ -219,6 +219,29 @@ feature 'Pipeline Schedules', :js do end end end + + context 'when active is true and next_run_at is NULL' do + background do + create(:ci_pipeline_schedule, project: project, owner: user).tap do |pipeline_schedule| + pipeline_schedule.update_attribute(:cron, nil) # Consequently next_run_at will be nil + pipeline_schedule.reload + expect(pipeline_schedule.active).to be_truthy + expect(pipeline_schedule.next_run_at).to be_nil + end + + visit_pipelines_schedules + find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click + end + + scenario 'user edit and recover the problematic pipeline schedule' do + expect(find("#schedule_cron").value).to eq('') + fill_in 'schedule_cron', with: '* 1 2 3 4' + click_button 'Save pipeline schedule' + page.within('.pipeline-schedule-table-row:nth-child(1)') do + expect(page).to have_css(".next-run-cell time") + end + end + end end context 'logged in as non-member' do From 3120b463a8517516d593cb8c31cf5f63c008dee9 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 4 Aug 2017 11:17:24 +0200 Subject: [PATCH 121/177] Use long curl options --- doc/install/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 769c1fd3664..22aedb5403e 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -168,7 +168,7 @@ are out of date, so we'll need to install through the following commands: curl --location https://deb.nodesource.com/setup_7.x | sudo bash - sudo apt-get install -y nodejs - curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - + curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list sudo apt-get update sudo apt-get install yarn From cb36c3b288a034ad4a1682d4b9d5d631f10930da Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 4 Aug 2017 11:19:20 +0200 Subject: [PATCH 122/177] Install yarn via apt in update guides --- doc/update/8.17-to-9.0.md | 5 ++++- doc/update/9.0-to-9.1.md | 5 ++++- doc/update/9.1-to-9.2.md | 5 ++++- doc/update/9.2-to-9.3.md | 5 ++++- doc/update/9.3-to-9.4.md | 5 ++++- 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/doc/update/8.17-to-9.0.md b/doc/update/8.17-to-9.0.md index 6308317b1f2..4d3ababaa41 100644 --- a/doc/update/8.17-to-9.0.md +++ b/doc/update/8.17-to-9.0.md @@ -65,7 +65,10 @@ Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage JavaScript dependencies. ```bash -curl --location https://yarnpkg.com/install.sh | bash - +curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - +echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list +sudo apt-get update +sudo apt-get install yarn ``` More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install). diff --git a/doc/update/9.0-to-9.1.md b/doc/update/9.0-to-9.1.md index 2d597894517..2b4a7bed27f 100644 --- a/doc/update/9.0-to-9.1.md +++ b/doc/update/9.0-to-9.1.md @@ -65,7 +65,10 @@ Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage JavaScript dependencies. ```bash -curl --location https://yarnpkg.com/install.sh | bash - +curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - +echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list +sudo apt-get update +sudo apt-get install yarn ``` More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install). diff --git a/doc/update/9.1-to-9.2.md b/doc/update/9.1-to-9.2.md index 225a4dcc924..f38547bba1a 100644 --- a/doc/update/9.1-to-9.2.md +++ b/doc/update/9.1-to-9.2.md @@ -65,7 +65,10 @@ Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage JavaScript dependencies. ```bash -curl --location https://yarnpkg.com/install.sh | bash - +curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - +echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list +sudo apt-get update +sudo apt-get install yarn ``` More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install). diff --git a/doc/update/9.2-to-9.3.md b/doc/update/9.2-to-9.3.md index 910539acc70..373f43eb3bb 100644 --- a/doc/update/9.2-to-9.3.md +++ b/doc/update/9.2-to-9.3.md @@ -65,7 +65,10 @@ Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage JavaScript dependencies. ```bash -curl --location https://yarnpkg.com/install.sh | bash - +curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - +echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list +sudo apt-get update +sudo apt-get install yarn ``` More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install). diff --git a/doc/update/9.3-to-9.4.md b/doc/update/9.3-to-9.4.md index 9540c36e7d0..b167f0737aa 100644 --- a/doc/update/9.3-to-9.4.md +++ b/doc/update/9.3-to-9.4.md @@ -65,7 +65,10 @@ Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage JavaScript dependencies. ```bash -curl --location https://yarnpkg.com/install.sh | bash - +curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - +echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list +sudo apt-get update +sudo apt-get install yarn ``` More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install). From ace7d7a2b51dd8d11c1ef21eaab5cc8372762704 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Fri, 4 Aug 2017 18:19:35 +0900 Subject: [PATCH 123/177] Add changelog --- ...-active-ci-pipelineschedule-have-nullified-next_run_at.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelogs/unreleased/fix-sm-35931-active-ci-pipelineschedule-have-nullified-next_run_at.yml diff --git a/changelogs/unreleased/fix-sm-35931-active-ci-pipelineschedule-have-nullified-next_run_at.yml b/changelogs/unreleased/fix-sm-35931-active-ci-pipelineschedule-have-nullified-next_run_at.yml new file mode 100644 index 00000000000..07840205b6e --- /dev/null +++ b/changelogs/unreleased/fix-sm-35931-active-ci-pipelineschedule-have-nullified-next_run_at.yml @@ -0,0 +1,4 @@ +--- +title: Fix pipeline_schedules pages when active schedule has an abnormal state +merge_request: 13286 +author: From 26d15a89dd4602b1d80d65b29fd48e79696dfb2c Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 1 Aug 2017 16:04:35 +0300 Subject: [PATCH 124/177] Fix Mattermost integration --- changelogs/unreleased/mattermost_fixes.yml | 4 ++++ lib/mattermost/session.rb | 26 +++++++++++++++++----- spec/lib/mattermost/session_spec.rb | 7 +++--- 3 files changed, 28 insertions(+), 9 deletions(-) create mode 100644 changelogs/unreleased/mattermost_fixes.yml diff --git a/changelogs/unreleased/mattermost_fixes.yml b/changelogs/unreleased/mattermost_fixes.yml new file mode 100644 index 00000000000..667109a0bb4 --- /dev/null +++ b/changelogs/unreleased/mattermost_fixes.yml @@ -0,0 +1,4 @@ +--- +title: Fix Mattermost integration +merge_request: +author: diff --git a/lib/mattermost/session.rb b/lib/mattermost/session.rb index 688a79c0441..ef08bd46e17 100644 --- a/lib/mattermost/session.rb +++ b/lib/mattermost/session.rb @@ -36,11 +36,12 @@ module Mattermost def with_session with_lease do - raise Mattermost::NoSessionError unless create + create begin yield self - rescue Errno::ECONNREFUSED + rescue Errno::ECONNREFUSED => e + Rails.logger.error(e.message + "\n" + e.backtrace.join("\n")) raise Mattermost::NoSessionError ensure destroy @@ -85,10 +86,12 @@ module Mattermost private def create - return unless oauth_uri - return unless token_uri + raise Mattermost::NoSessionError unless oauth_uri + raise Mattermost::NoSessionError unless token_uri @token = request_token + raise Mattermost::NoSessionError unless @token + @headers = { Authorization: "Bearer #{@token}" } @@ -106,11 +109,16 @@ module Mattermost @oauth_uri = nil response = get("/api/v3/oauth/gitlab/login", follow_redirects: false) - return unless 300 <= response.code && response.code < 400 + return unless (300...400) === response.code redirect_uri = response.headers['location'] return unless redirect_uri + oauth_cookie = parse_cookie(response) + @headers = { + Cookie: oauth_cookie.to_cookie_string + } + @oauth_uri = URI.parse(redirect_uri) end @@ -124,7 +132,7 @@ module Mattermost def request_token response = get(token_uri, follow_redirects: false) - if 200 <= response.code && response.code < 400 + if (200...400) === response.code response.headers['token'] end end @@ -156,5 +164,11 @@ module Mattermost rescue Errno::ECONNREFUSED => e raise Mattermost::ConnectionError.new(e.message) end + + def parse_cookie(response) + cookie_hash = CookieHash.new + response.get_fields('Set-Cookie').each { |c| cookie_hash.add_cookies(c) } + cookie_hash + end end end diff --git a/spec/lib/mattermost/session_spec.rb b/spec/lib/mattermost/session_spec.rb index be3908e8f6a..3db19d06305 100644 --- a/spec/lib/mattermost/session_spec.rb +++ b/spec/lib/mattermost/session_spec.rb @@ -20,9 +20,10 @@ describe Mattermost::Session, type: :request do describe '#with session' do let(:location) { 'http://location.tld' } + let(:cookie_header) {'MMOAUTH=taskik8az7rq8k6rkpuas7htia; Path=/;'} let!(:stub) do WebMock.stub_request(:get, "#{mattermost_url}/api/v3/oauth/gitlab/login") - .to_return(headers: { 'location' => location }, status: 307) + .to_return(headers: { 'location' => location, 'Set-Cookie' => cookie_header }, status: 307) end context 'without oauth uri' do @@ -34,9 +35,9 @@ describe Mattermost::Session, type: :request do context 'with oauth_uri' do let!(:doorkeeper) do Doorkeeper::Application.create( - name: "GitLab Mattermost", + name: 'GitLab Mattermost', redirect_uri: "#{mattermost_url}/signup/gitlab/complete\n#{mattermost_url}/login/gitlab/complete", - scopes: "") + scopes: '') end context 'without token_uri' do From d64fd953e2e032e7fa24c8e18239f5ffeea19410 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 4 Aug 2017 03:19:05 -0700 Subject: [PATCH 125/177] Bump GITLAB_SHELL_VERSION and GITALY_VERSION to support unhiding refs --- GITALY_SERVER_VERSION | 2 +- GITLAB_SHELL_VERSION | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 4e8f395fa5e..1b58cc10180 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -0.26.0 +0.27.0 diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION index 8a30e8f94a3..42cdd0b540f 100644 --- a/GITLAB_SHELL_VERSION +++ b/GITLAB_SHELL_VERSION @@ -1 +1 @@ -5.4.0 +5.7.0 From 5d775ea39463e8b1d7f4ecb3bb3017fcf94a83c7 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 4 Aug 2017 12:29:02 +0200 Subject: [PATCH 126/177] Rename raw -> rugged --- app/models/project.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/project.rb b/app/models/project.rb index d85782782aa..09b1305739c 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -941,7 +941,7 @@ class Project < ActiveRecord::Base end def repo - repository.raw + repository.rugged end def url_to_repo From 1b4fd63cf26ae0f19ec7735fd56bc0df6ce07058 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Fri, 4 Aug 2017 20:18:05 +0900 Subject: [PATCH 127/177] Fix spec --- spec/features/merge_requests/pipelines_spec.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spec/features/merge_requests/pipelines_spec.rb b/spec/features/merge_requests/pipelines_spec.rb index 2136f7d829c..44b965d5e6a 100644 --- a/spec/features/merge_requests/pipelines_spec.rb +++ b/spec/features/merge_requests/pipelines_spec.rb @@ -29,7 +29,7 @@ feature 'Pipelines for Merge Requests', js: true do end wait_for_requests - expect(page).to have_selector('.sssssssss') + expect(page).to have_selector('.stage-cell') end end @@ -66,6 +66,7 @@ feature 'Pipelines for Merge Requests', js: true do stub_ci_pipeline_to_return_yaml_file threads = [] + threads << Thread.new do @merge_request = MergeRequests::CreateService.new(project, user, merge_request_params).execute end @@ -79,6 +80,7 @@ feature 'Pipelines for Merge Requests', js: true do scenario 'user sees pipeline in merge request widget' do visit project_merge_request_path(project, @merge_request) + expect(page.find(".ci-widget")).to have_content(TestEnv::BRANCH_SHA['feature']) expect(page.find(".ci-widget")).to have_content("##{@pipeline.id}") end From 73146801e6b350c731a26dcfa68d79268fa314d4 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Fri, 4 Aug 2017 20:22:44 +0900 Subject: [PATCH 128/177] Fix spec --- spec/features/projects/pipeline_schedules_spec.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb index 280c8a183e6..24b335a7068 100644 --- a/spec/features/projects/pipeline_schedules_spec.rb +++ b/spec/features/projects/pipeline_schedules_spec.rb @@ -224,19 +224,15 @@ feature 'Pipeline Schedules', :js do background do create(:ci_pipeline_schedule, project: project, owner: user).tap do |pipeline_schedule| pipeline_schedule.update_attribute(:cron, nil) # Consequently next_run_at will be nil - pipeline_schedule.reload - expect(pipeline_schedule.active).to be_truthy - expect(pipeline_schedule.next_run_at).to be_nil end - - visit_pipelines_schedules - find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click end scenario 'user edit and recover the problematic pipeline schedule' do - expect(find("#schedule_cron").value).to eq('') + visit_pipelines_schedules + find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click fill_in 'schedule_cron', with: '* 1 2 3 4' click_button 'Save pipeline schedule' + page.within('.pipeline-schedule-table-row:nth-child(1)') do expect(page).to have_css(".next-run-cell time") end From ea2d0c4861ef957cbcfe32a189d7d399c16241ae Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Thu, 3 Aug 2017 18:11:26 +0200 Subject: [PATCH 129/177] Update the update guides for background migrations The introduction of background migrations means some of our requirements for online upgrades have to be adjusted / clarified. See https://gitlab.com/gitlab-org/gitlab-ce/issues/35939 for more information. --- doc/development/background_migrations.md | 9 ++++ doc/update/README.md | 66 +++++++++++++++++++++--- 2 files changed, 67 insertions(+), 8 deletions(-) diff --git a/doc/development/background_migrations.md b/doc/development/background_migrations.md index e67db9ff142..f83a60e49e8 100644 --- a/doc/development/background_migrations.md +++ b/doc/development/background_migrations.md @@ -7,6 +7,11 @@ storing data in a single JSON column the data is stored in a separate table. ## When To Use Background Migrations +>**Note:** +When adding background migrations _you must_ make sure they are announced in the +monthly release post along with an estimate of how long it will take to complete +the migrations. + In the vast majority of cases you will want to use a regular Rails migration instead. Background migrations should _only_ be used when migrating _data_ in tables that have so many rows this process would take hours when performed in a @@ -91,6 +96,10 @@ BackgroundMigrationWorker.perform_bulk_in(5.minutes, jobs) ## Cleaning Up +>**Note:** +Cleaning up any remaining background migrations _must_ be done in either a major +or minor release, you _must not_ do this in a patch release. + Because background migrations can take a long time you can't immediately clean things up after scheduling them. For example, you can't drop a column that's used in the migration process as this would cause jobs to fail. This means that diff --git a/doc/update/README.md b/doc/update/README.md index 22dbc7c750f..c98e20686e0 100644 --- a/doc/update/README.md +++ b/doc/update/README.md @@ -34,17 +34,67 @@ update them are in [a separate document][omnidocker]. ## Upgrading without downtime -Starting with GitLab 9.1.0 it's possible to upgrade to a newer major, minor, or patch version of GitLab -without having to take your GitLab instance offline. However, for this to work -there are the following requirements: +Starting with GitLab 9.1.0 it's possible to upgrade to a newer major, minor, or +patch version of GitLab without having to take your GitLab instance offline. +However, for this to work there are the following requirements: -1. You can only upgrade 1 minor release at a time. So from 9.1 to 9.2, not to 9.3. -2. You have to be on the most recent patch release. For example, if 9.1.15 is the last - release of 9.1 then you can safely upgrade from that version to any 9.2.x version. - However, if you are running 9.1.14 you first need to upgrade to 9.1.15. +1. You can only upgrade 1 minor release at a time. So from 9.1 to 9.2, not to + 9.3. 2. You have to use [post-deployment migrations](../development/post_deployment_migrations.md). -3. You are using PostgreSQL. If you are using MySQL please look at the release post to see if downtime is required. +3. You are using PostgreSQL. If you are using MySQL please look at the release + post to see if downtime is required. + +Most of the time you can safely upgrade from a patch release to the next minor +release if the patch release is not the latest. For example, upgrading from +9.1.1 to 9.2.0 should be safe even if 9.1.2 has been released. We do recommend +you check the release posts of any releases between your current and target +version just in case they include any migrations that may require you to upgrade +1 release at a time. + +Some releases may also include so called "background migrations". These +migrations are performed in the background by Sidekiq and are often used for +migrating data. Background migrations are only added in the monthly releases. + +Certain major/minor releases may require a set of background migrations to be +finished. To guarantee this such a release will process any remaining jobs +before continuing the upgrading procedure. While this won't require downtime +(if the above conditions are met) we recommend users to keep at least 1 week +between upgrading major/minor releases, allowing the background migrations to +finish. The time necessary to complete these migrations can be reduced by +increasing the number of Sidekiq workers that can process jobs in the +`background_migration` queue. + +As a rule of thumb, any database smaller than 10 GB won't take too much time to +upgrade; perhaps an hour at most per minor release. Larger databases however may +require more time, but this is highly dependent on the size of the database and +the migrations that are being performed. + +### Examples + +To help explain this, let's look at some examples. + +**Example 1:** You are running a large GitLab installation using version 9.4.2, +which is the latest patch release of 9.4. When GitLab 9.5.0 is released this +installation can be safely upgraded to 9.5.0 without requiring downtime if the +requirements mentioned above are met. You can also skip 9.5.0 and upgrade to +9.5.1 once it's released, but you **can not** upgrade straight to 9.6.0; you +_have_ to first upgrade to a 9.5.x release. + +**Example 2:** You are running a large GitLab installation using version 9.4.2, +which is the latest patch release of 9.4. GitLab 9.5 includes some background +migrations, and 10.0 will require these to be completed (processing any +remaining jobs for you). Skipping 9.5 is not possible without downtime, and due +to the background migrations would require potentially hours of downtime +depending on how long it takes for the background migrations to complete. To +work around this you will have to upgrade to 9.5.x first, then wait at least a +week before upgrading to 10.0. + +**Example 3:** You use MySQL as the database for GitLab. Any upgrade to a new +major/minor release will require downtime. If a release includes any background +migrations this could potentially lead to hours of downtime, depending on the +size of your database. To work around this you will have to use PostgreSQL and +meet the other online upgrade requirements mentioned above. ## Upgrading between editions From 9d3f27a22d0193de15cb40e5cab1c437c61eca69 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Fri, 4 Aug 2017 13:29:26 +0200 Subject: [PATCH 130/177] Removed commit guidelines for migrations At some point we decided this isn't really necessary, so let's get rid of it. --- doc/development/migration_style_guide.md | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md index 161d2544169..5aac243ae3d 100644 --- a/doc/development/migration_style_guide.md +++ b/doc/development/migration_style_guide.md @@ -35,13 +35,6 @@ Please don't depend on GitLab-specific code since it can change in future versions. If needed copy-paste GitLab code into the migration to make it forward compatible. -## Commit Guidelines - -Each migration **must** be added in its own commit with a descriptive commit -message. If a commit adds a migration it _should only_ include the migration and -any corresponding changes to `db/schema.rb`. This makes it easy to revert a -database migration without accidentally reverting other changes. - ## Downtime Tagging Every migration must specify if it requires downtime or not, and if it should @@ -224,9 +217,9 @@ add_column(:projects, :foo, :integer, default: 10, limit: 8) ## Timestamp column type -By default, Rails uses the `timestamp` data type that stores timestamp data without timezone information. -The `timestamp` data type is used by calling either the `add_timestamps` or the `timestamps` method. -Also Rails converts the `:datetime` data type to the `timestamp` one. +By default, Rails uses the `timestamp` data type that stores timestamp data without timezone information. +The `timestamp` data type is used by calling either the `add_timestamps` or the `timestamps` method. +Also Rails converts the `:datetime` data type to the `timestamp` one. Example: From d5cb29434a375bbbe10c4aa016bf6631bf8ede6c Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Fri, 4 Aug 2017 13:30:57 +0200 Subject: [PATCH 131/177] Mention schema migrations and patch releases --- doc/development/migration_style_guide.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md index 5aac243ae3d..9b8ab5da74e 100644 --- a/doc/development/migration_style_guide.md +++ b/doc/development/migration_style_guide.md @@ -35,6 +35,12 @@ Please don't depend on GitLab-specific code since it can change in future versions. If needed copy-paste GitLab code into the migration to make it forward compatible. +## Schema Changes + +Migrations that make changes to the database schema (e.g. adding a column) can +only be added in the monthly release, patch releases may only contain data +migrations _unless_ schema changes are absolutely required to solve a problem. + ## Downtime Tagging Every migration must specify if it requires downtime or not, and if it should From a92ccbcb9e0bcb1ed38c114f03af20245c2f360c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kim=20=22BKC=22=20Carlb=C3=A4cker?= Date: Fri, 4 Aug 2017 11:42:13 +0200 Subject: [PATCH 132/177] Have raketask tell gitaly where to find shell --- lib/tasks/gitlab/gitaly.rake | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/tasks/gitlab/gitaly.rake b/lib/tasks/gitlab/gitaly.rake index 3703f9cfb5c..7d35e0df53a 100644 --- a/lib/tasks/gitlab/gitaly.rake +++ b/lib/tasks/gitlab/gitaly.rake @@ -66,6 +66,7 @@ namespace :gitlab do config = { socket_path: address.sub(%r{\Aunix:}, ''), storage: storages } config[:auth] = { token: 'secret' } if Rails.env.test? config[:'gitaly-ruby'] = { dir: File.join(Dir.pwd, 'ruby') } if gitaly_ruby + config[:'gitlab-shell'] = { dir: Gitlab.config.gitlab_shell.path } TOML.dump(config) end From 4c68f22b0bf57b307abcef62e5f9ef927b1d047e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kim=20=22BKC=22=20Carlb=C3=A4cker?= Date: Fri, 4 Aug 2017 13:13:11 +0200 Subject: [PATCH 133/177] fix tests --- spec/tasks/gitlab/gitaly_rake_spec.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/tasks/gitlab/gitaly_rake_spec.rb b/spec/tasks/gitlab/gitaly_rake_spec.rb index a2f4ec39d89..6d453c19fc3 100644 --- a/spec/tasks/gitlab/gitaly_rake_spec.rb +++ b/spec/tasks/gitlab/gitaly_rake_spec.rb @@ -105,6 +105,8 @@ describe 'gitlab:gitaly namespace rake task' do # Gitaly storage configuration generated from #{Gitlab.config.source} on #{Time.current.to_s(:long)} # This is in TOML format suitable for use in Gitaly's config.toml file. socket_path = "/path/to/my.socket" + [gitlab-shell] + dir = "#{Gitlab.config.gitlab_shell.path}" [[storage]] name = "default" path = "/path/to/default" From 1614eb8b0a9fb2d719e6af7fec13d76db7d99892 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Fri, 4 Aug 2017 21:44:19 +0900 Subject: [PATCH 134/177] Fix spec --- spec/features/merge_requests/pipelines_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/features/merge_requests/pipelines_spec.rb b/spec/features/merge_requests/pipelines_spec.rb index 44b965d5e6a..347ce788b36 100644 --- a/spec/features/merge_requests/pipelines_spec.rb +++ b/spec/features/merge_requests/pipelines_spec.rb @@ -52,8 +52,8 @@ feature 'Pipelines for Merge Requests', js: true do given(:build_push_data) { { ref: 'feature', checkout_sha: TestEnv::BRANCH_SHA['feature'] } } given(:merge_request_params) do - { "source_branch" => "feature", "source_project_id" => project.id, - "target_branch" => "master", "target_project_id" => project.id, "title" => "A" } + { "source_branch" => "feature", "source_project_id" => project.id, + "target_branch" => "master", "target_project_id" => project.id, "title" => "A" } end background do From 65cf702da5130f66440fd362296a34ada7b5ebc1 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 4 Aug 2017 14:50:50 +0200 Subject: [PATCH 135/177] Add 9.5 update guide, with Gitaly specifics --- doc/update/9.4-to-9.5.md | 352 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 352 insertions(+) create mode 100644 doc/update/9.4-to-9.5.md diff --git a/doc/update/9.4-to-9.5.md b/doc/update/9.4-to-9.5.md new file mode 100644 index 00000000000..903d3d806a3 --- /dev/null +++ b/doc/update/9.4-to-9.5.md @@ -0,0 +1,352 @@ +# From 9.4 to 9.5 + +Make sure you view this update guide from the tag (version) of GitLab you would +like to install. In most cases this should be the highest numbered production +tag (without rc in it). You can select the tag in the version dropdown at the +top left corner of GitLab (below the menu bar). + +If the highest number stable branch is unclear please check the +[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation +guide links by version. + +### 1. Stop server + +```bash +sudo service gitlab stop +``` + +### 2. Backup + +```bash +cd /home/git/gitlab + +sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production +``` + +### 3. Update Ruby + +NOTE: GitLab 9.0 and higher only support Ruby 2.3.x and dropped support for Ruby 2.1.x. Be +sure to upgrade your interpreter if necessary. + +You can check which version you are running with `ruby -v`. + +Download and compile Ruby: + +```bash +mkdir /tmp/ruby && cd /tmp/ruby +curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.gz +echo '1014ee699071aa2ddd501907d18cbe15399c997d ruby-2.3.3.tar.gz' | shasum -c - && tar xzf ruby-2.3.3.tar.gz +cd ruby-2.3.3 +./configure --disable-install-rdoc +make +sudo make install +``` + +Install Bundler: + +```bash +sudo gem install bundler --no-ri --no-rdoc +``` + +### 4. Update Node + +GitLab now runs [webpack](http://webpack.js.org) to compile frontend assets and +it has a minimum requirement of node v4.3.0. + +You can check which version you are running with `node -v`. If you are running +a version older than `v4.3.0` you will need to update to a newer version. You +can find instructions to install from community maintained packages or compile +from source at the nodejs.org website. + + + + +Since 8.17, GitLab requires the use of yarn `>= v0.17.0` to manage +JavaScript dependencies. + +```bash +curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - +echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list +sudo apt-get update +sudo apt-get install yarn +``` + +More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install). + +### 5. Update Go + +NOTE: GitLab 9.2 and higher only supports Go 1.8.3 and dropped support for Go +1.5.x through 1.7.x. Be sure to upgrade your installation if necessary. + +You can check which version you are running with `go version`. + +Download and install Go: + +```bash +# Remove former Go installation folder +sudo rm -rf /usr/local/go + +curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz +echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \ + sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz +sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/ +rm go1.8.3.linux-amd64.tar.gz +``` + +### 6. Get latest code + +```bash +cd /home/git/gitlab + +sudo -u git -H git fetch --all +sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically +sudo -u git -H git checkout -- locale +``` + +For GitLab Community Edition: + +```bash +cd /home/git/gitlab + +sudo -u git -H git checkout 9-5-stable +``` + +OR + +For GitLab Enterprise Edition: + +```bash +cd /home/git/gitlab + +sudo -u git -H git checkout 9-5-stable-ee +``` + +### 7. Update gitlab-shell + +```bash +cd /home/git/gitlab-shell + +sudo -u git -H git fetch --all --tags +sudo -u git -H git checkout v$( Date: Wed, 17 May 2017 18:17:15 +0200 Subject: [PATCH 136/177] Add a Circuitbreaker for storage paths --- .../admin/health_check_controller.rb | 7 + app/controllers/application_controller.rb | 22 ++ app/helpers/storage_health_helper.rb | 37 +++ app/models/repository.rb | 41 ++- .../health_check/_failing_storages.html.haml | 15 + app/views/admin/health_check/show.html.haml | 27 +- .../unreleased/bvl-nfs-circuitbreaker.yml | 4 + config/gitlab.yml.example | 9 + config/initializers/1_settings.rb | 12 + config/initializers/6_validations.rb | 16 ++ config/routes/admin.rb | 4 +- doc/administration/img/failing_storage.png | Bin 0 -> 48281 bytes .../repository_storage_paths.md | 77 ++++- doc/api/repository_storage_health.md | 74 +++++ lib/api/api.rb | 1 + lib/api/circuit_breakers.rb | 50 ++++ lib/api/entities.rb | 6 + lib/gitlab/git/repository.rb | 8 +- lib/gitlab/git/storage.rb | 22 ++ lib/gitlab/git/storage/circuit_breaker.rb | 142 ++++++++++ .../git/storage/forked_storage_check.rb | 59 ++++ lib/gitlab/git/storage/health.rb | 101 +++++++ lib/gitlab/health_checks/fs_shards_check.rb | 21 +- .../admin/health_check_controller_spec.rb | 25 ++ .../application_controller_spec.rb | 24 ++ spec/controllers/projects_controller_spec.rb | 14 + spec/factories/projects.rb | 6 + .../features/admin/admin_health_check_spec.rb | 24 +- spec/helpers/storage_health_helper_spec.rb | 20 ++ spec/initializers/6_validations_spec.rb | 21 ++ spec/initializers/settings_spec.rb | 11 + .../cache/ci/project_pipeline_status_spec.rb | 14 +- spec/lib/gitlab/git/repository_spec.rb | 14 + .../git/storage/circuit_breaker_spec.rb | 265 ++++++++++++++++++ .../git/storage/forked_storage_check_spec.rb | 27 ++ spec/lib/gitlab/git/storage/health_spec.rb | 85 ++++++ .../health_checks/fs_shards_check_spec.rb | 15 + spec/models/repository_spec.rb | 69 ++++- spec/requests/api/circuit_breakers_spec.rb | 57 ++++ spec/support/stored_repositories.rb | 12 + 40 files changed, 1421 insertions(+), 37 deletions(-) create mode 100644 app/helpers/storage_health_helper.rb create mode 100644 app/views/admin/health_check/_failing_storages.html.haml create mode 100644 changelogs/unreleased/bvl-nfs-circuitbreaker.yml create mode 100644 doc/administration/img/failing_storage.png create mode 100644 doc/api/repository_storage_health.md create mode 100644 lib/api/circuit_breakers.rb create mode 100644 lib/gitlab/git/storage.rb create mode 100644 lib/gitlab/git/storage/circuit_breaker.rb create mode 100644 lib/gitlab/git/storage/forked_storage_check.rb create mode 100644 lib/gitlab/git/storage/health.rb create mode 100644 spec/controllers/admin/health_check_controller_spec.rb create mode 100644 spec/helpers/storage_health_helper_spec.rb create mode 100644 spec/lib/gitlab/git/storage/circuit_breaker_spec.rb create mode 100644 spec/lib/gitlab/git/storage/forked_storage_check_spec.rb create mode 100644 spec/lib/gitlab/git/storage/health_spec.rb create mode 100644 spec/requests/api/circuit_breakers_spec.rb diff --git a/app/controllers/admin/health_check_controller.rb b/app/controllers/admin/health_check_controller.rb index caf4c138da8..65a17828feb 100644 --- a/app/controllers/admin/health_check_controller.rb +++ b/app/controllers/admin/health_check_controller.rb @@ -1,5 +1,12 @@ class Admin::HealthCheckController < Admin::ApplicationController def show @errors = HealthCheck::Utils.process_checks(['standard']) + @failing_storage_statuses = Gitlab::Git::Storage::Health.for_failing_storages + end + + def reset_storage_health + Gitlab::Git::Storage::CircuitBreaker.reset_all! + redirect_to admin_health_check_path, + notice: _('Git storage health information has been reset') end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d14b1dbecf6..34d948bc3d2 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -52,6 +52,15 @@ class ApplicationController < ActionController::Base head :forbidden, retry_after: Gitlab::Auth::UniqueIpsLimiter.config.unique_ips_limit_time_window end + rescue_from Gitlab::Git::Storage::Inaccessible, GRPC::Unavailable do |exception| + Raven.capture_exception(exception) if sentry_enabled? + log_exception(exception) + + headers['Retry-After'] = exception.retry_after if exception.respond_to?(:retry_after) + + render_503 + end + def redirect_back_or_default(default: root_path, options: {}) redirect_to request.referer.present? ? :back : default, options end @@ -152,6 +161,19 @@ class ApplicationController < ActionController::Base head :unprocessable_entity end + def render_503 + respond_to do |format| + format.html do + render( + file: Rails.root.join("public", "503"), + layout: false, + status: :service_unavailable + ) + end + format.any { head :service_unavailable } + end + end + def no_cache_headers response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate" response.headers["Pragma"] = "no-cache" diff --git a/app/helpers/storage_health_helper.rb b/app/helpers/storage_health_helper.rb new file mode 100644 index 00000000000..544c9efb845 --- /dev/null +++ b/app/helpers/storage_health_helper.rb @@ -0,0 +1,37 @@ +module StorageHealthHelper + def failing_storage_health_message(storage_health) + storage_name = content_tag(:strong, h(storage_health.storage_name)) + host_names = h(storage_health.failing_on_hosts.to_sentence) + translation_params = { storage_name: storage_name, + host_names: host_names, + failed_attempts: storage_health.total_failures } + + translation = n_('%{storage_name}: failed storage access attempt on host:', + '%{storage_name}: %{failed_attempts} failed storage access attempts:', + storage_health.total_failures) % translation_params + + translation.html_safe + end + + def message_for_circuit_breaker(circuit_breaker) + maximum_failures = circuit_breaker.failure_count_threshold + current_failures = circuit_breaker.failure_count + permanently_broken = circuit_breaker.circuit_broken? && current_failures >= maximum_failures + + translation_params = { number_of_failures: current_failures, + maximum_failures: maximum_failures, + number_of_seconds: circuit_breaker.failure_wait_time } + + if permanently_broken + s_("%{number_of_failures} of %{maximum_failures} failures. GitLab will not "\ + "retry automatically. Reset storage information when the problem is "\ + "resolved.") % translation_params + elsif circuit_breaker.circuit_broken? + _("%{number_of_failures} of %{maximum_failures} failures. GitLab will "\ + "block access for %{number_of_seconds} seconds.") % translation_params + else + _("%{number_of_failures} of %{maximum_failures} failures. GitLab will "\ + "allow access on the next attempt.") % translation_params + end + end +end diff --git a/app/models/repository.rb b/app/models/repository.rb index 4e9fe759fdc..b04d434926f 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -133,12 +133,13 @@ class Repository ref ||= root_ref args = %W( - #{Gitlab.config.git.bin_path} log #{ref} --pretty=%H --skip #{offset} + log #{ref} --pretty=%H --skip #{offset} --max-count #{limit} --grep=#{query} --regexp-ignore-case ) args = args.concat(%W(-- #{path})) if path.present? - git_log_results = Gitlab::Popen.popen(args, path_to_repo).first.lines + git_log_results = run_git(args).first.lines + git_log_results.map { |c| commit(c.chomp) }.compact end @@ -622,8 +623,8 @@ class Repository key = path.blank? ? "last_commit_id_for_path:#{sha}" : "last_commit_id_for_path:#{sha}:#{Digest::SHA1.hexdigest(path)}" cache.fetch(key) do - args = %W(#{Gitlab.config.git.bin_path} rev-list --max-count=1 #{sha} -- #{path}) - Gitlab::Popen.popen(args, path_to_repo).first.strip + args = %W(rev-list --max-count=1 #{sha} -- #{path}) + run_git(args).first.strip end end @@ -678,8 +679,8 @@ class Repository end def refs_contains_sha(ref_type, sha) - args = %W(#{Gitlab.config.git.bin_path} #{ref_type} --contains #{sha}) - names = Gitlab::Popen.popen(args, path_to_repo).first + args = %W(#{ref_type} --contains #{sha}) + names = run_git(args).first if names.respond_to?(:split) names = names.split("\n").map(&:strip) @@ -957,15 +958,17 @@ class Repository return [] if empty_repo? || query.blank? offset = 2 - args = %W(#{Gitlab.config.git.bin_path} grep -i -I -n --before-context #{offset} --after-context #{offset} -E -e #{Regexp.escape(query)} #{ref || root_ref}) - Gitlab::Popen.popen(args, path_to_repo).first.scrub.split(/^--$/) + args = %W(grep -i -I -n --before-context #{offset} --after-context #{offset} -E -e #{Regexp.escape(query)} #{ref || root_ref}) + + run_git(args).first.scrub.split(/^--$/) end def search_files_by_name(query, ref) return [] if empty_repo? || query.blank? - args = %W(#{Gitlab.config.git.bin_path} ls-tree --full-tree -r #{ref || root_ref} --name-status | #{Regexp.escape(query)}) - Gitlab::Popen.popen(args, path_to_repo).first.lines.map(&:strip) + args = %W(ls-tree --full-tree -r #{ref || root_ref} --name-status | #{Regexp.escape(query)}) + + run_git(args).first.lines.map(&:strip) end def with_repo_branch_commit(start_repository, start_branch_name) @@ -1010,8 +1013,8 @@ class Repository end def fetch_ref(source_path, source_ref, target_ref) - args = %W(#{Gitlab.config.git.bin_path} fetch --no-tags -f #{source_path} #{source_ref}:#{target_ref}) - Gitlab::Popen.popen(args, path_to_repo) + args = %W(fetch --no-tags -f #{source_path} #{source_ref}:#{target_ref}) + run_git(args) end def create_ref(ref, ref_path) @@ -1092,6 +1095,12 @@ class Repository private + def run_git(args) + circuit_breaker.perform do + Gitlab::Popen.popen([Gitlab.config.git.bin_path, *args], path_to_repo) + end + end + def blob_data_at(sha, path) blob = blob_at(sha, path) return unless blob @@ -1101,7 +1110,9 @@ class Repository end def refs_directory_exists? - File.exist?(File.join(path_to_repo, 'refs')) + circuit_breaker.perform do + File.exist?(File.join(path_to_repo, 'refs')) + end end def cache @@ -1145,4 +1156,8 @@ class Repository def initialize_raw_repository Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git') end + + def circuit_breaker + @circuit_breaker ||= Gitlab::Git::Storage::CircuitBreaker.for_storage(project.repository_storage) + end end diff --git a/app/views/admin/health_check/_failing_storages.html.haml b/app/views/admin/health_check/_failing_storages.html.haml new file mode 100644 index 00000000000..6830201538d --- /dev/null +++ b/app/views/admin/health_check/_failing_storages.html.haml @@ -0,0 +1,15 @@ +- if failing_storages.any? + = _('There are problems accessing Git storage: ') + %ul + - failing_storages.each do |storage_health| + %li + = failing_storage_health_message(storage_health) + %ul + - storage_health.failing_circuit_breakers.each do |circuit_breaker| + %li + #{circuit_breaker.hostname}: #{message_for_circuit_breaker(circuit_breaker)} + + = _("Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again.") + .prepend-top-10 + = button_to _("Reset git storage health information"), reset_storage_health_admin_health_check_path, + method: :post, class: 'btn btn-default' diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml index f16f59623f7..517db50b97f 100644 --- a/app/views/admin/health_check/show.html.haml +++ b/app/views/admin/health_check/show.html.haml @@ -1,22 +1,22 @@ - @no_container = true -- page_title "Health Check" +- page_title _('Health Check') +- no_errors = @errors.blank? && @failing_storage_statuses.blank? = render 'admin/monitoring/head' %div{ class: container_class } - %h3.page-title - Health Check + %h3.page-title= page_title .bs-callout.clearfix .pull-left %p - Access token is + #{ s_('HealthCheck|Access token is') } %code#health-check-token= current_application_settings.health_check_access_token .prepend-top-10 - = button_to "Reset health check access token", reset_health_check_token_admin_application_settings_path, + = button_to _("Reset health check access token"), reset_health_check_token_admin_application_settings_path, method: :put, class: 'btn btn-default', - data: { confirm: 'Are you sure you want to reset the health check token?' } + data: { confirm: _('Are you sure you want to reset the health check token?') } %p.light - Health information can be retrieved from the following endpoints. More information is available - = link_to 'here', help_page_path('user/admin_area/monitoring/health_check') + #{ _('Health information can be retrieved from the following endpoints. More information is available') } + = link_to s_('More information is available|here'), help_page_path('user/admin_area/monitoring/health_check') %ul %li %code= readiness_url(token: current_application_settings.health_check_access_token) @@ -29,14 +29,15 @@ .panel.panel-default .panel-heading Current Status: - - if @errors.blank? + - if no_errors = icon('circle', class: 'cgreen') - Healthy + #{ s_('HealthCheck|Healthy') } - else = icon('warning', class: 'cred') - Unhealthy + #{ s_('HealthCheck|Unhealthy') } .panel-body - - if @errors.blank? - No Health Problems Detected + - if no_errors + #{ s_('HealthCheck|No Health Problems Detected') } - else = @errors + = render partial: 'failing_storages', object: @failing_storage_statuses diff --git a/changelogs/unreleased/bvl-nfs-circuitbreaker.yml b/changelogs/unreleased/bvl-nfs-circuitbreaker.yml new file mode 100644 index 00000000000..151854ed31f --- /dev/null +++ b/changelogs/unreleased/bvl-nfs-circuitbreaker.yml @@ -0,0 +1,4 @@ +--- +title: Block access to failing repository storage +merge_request: 11449 +author: diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 73a68c6da1b..45ab4e1a851 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -506,6 +506,11 @@ production: &base path: /home/git/repositories/ gitaly_address: unix:/home/git/gitlab/tmp/sockets/private/gitaly.socket # TCP connections are supported too (e.g. tcp://host:port) # gitaly_token: 'special token' # Optional: override global gitaly.token for this storage. + failure_count_threshold: 10 # number of failures before stopping attempts + failure_wait_time: 30 # Seconds after an access failure before allowing access again + failure_reset_time: 1800 # Time in seconds to expire failures + storage_timeout: 5 # Time in seconds to wait before aborting a storage access attempt + ## Backup settings backup: @@ -638,6 +643,10 @@ test: default: path: tmp/tests/repositories/ gitaly_address: unix:tmp/tests/gitaly/gitaly.socket + broken: + path: tmp/tests/non-existent-repositories + gitaly_address: unix:tmp/tests/gitaly/gitaly.socket + gitaly: enabled: true token: secret diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 63f4c8c9e0a..017537f30be 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -222,6 +222,7 @@ Settings.gitlab['default_branch_protection'] ||= 2 Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil? Settings.gitlab['host'] ||= ENV['GITLAB_HOST'] || 'localhost' Settings.gitlab['ssh_host'] ||= Settings.gitlab.host +Settings.gitlab['hostname'] ||= ENV['HOSTNAME'] || Socket.gethostname Settings.gitlab['https'] = false if Settings.gitlab['https'].nil? Settings.gitlab['port'] ||= ENV['GITLAB_PORT'] || (Settings.gitlab.https ? 443 : 80) Settings.gitlab['relative_url_root'] ||= ENV['RAILS_RELATIVE_URL_ROOT'] || '' @@ -433,6 +434,17 @@ end Settings.repositories.storages.values.each do |storage| # Expand relative paths storage['path'] = Settings.absolute(storage['path']) + # Set failure defaults + storage['failure_count_threshold'] ||= 10 + storage['failure_wait_time'] ||= 30 + storage['failure_reset_time'] ||= 1800 + storage['storage_timeout'] ||= 5 + # Set turn strings into numbers + storage['failure_count_threshold'] = storage['failure_count_threshold'].to_i + storage['failure_wait_time'] = storage['failure_wait_time'].to_i + storage['failure_reset_time'] = storage['failure_reset_time'].to_i + # We might want to have a timeout shorter than 1 second. + storage['storage_timeout'] = storage['storage_timeout'].to_f end # diff --git a/config/initializers/6_validations.rb b/config/initializers/6_validations.rb index 9e24f42d284..92ce4dd03cd 100644 --- a/config/initializers/6_validations.rb +++ b/config/initializers/6_validations.rb @@ -7,6 +7,13 @@ def find_parent_path(name, path) Gitlab.config.repositories.storages.detect do |n, rs| name != n && Pathname.new(rs['path']).realpath == parent end +rescue Errno::EIO, Errno::ENOENT => e + warning = "WARNING: couldn't verify #{path} (#{name}). "\ + "If this is an external storage, it might be offline." + message = "#{warning}\n#{e.message}" + Rails.logger.error("#{message}\n\t" + e.backtrace.join("\n\t")) + + nil end def storage_validation_error(message) @@ -29,6 +36,15 @@ def validate_storages_config if !repository_storage.is_a?(Hash) || repository_storage['path'].nil? storage_validation_error("#{name} is not a valid storage, because it has no `path` key. Refer to gitlab.yml.example for an updated example") end + + %w(failure_count_threshold failure_wait_time failure_reset_time storage_timeout).each do |setting| + # Falling back to the defaults is fine! + next if repository_storage[setting].nil? + + unless repository_storage[setting].to_f > 0 + storage_validation_error("#{setting}, for storage `#{name}` needs to be greater than 0") + end + end end end diff --git a/config/routes/admin.rb b/config/routes/admin.rb index 5427bab93ce..c0748231813 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -67,7 +67,9 @@ namespace :admin do end resource :logs, only: [:show] - resource :health_check, controller: 'health_check', only: [:show] + resource :health_check, controller: 'health_check', only: [:show] do + post :reset_storage_health + end resource :background_jobs, controller: 'background_jobs', only: [:show] resource :system_info, controller: 'system_info', only: [:show] resources :requests_profiles, only: [:index, :show], param: :name, constraints: { name: /.+\.html/ } diff --git a/doc/administration/img/failing_storage.png b/doc/administration/img/failing_storage.png new file mode 100644 index 0000000000000000000000000000000000000000..82b393a58b2e1a7ec147c3ba5a52d1475817c529 GIT binary patch literal 48281 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

LPVhEiH=E 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 z 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:** The [`gitlab_shell: repos_path` entry][repospath] in `gitlab.yml` will be @@ -97,9 +97,80 @@ be stored via the **Application Settings** in the Admin area. Beginning with GitLab 8.13.4, multiple paths can be chosen. New projects will be randomly placed on one of the selected paths. +## Handling failing repository storage + +> [Introduced][ce-11449] in GitLab 9.5. + +When GitLab detects access to the repositories storage fails repeatedly, it can +gracefully prevent attempts to access the storage. This might be useful when +the repositories are stored somewhere on the network. + +The configuration could look as follows: + +**For Omnibus installations** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ```ruby + git_data_dirs({ + "default" => { + "path" => "/mnt/nfs-01/git-data", + "failure_count_threshold" => 10, + "failure_wait_time" => 30, + "failure_reset_time" => 1800, + "storage_timeout" => 5 + } + }) + ``` + +1. Save the file and [reconfigure GitLab][reconfigure-gitlab] for the changes to take effect. + +--- + +**For installations from source** + +1. Edit `config/gitlab.yml`: + + ```yaml + repositories: + storages: # You must have at least a `default` storage path. + default: + path: /home/git/repositories/ + failure_count_threshold: 10 # number of failures before stopping attempts + failure_wait_time: 30 # Seconds after last access failure before trying again + failure_reset_time: 1800 # Time in seconds to expire failures + storage_timeout: 5 # Time in seconds to wait before aborting a storage access attempt + ``` + +1. Save the file and [restart GitLab][restart-gitlab] for the changes to take effect. + + +**`failure_count_threshold`:** The number of failures of after which GitLab will +completely prevent access to the storage. The number of failures can be reset in +the admin interface: `https://gitlab.example.com/admin/health_check` or using the +[api](../api/repository_storage_health.md) to allow access to the storage again. + +**`failure_wait_time`:** When access to a storage fails. GitLab will prevent +access to the storage for the time specified here. This allows the filesystem to +recover without. + +**`failure_reset_time`:** The time in seconds GitLab will keep failure +information. When no failures occur during this time, information about the +mount is reset. + +**`storage_timeout`:** The time in seconds GitLab will try to access storage. +After this time a timeout error will be raised. + +When storage failures occur, this will be visible in the admin interface like this: + +![failing storage](img/failing_storage.png) + +To allow access to all storages, click the `Reset git storage health information` button. + [ce-4578]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4578 -[restart gitlab]: restart_gitlab.md#installations-from-source -[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure +[restart-gitlab]: restart_gitlab.md#installations-from-source +[reconfigure-gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure [backups]: ../raketasks/backup_restore.md [raketask]: https://gitlab.com/gitlab-org/gitlab-ce/blob/033e5423a2594e08a7ebcd2379bd2331f4c39032/lib/backup/repository.rb#L54-56 [repospath]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-9-stable/config/gitlab.yml.example#L457 +[ce-11449]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11449 diff --git a/doc/api/repository_storage_health.md b/doc/api/repository_storage_health.md new file mode 100644 index 00000000000..e0c0315c2d7 --- /dev/null +++ b/doc/api/repository_storage_health.md @@ -0,0 +1,74 @@ +# Circuitbreaker API + +> [Introduced][ce-11449] in GitLab 9.5. + +The Circuitbreaker API is only accessible to administrators. All requests by +guests will respond with `401 Unauthorized`, and all requests by normal users +will respond with `403 Forbidden`. + +## Repository Storages + +### Get all storage information + +Returns of all currently configured storages and their health information. + +``` +GET /circuit_breakers/repository_storage +``` + +```bash +curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/circuit_breakers/repository_storage +``` + +```json +[ + { + "storage_name": "default", + "failing_on_hosts": [], + "total_failures": 0 + }, + { + "storage_name": "broken", + "failing_on_hosts": [ + "web01", "worker01" + ], + "total_failures": 1 + } +] +``` + +### Get failing storages + +This returns a list of all currently failing storages. + +``` +GET /circuit_breakers/repository_storage/failing +``` + +```bash +curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/circuit_breakers/repository_storage/failing +``` + +```json +[ + { + "storage_name":"broken", + "failing_on_hosts":["web01", "worker01"], + "total_failures":2 + } +] +``` + +## Reset failing storage information + +Use this remove all failing storage information and allow access to the storage again. + +``` +DELETE /circuit_breakers/repository_storage +``` + +```bash +curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/circuit_breakers/repository_storage +``` + +[ce-11449]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11449 diff --git a/lib/api/api.rb b/lib/api/api.rb index 982a2b88d62..94df543853b 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -95,6 +95,7 @@ module API mount ::API::Boards mount ::API::Branches mount ::API::BroadcastMessages + mount ::API::CircuitBreakers mount ::API::Commits mount ::API::CommitStatuses mount ::API::DeployKeys diff --git a/lib/api/circuit_breakers.rb b/lib/api/circuit_breakers.rb new file mode 100644 index 00000000000..118883f5ea5 --- /dev/null +++ b/lib/api/circuit_breakers.rb @@ -0,0 +1,50 @@ +module API + class CircuitBreakers < Grape::API + before { authenticated_as_admin! } + + resource :circuit_breakers do + params do + requires :type, + type: String, + desc: "The type of circuitbreaker", + values: ['repository_storage'] + end + resource ':type' do + namespace '', requirements: { type: 'repository_storage' } do + helpers do + def failing_storage_health + @failing_storage_health ||= Gitlab::Git::Storage::Health.for_failing_storages + end + + def storage_health + @failing_storage_health ||= Gitlab::Git::Storage::Health.for_all_storages + end + end + + desc 'Get all failing git storages' do + detail 'This feature was introduced in GitLab 9.5' + success Entities::RepositoryStorageHealth + end + get do + present storage_health, with: Entities::RepositoryStorageHealth + end + + desc 'Get all failing git storages' do + detail 'This feature was introduced in GitLab 9.5' + success Entities::RepositoryStorageHealth + end + get 'failing' do + present failing_storage_health, with: Entities::RepositoryStorageHealth + end + + desc 'Reset all storage failures and open circuitbreaker' do + detail 'This feature was introduced in GitLab 9.5' + end + delete do + Gitlab::Git::Storage::CircuitBreaker.reset_all! + end + end + end + end + end +end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 298831a8fdb..f25b408439a 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -954,5 +954,11 @@ module API expose :ip_address expose :submitted, as: :akismet_submitted end + + class RepositoryStorageHealth < Grape::Entity + expose :storage_name + expose :failing_on_hosts + expose :total_failures + end end end diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index ffe2c8b91bb..aa3252e1df8 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -64,11 +64,17 @@ module Gitlab end def rugged - @rugged ||= Rugged::Repository.new(path, alternates: alternate_object_directories) + @rugged ||= circuit_breaker.perform do + Rugged::Repository.new(path, alternates: alternate_object_directories) + end rescue Rugged::RepositoryError, Rugged::OSError raise NoRepository.new('no repository for such path') end + def circuit_breaker + @circuit_breaker ||= Gitlab::Git::Storage::CircuitBreaker.for_storage(storage) + end + # Returns an Array of branch names # sorted by name ASC def branch_names diff --git a/lib/gitlab/git/storage.rb b/lib/gitlab/git/storage.rb new file mode 100644 index 00000000000..e28be4b8a38 --- /dev/null +++ b/lib/gitlab/git/storage.rb @@ -0,0 +1,22 @@ +module Gitlab + module Git + module Storage + class Inaccessible < StandardError + attr_reader :retry_after + + def initialize(message = nil, retry_after = nil) + super(message) + @retry_after = retry_after + end + end + + CircuitOpen = Class.new(Inaccessible) + + REDIS_KEY_PREFIX = 'storage_accessible:'.freeze + + def self.redis + Gitlab::Redis::SharedState + end + end + end +end diff --git a/lib/gitlab/git/storage/circuit_breaker.rb b/lib/gitlab/git/storage/circuit_breaker.rb new file mode 100644 index 00000000000..c722771e0d5 --- /dev/null +++ b/lib/gitlab/git/storage/circuit_breaker.rb @@ -0,0 +1,142 @@ +module Gitlab + module Git + module Storage + class CircuitBreaker + attr_reader :storage, + :hostname, + :storage_path, + :failure_count_threshold, + :failure_wait_time, + :failure_reset_time, + :storage_timeout + + def self.reset_all! + pattern = "#{Gitlab::Git::Storage::REDIS_KEY_PREFIX}*" + + Gitlab::Git::Storage.redis.with do |redis| + all_storage_keys = redis.scan_each(match: pattern).to_a + redis.del(*all_storage_keys) unless all_storage_keys.empty? + end + + RequestStore.delete(:circuitbreaker_cache) + end + + def self.for_storage(storage) + cached_circuitbreakers = RequestStore.fetch(:circuitbreaker_cache) do + Hash.new do |hash, storage_name| + hash[storage_name] = new(storage_name) + end + end + + cached_circuitbreakers[storage] + end + + def initialize(storage, hostname = Gitlab.config.gitlab.hostname) + @storage = storage + @hostname = hostname + + config = Gitlab.config.repositories.storages[@storage] + @storage_path = config['path'] + @failure_count_threshold = config['failure_count_threshold'] + @failure_wait_time = config['failure_wait_time'] + @failure_reset_time = config['failure_reset_time'] + @storage_timeout = config['storage_timeout'] + end + + def perform + return yield unless Feature.enabled?('git_storage_circuit_breaker') + + if circuit_broken? + raise Gitlab::Git::Storage::CircuitOpen.new("Circuit for #{storage} open", failure_wait_time) + end + + check_storage_accessible! + + yield + end + + def circuit_broken? + return false if no_failures? + + recent_failure = last_failure > failure_wait_time.seconds.ago + too_many_failures = failure_count > failure_count_threshold + + recent_failure || too_many_failures + end + + # Memoizing the `storage_available` call means we only do it once per + # request when the storage is available. + # + # When the storage appears not available, and the memoized value is `false` + # we might want to try again. + def storage_available? + @storage_available ||= Gitlab::Git::Storage::ForkedStorageCheck.storage_available?(storage_path, storage_timeout) + end + + def check_storage_accessible! + if storage_available? + track_storage_accessible + else + track_storage_inaccessible + raise Gitlab::Git::Storage::Inaccessible.new("#{storage} not accessible", failure_wait_time) + end + end + + def no_failures? + last_failure.blank? && failure_count == 0 + end + + def track_storage_inaccessible + @failure_info = [Time.now, failure_count + 1] + + Gitlab::Git::Storage.redis.with do |redis| + redis.pipelined do + redis.hset(cache_key, :last_failure, last_failure.to_i) + redis.hincrby(cache_key, :failure_count, 1) + redis.expire(cache_key, failure_reset_time) + end + end + end + + def track_storage_accessible + return if no_failures? + + @failure_info = [nil, 0] + + Gitlab::Git::Storage.redis.with do |redis| + redis.pipelined do + redis.hset(cache_key, :last_failure, nil) + redis.hset(cache_key, :failure_count, 0) + end + end + end + + def last_failure + failure_info.first + end + + def failure_count + failure_info.last + end + + def failure_info + @failure_info ||= get_failure_info + end + + def get_failure_info + last_failure, failure_count = Gitlab::Git::Storage.redis.with do |redis| + redis.hmget(cache_key, :last_failure, :failure_count) + end + + last_failure = Time.at(last_failure.to_i) if last_failure.present? + + [last_failure, failure_count.to_i] + end + + def cache_key + @cache_key ||= "#{Gitlab::Git::Storage::REDIS_KEY_PREFIX}#{storage}:#{hostname}" + end + end + end + end +end diff --git a/lib/gitlab/git/storage/forked_storage_check.rb b/lib/gitlab/git/storage/forked_storage_check.rb new file mode 100644 index 00000000000..557a3b0e61d --- /dev/null +++ b/lib/gitlab/git/storage/forked_storage_check.rb @@ -0,0 +1,59 @@ +module Gitlab + module Git + module Storage + module ForkedStorageCheck + extend self + + def storage_available?(path, timeout_seconds = 5) + status = timeout_check(path, timeout_seconds) + + status.success? + end + + def timeout_check(path, timeout_seconds) + filesystem_check_pid = check_filesystem_in_fork(path) + + deadline = timeout_seconds.seconds.from_now.utc + wait_time = 0.01 + status = nil + + while status.nil? + if deadline > Time.now.utc + sleep(wait_time) + _pid, status = Process.wait2(filesystem_check_pid, Process::WNOHANG) + else + Process.kill('KILL', filesystem_check_pid) + # Blocking wait, so we are sure the process is gone before continuing + _pid, status = Process.wait2(filesystem_check_pid) + end + end + + status + end + + # This call forks out into a process, that process will then be replaced + # With an `exec` call, since we fork out into a shell, we can create a + # child process without needing an ActiveRecord-connection. + # + # Inside the shell, we use `& wait` to fork another child. We do this + # to prevent leaving a zombie process when the parent gets killed by the + # timeout. + # + # https://stackoverflow.com/questions/27892975/what-causes-activerecord-breaking-postgres-connection-after-forking + # https://stackoverflow.com/questions/22012943/activerecordstatementinvalid-runtimeerror-the-connection-cannot-be-reused-in + def check_filesystem_in_fork(path) + fork do + STDOUT.reopen('/dev/null') + STDERR.reopen('/dev/null') + + exec("(#{test_script(path)}) & wait %1") + end + end + + def test_script(path) + "testpath=\"$(realpath #{Shellwords.escape(path)})\" && stat $testpath" + end + end + end + end +end diff --git a/lib/gitlab/git/storage/health.rb b/lib/gitlab/git/storage/health.rb new file mode 100644 index 00000000000..0a28052fd81 --- /dev/null +++ b/lib/gitlab/git/storage/health.rb @@ -0,0 +1,101 @@ +module Gitlab + module Git + module Storage + class Health + attr_reader :storage_name, :info + + def self.pattern_for_storage(storage_name) + "#{Gitlab::Git::Storage::REDIS_KEY_PREFIX}#{storage_name}:*" + end + + def self.for_all_storages + storage_names = Gitlab.config.repositories.storages.keys + results_per_storage = nil + + Gitlab::Git::Storage.redis.with do |redis| + keys_per_storage = all_keys_for_storages(storage_names, redis) + + # We need to make sure all keys are actually loaded as an array. + # Otherwise when using the enumerator of the `scan_each` within a + # second pipeline, it will be assumed unloaded, wich would make the + # result unusable inside the pipeline. + loaded_keys_per_storage = keys_per_storage.inject({}) do |loaded_keys, (storage_name, keys)| + loaded_keys[storage_name] = keys.to_a + loaded_keys + end + + results_per_storage = load_for_keys(loaded_keys_per_storage, redis) + end + + results_per_storage.map do |name, info| + info.each { |i| i[:failure_count] = i[:failure_count].value.to_i } + new(name, info) + end + end + + def self.all_keys_for_storages(storage_names, redis) + keys_per_storage = nil + + redis.pipelined do + keys_per_storage = storage_names.inject({}) do |result, storage_name| + key = pattern_for_storage(storage_name) + + result.merge(storage_name => redis.scan_each(match: key)) + end + end + + keys_per_storage + end + + def self.load_for_keys(keys_per_storage, redis) + info_for_keys = nil + + redis.pipelined do + info_for_keys = keys_per_storage.inject({}) do |result, (storage_name, keys)| + info_for_storage = keys.map do |key| + { name: key, failure_count: redis.hget(key, :failure_count) } + end + + result.merge(storage_name => info_for_storage) + end + end + + info_for_keys + end + + def self.for_failing_storages + for_all_storages.select(&:failing?) + end + + def initialize(storage_name, info) + @storage_name = storage_name + @info = info + end + + def failing_info + @failing_info ||= info.select { |info_for_host| info_for_host[:failure_count] > 0 } + end + + def failing? + failing_info.any? + end + + def failing_on_hosts + @failing_on_hosts ||= failing_info.map do |info_for_host| + info_for_host[:name].split(':').last + end + end + + def failing_circuit_breakers + @failing_circuit_breakers ||= failing_on_hosts.map do |hostname| + CircuitBreaker.new(storage_name, hostname) + end + end + + def total_failures + @total_failures ||= failing_info.sum { |info_for_host| info_for_host[:failure_count] } + end + end + end + end +end diff --git a/lib/gitlab/health_checks/fs_shards_check.rb b/lib/gitlab/health_checks/fs_shards_check.rb index 9e91c135956..eef97f54962 100644 --- a/lib/gitlab/health_checks/fs_shards_check.rb +++ b/lib/gitlab/health_checks/fs_shards_check.rb @@ -10,7 +10,9 @@ module Gitlab def readiness repository_storages.map do |storage_name| begin - if !storage_stat_test(storage_name) + if !storage_circuitbreaker_test(storage_name) + HealthChecks::Result.new(false, 'circuitbreaker tripped', shard: storage_name) + elsif !storage_stat_test(storage_name) HealthChecks::Result.new(false, 'cannot stat storage', shard: storage_name) else with_temp_file(storage_name) do |tmp_file_path| @@ -36,7 +38,8 @@ module Gitlab [ storage_stat_metrics(storage_name), storage_write_metrics(storage_name), - storage_read_metrics(storage_name) + storage_read_metrics(storage_name), + storage_circuitbreaker_metrics(storage_name) ].flatten end end @@ -121,6 +124,12 @@ module Gitlab file_contents == RANDOM_STRING end + def storage_circuitbreaker_test(storage_name) + Gitlab::Git::Storage::CircuitBreaker.new(storage_name).perform { "OK" } + rescue Gitlab::Git::Storage::Inaccessible + nil + end + def storage_stat_metrics(storage_name) operation_metrics(:filesystem_accessible, :filesystem_access_latency_seconds, shard: storage_name) do with_timing { storage_stat_test(storage_name) } @@ -143,6 +152,14 @@ module Gitlab end end end + + def storage_circuitbreaker_metrics(storage_name) + operation_metrics(:filesystem_circuitbreaker, + :filesystem_circuitbreaker_latency_seconds, + shard: storage_name) do + with_timing { storage_circuitbreaker_test(storage_name) } + end + end end end end diff --git a/spec/controllers/admin/health_check_controller_spec.rb b/spec/controllers/admin/health_check_controller_spec.rb new file mode 100644 index 00000000000..0b8e0c8a065 --- /dev/null +++ b/spec/controllers/admin/health_check_controller_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe Admin::HealthCheckController, broken_storage: true do + let(:admin) { create(:admin) } + + before do + sign_in(admin) + end + + describe 'GET show' do + it 'loads the git storage health information' do + get :show + + expect(assigns[:failing_storage_statuses]).not_to be_nil + end + end + + describe 'POST reset_storage_health' do + it 'resets all storage health information' do + expect(Gitlab::Git::Storage::CircuitBreaker).to receive(:reset_all!) + + post :reset_storage_health + end + end +end diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 1641bddea11..331903a5543 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -108,6 +108,30 @@ describe ApplicationController do end end + describe 'rescue from Gitlab::Git::Storage::Inaccessible' do + controller(described_class) do + def index + raise Gitlab::Git::Storage::Inaccessible.new('broken', 100) + end + end + + it 'renders a 503 when storage is not available' do + sign_in(create(:user)) + + get :index + + expect(response.status).to eq(503) + end + + it 'renders includes a Retry-After header' do + sign_in(create(:user)) + + get :index + + expect(response.headers['Retry-After']).to eq(100) + end + end + describe 'response format' do controller(described_class) do def index diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 34095ef6250..8ecd8b6ca71 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -107,6 +107,20 @@ describe ProjectsController do end end + context 'when the storage is not available', broken_storage: true do + let(:project) { create(:project, :broken_storage) } + before do + project.add_developer(user) + sign_in(user) + end + + it 'renders a 503' do + get :show, namespace_id: project.namespace, id: project + + expect(response).to have_http_status(503) + end + end + context "project with empty repo" do let(:empty_project) { create(:project_empty_repo, :public) } diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index be3f219e8bf..3f8e7030b1c 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -54,6 +54,12 @@ FactoryGirl.define do avatar { File.open(Rails.root.join('spec/fixtures/dk.png')) } end + trait :broken_storage do + after(:create) do |project| + project.update_column(:repository_storage, 'broken') + end + end + # Test repository - https://gitlab.com/gitlab-org/gitlab-test trait :repository do path { 'gitlabhq' } diff --git a/spec/features/admin/admin_health_check_spec.rb b/spec/features/admin/admin_health_check_spec.rb index 106e7370a98..634dfd53f71 100644 --- a/spec/features/admin/admin_health_check_spec.rb +++ b/spec/features/admin/admin_health_check_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature "Admin Health Check" do +feature "Admin Health Check", feature: true, broken_storage: true do include StubENV before do @@ -55,4 +55,26 @@ feature "Admin Health Check" do expect(page).to have_content('The server is on fire') end end + + context 'with repository storage failures' do + before do + # Track a failure + Gitlab::Git::Storage::CircuitBreaker.for_storage('broken').perform { nil } rescue nil + visit admin_health_check_path + end + + it 'shows storage failure information' do + hostname = Gitlab.config.gitlab.hostname + + expect(page).to have_content('broken: failed storage access attempt on host:') + expect(page).to have_content("#{hostname}: 1 of 10 failures.") + end + + it 'allows resetting storage failures' do + click_button 'Reset git storage health information' + + expect(page).to have_content('Git storage health information has been reset') + expect(page).not_to have_content('failed storage access attempt') + end + end end diff --git a/spec/helpers/storage_health_helper_spec.rb b/spec/helpers/storage_health_helper_spec.rb new file mode 100644 index 00000000000..874498e6338 --- /dev/null +++ b/spec/helpers/storage_health_helper_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe StorageHealthHelper do + describe '#failing_storage_health_message' do + let(:health) do + Gitlab::Git::Storage::Health.new( + "", + [] + ) + end + + it 'escapes storage names' do + escaped_storage_name = '<script>alert('storage name');)</script>' + + result = helper.failing_storage_health_message(health) + + expect(result).to include(escaped_storage_name) + end + end +end diff --git a/spec/initializers/6_validations_spec.rb b/spec/initializers/6_validations_spec.rb index 0877770c167..83283f03940 100644 --- a/spec/initializers/6_validations_spec.rb +++ b/spec/initializers/6_validations_spec.rb @@ -23,6 +23,16 @@ describe '6_validations' do end end + context 'when one of the settings is incorrect' do + before do + mock_storages('foo' => { 'path' => 'tmp/tests/paths/a/b/c', 'failure_count_threshold' => 'not a number' }) + end + + it 'throws an error' do + expect { validate_storages_config }.to raise_error(/failure_count_threshold/) + end + end + context 'with invalid storage names' do before do mock_storages('name with spaces' => { 'path' => 'tmp/tests/paths/a/b/c' }) @@ -84,6 +94,17 @@ describe '6_validations' do expect { validate_storages_paths }.not_to raise_error end end + + describe 'inaccessible storage' do + before do + mock_storages('foo' => { 'path' => 'tmp/tests/a/path/that/does/not/exist' }) + end + + it 'passes through with a warning' do + expect(Rails.logger).to receive(:error) + expect { validate_storages_paths }.not_to raise_error + end + end end def mock_storages(storages) diff --git a/spec/initializers/settings_spec.rb b/spec/initializers/settings_spec.rb index ebdabcf93f1..e5ec90cb8f9 100644 --- a/spec/initializers/settings_spec.rb +++ b/spec/initializers/settings_spec.rb @@ -2,6 +2,17 @@ require 'spec_helper' require_relative '../../config/initializers/1_settings' describe Settings do + describe '#repositories' do + it 'assigns the default failure attributes' do + repository_settings = Gitlab.config.repositories.storages['broken'] + + expect(repository_settings['failure_count_threshold']).to eq(10) + expect(repository_settings['failure_wait_time']).to eq(30) + expect(repository_settings['failure_reset_time']).to eq(1800) + expect(repository_settings['storage_timeout']).to eq(5) + end + end + describe '#host_without_www' do context 'URL with protocol' do it 'returns the host' do diff --git a/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb b/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb index f43d89d7ccd..16704ff5e77 100644 --- a/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb +++ b/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb @@ -48,8 +48,9 @@ describe Gitlab::Cache::Ci::ProjectPipelineStatus, :clean_gitlab_redis_cache do described_class.load_in_batch_for_projects([project_without_status]) end - it 'only connects to redis_cache twice' do - # Once to load, once to store in the cache + it 'only connects to redis twice' do + # Stub circuitbreaker so it doesn't count the redis connections in there + stub_circuit_breaker(project_without_status) expect(Gitlab::Redis::Cache).to receive(:with).exactly(2).and_call_original described_class.load_in_batch_for_projects([project_without_status]) @@ -301,4 +302,13 @@ describe Gitlab::Cache::Ci::ProjectPipelineStatus, :clean_gitlab_redis_cache do end end end + + def stub_circuit_breaker(project) + fake_circuitbreaker = double + allow(fake_circuitbreaker).to receive(:perform).and_yield + allow(project.repository.raw_repository) + .to receive(:circuit_breaker).and_return(fake_circuitbreaker) + allow(project.repository) + .to receive(:circuit_breaker).and_return(fake_circuitbreaker) + end end diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index 9bfad0c9bdf..07cd6db2200 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -55,6 +55,20 @@ describe Gitlab::Git::Repository, seed_helper: true do end describe "#rugged" do + describe 'when storage is broken', broken_storage: true do + it 'raises a storage exception when storage is not available' do + broken_repo = described_class.new('broken', 'a/path.git') + + expect { broken_repo.rugged }.to raise_error(Gitlab::Git::Storage::Inaccessible) + end + end + + it 'raises a no repository exception when there is no repo' do + broken_repo = described_class.new('default', 'a/path.git') + + expect { broken_repo.rugged }.to raise_error(Gitlab::Git::Repository::NoRepository) + end + context 'with no Git env stored' do before do expect(Gitlab::Git::Env).to receive(:all).and_return({}) diff --git a/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb b/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb new file mode 100644 index 00000000000..479e53230bc --- /dev/null +++ b/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb @@ -0,0 +1,265 @@ +require 'spec_helper' + +describe Gitlab::Git::Storage::CircuitBreaker, clean_gitlab_redis_shared_state: true, broken_storage: true do + let(:circuit_breaker) { described_class.new('default') } + let(:hostname) { Gitlab.config.gitlab.hostname } + let(:cache_key) { "storage_accessible:default:#{hostname}" } + + def value_from_redis(name) + Gitlab::Git::Storage.redis.with do |redis| + redis.hmget(cache_key, name) + end.first + end + + def set_in_redis(name, value) + Gitlab::Git::Storage.redis.with do |redis| + redis.hmset(cache_key, name, value) + end.first + end + + describe '.reset_all!' do + it 'clears all entries form redis' do + set_in_redis(:failure_count, 10) + + described_class.reset_all! + + key_exists = Gitlab::Git::Storage.redis.with { |redis| redis.exists(cache_key) } + + expect(key_exists).to be_falsey + end + end + + describe '.for_storage' do + it 'only builds a single circuitbreaker per storage' do + expect(described_class).to receive(:new).once.and_call_original + + breaker = described_class.for_storage('default') + + expect(breaker).to be_a(described_class) + expect(described_class.for_storage('default')).to eq(breaker) + end + end + + describe '#initialize' do + it 'assigns the settings' do + expect(circuit_breaker.hostname).to eq(hostname) + expect(circuit_breaker.storage).to eq('default') + expect(circuit_breaker.storage_path).to eq(TestEnv.repos_path) + expect(circuit_breaker.failure_count_threshold).to eq(10) + expect(circuit_breaker.failure_wait_time).to eq(30) + expect(circuit_breaker.failure_reset_time).to eq(1800) + expect(circuit_breaker.storage_timeout).to eq(5) + end + end + + describe '#perform' do + it 'raises an exception with retry time when the circuit is open' do + allow(circuit_breaker).to receive(:circuit_broken?).and_return(true) + + expect { |b| circuit_breaker.perform(&b) } + .to raise_error(Gitlab::Git::Storage::CircuitOpen) + end + + it 'yields the block' do + expect { |b| circuit_breaker.perform(&b) } + .to yield_control + end + + it 'checks if the storage is available' do + expect(circuit_breaker).to receive(:check_storage_accessible!) + + circuit_breaker.perform { 'hello world' } + end + + it 'returns the value of the block' do + result = circuit_breaker.perform { 'return value' } + + expect(result).to eq('return value') + end + + it 'raises possible errors' do + expect { circuit_breaker.perform { raise Rugged::OSError.new('Broken') } } + .to raise_error(Rugged::OSError) + end + + context 'with the feature disabled' do + it 'returns the block without checking accessibility' do + stub_feature_flags(git_storage_circuit_breaker: false) + + expect(circuit_breaker).not_to receive(:circuit_broken?) + + result = circuit_breaker.perform { 'hello' } + + expect(result).to eq('hello') + end + end + end + + describe '#circuit_broken?' do + it 'is closed when there is no last failure' do + set_in_redis(:last_failure, nil) + set_in_redis(:failure_count, 0) + + expect(circuit_breaker.circuit_broken?).to be_falsey + end + + it 'is open when there was a recent failure' do + Timecop.freeze do + set_in_redis(:last_failure, 1.second.ago.to_f) + set_in_redis(:failure_count, 1) + + expect(circuit_breaker.circuit_broken?).to be_truthy + end + end + + it 'is open when there are to many failures' do + set_in_redis(:last_failure, 1.day.ago.to_f) + set_in_redis(:failure_count, 200) + + expect(circuit_breaker.circuit_broken?).to be_truthy + end + end + + describe '#check_storage_accessible!' do + context 'when the storage is available' do + it 'tracks that the storage was accessible an raises the error' do + expect(circuit_breaker).to receive(:track_storage_accessible) + + circuit_breaker.check_storage_accessible! + end + end + + context 'when the storage is not available' do + let(:circuit_breaker) { described_class.new('broken') } + + it 'tracks that the storage was unavailable and raises an error with retry time' do + expect(circuit_breaker).to receive(:track_storage_inaccessible) + + expect { circuit_breaker.check_storage_accessible! } + .to raise_error do |exception| + expect(exception).to be_kind_of(Gitlab::Git::Storage::Inaccessible) + expect(exception.retry_after).to eq(30) + end + end + end + end + + describe '#track_storage_inaccessible' do + around(:each) do |example| + Timecop.freeze + + example.run + + Timecop.return + end + + it 'records the failure time in redis' do + circuit_breaker.track_storage_inaccessible + + failure_time = value_from_redis(:last_failure) + + expect(Time.at(failure_time.to_i)).to be_within(1.second).of(Time.now) + end + + it 'sets the failure time on the breaker without reloading' do + circuit_breaker.track_storage_inaccessible + + expect(circuit_breaker).not_to receive(:get_failure_info) + expect(circuit_breaker.last_failure).to eq(Time.now) + end + + it 'increments the failure count in redis' do + set_in_redis(:failure_count, 10) + + circuit_breaker.track_storage_inaccessible + + expect(value_from_redis(:failure_count).to_i).to be(11) + end + + it 'increments the failure count on the breaker without reloading' do + set_in_redis(:failure_count, 10) + + circuit_breaker.track_storage_inaccessible + + expect(circuit_breaker).not_to receive(:get_failure_info) + expect(circuit_breaker.failure_count).to eq(11) + end + end + + describe '#track_storage_accessible' do + it 'sets the failure count to zero in redis' do + set_in_redis(:failure_count, 10) + + circuit_breaker.track_storage_accessible + + expect(value_from_redis(:failure_count).to_i).to be(0) + end + + it 'sets the failure count to zero on the breaker without reloading' do + set_in_redis(:failure_count, 10) + + circuit_breaker.track_storage_accessible + + expect(circuit_breaker).not_to receive(:get_failure_info) + expect(circuit_breaker.failure_count).to eq(0) + end + + it 'removes the last failure time from redis' do + set_in_redis(:last_failure, Time.now.to_i) + + circuit_breaker.track_storage_accessible + + expect(circuit_breaker).not_to receive(:get_failure_info) + expect(circuit_breaker.last_failure).to be_nil + end + + it 'removes the last failure time from the breaker without reloading' do + set_in_redis(:last_failure, Time.now.to_i) + + circuit_breaker.track_storage_accessible + + expect(value_from_redis(:last_failure)).to be_empty + end + + it 'wont connect to redis when there are no failures' do + expect(Gitlab::Git::Storage.redis).to receive(:with).once + .and_call_original + expect(circuit_breaker).to receive(:track_storage_accessible) + .and_call_original + + circuit_breaker.track_storage_accessible + end + end + + describe '#no_failures?' do + it 'is false when a failure was tracked' do + set_in_redis(:last_failure, Time.now.to_i) + set_in_redis(:failure_count, 1) + + expect(circuit_breaker.no_failures?).to be_falsey + end + end + + describe '#last_failure' do + it 'returns the last failure time' do + time = Time.parse("2017-05-26 17:52:30") + set_in_redis(:last_failure, time.to_i) + + expect(circuit_breaker.last_failure).to eq(time) + end + end + + describe '#failure_count' do + it 'returns the failure count' do + set_in_redis(:failure_count, 7) + + expect(circuit_breaker.failure_count).to eq(7) + end + end + + describe '#cache_key' do + it 'includes storage and host' do + expect(circuit_breaker.cache_key).to eq(cache_key) + end + end +end diff --git a/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb b/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb new file mode 100644 index 00000000000..a9e048b316d --- /dev/null +++ b/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb @@ -0,0 +1,27 @@ +require 'spec_helper' + +describe Gitlab::Git::Storage::ForkedStorageCheck, skip_database_cleaner: true do + let(:existing_path) do + existing_path = TestEnv.repos_path + FileUtils.mkdir_p(existing_path) + existing_path + end + + describe '.storage_accessible?' do + it 'detects when a storage is not available' do + expect(described_class.storage_available?('/non/existant/path')).to be_falsey + end + + it 'detects when a storage is available' do + expect(described_class.storage_available?(existing_path)).to be_truthy + end + + it 'returns false when the check takes to long' do + allow(described_class).to receive(:check_filesystem_in_fork) do + fork { sleep 10 } + end + + expect(described_class.storage_available?(existing_path, 0.5)).to be_falsey + end + end +end diff --git a/spec/lib/gitlab/git/storage/health_spec.rb b/spec/lib/gitlab/git/storage/health_spec.rb new file mode 100644 index 00000000000..28b74a0581f --- /dev/null +++ b/spec/lib/gitlab/git/storage/health_spec.rb @@ -0,0 +1,85 @@ +require 'spec_helper' + +describe Gitlab::Git::Storage::Health, clean_gitlab_redis_shared_state: true, broken_storage: true do + let(:host1_key) { 'storage_accessible:broken:web01' } + let(:host2_key) { 'storage_accessible:default:kiq01' } + + def set_in_redis(cache_key, value) + Gitlab::Git::Storage.redis.with do |redis| + redis.hmset(cache_key, :failure_count, value) + end.first + end + + describe '.for_failing_storages' do + it 'only includes health status for failures' do + set_in_redis(host1_key, 10) + set_in_redis(host2_key, 0) + + expect(described_class.for_failing_storages.map(&:storage_name)) + .to contain_exactly('broken') + end + end + + describe '.load_for_keys' do + let(:subject) do + results = Gitlab::Git::Storage.redis.with do |redis| + described_class.load_for_keys({ 'broken' => [host1_key] }, redis) + end + + # Make sure the `Redis#future is loaded + results.inject({}) do |result, (name, info)| + info.each { |i| i[:failure_count] = i[:failure_count].value.to_i } + + result[name] = info + + result + end + end + + it 'loads when there is no info in redis' do + expect(subject).to eq('broken' => [{ name: host1_key, failure_count: 0 }]) + end + + it 'reads the correct values for a storage from redis' do + set_in_redis(host1_key, 5) + set_in_redis(host2_key, 7) + + expect(subject).to eq('broken' => [{ name: host1_key, failure_count: 5 }]) + end + end + + describe '.for_all_storages' do + it 'loads health status for all configured storages' do + healths = described_class.for_all_storages + + expect(healths.map(&:storage_name)).to contain_exactly('default', 'broken') + end + end + + describe '#failing_info' do + it 'only contains storages that have failures' do + health = described_class.new('broken', [{ name: host1_key, failure_count: 0 }, + { name: host2_key, failure_count: 3 }]) + + expect(health.failing_info).to contain_exactly({ name: host2_key, failure_count: 3 }) + end + end + + describe '#total_failures' do + it 'sums up all the failures' do + health = described_class.new('broken', [{ name: host1_key, failure_count: 2 }, + { name: host2_key, failure_count: 3 }]) + + expect(health.total_failures).to eq(5) + end + end + + describe '#failing_on_hosts' do + it 'collects only the failing hostnames' do + health = described_class.new('broken', [{ name: host1_key, failure_count: 2 }, + { name: host2_key, failure_count: 0 }]) + + expect(health.failing_on_hosts).to contain_exactly('web01') + end + end +end diff --git a/spec/lib/gitlab/health_checks/fs_shards_check_spec.rb b/spec/lib/gitlab/health_checks/fs_shards_check_spec.rb index 8abc4320c59..8539c6deea6 100644 --- a/spec/lib/gitlab/health_checks/fs_shards_check_spec.rb +++ b/spec/lib/gitlab/health_checks/fs_shards_check_spec.rb @@ -44,6 +44,15 @@ describe Gitlab::HealthChecks::FsShardsCheck do describe '#readiness' do subject { described_class.readiness } + context 'storage has a tripped circuitbreaker' do + let(:repository_storages) { ['broken'] } + let(:storages_paths) do + Gitlab.config.repositories.storages + end + + it { is_expected.to include(result_class.new(false, 'circuitbreaker tripped', shard: 'broken')) } + end + context 'storage points to not existing folder' do let(:storages_paths) do { @@ -51,6 +60,10 @@ describe Gitlab::HealthChecks::FsShardsCheck do }.with_indifferent_access end + before do + allow(described_class).to receive(:storage_circuitbreaker_test) { true } + end + it { is_expected.to include(result_class.new(false, 'cannot stat storage', shard: :default)) } end @@ -109,6 +122,7 @@ describe Gitlab::HealthChecks::FsShardsCheck do expect(metrics).to include(an_object_having_attributes(name: :filesystem_access_latency_seconds, value: be >= 0)) expect(metrics).to include(an_object_having_attributes(name: :filesystem_read_latency_seconds, value: be >= 0)) expect(metrics).to include(an_object_having_attributes(name: :filesystem_write_latency_seconds, value: be >= 0)) + expect(metrics).to include(an_object_having_attributes(name: :filesystem_circuitbreaker_latency_seconds, value: be >= 0)) end end @@ -127,6 +141,7 @@ describe Gitlab::HealthChecks::FsShardsCheck do expect(metrics).to include(an_object_having_attributes(name: :filesystem_access_latency_seconds, value: be >= 0)) expect(metrics).to include(an_object_having_attributes(name: :filesystem_read_latency_seconds, value: be >= 0)) expect(metrics).to include(an_object_having_attributes(name: :filesystem_write_latency_seconds, value: be >= 0)) + expect(metrics).to include(an_object_having_attributes(name: :filesystem_circuitbreaker_latency_seconds, value: be >= 0)) end it 'cleans up files used for metrics' do diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 764f548be45..d077925a1cf 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -1,11 +1,12 @@ require 'spec_helper' -describe Repository do +describe Repository, models: true do include RepoHelpers TestBlob = Struct.new(:path) let(:project) { create(:project, :repository) } let(:repository) { project.repository } + let(:broken_repository) { create(:project, :broken_storage).repository } let(:user) { create(:user) } let(:commit_options) do @@ -27,12 +28,26 @@ describe Repository do let(:author_email) { 'user@example.org' } let(:author_name) { 'John Doe' } + def expect_to_raise_storage_error + expect { yield }.to raise_error do |exception| + expect(exception.class).to be_in([Gitlab::Git::Storage::Inaccessible, GRPC::Unavailable]) + end + end + describe '#branch_names_contains' do subject { repository.branch_names_contains(sample_commit.id) } it { is_expected.to include('master') } it { is_expected.not_to include('feature') } it { is_expected.not_to include('fix') } + + describe 'when storage is broken', broken_storage: true do + it 'should raise a storage error' do + expect_to_raise_storage_error do + broken_repository.branch_names_contains(sample_commit.id) + end + end + end end describe '#tag_names_contains' do @@ -142,6 +157,14 @@ describe Repository do subject { repository.last_commit_for_path(sample_commit.id, '.gitignore').id } it { is_expected.to eq('c1acaa58bbcbc3eafe538cb8274ba387047b69f8') } + + describe 'when storage is broken', broken_storage: true do + it 'should raise a storage error' do + expect_to_raise_storage_error do + broken_repository.last_commit_for_path(sample_commit.id, '.gitignore').id + end + end + end end describe '#last_commit_id_for_path' do @@ -158,6 +181,14 @@ describe Repository do expect(cache).to receive(:fetch).with(key).and_return('c1acaa5') is_expected.to eq('c1acaa5') end + + describe 'when storage is broken', broken_storage: true do + it 'should raise a storage error' do + expect_to_raise_storage_error do + broken_repository.last_commit_id_for_path(sample_commit.id, '.gitignore') + end + end + end end describe '#commits' do @@ -196,6 +227,12 @@ describe Repository do expect(commit_ids).to include('5937ac0a7beb003549fc5fd26fc247adbce4a52e') end + + describe 'when storage is broken', broken_storage: true do + it 'should raise a storage error' do + expect_to_raise_storage_error { broken_repository.find_commits_by_message('s') } + end + end end describe '#blob_at' do @@ -521,6 +558,14 @@ describe Repository do expect(results).to match_array([]) end + describe 'when storage is broken', broken_storage: true do + it 'should raise a storage error' do + expect_to_raise_storage_error do + broken_repository.search_files_by_content('feature', 'master') + end + end + end + describe 'result' do subject { results.first } @@ -549,6 +594,22 @@ describe Repository do expect(results).to match_array([]) end + + describe 'when storage is broken', broken_storage: true do + it 'should raise a storage error' do + expect_to_raise_storage_error { broken_repository.search_files_by_name('files', 'master') } + end + end + end + + describe '#fetch_ref' do + describe 'when storage is broken', broken_storage: true do + it 'should raise a storage error' do + path = broken_repository.path_to_repo + + expect_to_raise_storage_error { broken_repository.fetch_ref(path, '1', '2') } + end + end end describe '#create_ref' do @@ -966,6 +1027,12 @@ describe Repository do expect(repository.exists?).to eq(false) end + + context 'with broken storage', broken_storage: true do + it 'should raise a storage error' do + expect_to_raise_storage_error { broken_repository.exists? } + end + end end describe '#exists?' do diff --git a/spec/requests/api/circuit_breakers_spec.rb b/spec/requests/api/circuit_breakers_spec.rb new file mode 100644 index 00000000000..76521e55994 --- /dev/null +++ b/spec/requests/api/circuit_breakers_spec.rb @@ -0,0 +1,57 @@ +require 'spec_helper' + +describe API::CircuitBreakers do + let(:user) { create(:user) } + let(:admin) { create(:admin) } + + describe 'GET circuit_breakers/repository_storage' do + it 'returns a 401 for anonymous users' do + get api('/circuit_breakers/repository_storage') + + expect(response).to have_http_status(401) + end + + it 'returns a 403 for users' do + get api('/circuit_breakers/repository_storage', user) + + expect(response).to have_http_status(403) + end + + it 'returns an Array of storages' do + expect(Gitlab::Git::Storage::Health).to receive(:for_all_storages) do + [Gitlab::Git::Storage::Health.new('broken', [{ name: 'prefix:broken:web01', failure_count: 4 }])] + end + + get api('/circuit_breakers/repository_storage', admin) + + expect(response).to have_http_status(200) + expect(json_response).to be_kind_of(Array) + expect(json_response.first['storage_name']).to eq('broken') + expect(json_response.first['failing_on_hosts']).to eq(['web01']) + expect(json_response.first['total_failures']).to eq(4) + end + + describe 'GET circuit_breakers/repository_storage/failing' do + it 'returns an array of failing storages' do + expect(Gitlab::Git::Storage::Health).to receive(:for_failing_storages) do + [Gitlab::Git::Storage::Health.new('broken', [{ name: 'prefix:broken:web01', failure_count: 4 }])] + end + + get api('/circuit_breakers/repository_storage/failing', admin) + + expect(response).to have_http_status(200) + expect(json_response).to be_kind_of(Array) + end + end + end + + describe 'DELETE circuit_breakers/repository_storage' do + it 'clears all circuit_breakers' do + expect(Gitlab::Git::Storage::CircuitBreaker).to receive(:reset_all!) + + delete api('/circuit_breakers/repository_storage', admin) + + expect(response).to have_http_status(204) + end + end +end diff --git a/spec/support/stored_repositories.rb b/spec/support/stored_repositories.rb index df18926d58c..f3deae0f455 100644 --- a/spec/support/stored_repositories.rb +++ b/spec/support/stored_repositories.rb @@ -2,4 +2,16 @@ RSpec.configure do |config| config.before(:each, :repository) do TestEnv.clean_test_path end + + config.before(:all, :broken_storage) do + FileUtils.rm_rf Gitlab.config.repositories.storages.broken['path'] + end + + config.before(:each, :broken_storage) do + allow(Gitlab::GitalyClient).to receive(:call) do + raise GRPC::Unavailable.new('Gitaly broken in this spec') + end + + Gitlab::Git::Storage::CircuitBreaker.reset_all! + end end From 0fa94a0dddfc38635abf49a38dbadc9b9ead4d7a Mon Sep 17 00:00:00 2001 From: Bob Van Landuyt Date: Wed, 2 Aug 2017 08:34:41 +0200 Subject: [PATCH 137/177] Make sure the check works for paths with spaces. --- .../git/storage/forked_storage_check.rb | 2 +- .../git/storage/forked_storage_check_spec.rb | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/gitlab/git/storage/forked_storage_check.rb b/lib/gitlab/git/storage/forked_storage_check.rb index 557a3b0e61d..0e9e7ba596b 100644 --- a/lib/gitlab/git/storage/forked_storage_check.rb +++ b/lib/gitlab/git/storage/forked_storage_check.rb @@ -51,7 +51,7 @@ module Gitlab end def test_script(path) - "testpath=\"$(realpath #{Shellwords.escape(path)})\" && stat $testpath" + "testpath=$(realpath #{Shellwords.escape(path)}) && stat \"$testpath\"" end end end diff --git a/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb b/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb index a9e048b316d..20cee123ede 100644 --- a/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb +++ b/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb @@ -23,5 +23,27 @@ describe Gitlab::Git::Storage::ForkedStorageCheck, skip_database_cleaner: true d expect(described_class.storage_available?(existing_path, 0.5)).to be_falsey end + + describe 'when using paths with spaces' do + let(:test_dir) { Rails.root.join('tmp', 'tests', 'storage_check') } + let(:path_with_spaces) { File.join(test_dir, 'path with spaces') } + + around do |example| + FileUtils.mkdir_p(path_with_spaces) + example.run + FileUtils.rm_r(test_dir) + end + + it 'works for paths with spaces' do + expect(described_class.storage_available?(path_with_spaces)).to be_truthy + end + + it 'works for a realpath with spaces' do + symlink_location = File.join(test_dir, 'a symlink') + FileUtils.ln_s(path_with_spaces, symlink_location) + + expect(described_class.storage_available?(symlink_location)).to be_truthy + end + end end end From 3899d07f9eb5ffa2369195c800be18e297f67613 Mon Sep 17 00:00:00 2001 From: Bob Van Landuyt Date: Thu, 3 Aug 2017 12:16:45 +0200 Subject: [PATCH 138/177] Move hostname to Gitlab::Environment --- config/initializers/1_settings.rb | 1 - lib/gitlab/environment.rb | 7 +++++++ lib/gitlab/git/storage/circuit_breaker.rb | 2 +- spec/features/admin/admin_health_check_spec.rb | 2 +- spec/lib/gitlab/git/storage/circuit_breaker_spec.rb | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 lib/gitlab/environment.rb diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 017537f30be..7a43bf939ea 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -222,7 +222,6 @@ Settings.gitlab['default_branch_protection'] ||= 2 Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil? Settings.gitlab['host'] ||= ENV['GITLAB_HOST'] || 'localhost' Settings.gitlab['ssh_host'] ||= Settings.gitlab.host -Settings.gitlab['hostname'] ||= ENV['HOSTNAME'] || Socket.gethostname Settings.gitlab['https'] = false if Settings.gitlab['https'].nil? Settings.gitlab['port'] ||= ENV['GITLAB_PORT'] || (Settings.gitlab.https ? 443 : 80) Settings.gitlab['relative_url_root'] ||= ENV['RAILS_RELATIVE_URL_ROOT'] || '' diff --git a/lib/gitlab/environment.rb b/lib/gitlab/environment.rb new file mode 100644 index 00000000000..5e0dd6e7859 --- /dev/null +++ b/lib/gitlab/environment.rb @@ -0,0 +1,7 @@ +module Gitlab + module Environment + def self.hostname + @hostname ||= ENV['HOSTNAME'] || Socket.gethostname + end + end +end diff --git a/lib/gitlab/git/storage/circuit_breaker.rb b/lib/gitlab/git/storage/circuit_breaker.rb index c722771e0d5..7b040a05c42 100644 --- a/lib/gitlab/git/storage/circuit_breaker.rb +++ b/lib/gitlab/git/storage/circuit_breaker.rb @@ -31,7 +31,7 @@ module Gitlab cached_circuitbreakers[storage] end - def initialize(storage, hostname = Gitlab.config.gitlab.hostname) + def initialize(storage, hostname = Gitlab::Environment.hostname) @storage = storage @hostname = hostname diff --git a/spec/features/admin/admin_health_check_spec.rb b/spec/features/admin/admin_health_check_spec.rb index 634dfd53f71..37fd3e171eb 100644 --- a/spec/features/admin/admin_health_check_spec.rb +++ b/spec/features/admin/admin_health_check_spec.rb @@ -64,7 +64,7 @@ feature "Admin Health Check", feature: true, broken_storage: true do end it 'shows storage failure information' do - hostname = Gitlab.config.gitlab.hostname + hostname = Gitlab::Environment.hostname expect(page).to have_content('broken: failed storage access attempt on host:') expect(page).to have_content("#{hostname}: 1 of 10 failures.") diff --git a/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb b/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb index 479e53230bc..6fab224ad0d 100644 --- a/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb +++ b/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe Gitlab::Git::Storage::CircuitBreaker, clean_gitlab_redis_shared_state: true, broken_storage: true do let(:circuit_breaker) { described_class.new('default') } - let(:hostname) { Gitlab.config.gitlab.hostname } + let(:hostname) { Gitlab::Environment.hostname } let(:cache_key) { "storage_accessible:default:#{hostname}" } def value_from_redis(name) From 022c38e63e202e9da2608d020face6c108e47313 Mon Sep 17 00:00:00 2001 From: Bob Van Landuyt Date: Thu, 3 Aug 2017 13:28:43 +0200 Subject: [PATCH 139/177] Use `keys` instead of `scan_each` --- lib/gitlab/git/storage/circuit_breaker.rb | 2 +- lib/gitlab/git/storage/health.rb | 28 +++++++--------------- spec/lib/gitlab/git/storage/health_spec.rb | 4 +++- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/lib/gitlab/git/storage/circuit_breaker.rb b/lib/gitlab/git/storage/circuit_breaker.rb index 7b040a05c42..237b4598730 100644 --- a/lib/gitlab/git/storage/circuit_breaker.rb +++ b/lib/gitlab/git/storage/circuit_breaker.rb @@ -14,7 +14,7 @@ module Gitlab pattern = "#{Gitlab::Git::Storage::REDIS_KEY_PREFIX}*" Gitlab::Git::Storage.redis.with do |redis| - all_storage_keys = redis.scan_each(match: pattern).to_a + all_storage_keys = redis.keys(pattern) redis.del(*all_storage_keys) unless all_storage_keys.empty? end diff --git a/lib/gitlab/git/storage/health.rb b/lib/gitlab/git/storage/health.rb index 0a28052fd81..2d723147f4f 100644 --- a/lib/gitlab/git/storage/health.rb +++ b/lib/gitlab/git/storage/health.rb @@ -14,17 +14,7 @@ module Gitlab Gitlab::Git::Storage.redis.with do |redis| keys_per_storage = all_keys_for_storages(storage_names, redis) - - # We need to make sure all keys are actually loaded as an array. - # Otherwise when using the enumerator of the `scan_each` within a - # second pipeline, it will be assumed unloaded, wich would make the - # result unusable inside the pipeline. - loaded_keys_per_storage = keys_per_storage.inject({}) do |loaded_keys, (storage_name, keys)| - loaded_keys[storage_name] = keys.to_a - loaded_keys - end - - results_per_storage = load_for_keys(loaded_keys_per_storage, redis) + results_per_storage = load_for_keys(keys_per_storage, redis) end results_per_storage.map do |name, info| @@ -34,13 +24,13 @@ module Gitlab end def self.all_keys_for_storages(storage_names, redis) - keys_per_storage = nil + keys_per_storage = {} redis.pipelined do - keys_per_storage = storage_names.inject({}) do |result, storage_name| - key = pattern_for_storage(storage_name) + storage_names.each do |storage_name| + pattern = pattern_for_storage(storage_name) - result.merge(storage_name => redis.scan_each(match: key)) + keys_per_storage[storage_name] = redis.keys(pattern) end end @@ -48,15 +38,15 @@ module Gitlab end def self.load_for_keys(keys_per_storage, redis) - info_for_keys = nil + info_for_keys = {} redis.pipelined do - info_for_keys = keys_per_storage.inject({}) do |result, (storage_name, keys)| - info_for_storage = keys.map do |key| + keys_per_storage.each do |storage_name, keys_future| + info_for_storage = keys_future.value.map do |key| { name: key, failure_count: redis.hget(key, :failure_count) } end - result.merge(storage_name => info_for_storage) + info_for_keys[storage_name] = info_for_storage end end diff --git a/spec/lib/gitlab/git/storage/health_spec.rb b/spec/lib/gitlab/git/storage/health_spec.rb index 28b74a0581f..2d3af387971 100644 --- a/spec/lib/gitlab/git/storage/health_spec.rb +++ b/spec/lib/gitlab/git/storage/health_spec.rb @@ -23,7 +23,9 @@ describe Gitlab::Git::Storage::Health, clean_gitlab_redis_shared_state: true, br describe '.load_for_keys' do let(:subject) do results = Gitlab::Git::Storage.redis.with do |redis| - described_class.load_for_keys({ 'broken' => [host1_key] }, redis) + fake_future = double + allow(fake_future).to receive(:value).and_return([host1_key]) + described_class.load_for_keys({ 'broken' => fake_future }, redis) end # Make sure the `Redis#future is loaded From 0dd4c306ca953e6d09a862f9641469340f8e822f Mon Sep 17 00:00:00 2001 From: Bob Van Landuyt Date: Thu, 3 Aug 2017 15:24:43 +0200 Subject: [PATCH 140/177] Only track accessibility once --- lib/gitlab/git/storage/circuit_breaker.rb | 22 +++++++----- .../git/storage/circuit_breaker_spec.rb | 35 +++++++++++++++++-- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/lib/gitlab/git/storage/circuit_breaker.rb b/lib/gitlab/git/storage/circuit_breaker.rb index 237b4598730..c3ef82d4e98 100644 --- a/lib/gitlab/git/storage/circuit_breaker.rb +++ b/lib/gitlab/git/storage/circuit_breaker.rb @@ -46,10 +46,6 @@ module Gitlab def perform return yield unless Feature.enabled?('git_storage_circuit_breaker') - if circuit_broken? - raise Gitlab::Git::Storage::CircuitOpen.new("Circuit for #{storage} open", failure_wait_time) - end - check_storage_accessible! yield @@ -70,14 +66,24 @@ module Gitlab # When the storage appears not available, and the memoized value is `false` # we might want to try again. def storage_available? - @storage_available ||= Gitlab::Git::Storage::ForkedStorageCheck.storage_available?(storage_path, storage_timeout) - end + return @storage_available if @storage_available - def check_storage_accessible! - if storage_available? + if @storage_available = Gitlab::Git::Storage::ForkedStorageCheck + .storage_available?(storage_path, storage_timeout) track_storage_accessible else track_storage_inaccessible + end + + @storage_available + end + + def check_storage_accessible! + if circuit_broken? + raise Gitlab::Git::Storage::CircuitOpen.new("Circuit for #{storage} is broken", failure_wait_time) + end + + unless storage_available? raise Gitlab::Git::Storage::Inaccessible.new("#{storage} not accessible", failure_wait_time) end end diff --git a/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb b/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb index 6fab224ad0d..b2886628601 100644 --- a/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb +++ b/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb @@ -120,19 +120,48 @@ describe Gitlab::Git::Storage::CircuitBreaker, clean_gitlab_redis_shared_state: end end - describe '#check_storage_accessible!' do + describe "storage_available?" do context 'when the storage is available' do it 'tracks that the storage was accessible an raises the error' do expect(circuit_breaker).to receive(:track_storage_accessible) - circuit_breaker.check_storage_accessible! + circuit_breaker.storage_available? + end + + it 'only performs the check once' do + expect(Gitlab::Git::Storage::ForkedStorageCheck) + .to receive(:storage_available?).once.and_call_original + + 2.times { circuit_breaker.storage_available? } + end + end + + context 'when storage is not available' do + let(:circuit_breaker) { described_class.new('broken') } + + it 'tracks that the storage was inaccessible' do + expect(circuit_breaker).to receive(:track_storage_inaccessible) + + circuit_breaker.storage_available? + end + end + end + + describe '#check_storage_accessible!' do + it 'raises an exception with retry time when the circuit is open' do + allow(circuit_breaker).to receive(:circuit_broken?).and_return(true) + + expect { circuit_breaker.check_storage_accessible! } + .to raise_error do |exception| + expect(exception).to be_kind_of(Gitlab::Git::Storage::CircuitOpen) + expect(exception.retry_after).to eq(30) end end context 'when the storage is not available' do let(:circuit_breaker) { described_class.new('broken') } - it 'tracks that the storage was unavailable and raises an error with retry time' do + it 'raises an error' do expect(circuit_breaker).to receive(:track_storage_inaccessible) expect { circuit_breaker.check_storage_accessible! } From 3a2aaed881f8925b08acd4204f3e130939c73946 Mon Sep 17 00:00:00 2001 From: Bob Van Landuyt Date: Thu, 3 Aug 2017 15:50:16 +0200 Subject: [PATCH 141/177] Use a Struct to keep track of failure info --- lib/gitlab/git/storage/circuit_breaker.rb | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/lib/gitlab/git/storage/circuit_breaker.rb b/lib/gitlab/git/storage/circuit_breaker.rb index c3ef82d4e98..9ea9367d4b7 100644 --- a/lib/gitlab/git/storage/circuit_breaker.rb +++ b/lib/gitlab/git/storage/circuit_breaker.rb @@ -2,6 +2,8 @@ module Gitlab module Git module Storage class CircuitBreaker + FailureInfo = Struct.new(:last_failure, :failure_count) + attr_reader :storage, :hostname, :storage_path, @@ -10,6 +12,8 @@ module Gitlab :failure_reset_time, :storage_timeout + delegate :last_failure, :failure_count, to: :failure_info + def self.reset_all! pattern = "#{Gitlab::Git::Storage::REDIS_KEY_PREFIX}*" @@ -93,7 +97,7 @@ module Gitlab end def track_storage_inaccessible - @failure_info = [Time.now, failure_count + 1] + @failure_info = FailureInfo.new(Time.now, failure_count + 1) Gitlab::Git::Storage.redis.with do |redis| redis.pipelined do @@ -107,7 +111,7 @@ module Gitlab def track_storage_accessible return if no_failures? - @failure_info = [nil, 0] + @failure_info = FailureInfo.new(nil, 0) Gitlab::Git::Storage.redis.with do |redis| redis.pipelined do @@ -117,14 +121,6 @@ module Gitlab end end - def last_failure - failure_info.first - end - - def failure_count - failure_info.last - end - def failure_info @failure_info ||= get_failure_info end @@ -136,7 +132,7 @@ module Gitlab last_failure = Time.at(last_failure.to_i) if last_failure.present? - [last_failure, failure_count.to_i] + FailureInfo.new(last_failure, failure_count.to_i) end def cache_key From 4b34720c0ca8b5459cc56a4e52e11e213ab6ae9a Mon Sep 17 00:00:00 2001 From: Bob Van Landuyt Date: Thu, 3 Aug 2017 16:22:52 +0200 Subject: [PATCH 142/177] Use ruby's `File.stat` to check storage availability --- .../git/storage/forked_storage_check.rb | 34 ++++++++----------- .../git/storage/forked_storage_check_spec.rb | 15 ++++++-- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/lib/gitlab/git/storage/forked_storage_check.rb b/lib/gitlab/git/storage/forked_storage_check.rb index 0e9e7ba596b..91d8241f17b 100644 --- a/lib/gitlab/git/storage/forked_storage_check.rb +++ b/lib/gitlab/git/storage/forked_storage_check.rb @@ -11,7 +11,7 @@ module Gitlab end def timeout_check(path, timeout_seconds) - filesystem_check_pid = check_filesystem_in_fork(path) + filesystem_check_pid = check_filesystem_in_process(path) deadline = timeout_seconds.seconds.from_now.utc wait_time = 0.01 @@ -31,27 +31,23 @@ module Gitlab status end - # This call forks out into a process, that process will then be replaced - # With an `exec` call, since we fork out into a shell, we can create a - # child process without needing an ActiveRecord-connection. + # This will spawn a new 2 processes to do the check: + # The outer child (waiter) will spawn another child process (stater). # - # Inside the shell, we use `& wait` to fork another child. We do this - # to prevent leaving a zombie process when the parent gets killed by the - # timeout. - # - # https://stackoverflow.com/questions/27892975/what-causes-activerecord-breaking-postgres-connection-after-forking - # https://stackoverflow.com/questions/22012943/activerecordstatementinvalid-runtimeerror-the-connection-cannot-be-reused-in - def check_filesystem_in_fork(path) - fork do - STDOUT.reopen('/dev/null') - STDERR.reopen('/dev/null') - - exec("(#{test_script(path)}) & wait %1") - end + # The stater is the process is performing the actual filesystem check + # the check might hang if the filesystem is acting up. + # In this case we will send a `KILL` to the waiter, which will still + # be responsive while the stater is hanging. + def check_filesystem_in_process(path) + spawn('ruby', '-e', ruby_check, path, [:out, :err] => '/dev/null') end - def test_script(path) - "testpath=$(realpath #{Shellwords.escape(path)}) && stat \"$testpath\"" + def ruby_check + <<~RUBY_FILESYSTEM_CHECK + inner_pid = fork { File.stat(ARGV.first) } + Process.waitpid(inner_pid) + exit $?.exitstatus + RUBY_FILESYSTEM_CHECK end end end diff --git a/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb b/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb index 20cee123ede..12366151f44 100644 --- a/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb +++ b/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb @@ -17,11 +17,20 @@ describe Gitlab::Git::Storage::ForkedStorageCheck, skip_database_cleaner: true d end it 'returns false when the check takes to long' do - allow(described_class).to receive(:check_filesystem_in_fork) do - fork { sleep 10 } + # We're forking a process here that takes too long + # It will be killed it's parent process will be killed by it's parent + # and waited for inside `Gitlab::Git::Storage::ForkedStorageCheck.timeout_check` + allow(described_class).to receive(:check_filesystem_in_process) do + Process.spawn("sleep 10") + end + result = true + + runtime = Benchmark.realtime do + result = described_class.storage_available?(existing_path, 0.5) end - expect(described_class.storage_available?(existing_path, 0.5)).to be_falsey + expect(result).to be_falsey + expect(runtime).to be < 1.0 end describe 'when using paths with spaces' do From a1be8bb8afbe77814888a6c3cba6534b950f51a5 Mon Sep 17 00:00:00 2001 From: winh Date: Thu, 3 Aug 2017 14:30:35 +0200 Subject: [PATCH 143/177] Make new dropdown dividers full width --- app/assets/stylesheets/framework/dropdowns.scss | 4 ++++ app/assets/stylesheets/new_nav.scss | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index bd4bd541c3a..02e0ba74158 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -728,6 +728,10 @@ @mixin new-style-dropdown { .dropdown-menu, .dropdown-menu-nav { + .divider { + margin: 6px 0; + } + li { padding: 0 1px; diff --git a/app/assets/stylesheets/new_nav.scss b/app/assets/stylesheets/new_nav.scss index 1c4a84de7ec..795ee91af8b 100644 --- a/app/assets/stylesheets/new_nav.scss +++ b/app/assets/stylesheets/new_nav.scss @@ -312,6 +312,10 @@ header.navbar-gitlab-new { // TODO: fallback to global style .dropdown-menu { + .divider { + margin: 6px 0; + } + li { padding: 0 1px; From b7547ade672fdcb9315ae9821c1eca195d87022a Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 4 Aug 2017 21:45:14 +0800 Subject: [PATCH 144/177] Backport to CE for: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2483 --- .../boards/components/modal/index.js | 4 +- .../components/graph/graph_component.vue | 4 +- .../vue_merge_request_widget/dependencies.js | 2 +- config/application.rb | 4 +- doc/development/fe_guide/style_guide_js.md | 54 ++++++++++++------- spec/support/api/schema_matcher.rb | 18 ++++--- 6 files changed, 53 insertions(+), 33 deletions(-) diff --git a/app/assets/javascripts/boards/components/modal/index.js b/app/assets/javascripts/boards/components/modal/index.js index 1d36519c75c..96af69e7a36 100644 --- a/app/assets/javascripts/boards/components/modal/index.js +++ b/app/assets/javascripts/boards/components/modal/index.js @@ -1,8 +1,8 @@ /* global ListIssue */ import Vue from 'vue'; -import queryData from '../../utils/query_data'; -import loadingIcon from '../../../vue_shared/components/loading_icon.vue'; +import queryData from '~/boards/utils/query_data'; +import loadingIcon from '~/vue_shared/components/loading_icon.vue'; import './header'; import './list'; import './footer'; diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue index 77cbaeb43ef..66bc1d1979c 100644 --- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue +++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue @@ -1,7 +1,7 @@