summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.flayignore1
-rw-r--r--.gitignore3
-rw-r--r--.gitlab-ci.yml126
-rw-r--r--.scss-lint.yml10
-rw-r--r--CHANGELOG.md7
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--GITLAB_SHELL_VERSION2
-rw-r--r--Gemfile3
-rw-r--r--Gemfile.lock12
-rw-r--r--app/assets/images/new_nav.pngbin23771 -> 14322 bytes
-rw-r--r--app/assets/javascripts/blob/notebook/index.js3
-rw-r--r--app/assets/javascripts/boards/boards_bundle.js6
-rw-r--r--app/assets/javascripts/boards/components/board_blank_state.js5
-rw-r--r--app/assets/javascripts/boards/components/modal/index.js6
-rw-r--r--app/assets/javascripts/boards/models/list.js13
-rw-r--r--app/assets/javascripts/boards/services/board_service.js5
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_table.vue10
-rw-r--r--app/assets/javascripts/diff_notes/components/resolve_btn.js22
-rw-r--r--app/assets/javascripts/diff_notes/services/resolve.js26
-rw-r--r--app/assets/javascripts/environments/mixins/environments_mixin.js18
-rw-r--r--app/assets/javascripts/groups/index.js13
-rw-r--r--app/assets/javascripts/issue_show/components/app.vue5
-rw-r--r--app/assets/javascripts/jobs/job_details_mediator.js3
-rw-r--r--app/assets/javascripts/notes.js2
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines.vue13
-rw-r--r--app/assets/javascripts/pipelines/components/stage.vue5
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_mediatior.js8
-rw-r--r--app/assets/javascripts/sidebar/sidebar_mediator.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/field.vue5
-rw-r--r--app/assets/javascripts/vue_shared/vue_resource_interceptor.js19
-rw-r--r--app/assets/stylesheets/application.scss2
-rw-r--r--app/assets/stylesheets/framework.scss88
-rw-r--r--app/assets/stylesheets/framework/awards.scss2
-rw-r--r--app/assets/stylesheets/framework/blank.scss91
-rw-r--r--app/assets/stylesheets/framework/common.scss6
-rw-r--r--app/assets/stylesheets/framework/filters.scss4
-rw-r--r--app/assets/stylesheets/framework/highlight.scss2
-rw-r--r--app/assets/stylesheets/framework/variables.scss5
-rw-r--r--app/assets/stylesheets/highlight/white.scss8
-rw-r--r--app/assets/stylesheets/new_sidebar.scss4
-rw-r--r--app/assets/stylesheets/pages/builds.scss16
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss4
-rw-r--r--app/assets/stylesheets/pages/notes.scss2
-rw-r--r--app/assets/stylesheets/pages/pipeline_schedules.scss4
-rw-r--r--app/assets/stylesheets/pages/projects.scss4
-rw-r--r--app/assets/stylesheets/pages/todos.scss2
-rw-r--r--app/assets/stylesheets/pages/wiki.scss4
-rw-r--r--app/controllers/concerns/requires_health_token.rb25
-rw-r--r--app/controllers/concerns/requires_whitelisted_monitoring_client.rb33
-rw-r--r--app/controllers/health_check_controller.rb2
-rw-r--r--app/controllers/health_controller.rb7
-rw-r--r--app/controllers/metrics_controller.rb4
-rw-r--r--app/models/ci/runner.rb2
-rw-r--r--app/models/project.rb8
-rw-r--r--app/models/user.rb2
-rw-r--r--app/services/metrics_service.rb5
-rw-r--r--app/services/milestones/destroy_service.rb6
-rw-r--r--app/views/dashboard/projects/_blank_state_admin_welcome.html.haml18
-rw-r--r--app/views/dashboard/projects/_blank_state_welcome.html.haml18
-rw-r--r--app/views/dashboard/projects/_zero_authorized_projects.html.haml4
-rw-r--r--app/views/help/ui.html.haml2
-rw-r--r--app/views/layouts/nav/_breadcrumbs.html.haml2
-rw-r--r--app/views/layouts/nav/_new_project_sidebar.html.haml4
-rw-r--r--app/views/projects/commit/show.html.haml1
-rw-r--r--app/views/projects/new.html.haml5
-rw-r--r--app/views/projects/pipeline_schedules/index.html.haml7
-rw-r--r--app/views/projects/show.html.haml1
-rw-r--r--app/views/projects/tree/show.html.haml1
-rw-r--r--changelogs/unreleased/10085-stop-encoding-user-name.yml4
-rw-r--r--changelogs/unreleased/33580-fix-api-scoping.yml4
-rw-r--r--changelogs/unreleased/33949-deprecate-healthcheck-access-token.yml4
-rw-r--r--changelogs/unreleased/34325-reinstate-is_admin-for-user-api.yml4
-rw-r--r--changelogs/unreleased/34534-update-vue-resource.yml4
-rw-r--r--changelogs/unreleased/34729-blob.yml4
-rw-r--r--changelogs/unreleased/34858-bump-scss-lint-to-0-54-0.yml4
-rw-r--r--changelogs/unreleased/34867-remove-net-ssh-gem.yml4
-rw-r--r--changelogs/unreleased/34907-dont-show-pipeline-schedule-button-for-non-member.yml4
-rw-r--r--changelogs/unreleased/34978-remove-public-ci-favicon-ico.yml4
-rw-r--r--changelogs/unreleased/dm-encode-tree-and-blob-paths.yml5
-rw-r--r--changelogs/unreleased/enable-scss-lint-import-path.yml4
-rw-r--r--changelogs/unreleased/enable-scss-lint-property-spelling.yml4
-rw-r--r--changelogs/unreleased/enable-scss-lint-space-after-comma.yml4
-rw-r--r--changelogs/unreleased/enable-scss-lint-unnecessary-parent-reference.yml4
-rw-r--r--changelogs/unreleased/fix-n-plus-one-in-url-builder.yml4
-rw-r--r--changelogs/unreleased/issue-description-gfm.yml4
-rw-r--r--changelogs/unreleased/remove-nprogress-gleaning.yml4
-rw-r--r--changelogs/unreleased/replace_spinach_spec_browse_files.yml4
-rw-r--r--changelogs/unreleased/sh-add-mr-simple-mode.yml4
-rw-r--r--changelogs/unreleased/toggle-new-project-import-description.yml4
-rw-r--r--changelogs/unreleased/username-password-stripped-from-import-url-fix.yml4
-rw-r--r--config/README.md130
-rw-r--r--config/application.rb18
-rw-r--r--config/database.yml.mysql1
-rw-r--r--config/database.yml.postgresql1
-rw-r--r--config/gitlab.yml.example9
-rw-r--r--config/initializers/1_settings.rb7
-rw-r--r--config/initializers/7_redis.rb11
-rw-r--r--config/initializers/8_metrics.rb2
-rw-r--r--config/initializers/peek.rb2
-rw-r--r--config/initializers/session_store.rb6
-rw-r--r--config/initializers/sidekiq.rb12
-rw-r--r--config/mail_room.yml4
-rw-r--r--config/redis.cache.yml.example38
-rw-r--r--config/redis.queues.yml.example38
-rw-r--r--config/redis.shared_state.yml.example38
-rw-r--r--db/post_migrate/20170324160416_migrate_user_activities_to_users_last_activity_on.rb4
-rw-r--r--doc/administration/high_availability/redis_source.md5
-rw-r--r--doc/administration/operations/cleaning_up_redis_sessions.md6
-rw-r--r--doc/api/merge_requests.md1
-rw-r--r--doc/api/users.md2
-rw-r--r--doc/development/fe_guide/vue.md119
-rw-r--r--doc/install/installation.md10
-rw-r--r--doc/install/requirements.md2
-rw-r--r--doc/update/9.3-to-9.4.md45
-rw-r--r--doc/user/admin_area/monitoring/health_check.md26
-rw-r--r--features/project/source/browse_files.feature323
-rw-r--r--lib/api/entities.rb7
-rw-r--r--lib/api/merge_requests.rb23
-rw-r--r--lib/api/users.rb11
-rw-r--r--lib/gitlab/auth/unique_ips_limiter.rb2
-rw-r--r--lib/gitlab/cache/ci/project_pipeline_status.rb10
-rw-r--r--lib/gitlab/chat_name_token.rb14
-rw-r--r--lib/gitlab/current_settings.rb2
-rw-r--r--lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb4
-rw-r--r--lib/gitlab/etag_caching/store.rb12
-rw-r--r--lib/gitlab/exclusive_lease.rb20
-rw-r--r--lib/gitlab/health_checks/redis/cache_check.rb31
-rw-r--r--lib/gitlab/health_checks/redis/queues_check.rb31
-rw-r--r--lib/gitlab/health_checks/redis/redis_check.rb27
-rw-r--r--lib/gitlab/health_checks/redis/shared_state_check.rb31
-rw-r--r--lib/gitlab/health_checks/redis_check.rb25
-rw-r--r--lib/gitlab/lfs_token.rb8
-rw-r--r--lib/gitlab/mail_room.rb10
-rw-r--r--lib/gitlab/o_auth/user.rb10
-rw-r--r--lib/gitlab/redis.rb102
-rw-r--r--lib/gitlab/redis/cache.rb34
-rw-r--r--lib/gitlab/redis/queues.rb35
-rw-r--r--lib/gitlab/redis/shared_state.rb34
-rw-r--r--lib/gitlab/redis/wrapper.rb135
-rw-r--r--lib/gitlab/url_builder.rb8
-rw-r--r--lib/gitlab/user_activities.rb6
-rw-r--r--lib/gitlab/workhorse.rb2
-rw-r--r--lib/tasks/cache.rake4
-rw-r--r--locale/bg/gitlab.po61
-rw-r--r--locale/eo/gitlab.po61
-rw-r--r--locale/it/gitlab.po73
-rw-r--r--locale/zh_CN/gitlab.po58
-rw-r--r--locale/zh_HK/gitlab.po62
-rw-r--r--locale/zh_TW/gitlab.po62
-rw-r--r--package.json2
-rw-r--r--public/ci/favicon.icobin5430 -> 0 bytes
-rw-r--r--scripts/prepare_build.sh15
-rw-r--r--spec/config/mail_room_spec.rb22
-rw-r--r--spec/controllers/health_check_controller_spec.rb75
-rw-r--r--spec/controllers/health_controller_spec.rb103
-rw-r--r--spec/controllers/metrics_controller_spec.rb58
-rw-r--r--spec/controllers/sessions_controller_spec.rb2
-rw-r--r--spec/features/dashboard/issuables_counter_spec.rb2
-rw-r--r--spec/features/dashboard/projects_spec.rb2
-rw-r--r--spec/features/groups/members/sort_members_spec.rb4
-rw-r--r--spec/features/login_spec.rb4
-rw-r--r--spec/features/projects/members/sorting_spec.rb4
-rw-r--r--spec/features/projects/pipeline_schedules_spec.rb288
-rw-r--r--spec/features/projects/user_browses_files_spec.rb188
-rw-r--r--spec/features/projects/user_create_dir_spec.rb57
-rw-r--r--spec/features/projects/user_creates_directory_spec.rb87
-rw-r--r--spec/features/projects/user_creates_files_spec.rb153
-rw-r--r--spec/features/projects/user_deletes_files_spec.rb68
-rw-r--r--spec/features/projects/user_edits_files_spec.rb122
-rw-r--r--spec/features/projects/user_replaces_files_spec.rb87
-rw-r--r--spec/features/projects/user_uploads_files_spec.rb82
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/user/admin.json34
-rw-r--r--spec/fixtures/config/redis_cache_config_with_env.yml2
-rw-r--r--spec/fixtures/config/redis_cache_new_format_host.yml29
-rw-r--r--spec/fixtures/config/redis_cache_new_format_socket.yml6
-rw-r--r--spec/fixtures/config/redis_cache_old_format_host.yml5
-rw-r--r--spec/fixtures/config/redis_cache_old_format_socket.yml3
-rw-r--r--spec/fixtures/config/redis_new_format_host.yml12
-rw-r--r--spec/fixtures/config/redis_queues_config_with_env.yml2
-rw-r--r--spec/fixtures/config/redis_queues_new_format_host.yml29
-rw-r--r--spec/fixtures/config/redis_queues_new_format_socket.yml6
-rw-r--r--spec/fixtures/config/redis_queues_old_format_host.yml5
-rw-r--r--spec/fixtures/config/redis_queues_old_format_socket.yml3
-rw-r--r--spec/fixtures/config/redis_shared_state_config_with_env.yml2
-rw-r--r--spec/fixtures/config/redis_shared_state_new_format_host.yml29
-rw-r--r--spec/fixtures/config/redis_shared_state_new_format_socket.yml6
-rw-r--r--spec/fixtures/config/redis_shared_state_old_format_host.yml5
-rw-r--r--spec/fixtures/config/redis_shared_state_old_format_socket.yml3
-rw-r--r--spec/helpers/award_emoji_helper_spec.rb4
-rw-r--r--spec/helpers/issuables_helper_spec.rb2
-rw-r--r--spec/helpers/projects_helper_spec.rb2
-rw-r--r--spec/javascripts/environments/environment_spec.js9
-rw-r--r--spec/javascripts/environments/folder/environments_folder_view_spec.js4
-rw-r--r--spec/javascripts/helpers/vue_resource_helper.js11
-rw-r--r--spec/javascripts/issue_show/components/app_spec.js55
-rw-r--r--spec/lib/gitlab/auth/unique_ips_limiter_spec.rb2
-rw-r--r--spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb52
-rw-r--r--spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb4
-rw-r--r--spec/lib/gitlab/exclusive_lease_spec.rb2
-rw-r--r--spec/lib/gitlab/git/hook_spec.rb6
-rw-r--r--spec/lib/gitlab/health_checks/redis/cache_check_spec.rb6
-rw-r--r--spec/lib/gitlab/health_checks/redis/queues_check_spec.rb6
-rw-r--r--spec/lib/gitlab/health_checks/redis/redis_check_spec.rb6
-rw-r--r--spec/lib/gitlab/health_checks/redis/shared_state_check_spec.rb6
-rw-r--r--spec/lib/gitlab/health_checks/redis_check_spec.rb6
-rw-r--r--spec/lib/gitlab/health_checks/simple_check_shared.rb4
-rw-r--r--spec/lib/gitlab/performance_bar_spec.rb2
-rw-r--r--spec/lib/gitlab/redis/cache_spec.rb20
-rw-r--r--spec/lib/gitlab/redis/queues_spec.rb20
-rw-r--r--spec/lib/gitlab/redis/shared_state_spec.rb20
-rw-r--r--spec/lib/gitlab/redis/wrapper_spec.rb20
-rw-r--r--spec/lib/gitlab/sidekiq_status_spec.rb12
-rw-r--r--spec/lib/gitlab/user_activities_spec.rb34
-rw-r--r--spec/lib/gitlab/workhorse_spec.rb4
-rw-r--r--spec/migrations/migrate_process_commit_worker_jobs_spec.rb4
-rw-r--r--spec/migrations/migrate_user_activities_to_users_last_activity_on_spec.rb4
-rw-r--r--spec/models/ci/runner_spec.rb14
-rw-r--r--spec/models/concerns/reactive_caching_spec.rb2
-rw-r--r--spec/models/project_services/bamboo_service_spec.rb2
-rw-r--r--spec/models/project_services/buildkite_service_spec.rb2
-rw-r--r--spec/models/project_services/drone_ci_service_spec.rb2
-rw-r--r--spec/models/project_services/kubernetes_service_spec.rb2
-rw-r--r--spec/models/project_services/prometheus_service_spec.rb2
-rw-r--r--spec/models/project_services/teamcity_service_spec.rb2
-rw-r--r--spec/models/project_spec.rb2
-rw-r--r--spec/models/repository_spec.rb18
-rw-r--r--spec/models/user_spec.rb16
-rw-r--r--spec/requests/api/internal_spec.rb2
-rw-r--r--spec/requests/api/merge_requests_spec.rb16
-rw-r--r--spec/requests/api/users_spec.rb10
-rw-r--r--spec/requests/git_http_spec.rb2
-rw-r--r--spec/requests/openid_connect_spec.rb2
-rw-r--r--spec/services/event_create_service_spec.rb2
-rw-r--r--spec/services/git_push_service_spec.rb10
-rw-r--r--spec/services/milestones/destroy_service_spec.rb51
-rw-r--r--spec/services/projects/destroy_service_spec.rb4
-rw-r--r--spec/services/todo_service_spec.rb2
-rw-r--r--spec/services/users/activity_service_spec.rb2
-rw-r--r--spec/services/users/refresh_authorized_projects_service_spec.rb2
-rw-r--r--spec/spec_helper.rb25
-rw-r--r--spec/support/dropzone_helper.rb19
-rw-r--r--spec/support/redis/redis_shared_examples.rb (renamed from spec/lib/gitlab/redis_spec.rb)82
-rw-r--r--spec/support/test_env.rb1
-rw-r--r--spec/support/unique_ip_check_shared_examples.rb4
-rw-r--r--spec/workers/schedule_update_user_activity_worker_spec.rb2
-rw-r--r--spec/workers/update_user_activity_worker_spec.rb4
-rw-r--r--vendor/gitlab-ci-yml/Docker.gitlab-ci.yml19
-rw-r--r--vendor/gitlab-ci-yml/autodeploy/Kubernetes-with-canary.gitlab-ci.yml8
-rw-r--r--vendor/gitlab-ci-yml/autodeploy/Kubernetes.gitlab-ci.yml6
-rw-r--r--vendor/gitlab-ci-yml/autodeploy/OpenShift.gitlab-ci.yml12
-rw-r--r--vendor/licenses.csv560
-rw-r--r--yarn.lock102
252 files changed, 3889 insertions, 1783 deletions
diff --git a/.flayignore b/.flayignore
index 47597025115..e2d0a2e50c5 100644
--- a/.flayignore
+++ b/.flayignore
@@ -3,3 +3,4 @@ lib/gitlab/sanitizers/svg/whitelist.rb
lib/gitlab/diff/position_tracer.rb
app/policies/project_policy.rb
app/models/concerns/relative_positioning.rb
+lib/gitlab/redis/*.rb
diff --git a/.gitignore b/.gitignore
index 0d6194dd1e5..3baf640a9c3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,6 +31,9 @@ eslint-report.html
/config/initializers/smtp_settings.rb
/config/initializers/relative_url.rb
/config/resque.yml
+/config/redis.cache.yml
+/config/redis.queues.yml
+/config/redis.shared_state.yml
/config/unicorn.rb
/config/secrets.yml
/config/sidekiq.yml
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f7ab0259448..a54b38d284d 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -203,69 +203,69 @@ setup-test-env:
- public/assets
- tmp/tests
-rspec-pg 0 20: *rspec-knapsack-pg
-rspec-pg 1 20: *rspec-knapsack-pg
-rspec-pg 2 20: *rspec-knapsack-pg
-rspec-pg 3 20: *rspec-knapsack-pg
-rspec-pg 4 20: *rspec-knapsack-pg
-rspec-pg 5 20: *rspec-knapsack-pg
-rspec-pg 6 20: *rspec-knapsack-pg
-rspec-pg 7 20: *rspec-knapsack-pg
-rspec-pg 8 20: *rspec-knapsack-pg
-rspec-pg 9 20: *rspec-knapsack-pg
-rspec-pg 10 20: *rspec-knapsack-pg
-rspec-pg 11 20: *rspec-knapsack-pg
-rspec-pg 12 20: *rspec-knapsack-pg
-rspec-pg 13 20: *rspec-knapsack-pg
-rspec-pg 14 20: *rspec-knapsack-pg
-rspec-pg 15 20: *rspec-knapsack-pg
-rspec-pg 16 20: *rspec-knapsack-pg
-rspec-pg 17 20: *rspec-knapsack-pg
-rspec-pg 18 20: *rspec-knapsack-pg
-rspec-pg 19 20: *rspec-knapsack-pg
-
-rspec-mysql 0 20: *rspec-knapsack-mysql
-rspec-mysql 1 20: *rspec-knapsack-mysql
-rspec-mysql 2 20: *rspec-knapsack-mysql
-rspec-mysql 3 20: *rspec-knapsack-mysql
-rspec-mysql 4 20: *rspec-knapsack-mysql
-rspec-mysql 5 20: *rspec-knapsack-mysql
-rspec-mysql 6 20: *rspec-knapsack-mysql
-rspec-mysql 7 20: *rspec-knapsack-mysql
-rspec-mysql 8 20: *rspec-knapsack-mysql
-rspec-mysql 9 20: *rspec-knapsack-mysql
-rspec-mysql 10 20: *rspec-knapsack-mysql
-rspec-mysql 11 20: *rspec-knapsack-mysql
-rspec-mysql 12 20: *rspec-knapsack-mysql
-rspec-mysql 13 20: *rspec-knapsack-mysql
-rspec-mysql 14 20: *rspec-knapsack-mysql
-rspec-mysql 15 20: *rspec-knapsack-mysql
-rspec-mysql 16 20: *rspec-knapsack-mysql
-rspec-mysql 17 20: *rspec-knapsack-mysql
-rspec-mysql 18 20: *rspec-knapsack-mysql
-rspec-mysql 19 20: *rspec-knapsack-mysql
-
-spinach-pg 0 10: *spinach-knapsack-pg
-spinach-pg 1 10: *spinach-knapsack-pg
-spinach-pg 2 10: *spinach-knapsack-pg
-spinach-pg 3 10: *spinach-knapsack-pg
-spinach-pg 4 10: *spinach-knapsack-pg
-spinach-pg 5 10: *spinach-knapsack-pg
-spinach-pg 6 10: *spinach-knapsack-pg
-spinach-pg 7 10: *spinach-knapsack-pg
-spinach-pg 8 10: *spinach-knapsack-pg
-spinach-pg 9 10: *spinach-knapsack-pg
-
-spinach-mysql 0 10: *spinach-knapsack-mysql
-spinach-mysql 1 10: *spinach-knapsack-mysql
-spinach-mysql 2 10: *spinach-knapsack-mysql
-spinach-mysql 3 10: *spinach-knapsack-mysql
-spinach-mysql 4 10: *spinach-knapsack-mysql
-spinach-mysql 5 10: *spinach-knapsack-mysql
-spinach-mysql 6 10: *spinach-knapsack-mysql
-spinach-mysql 7 10: *spinach-knapsack-mysql
-spinach-mysql 8 10: *spinach-knapsack-mysql
-spinach-mysql 9 10: *spinach-knapsack-mysql
+rspec-pg 0 25: *rspec-knapsack-pg
+rspec-pg 1 25: *rspec-knapsack-pg
+rspec-pg 2 25: *rspec-knapsack-pg
+rspec-pg 3 25: *rspec-knapsack-pg
+rspec-pg 4 25: *rspec-knapsack-pg
+rspec-pg 5 25: *rspec-knapsack-pg
+rspec-pg 6 25: *rspec-knapsack-pg
+rspec-pg 7 25: *rspec-knapsack-pg
+rspec-pg 8 25: *rspec-knapsack-pg
+rspec-pg 9 25: *rspec-knapsack-pg
+rspec-pg 10 25: *rspec-knapsack-pg
+rspec-pg 11 25: *rspec-knapsack-pg
+rspec-pg 12 25: *rspec-knapsack-pg
+rspec-pg 13 25: *rspec-knapsack-pg
+rspec-pg 14 25: *rspec-knapsack-pg
+rspec-pg 15 25: *rspec-knapsack-pg
+rspec-pg 16 25: *rspec-knapsack-pg
+rspec-pg 17 25: *rspec-knapsack-pg
+rspec-pg 18 25: *rspec-knapsack-pg
+rspec-pg 19 25: *rspec-knapsack-pg
+rspec-pg 20 25: *rspec-knapsack-pg
+rspec-pg 21 25: *rspec-knapsack-pg
+rspec-pg 22 25: *rspec-knapsack-pg
+rspec-pg 23 25: *rspec-knapsack-pg
+rspec-pg 24 25: *rspec-knapsack-pg
+
+rspec-mysql 0 25: *rspec-knapsack-mysql
+rspec-mysql 1 25: *rspec-knapsack-mysql
+rspec-mysql 2 25: *rspec-knapsack-mysql
+rspec-mysql 3 25: *rspec-knapsack-mysql
+rspec-mysql 4 25: *rspec-knapsack-mysql
+rspec-mysql 5 25: *rspec-knapsack-mysql
+rspec-mysql 6 25: *rspec-knapsack-mysql
+rspec-mysql 7 25: *rspec-knapsack-mysql
+rspec-mysql 8 25: *rspec-knapsack-mysql
+rspec-mysql 9 25: *rspec-knapsack-mysql
+rspec-mysql 10 25: *rspec-knapsack-mysql
+rspec-mysql 11 25: *rspec-knapsack-mysql
+rspec-mysql 12 25: *rspec-knapsack-mysql
+rspec-mysql 13 25: *rspec-knapsack-mysql
+rspec-mysql 14 25: *rspec-knapsack-mysql
+rspec-mysql 15 25: *rspec-knapsack-mysql
+rspec-mysql 16 25: *rspec-knapsack-mysql
+rspec-mysql 17 25: *rspec-knapsack-mysql
+rspec-mysql 18 25: *rspec-knapsack-mysql
+rspec-mysql 19 25: *rspec-knapsack-mysql
+rspec-mysql 20 25: *rspec-knapsack-mysql
+rspec-mysql 21 25: *rspec-knapsack-mysql
+rspec-mysql 22 25: *rspec-knapsack-mysql
+rspec-mysql 23 25: *rspec-knapsack-mysql
+rspec-mysql 24 25: *rspec-knapsack-mysql
+
+spinach-pg 0 5: *spinach-knapsack-pg
+spinach-pg 1 5: *spinach-knapsack-pg
+spinach-pg 2 5: *spinach-knapsack-pg
+spinach-pg 3 5: *spinach-knapsack-pg
+spinach-pg 4 5: *spinach-knapsack-pg
+
+spinach-mysql 0 5: *spinach-knapsack-mysql
+spinach-mysql 1 5: *spinach-knapsack-mysql
+spinach-mysql 2 5: *spinach-knapsack-mysql
+spinach-mysql 3 5: *spinach-knapsack-mysql
+spinach-mysql 4 5: *spinach-knapsack-mysql
# Static analysis jobs
.ruby-static-analysis: &ruby-static-analysis
diff --git a/.scss-lint.yml b/.scss-lint.yml
index db234ad739c..2326a8a8c65 100644
--- a/.scss-lint.yml
+++ b/.scss-lint.yml
@@ -93,7 +93,7 @@ linters:
# The basenames of @imported SCSS partials should not begin with an
# underscore and should not include the filename extension.
ImportPath:
- enabled: false
+ enabled: true
# Avoid using !important in properties. It is usually indicative of a
# misunderstanding of CSS specificity and can lead to brittle code.
@@ -133,7 +133,7 @@ linters:
# Reports when you use an unknown or disabled CSS property
# (ignoring vendor-prefixed properties).
PropertySpelling:
- enabled: false
+ enabled: true
# Configure which units are allowed for property values.
PropertyUnits:
@@ -176,6 +176,10 @@ linters:
# Commas in lists should be followed by a space.
SpaceAfterComma:
+ enabled: true
+
+ # Comment literals should be followed by a space.
+ SpaceAfterComment:
enabled: false
# Properties should be formatted with a single space separating the colon
@@ -240,7 +244,7 @@ linters:
# Do not use parent selector references (&) when they would otherwise
# be unnecessary.
UnnecessaryParentReference:
- enabled: false
+ enabled: true
# URLs should be valid and not contain protocols or domain names.
UrlFormat:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c15a59d25d4..c181aba0205 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,13 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 9.3.6 (2017-07-12)
+
+- Fix API Scoping. !12300
+- Username and password are no longer stripped from import url on mirror update. !12725
+- Fix issues with non-UTF8 filenames by always fixing the encoding of tree and blob paths.
+- Fixed GFM references not being included when updating issues inline.
+
## 9.3.5 (2017-07-05)
- Remove "Remove from board" button from backlog and closed list. !12430
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 04a373efe6b..c5523bd09b1 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-0.16.0
+0.17.0
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index ac14c3dfaa8..e230c8396d1 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-5.1.1
+5.3.0 \ No newline at end of file
diff --git a/Gemfile b/Gemfile
index 233a50c6e47..0eeb5807d04 100644
--- a/Gemfile
+++ b/Gemfile
@@ -250,7 +250,6 @@ gem 'jquery-rails', '~> 4.1.0'
gem 'request_store', '~> 1.3'
gem 'select2-rails', '~> 3.5.9'
gem 'virtus', '~> 1.0.1'
-gem 'net-ssh', '~> 3.0.1'
gem 'base32', '~> 0.3.0'
# Sentry integration
@@ -335,7 +334,7 @@ group :development, :test do
gem 'rubocop', '~> 0.47.1', require: false
gem 'rubocop-rspec', '~> 1.15.0', require: false
- gem 'scss_lint', '~> 0.47.0', require: false
+ gem 'scss_lint', '~> 0.54.0', require: false
gem 'haml_lint', '~> 0.21.0', require: false
gem 'simplecov', '~> 0.14.0', require: false
gem 'flay', '~> 2.8.0', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index deaf3ded2f9..c27c06e9c34 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -472,7 +472,6 @@ GEM
mustermann (= 0.4.0)
mysql2 (0.3.20)
net-ldap (0.12.1)
- net-ssh (3.0.1)
netrc (0.11.0)
nokogiri (1.6.8.1)
mini_portile2 (~> 2.1.0)
@@ -763,9 +762,9 @@ GEM
sawyer (0.8.1)
addressable (>= 2.3.5, < 2.6)
faraday (~> 0.8, < 1.0)
- scss_lint (0.47.1)
- rake (>= 0.9, < 11)
- sass (~> 3.4.15)
+ scss_lint (0.54.0)
+ rake (>= 0.9, < 13)
+ sass (~> 3.4.20)
securecompare (1.0.0)
seed-fu (2.3.6)
activerecord (>= 3.1)
@@ -780,7 +779,7 @@ GEM
rack
shoulda-matchers (2.8.0)
activesupport (>= 3.0.0)
- sidekiq (5.0.0)
+ sidekiq (5.0.4)
concurrent-ruby (~> 1.0)
connection_pool (~> 2.2, >= 2.2.0)
rack-protection (>= 1.5.0)
@@ -1013,7 +1012,6 @@ DEPENDENCIES
minitest (~> 5.7.0)
mousetrap-rails (~> 1.4.6)
mysql2 (~> 0.3.16)
- net-ssh (~> 3.0.1)
nokogiri (~> 1.6.7, >= 1.6.7.2)
oauth2 (~> 1.4)
octokit (~> 4.6.2)
@@ -1083,7 +1081,7 @@ DEPENDENCIES
rugged (~> 0.25.1.1)
sanitize (~> 2.0)
sass-rails (~> 5.0.6)
- scss_lint (~> 0.47.0)
+ scss_lint (~> 0.54.0)
seed-fu (~> 2.3.5)
select2-rails (~> 3.5.9)
sentry-raven (~> 2.5.3)
diff --git a/app/assets/images/new_nav.png b/app/assets/images/new_nav.png
index 8879d26d341..f98ca15d787 100644
--- a/app/assets/images/new_nav.png
+++ b/app/assets/images/new_nav.png
Binary files differ
diff --git a/app/assets/javascripts/blob/notebook/index.js b/app/assets/javascripts/blob/notebook/index.js
index 36fe8a7184f..27312d718b0 100644
--- a/app/assets/javascripts/blob/notebook/index.js
+++ b/app/assets/javascripts/blob/notebook/index.js
@@ -51,8 +51,9 @@ export default () => {
methods: {
loadFile() {
this.$http.get(el.dataset.endpoint)
+ .then(response => response.json())
.then((res) => {
- this.json = res.json();
+ this.json = res;
this.loading = false;
})
.catch((e) => {
diff --git a/app/assets/javascripts/boards/boards_bundle.js b/app/assets/javascripts/boards/boards_bundle.js
index b94009ee76b..88b054b76e6 100644
--- a/app/assets/javascripts/boards/boards_bundle.js
+++ b/app/assets/javascripts/boards/boards_bundle.js
@@ -81,8 +81,9 @@ $(() => {
mounted () {
Store.disabled = this.disabled;
gl.boardService.all()
+ .then(response => response.json())
.then((resp) => {
- resp.json().forEach((board) => {
+ resp.forEach((board) => {
const list = Store.addList(board, this.defaultAvatar);
if (list.type === 'closed') {
@@ -97,7 +98,8 @@ $(() => {
Store.addBlankState();
this.loading = false;
- }).catch(() => new Flash('An error occurred. Please try again.'));
+ })
+ .catch(() => new Flash('An error occurred. Please try again.'));
},
methods: {
updateTokens() {
diff --git a/app/assets/javascripts/boards/components/board_blank_state.js b/app/assets/javascripts/boards/components/board_blank_state.js
index 870e115bd1a..e7f16899362 100644
--- a/app/assets/javascripts/boards/components/board_blank_state.js
+++ b/app/assets/javascripts/boards/components/board_blank_state.js
@@ -64,8 +64,9 @@ export default {
// Save the labels
gl.boardService.generateDefaultLists()
- .then((resp) => {
- resp.json().forEach((listObj) => {
+ .then(resp => resp.json())
+ .then((data) => {
+ data.forEach((listObj) => {
const list = Store.findList('title', listObj.title);
list.id = listObj.id;
diff --git a/app/assets/javascripts/boards/components/modal/index.js b/app/assets/javascripts/boards/components/modal/index.js
index 6356c266ee2..1d36519c75c 100644
--- a/app/assets/javascripts/boards/components/modal/index.js
+++ b/app/assets/javascripts/boards/components/modal/index.js
@@ -88,9 +88,9 @@ gl.issueBoards.IssuesModal = Vue.extend({
return gl.boardService.getBacklog(queryData(this.filter.path, {
page: this.page,
per: this.perPage,
- })).then((res) => {
- const data = res.json();
-
+ }))
+ .then(resp => resp.json())
+ .then((data) => {
if (clearIssues) {
this.issues = [];
}
diff --git a/app/assets/javascripts/boards/models/list.js b/app/assets/javascripts/boards/models/list.js
index b4b09b3876e..08f7c5ddcd2 100644
--- a/app/assets/javascripts/boards/models/list.js
+++ b/app/assets/javascripts/boards/models/list.js
@@ -40,9 +40,8 @@ class List {
save () {
return gl.boardService.createList(this.label.id)
- .then((resp) => {
- const data = resp.json();
-
+ .then(resp => resp.json())
+ .then((data) => {
this.id = data.id;
this.type = data.list_type;
this.position = data.position;
@@ -91,8 +90,8 @@ class List {
}
return gl.boardService.getIssuesForList(this.id, data)
- .then((resp) => {
- const data = resp.json();
+ .then(resp => resp.json())
+ .then((data) => {
this.loading = false;
this.issuesSize = data.size;
@@ -109,8 +108,8 @@ class List {
this.issuesSize += 1;
return gl.boardService.newIssue(this.id, issue)
- .then((resp) => {
- const data = resp.json();
+ .then(resp => resp.json())
+ .then((data) => {
issue.id = data.iid;
if (this.issuesSize > 1) {
diff --git a/app/assets/javascripts/boards/services/board_service.js b/app/assets/javascripts/boards/services/board_service.js
index db9bced2f89..3742507b236 100644
--- a/app/assets/javascripts/boards/services/board_service.js
+++ b/app/assets/javascripts/boards/services/board_service.js
@@ -23,11 +23,6 @@ class BoardService {
url: bulkUpdatePath,
},
});
-
- Vue.http.interceptors.push((request, next) => {
- request.headers['X-CSRF-Token'] = $.rails.csrfToken();
- next();
- });
}
all () {
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.vue b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
index 3c77f14d533..6d31b78b36d 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_table.vue
+++ b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
@@ -51,11 +51,11 @@
},
methods: {
successCallback(resp) {
- const response = resp.json();
-
- // depending of the endpoint the response can either bring a `pipelines` key or not.
- const pipelines = response.pipelines || response;
- this.setCommonData(pipelines);
+ return resp.json().then((response) => {
+ // depending of the endpoint the response can either bring a `pipelines` key or not.
+ const pipelines = response.pipelines || response;
+ this.setCommonData(pipelines);
+ });
},
},
};
diff --git a/app/assets/javascripts/diff_notes/components/resolve_btn.js b/app/assets/javascripts/diff_notes/components/resolve_btn.js
index 9d51fb53eb2..efb6ced9f46 100644
--- a/app/assets/javascripts/diff_notes/components/resolve_btn.js
+++ b/app/assets/javascripts/diff_notes/components/resolve_btn.js
@@ -1,4 +1,4 @@
-/* eslint-disable comma-dangle, object-shorthand, func-names, quote-props, no-else-return, camelcase, no-new, max-len */
+/* eslint-disable comma-dangle, object-shorthand, func-names, quote-props, no-else-return, camelcase, max-len */
/* global CommentsStore */
/* global ResolveService */
/* global Flash */
@@ -64,8 +64,6 @@ const ResolveBtn = Vue.extend({
});
},
resolve: function () {
- const errorFlashMsg = 'An error occurred when trying to resolve a comment. Please try again.';
-
if (!this.canResolve) return;
let promise;
@@ -79,24 +77,20 @@ const ResolveBtn = Vue.extend({
.resolve(this.noteId);
}
- promise.then((response) => {
- this.loading = false;
+ promise
+ .then(resp => resp.json())
+ .then((data) => {
+ this.loading = false;
- if (response.status === 200) {
- const data = response.json();
const resolved_by = data ? data.resolved_by : null;
CommentsStore.update(this.discussionId, this.noteId, !this.isResolved, resolved_by);
this.discussion.updateHeadline(data);
gl.mrWidget.checkStatus();
- } else {
- new Flash(errorFlashMsg);
- }
- this.updateTooltip();
- }).catch(() => {
- new Flash(errorFlashMsg);
- });
+ this.updateTooltip();
+ })
+ .catch(() => new Flash('An error occurred when trying to resolve a comment. Please try again.'));
}
},
mounted: function () {
diff --git a/app/assets/javascripts/diff_notes/services/resolve.js b/app/assets/javascripts/diff_notes/services/resolve.js
index 807ab11d292..2f063f6fe1f 100644
--- a/app/assets/javascripts/diff_notes/services/resolve.js
+++ b/app/assets/javascripts/diff_notes/services/resolve.js
@@ -1,4 +1,3 @@
-/* eslint-disable class-methods-use-this, one-var, camelcase, no-new, comma-dangle, no-param-reassign, max-len */
/* global Flash */
/* global CommentsStore */
@@ -32,27 +31,22 @@ class ResolveServiceClass {
promise = this.resolveAll(mergeRequestId, discussionId);
}
- promise.then((response) => {
- discussion.loading = false;
-
- if (response.status === 200) {
- const data = response.json();
- const resolved_by = data ? data.resolved_by : null;
+ promise
+ .then(resp => resp.json())
+ .then((data) => {
+ discussion.loading = false;
+ const resolvedBy = data ? data.resolved_by : null;
if (isResolved) {
discussion.unResolveAllNotes();
} else {
- discussion.resolveAllNotes(resolved_by);
+ discussion.resolveAllNotes(resolvedBy);
}
gl.mrWidget.checkStatus();
discussion.updateHeadline(data);
- } else {
- throw new Error('An error occurred when trying to resolve discussion.');
- }
- }).catch(() => {
- new Flash('An error occurred when trying to resolve a discussion. Please try again.');
- });
+ })
+ .catch(() => new Flash('An error occurred when trying to resolve a discussion. Please try again.'));
}
resolveAll(mergeRequestId, discussionId) {
@@ -62,7 +56,7 @@ class ResolveServiceClass {
return this.discussionResource.save({
mergeRequestId,
- discussionId
+ discussionId,
}, {});
}
@@ -73,7 +67,7 @@ class ResolveServiceClass {
return this.discussionResource.delete({
mergeRequestId,
- discussionId
+ discussionId,
}, {});
}
}
diff --git a/app/assets/javascripts/environments/mixins/environments_mixin.js b/app/assets/javascripts/environments/mixins/environments_mixin.js
index 25b24fbd6dc..8f4066e3a6e 100644
--- a/app/assets/javascripts/environments/mixins/environments_mixin.js
+++ b/app/assets/javascripts/environments/mixins/environments_mixin.js
@@ -1,17 +1,15 @@
export default {
methods: {
saveData(resp) {
- const response = {
- headers: resp.headers,
- body: resp.json(),
- };
+ const headers = resp.headers;
+ return resp.json().then((response) => {
+ this.isLoading = false;
- this.isLoading = false;
-
- this.store.storeAvailableCount(response.body.available_count);
- this.store.storeStoppedCount(response.body.stopped_count);
- this.store.storeEnvironments(response.body.environments);
- this.store.setPagination(response.headers);
+ this.store.storeAvailableCount(response.available_count);
+ this.store.storeStoppedCount(response.stopped_count);
+ this.store.storeEnvironments(response.environments);
+ this.store.setPagination(headers);
+ });
},
},
};
diff --git a/app/assets/javascripts/groups/index.js b/app/assets/javascripts/groups/index.js
index ff601db2aa6..00e1bd94c9c 100644
--- a/app/assets/javascripts/groups/index.js
+++ b/app/assets/javascripts/groups/index.js
@@ -99,8 +99,10 @@ document.addEventListener('DOMContentLoaded', () => {
page: currentPath,
}, document.title, currentPath);
- this.updateGroups(response.json());
- this.updatePagination(response.headers);
+ return response.json().then((data) => {
+ this.updateGroups(data);
+ this.updatePagination(response.headers);
+ });
})
.catch(this.handleErrorResponse);
},
@@ -114,18 +116,19 @@ document.addEventListener('DOMContentLoaded', () => {
},
leaveGroup(group, collection) {
this.service.leaveGroup(group.leavePath)
+ .then(resp => resp.json())
.then((response) => {
$.scrollTo(0);
this.store.removeGroup(group, collection);
// eslint-disable-next-line no-new
- new Flash(response.json().notice, 'notice');
+ new Flash(response.notice, 'notice');
})
- .catch((response) => {
+ .catch((error) => {
let message = 'An error occurred. Please try again.';
- if (response.status === 403) {
+ if (error.status === 403) {
message = 'Failed to leave the group. Please make sure you are not the only owner';
}
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue
index 3d5fb7f441c..efae112923d 100644
--- a/app/assets/javascripts/issue_show/components/app.vue
+++ b/app/assets/javascripts/issue_show/components/app.vue
@@ -202,10 +202,7 @@ export default {
this.poll = new Poll({
resource: this.service,
method: 'getData',
- successCallback: (res) => {
- const data = res.json();
- this.store.updateState(data);
- },
+ successCallback: res => res.json().then(data => this.store.updateState(data)),
errorCallback(err) {
throw new Error(err);
},
diff --git a/app/assets/javascripts/jobs/job_details_mediator.js b/app/assets/javascripts/jobs/job_details_mediator.js
index 063c52fac74..cc014b815c4 100644
--- a/app/assets/javascripts/jobs/job_details_mediator.js
+++ b/app/assets/javascripts/jobs/job_details_mediator.js
@@ -54,9 +54,8 @@ export default class JobMediator {
}
successCallback(response) {
- const data = response.json();
this.state.isLoading = false;
- this.store.storeJob(data);
+ return response.json().then(data => this.store.storeJob(data));
}
errorCallback() {
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 1a68c5bca00..b2c503d1656 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -1270,7 +1270,7 @@ export default class Notes {
<div class="timeline-entry-inner">
<div class="timeline-icon">
<a href="/${currentUsername}">
- <img class="avatar s40" src="${currentUserAvatar}">
+ <img class="avatar s40" src="${currentUserAvatar}" />
</a>
</div>
<div class="timeline-content ${discussionClass}">
diff --git a/app/assets/javascripts/pipelines/components/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines.vue
index 01ae07aad65..5df317a76bf 100644
--- a/app/assets/javascripts/pipelines/components/pipelines.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines.vue
@@ -129,14 +129,11 @@
},
successCallback(resp) {
- const response = {
- headers: resp.headers,
- body: resp.json(),
- };
-
- this.store.storeCount(response.body.count);
- this.store.storePagination(response.headers);
- this.setCommonData(response.body.pipelines);
+ return resp.json().then((response) => {
+ this.store.storeCount(response.count);
+ this.store.storePagination(resp.headers);
+ this.setCommonData(response.pipelines);
+ });
},
},
};
diff --git a/app/assets/javascripts/pipelines/components/stage.vue b/app/assets/javascripts/pipelines/components/stage.vue
index 87b2725a045..a4a27247406 100644
--- a/app/assets/javascripts/pipelines/components/stage.vue
+++ b/app/assets/javascripts/pipelines/components/stage.vue
@@ -73,8 +73,9 @@ export default {
fetchJobs() {
this.$http.get(this.stage.dropdown_path)
- .then((response) => {
- this.dropdownContent = response.json().html;
+ .then(response => response.json())
+ .then((data) => {
+ this.dropdownContent = data.html;
this.isLoading = false;
})
.catch(() => {
diff --git a/app/assets/javascripts/pipelines/pipeline_details_mediatior.js b/app/assets/javascripts/pipelines/pipeline_details_mediatior.js
index 82537ea06f5..385e7430a7d 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_mediatior.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_mediatior.js
@@ -40,10 +40,10 @@ export default class pipelinesMediator {
}
successCallback(response) {
- const data = response.json();
-
- this.state.isLoading = false;
- this.store.storePipeline(data);
+ return response.json().then((data) => {
+ this.state.isLoading = false;
+ this.store.storePipeline(data);
+ });
}
errorCallback() {
diff --git a/app/assets/javascripts/sidebar/sidebar_mediator.js b/app/assets/javascripts/sidebar/sidebar_mediator.js
index 5ccfb4ee9c1..721e92221cf 100644
--- a/app/assets/javascripts/sidebar/sidebar_mediator.js
+++ b/app/assets/javascripts/sidebar/sidebar_mediator.js
@@ -28,8 +28,8 @@ export default class SidebarMediator {
fetch() {
this.service.get()
- .then((response) => {
- const data = response.json();
+ .then(response => response.json())
+ .then((data) => {
this.store.setAssigneeData(data);
this.store.setTimeTrackingData(data);
})
diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue
index 8303c556f64..4e10bbc7408 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/field.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue
@@ -44,9 +44,8 @@
text: this.$slots.textarea[0].elm.value,
},
)
- .then((res) => {
- const data = res.json();
-
+ .then(resp => resp.json())
+ .then((data) => {
this.markdownPreviewLoading = false;
this.markdownPreview = data.body;
diff --git a/app/assets/javascripts/vue_shared/vue_resource_interceptor.js b/app/assets/javascripts/vue_shared/vue_resource_interceptor.js
index 740930dce5b..7f8e514fda1 100644
--- a/app/assets/javascripts/vue_shared/vue_resource_interceptor.js
+++ b/app/assets/javascripts/vue_shared/vue_resource_interceptor.js
@@ -14,11 +14,22 @@ Vue.http.interceptors.push((request, next) => {
});
});
-// Inject CSRF token so we don't break any tests.
+// Inject CSRF token and parse headers.
+// New Vue Resource version uses Headers, we are expecting a plain object to render pagination
+// and polling.
Vue.http.interceptors.push((request, next) => {
if ($.rails) {
- // eslint-disable-next-line no-param-reassign
- request.headers['X-CSRF-Token'] = $.rails.csrfToken();
+ request.headers.set('X-CSRF-Token', $.rails.csrfToken());
}
- next();
+
+ next((response) => {
+ // Headers object has a `forEach` property that iterates through all values.
+ const headers = {};
+
+ response.headers.forEach((value, key) => {
+ headers[key] = value;
+ });
+ // eslint-disable-next-line no-param-reassign
+ response.headers = headers;
+ });
});
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
index 83a8eeaafde..0665622fe4a 100644
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -42,4 +42,4 @@
/*
* Styles for JS behaviors.
*/
-@import "behaviors.scss";
+@import "behaviors";
diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss
index 9dc9f9a9068..6ce331a9129 100644
--- a/app/assets/stylesheets/framework.scss
+++ b/app/assets/stylesheets/framework.scss
@@ -4,49 +4,49 @@
@import 'framework/tw_bootstrap';
@import "framework/layout";
-@import "framework/animations.scss";
-@import "framework/avatar.scss";
-@import "framework/asciidoctor.scss";
-@import "framework/blocks.scss";
-@import "framework/buttons.scss";
-@import "framework/badges.scss";
-@import "framework/calendar.scss";
-@import "framework/callout.scss";
-@import "framework/common.scss";
-@import "framework/dropdowns.scss";
-@import "framework/files.scss";
-@import "framework/filters.scss";
-@import "framework/flash.scss";
-@import "framework/forms.scss";
-@import "framework/gfm.scss";
-@import "framework/header.scss";
-@import "framework/highlight.scss";
-@import "framework/issue_box.scss";
-@import "framework/jquery.scss";
-@import "framework/lists.scss";
-@import "framework/logo.scss";
-@import "framework/markdown_area.scss";
-@import "framework/mobile.scss";
-@import "framework/modal.scss";
-@import "framework/nav.scss";
-@import "framework/pagination.scss";
-@import "framework/panels.scss";
-@import "framework/selects.scss";
-@import "framework/sidebar.scss";
-@import "framework/tables.scss";
-@import "framework/notes.scss";
-@import "framework/timeline.scss";
-@import "framework/typography.scss";
-@import "framework/zen.scss";
+@import "framework/animations";
+@import "framework/avatar";
+@import "framework/asciidoctor";
+@import "framework/blocks";
+@import "framework/buttons";
+@import "framework/badges";
+@import "framework/calendar";
+@import "framework/callout";
+@import "framework/common";
+@import "framework/dropdowns";
+@import "framework/files";
+@import "framework/filters";
+@import "framework/flash";
+@import "framework/forms";
+@import "framework/gfm";
+@import "framework/header";
+@import "framework/highlight";
+@import "framework/issue_box";
+@import "framework/jquery";
+@import "framework/lists";
+@import "framework/logo";
+@import "framework/markdown_area";
+@import "framework/mobile";
+@import "framework/modal";
+@import "framework/nav";
+@import "framework/pagination";
+@import "framework/panels";
+@import "framework/selects";
+@import "framework/sidebar";
+@import "framework/tables";
+@import "framework/notes";
+@import "framework/timeline";
+@import "framework/typography";
+@import "framework/zen";
@import "framework/blank";
-@import "framework/wells.scss";
-@import "framework/page-header.scss";
-@import "framework/awards.scss";
-@import "framework/images.scss";
+@import "framework/wells";
+@import "framework/page-header";
+@import "framework/awards";
+@import "framework/images";
@import "framework/broadcast-messages";
-@import "framework/emojis.scss";
-@import "framework/emoji-sprites.scss";
-@import "framework/icons.scss";
-@import "framework/snippets.scss";
-@import "framework/memory_graph.scss";
-@import "framework/responsive-tables.scss";
+@import "framework/emojis";
+@import "framework/emoji-sprites";
+@import "framework/icons";
+@import "framework/snippets";
+@import "framework/memory_graph";
+@import "framework/responsive-tables";
diff --git a/app/assets/stylesheets/framework/awards.scss b/app/assets/stylesheets/framework/awards.scss
index 19166757e64..e474839d95c 100644
--- a/app/assets/stylesheets/framework/awards.scss
+++ b/app/assets/stylesheets/framework/awards.scss
@@ -24,7 +24,7 @@
opacity: 0;
transform: scale(.2);
transform-origin: 0 -45px;
- transition: .3s cubic-bezier(.67,.06,.19,1.44);
+ transition: .3s cubic-bezier(.67, .06, .19, 1.44);
transition-property: transform, opacity;
&.is-aligned-right {
diff --git a/app/assets/stylesheets/framework/blank.scss b/app/assets/stylesheets/framework/blank.scss
index c0224d3bfa9..6bb096fc5bd 100644
--- a/app/assets/stylesheets/framework/blank.scss
+++ b/app/assets/stylesheets/framework/blank.scss
@@ -1,9 +1,5 @@
.blank-state-parent-container {
- display: flex;
-
.section-container {
- display: flex;
- flex: 1;
padding: 10px;
}
@@ -13,91 +9,42 @@
padding-bottom: 25px;
border: 1px solid $border-color;
border-radius: $border-radius-default;
-
- &.section-ee-trial {
- display: flex;
- align-items: center;
- justify-content: center;
- }
- }
-}
-
-.blank-state-welcome {
- text-align: center;
-
- .blank-state-text {
- margin-bottom: 0;
}
}
.blank-state {
padding-top: 20px;
padding-bottom: 20px;
-}
-
-.blank-state.ee-trial {
- padding: 20px;
text-align: center;
-}
-
-.blank-state-no-icon {
- padding-top: 40px;
- padding-bottom: 40px;
-}
-
-.blank-state-icon {
- padding-bottom: 20px;
- font-size: 56px;
- svg {
- display: block;
- margin: auto;
- }
-}
-
-@media (min-width: $screen-sm-max) {
- .section-welcome .blank-state-icon svg {
- width: 130%;
- }
-}
-
-.blank-state-title {
- margin-top: 0;
- margin-bottom: 10px;
- font-size: 18px;
-}
-
-.blank-state-text {
- margin-top: 0;
- margin-bottom: $gl-padding;
- font-size: 14px;
+ &.blank-state-welcome {
+ .blank-state-welcome-title {
+ font-size: 24px;
+ }
- > strong {
- font-weight: 600;
+ .blank-state-text {
+ margin-bottom: 0;
+ }
}
-}
-.blank-state-welcome-title {
- font-size: 24px;
-}
+ .blank-state-icon {
+ padding-bottom: 20px;
-@media (max-width: $screen-md-min) {
- .blank-state-parent-container {
- &,
- .section-container {
+ svg {
display: block;
+ margin: auto;
}
}
- .blank-state {
- text-align: center;
+ .blank-state-title {
+ margin-top: 0;
+ margin-bottom: 10px;
+ font-size: 18px;
}
- .blank-state-icon {
- padding-bottom: 0;
- }
-
- .blank-state-body {
- margin-top: 15px;
+ .blank-state-text {
+ max-width: $container-text-max-width;
+ margin: 0 auto $gl-padding;
+ font-size: 14px;
}
}
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 00c981f64c5..5e374360359 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -336,11 +336,6 @@ table {
text-align: center;
}
-#nprogress .spinner {
- top: 15px !important;
- right: 10px !important;
-}
-
.header-with-avatar {
h3 {
margin: 0;
@@ -450,4 +445,3 @@ table {
pointer-events: none;
opacity: .5;
}
-
diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss
index f05348ee4e3..7e4e5fd7f1c 100644
--- a/app/assets/stylesheets/framework/filters.scss
+++ b/app/assets/stylesheets/framework/filters.scss
@@ -368,7 +368,7 @@
margin-right: 0.3em;
}
- & > .value {
+ > .value {
font-weight: 600;
}
}
@@ -467,7 +467,7 @@
-webkit-flex-direction: column;
flex-direction: column;
- &> span {
+ > span {
white-space: normal;
word-break: break-all;
}
diff --git a/app/assets/stylesheets/framework/highlight.scss b/app/assets/stylesheets/framework/highlight.scss
index 6d27d7568cf..71d5949b023 100644
--- a/app/assets/stylesheets/framework/highlight.scss
+++ b/app/assets/stylesheets/framework/highlight.scss
@@ -61,7 +61,7 @@
&:focus {
outline: none;
- & i {
+ i {
visibility: visible;
}
}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 3f032776d82..3405f142428 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -176,6 +176,7 @@ $header-height: 50px;
$fixed-layout-width: 1280px;
$limited-layout-width: 990px;
$limited-layout-width-sm: 790px;
+$container-text-max-width: 540px;
$gl-avatar-size: 40px;
$error-exclamation-point: $red-500;
$border-radius-default: 3px;
@@ -316,7 +317,7 @@ $badge-color: $gl-text-color-secondary;
/*
* Award emoji
*/
-$award-emoji-menu-shadow: rgba(0,0,0,.175);
+$award-emoji-menu-shadow: rgba(0, 0, 0, .175);
$award-emoji-positive-add-bg: #fed159;
$award-emoji-positive-add-lines: #bb9c13;
@@ -567,7 +568,7 @@ $kdb-color: #555;
$kdb-border: #ccc;
$kdb-border-bottom: #bbb;
$kdb-shadow: #bbb;
-$body-text-shadow: rgba(255,255,255,0.01);
+$body-text-shadow: rgba(255, 255, 255, 0.01);
/*
* UI Dev Kit
diff --git a/app/assets/stylesheets/highlight/white.scss b/app/assets/stylesheets/highlight/white.scss
index 1daa10aef24..578f1902cce 100644
--- a/app/assets/stylesheets/highlight/white.scss
+++ b/app/assets/stylesheets/highlight/white.scss
@@ -113,7 +113,7 @@ $white-gc-bg: #eaf2f5;
border-color: $line-removed-dark;
a {
- color: scale-color($line-number-old,$red: -30%, $green: -30%, $blue: -30%);
+ color: scale-color($line-number-old, $red: -30%, $green: -30%, $blue: -30%);
}
}
@@ -122,7 +122,7 @@ $white-gc-bg: #eaf2f5;
border-color: $line-added-dark;
a {
- color: scale-color($line-number-new,$red: -30%, $green: -30%, $blue: -30%);
+ color: scale-color($line-number-new, $red: -30%, $green: -30%, $blue: -30%);
}
}
@@ -163,7 +163,7 @@ $white-gc-bg: #eaf2f5;
background-color: $line-removed;
&::before {
- color: scale-color($line-number-old,$red: -30%, $green: -30%, $blue: -30%);
+ color: scale-color($line-number-old, $red: -30%, $green: -30%, $blue: -30%);
}
span.idiff {
@@ -175,7 +175,7 @@ $white-gc-bg: #eaf2f5;
background-color: $line-added;
&::before {
- color: scale-color($line-number-new,$red: -30%, $green: -30%, $blue: -30%);
+ color: scale-color($line-number-new, $red: -30%, $green: -30%, $blue: -30%);
}
span.idiff {
diff --git a/app/assets/stylesheets/new_sidebar.scss b/app/assets/stylesheets/new_sidebar.scss
index 96459fe31cc..07b487cd090 100644
--- a/app/assets/stylesheets/new_sidebar.scss
+++ b/app/assets/stylesheets/new_sidebar.scss
@@ -2,12 +2,12 @@
@import 'framework/tw_bootstrap_variables';
@import "bootstrap/variables";
-$active-background: rgba(0,0,0,.04);
+$active-background: rgba(0, 0, 0, .04);
$active-border: $indigo-500;
$active-color: $indigo-700;
$active-hover-background: $active-background;
$active-hover-color: $gl-text-color;
-$inactive-badge-background: rgba(0,0,0,.08);
+$inactive-badge-background: rgba(0, 0, 0, .08);
$hover-background: $indigo-700;
$hover-color: $white-light;
$inactive-color: $gl-text-color-secondary;
diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss
index 23c06eca3c3..0393820dee6 100644
--- a/app/assets/stylesheets/pages/builds.scss
+++ b/app/assets/stylesheets/pages/builds.scss
@@ -6,26 +6,26 @@
@keyframes blinking-dots {
0% {
background-color: rgba($white-light, 1);
- box-shadow: 12px 0 0 0 rgba($white-light,0.2),
- 24px 0 0 0 rgba($white-light,0.2);
+ box-shadow: 12px 0 0 0 rgba($white-light, 0.2),
+ 24px 0 0 0 rgba($white-light, 0.2);
}
25% {
background-color: rgba($white-light, 0.4);
- box-shadow: 12px 0 0 0 rgba($white-light,2),
- 24px 0 0 0 rgba($white-light,0.2);
+ box-shadow: 12px 0 0 0 rgba($white-light, 2),
+ 24px 0 0 0 rgba($white-light, 0.2);
}
75% {
background-color: rgba($white-light, 0.4);
- box-shadow: 12px 0 0 0 rgba($white-light,0.2),
- 24px 0 0 0 rgba($white-light,1);
+ box-shadow: 12px 0 0 0 rgba($white-light, 0.2),
+ 24px 0 0 0 rgba($white-light, 1);
}
100% {
background-color: rgba($white-light, 1);
- box-shadow: 12px 0 0 0 rgba($white-light,0.2),
- 24px 0 0 0 rgba($white-light,0.2);
+ box-shadow: 12px 0 0 0 rgba($white-light, 0.2),
+ 24px 0 0 0 rgba($white-light, 0.2);
}
}
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 7adf17dddb8..2db967547dd 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -96,7 +96,7 @@
overflow: visible;
}
- & > span {
+ > span {
padding-right: 4px;
}
@@ -125,7 +125,7 @@
.dropdown-menu {
margin-top: 11px;
- z-index: 200;
+ z-index: 300;
}
.ci-action-icon-wrapper {
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index 303425041df..64a48e226bc 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -250,7 +250,7 @@ ul.notes {
}
.note-text {
- & p:first-child {
+ p:first-child {
display: none;
}
diff --git a/app/assets/stylesheets/pages/pipeline_schedules.scss b/app/assets/stylesheets/pages/pipeline_schedules.scss
index dc719a6ba94..284b38ad370 100644
--- a/app/assets/stylesheets/pages/pipeline_schedules.scss
+++ b/app/assets/stylesheets/pages/pipeline_schedules.scss
@@ -96,12 +96,12 @@
}
&:last-child {
- & .pipeline-variable-row-remove-button {
+ .pipeline-variable-row-remove-button {
display: none;
}
@media (max-width: $screen-sm-max) {
- & .pipeline-variable-value-input {
+ .pipeline-variable-value-input {
margin-right: $pipeline-variable-remove-button-width;
}
}
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 7d7c34115f9..46434eab8f3 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -26,7 +26,7 @@
margin-bottom: 5px;
}
- & > .form-group {
+ > .form-group {
padding-left: 0;
}
@@ -83,7 +83,7 @@
border: 1px solid $border-color;
}
- & + .select2 a {
+ + .select2 a {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss
index de652a79369..d7a9dda3770 100644
--- a/app/assets/stylesheets/pages/todos.scss
+++ b/app/assets/stylesheets/pages/todos.scss
@@ -81,7 +81,7 @@
.todo-title {
display: flex;
- & > .title-item {
+ > .title-item {
-webkit-flex: 0 0 auto;
flex: 0 0 auto;
margin: 0 2px;
diff --git a/app/assets/stylesheets/pages/wiki.scss b/app/assets/stylesheets/pages/wiki.scss
index 94d0a39f397..45c21c5d274 100644
--- a/app/assets/stylesheets/pages/wiki.scss
+++ b/app/assets/stylesheets/pages/wiki.scss
@@ -147,13 +147,13 @@
}
ul.wiki-pages-list.content-list {
- & ul {
+ ul {
list-style: none;
margin-left: 0;
padding-left: 15px;
}
- & ul li {
+ ul li {
padding: 5px 0;
}
}
diff --git a/app/controllers/concerns/requires_health_token.rb b/app/controllers/concerns/requires_health_token.rb
deleted file mode 100644
index 34ab1a97649..00000000000
--- a/app/controllers/concerns/requires_health_token.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-module RequiresHealthToken
- extend ActiveSupport::Concern
- included do
- before_action :validate_health_check_access!
- end
-
- private
-
- def validate_health_check_access!
- render_404 unless token_valid?
- end
-
- def token_valid?
- token = params[:token].presence || request.headers['TOKEN']
- token.present? &&
- ActiveSupport::SecurityUtils.variable_size_secure_compare(
- token,
- current_application_settings.health_check_access_token
- )
- end
-
- def render_404
- render file: Rails.root.join('public', '404'), layout: false, status: '404'
- end
-end
diff --git a/app/controllers/concerns/requires_whitelisted_monitoring_client.rb b/app/controllers/concerns/requires_whitelisted_monitoring_client.rb
new file mode 100644
index 00000000000..ad2f4bbc486
--- /dev/null
+++ b/app/controllers/concerns/requires_whitelisted_monitoring_client.rb
@@ -0,0 +1,33 @@
+module RequiresWhitelistedMonitoringClient
+ extend ActiveSupport::Concern
+ included do
+ before_action :validate_ip_whitelisted_or_valid_token!
+ end
+
+ private
+
+ def validate_ip_whitelisted_or_valid_token!
+ render_404 unless client_ip_whitelisted? || valid_token?
+ end
+
+ def client_ip_whitelisted?
+ ip_whitelist.any? { |e| e.include?(Gitlab::RequestContext.client_ip) }
+ end
+
+ def ip_whitelist
+ @ip_whitelist ||= Settings.monitoring.ip_whitelist.map(&IPAddr.method(:new))
+ end
+
+ def valid_token?
+ token = params[:token].presence || request.headers['TOKEN']
+ token.present? &&
+ ActiveSupport::SecurityUtils.variable_size_secure_compare(
+ token,
+ current_application_settings.health_check_access_token
+ )
+ end
+
+ def render_404
+ render file: Rails.root.join('public', '404'), layout: false, status: '404'
+ end
+end
diff --git a/app/controllers/health_check_controller.rb b/app/controllers/health_check_controller.rb
index 5d3109b7187..c3d18991fd4 100644
--- a/app/controllers/health_check_controller.rb
+++ b/app/controllers/health_check_controller.rb
@@ -1,3 +1,3 @@
class HealthCheckController < HealthCheck::HealthCheckController
- include RequiresHealthToken
+ include RequiresWhitelistedMonitoringClient
end
diff --git a/app/controllers/health_controller.rb b/app/controllers/health_controller.rb
index abc832e6ddc..98c2aaa3526 100644
--- a/app/controllers/health_controller.rb
+++ b/app/controllers/health_controller.rb
@@ -1,10 +1,13 @@
class HealthController < ActionController::Base
protect_from_forgery with: :exception
- include RequiresHealthToken
+ include RequiresWhitelistedMonitoringClient
CHECKS = [
Gitlab::HealthChecks::DbCheck,
- Gitlab::HealthChecks::RedisCheck,
+ Gitlab::HealthChecks::Redis::RedisCheck,
+ Gitlab::HealthChecks::Redis::CacheCheck,
+ Gitlab::HealthChecks::Redis::QueuesCheck,
+ Gitlab::HealthChecks::Redis::SharedStateCheck,
Gitlab::HealthChecks::FsShardsCheck
].freeze
diff --git a/app/controllers/metrics_controller.rb b/app/controllers/metrics_controller.rb
index 0e9a19c0b6f..37587a52eaf 100644
--- a/app/controllers/metrics_controller.rb
+++ b/app/controllers/metrics_controller.rb
@@ -1,12 +1,12 @@
class MetricsController < ActionController::Base
- include RequiresHealthToken
+ include RequiresWhitelistedMonitoringClient
protect_from_forgery with: :exception
before_action :validate_prometheus_metrics
def index
- render text: metrics_service.metrics_text, content_type: 'text/plain; verssion=0.0.4'
+ render text: metrics_service.metrics_text, content_type: 'text/plain; version=0.0.4'
end
private
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index fb0fbb43fb1..c6d23898560 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -149,7 +149,7 @@ module Ci
private
def cleanup_runner_queue
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::Queues.with do |redis|
redis.del(runner_queue_key)
end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index d5760164663..e50818e3dff 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -1386,15 +1386,15 @@ class Project < ActiveRecord::Base
end
def pushes_since_gc
- Gitlab::Redis.with { |redis| redis.get(pushes_since_gc_redis_key).to_i }
+ Gitlab::Redis::SharedState.with { |redis| redis.get(pushes_since_gc_redis_shared_state_key).to_i }
end
def increment_pushes_since_gc
- Gitlab::Redis.with { |redis| redis.incr(pushes_since_gc_redis_key) }
+ Gitlab::Redis::SharedState.with { |redis| redis.incr(pushes_since_gc_redis_shared_state_key) }
end
def reset_pushes_since_gc
- Gitlab::Redis.with { |redis| redis.del(pushes_since_gc_redis_key) }
+ Gitlab::Redis::SharedState.with { |redis| redis.del(pushes_since_gc_redis_shared_state_key) }
end
def route_map_for(commit_sha)
@@ -1457,7 +1457,7 @@ class Project < ActiveRecord::Base
from && self != from
end
- def pushes_since_gc_redis_key
+ def pushes_since_gc_redis_shared_state_key
"projects/#{id}/pushes_since_gc"
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 4b01c2f19f0..2d39b1c1c34 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -699,7 +699,7 @@ class User < ActiveRecord::Base
end
def sanitize_attrs
- %w[name username skype linkedin twitter].each do |attr|
+ %w[username skype linkedin twitter].each do |attr|
value = public_send(attr)
public_send("#{attr}=", Sanitize.clean(value)) if value.present?
end
diff --git a/app/services/metrics_service.rb b/app/services/metrics_service.rb
index d726db4e99b..c92f070601c 100644
--- a/app/services/metrics_service.rb
+++ b/app/services/metrics_service.rb
@@ -3,7 +3,10 @@ require 'prometheus/client/formats/text'
class MetricsService
CHECKS = [
Gitlab::HealthChecks::DbCheck,
- Gitlab::HealthChecks::RedisCheck,
+ Gitlab::HealthChecks::Redis::RedisCheck,
+ Gitlab::HealthChecks::Redis::CacheCheck,
+ Gitlab::HealthChecks::Redis::QueuesCheck,
+ Gitlab::HealthChecks::Redis::SharedStateCheck,
Gitlab::HealthChecks::FsShardsCheck
].freeze
diff --git a/app/services/milestones/destroy_service.rb b/app/services/milestones/destroy_service.rb
index e457212508f..600ebcfbecb 100644
--- a/app/services/milestones/destroy_service.rb
+++ b/app/services/milestones/destroy_service.rb
@@ -1,15 +1,17 @@
module Milestones
class DestroyService < Milestones::BaseService
def execute(milestone)
+ return unless milestone.is_project_milestone?
+
Milestone.transaction do
update_params = { milestone: nil }
milestone.issues.each do |issue|
- Issues::UpdateService.new(project, current_user, update_params).execute(issue)
+ Issues::UpdateService.new(parent, current_user, update_params).execute(issue)
end
milestone.merge_requests.each do |merge_request|
- MergeRequests::UpdateService.new(project, current_user, update_params).execute(merge_request)
+ MergeRequests::UpdateService.new(parent, current_user, update_params).execute(merge_request)
end
event_service.destroy_milestone(milestone, current_user)
diff --git a/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml b/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml
index 0319838bdb4..209afd4aab4 100644
--- a/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml
+++ b/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml
@@ -1,7 +1,7 @@
-.row.blank-state.clearfix
- .col-md-1.col-md-offset-3.blank-state-icon
+.blank-state
+ .blank-state-icon
= custom_icon("add_new_user", size: 50)
- .col-md-5.blank-state-body
+ .blank-state-body
%h3.blank-state-title
Add user
%p.blank-state-text
@@ -9,10 +9,10 @@
= link_to new_admin_user_path, class: "btn btn-new" do
New user
-.row.blank-state.clearfix
- .col-md-1.col-md-offset-3.blank-state-icon
+.blank-state
+ .blank-state-icon
= custom_icon("configure_server", size: 50)
- .col-md-5.blank-state-body
+ .blank-state-body
%h3.blank-state-title
Configure GitLab
%p.blank-state-text
@@ -21,10 +21,10 @@
Configure
- if current_user.can_create_group?
- .row.blank-state.clearfix
- .col-md-1.col-md-offset-3.blank-state-icon
+ .blank-state
+ .blank-state-icon
= custom_icon("add_new_group", size: 50)
- .col-md-5.blank-state-body
+ .blank-state-body
%h3.blank-state-title
Create a group
%p.blank-state-text
diff --git a/app/views/dashboard/projects/_blank_state_welcome.html.haml b/app/views/dashboard/projects/_blank_state_welcome.html.haml
index a079f0ac1a4..a93a3415ee1 100644
--- a/app/views/dashboard/projects/_blank_state_welcome.html.haml
+++ b/app/views/dashboard/projects/_blank_state_welcome.html.haml
@@ -1,10 +1,10 @@
- public_project_count = ProjectsFinder.new(current_user: current_user).execute.count
- if current_user.can_create_group?
- .row.blank-state.clearfix
- .col-md-1.col-md-offset-3.blank-state-icon
+ .blank-state
+ .blank-state-icon
= custom_icon("add_new_group", size: 50)
- .col-md-5.blank-state-body
+ .blank-state-body
%h3.blank-state-title
Create a group for several dependent projects.
%p.blank-state-text
@@ -12,10 +12,10 @@
= link_to new_group_path, class: "btn btn-new" do
New group
-.row.blank-state.clearfix
- .col-md-1.col-md-offset-3.blank-state-icon
+.blank-state
+ .blank-state-icon
= custom_icon("add_new_project", size: 50)
- .col-md-5.blank-state-body
+ .blank-state-body
%h3.blank-state-title
Create a project
%p.blank-state-text
@@ -32,10 +32,10 @@
New project
- if public_project_count > 0
- .row.blank-state.clearfix
- .col-md-1.col-md-offset-3.blank-state-icon
+ .blank-state
+ .blank-state-icon
= custom_icon("globe", size: 50)
- .col-md-5.blank-state-body
+ .blank-state-body
%h3.blank-state-title
Explore public projects
%p.blank-state-text
diff --git a/app/views/dashboard/projects/_zero_authorized_projects.html.haml b/app/views/dashboard/projects/_zero_authorized_projects.html.haml
index 94af033c1e3..ad3fac6d164 100644
--- a/app/views/dashboard/projects/_zero_authorized_projects.html.haml
+++ b/app/views/dashboard/projects/_zero_authorized_projects.html.haml
@@ -1,6 +1,6 @@
.row.blank-state-parent-container
- .section-container
- .container.section-body.section-welcome{ class: "#{ 'section-admin-welcome' if current_user.admin? }" }
+ .section-container.section-welcome{ class: "#{ 'section-admin-welcome' if current_user.admin? }" }
+ .container.section-body
.blank-state.blank-state-welcome
%h2.blank-state-welcome-title
Welcome to GitLab
diff --git a/app/views/help/ui.html.haml b/app/views/help/ui.html.haml
index 615dd56afbd..48edbb8c16f 100644
--- a/app/views/help/ui.html.haml
+++ b/app/views/help/ui.html.haml
@@ -525,7 +525,7 @@
%h4
%code .file-holder
- - blob = Snippet.new(content: "Wow\nSuch\nFile")
+ - blob = Snippet.new(content: "Wow\nSuch\nFile").blob
.example
.file-holder
.js-file-title.file-title
diff --git a/app/views/layouts/nav/_breadcrumbs.html.haml b/app/views/layouts/nav/_breadcrumbs.html.haml
index 5f1641f4300..b0c1ab7420f 100644
--- a/app/views/layouts/nav/_breadcrumbs.html.haml
+++ b/app/views/layouts/nav/_breadcrumbs.html.haml
@@ -2,7 +2,7 @@
- hide_top_links = @hide_top_links || false
%nav.breadcrumbs{ role: "navigation" }
- .breadcrumbs-container{ class: container_class }
+ .breadcrumbs-container{ class: [container_class, @content_class] }
.breadcrumbs-links.js-title-container
- unless hide_top_links
.title
diff --git a/app/views/layouts/nav/_new_project_sidebar.html.haml b/app/views/layouts/nav/_new_project_sidebar.html.haml
index cc731db3cc1..8838852803b 100644
--- a/app/views/layouts/nav/_new_project_sidebar.html.haml
+++ b/app/views/layouts/nav/_new_project_sidebar.html.haml
@@ -74,9 +74,9 @@
= nav_link(controller: @project.default_issues_tracker? ? [:issues, :labels, :milestones, :boards] : :issues) do
= link_to project_issues_path(@project), title: 'Issues', class: 'shortcuts-issues' do
%span
- Issues
- if @project.default_issues_tracker?
%span.badge.count.issue_counter= number_with_delimiter(IssuesFinder.new(current_user, project_id: @project.id).execute.opened.count)
+ Issues
%ul.sidebar-sub-level-items
- if project_nav_tab?(:issues) && !current_controller?(:merge_requests)
@@ -112,8 +112,8 @@
= nav_link(controller: @project.default_issues_tracker? ? :merge_requests : [:merge_requests, :labels, :milestones]) do
= link_to project_merge_requests_path(@project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do
%span
- Merge Requests
%span.badge.count.merge_counter.js-merge-counter= number_with_delimiter(MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened.count)
+ Merge Requests
- if project_nav_tab? :pipelines
= nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :environments, :artifacts]) do
diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml
index b778e8af121..07c83c0a590 100644
--- a/app/views/projects/commit/show.html.haml
+++ b/app/views/projects/commit/show.html.haml
@@ -1,6 +1,7 @@
- @no_container = true
- container_class = !fluid_layout && diff_view == :inline ? 'container-limited' : ''
- limited_container_width = fluid_layout ? '' : 'limit-container-width'
+- @content_class = limited_container_width
- page_title "#{@commit.title} (#{@commit.short_id})", "Commits"
- page_description @commit.description
= render "projects/commits/head"
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index 7b8be58554a..b0b7575f0d1 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -9,8 +9,9 @@
.col-lg-3.profile-settings-sidebar
%h4.prepend-top-0
New project
- %p
- Create or Import your project from popular Git services
+ - if import_sources_enabled?
+ %p
+ Create or Import your project from popular Git services
.col-lg-9
= form_for @project, html: { class: 'new_project' } do |f|
.row
diff --git a/app/views/projects/pipeline_schedules/index.html.haml b/app/views/projects/pipeline_schedules/index.html.haml
index 05fe80e5fed..c4ee064ac43 100644
--- a/app/views/projects/pipeline_schedules/index.html.haml
+++ b/app/views/projects/pipeline_schedules/index.html.haml
@@ -12,9 +12,10 @@
- schedule_path_proc = ->(scope) { pipeline_schedules_path(@project, scope: scope) }
= render "tabs", schedule_path_proc: schedule_path_proc, all_schedules: @all_schedules, scope: @scope
- .nav-controls
- = link_to new_project_pipeline_schedule_path(@project), class: 'btn btn-create' do
- %span= _('New schedule')
+ - if can?(current_user, :create_pipeline_schedule, @project)
+ .nav-controls
+ = link_to new_project_pipeline_schedule_path(@project), class: 'btn btn-create' do
+ %span= _('New schedule')
- if @schedules.present?
%ul.content-list
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index d413c4619be..a73e111ad6d 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -1,4 +1,5 @@
- @no_container = true
+- @content_class = "limit-container-width" unless fluid_layout
- flash_message_container = show_new_nav? ? :new_global_flash : :flash_message
= content_for :meta_tags do
diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml
index 130980556c1..f727f340bb9 100644
--- a/app/views/projects/tree/show.html.haml
+++ b/app/views/projects/tree/show.html.haml
@@ -1,4 +1,5 @@
- @no_container = true
+- @content_class = "limit-container-width" unless fluid_layout
- page_title @path.presence || _("Files"), @ref
= content_for :meta_tags do
diff --git a/changelogs/unreleased/10085-stop-encoding-user-name.yml b/changelogs/unreleased/10085-stop-encoding-user-name.yml
new file mode 100644
index 00000000000..8fab474e047
--- /dev/null
+++ b/changelogs/unreleased/10085-stop-encoding-user-name.yml
@@ -0,0 +1,4 @@
+---
+title: "Insert user name directly without encoding"
+merge_request: 10085
+author: Nathan Neulinger <nneul@neulinger.org>
diff --git a/changelogs/unreleased/33580-fix-api-scoping.yml b/changelogs/unreleased/33580-fix-api-scoping.yml
deleted file mode 100644
index f4ebb13c082..00000000000
--- a/changelogs/unreleased/33580-fix-api-scoping.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix API Scoping
-merge_request: 12300
-author:
diff --git a/changelogs/unreleased/33949-deprecate-healthcheck-access-token.yml b/changelogs/unreleased/33949-deprecate-healthcheck-access-token.yml
new file mode 100644
index 00000000000..a08795e1a26
--- /dev/null
+++ b/changelogs/unreleased/33949-deprecate-healthcheck-access-token.yml
@@ -0,0 +1,4 @@
+---
+title: Deprecate Healthcheck Access Token in favor of IP whitelist
+merge_request:
+author:
diff --git a/changelogs/unreleased/34325-reinstate-is_admin-for-user-api.yml b/changelogs/unreleased/34325-reinstate-is_admin-for-user-api.yml
new file mode 100644
index 00000000000..3bed1fbe16e
--- /dev/null
+++ b/changelogs/unreleased/34325-reinstate-is_admin-for-user-api.yml
@@ -0,0 +1,4 @@
+---
+title: Return `is_admin` attribute in the GET /user endpoint for admins
+merge_request: 12811
+author:
diff --git a/changelogs/unreleased/34534-update-vue-resource.yml b/changelogs/unreleased/34534-update-vue-resource.yml
new file mode 100644
index 00000000000..2d0af0c9bfe
--- /dev/null
+++ b/changelogs/unreleased/34534-update-vue-resource.yml
@@ -0,0 +1,4 @@
+---
+title: Updates vue resource and code according to breaking changes
+merge_request:
+author:
diff --git a/changelogs/unreleased/34729-blob.yml b/changelogs/unreleased/34729-blob.yml
new file mode 100644
index 00000000000..15a469d3af0
--- /dev/null
+++ b/changelogs/unreleased/34729-blob.yml
@@ -0,0 +1,4 @@
+---
+title: Fix crash on /help/ui
+merge_request:
+author:
diff --git a/changelogs/unreleased/34858-bump-scss-lint-to-0-54-0.yml b/changelogs/unreleased/34858-bump-scss-lint-to-0-54-0.yml
new file mode 100644
index 00000000000..e6cd834aed2
--- /dev/null
+++ b/changelogs/unreleased/34858-bump-scss-lint-to-0-54-0.yml
@@ -0,0 +1,4 @@
+---
+title: Bump scss-lint to 0.54.0
+merge_request: 12733
+author: Takuya Noguchi
diff --git a/changelogs/unreleased/34867-remove-net-ssh-gem.yml b/changelogs/unreleased/34867-remove-net-ssh-gem.yml
new file mode 100644
index 00000000000..f5648d62467
--- /dev/null
+++ b/changelogs/unreleased/34867-remove-net-ssh-gem.yml
@@ -0,0 +1,4 @@
+---
+title: Remove net-ssh gem
+merge_request:
+author: Takuya Noguchi
diff --git a/changelogs/unreleased/34907-dont-show-pipeline-schedule-button-for-non-member.yml b/changelogs/unreleased/34907-dont-show-pipeline-schedule-button-for-non-member.yml
new file mode 100644
index 00000000000..22c9c45bc75
--- /dev/null
+++ b/changelogs/unreleased/34907-dont-show-pipeline-schedule-button-for-non-member.yml
@@ -0,0 +1,4 @@
+---
+title: Do not show pipeline schedule button for non-member
+merge_request: 12757
+author: Takuya Noguchi
diff --git a/changelogs/unreleased/34978-remove-public-ci-favicon-ico.yml b/changelogs/unreleased/34978-remove-public-ci-favicon-ico.yml
new file mode 100644
index 00000000000..25cc8b5e45f
--- /dev/null
+++ b/changelogs/unreleased/34978-remove-public-ci-favicon-ico.yml
@@ -0,0 +1,4 @@
+---
+title: Remove public/ci/favicon.ico
+merge_request: 12803
+author: Takuya Noguchi
diff --git a/changelogs/unreleased/dm-encode-tree-and-blob-paths.yml b/changelogs/unreleased/dm-encode-tree-and-blob-paths.yml
deleted file mode 100644
index c1a026e1f29..00000000000
--- a/changelogs/unreleased/dm-encode-tree-and-blob-paths.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix issues with non-UTF8 filenames by always fixing the encoding of tree and
- blob paths
-merge_request:
-author:
diff --git a/changelogs/unreleased/enable-scss-lint-import-path.yml b/changelogs/unreleased/enable-scss-lint-import-path.yml
new file mode 100644
index 00000000000..d158cf5b5f3
--- /dev/null
+++ b/changelogs/unreleased/enable-scss-lint-import-path.yml
@@ -0,0 +1,4 @@
+---
+title: Enable ImportPath in scss-lint
+merge_request: 12749
+author: Takuya Noguchi
diff --git a/changelogs/unreleased/enable-scss-lint-property-spelling.yml b/changelogs/unreleased/enable-scss-lint-property-spelling.yml
new file mode 100644
index 00000000000..c5a5a4dddb6
--- /dev/null
+++ b/changelogs/unreleased/enable-scss-lint-property-spelling.yml
@@ -0,0 +1,4 @@
+---
+title: Enable PropertySpelling in scss-lint
+merge_request: 12752
+author: Takuya Noguchi
diff --git a/changelogs/unreleased/enable-scss-lint-space-after-comma.yml b/changelogs/unreleased/enable-scss-lint-space-after-comma.yml
new file mode 100644
index 00000000000..210f34fbb87
--- /dev/null
+++ b/changelogs/unreleased/enable-scss-lint-space-after-comma.yml
@@ -0,0 +1,4 @@
+---
+title: Enable SpaceAfterComma in scss-lint
+merge_request: 12734
+author: Takuya Noguchi
diff --git a/changelogs/unreleased/enable-scss-lint-unnecessary-parent-reference.yml b/changelogs/unreleased/enable-scss-lint-unnecessary-parent-reference.yml
new file mode 100644
index 00000000000..59d5df56525
--- /dev/null
+++ b/changelogs/unreleased/enable-scss-lint-unnecessary-parent-reference.yml
@@ -0,0 +1,4 @@
+---
+title: Enable UnnecessaryParentReference in scss-lint
+merge_request: 12738
+author: Takuya Noguchi
diff --git a/changelogs/unreleased/fix-n-plus-one-in-url-builder.yml b/changelogs/unreleased/fix-n-plus-one-in-url-builder.yml
new file mode 100644
index 00000000000..5781316cfd9
--- /dev/null
+++ b/changelogs/unreleased/fix-n-plus-one-in-url-builder.yml
@@ -0,0 +1,4 @@
+---
+title: Improve issue rendering performance with lots of notes from other users
+merge_request:
+author:
diff --git a/changelogs/unreleased/issue-description-gfm.yml b/changelogs/unreleased/issue-description-gfm.yml
deleted file mode 100644
index 4d421bff677..00000000000
--- a/changelogs/unreleased/issue-description-gfm.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fixed GFM references not being included when updating issues inline
-merge_request:
-author:
diff --git a/changelogs/unreleased/remove-nprogress-gleaning.yml b/changelogs/unreleased/remove-nprogress-gleaning.yml
new file mode 100644
index 00000000000..78e4dc82dd4
--- /dev/null
+++ b/changelogs/unreleased/remove-nprogress-gleaning.yml
@@ -0,0 +1,4 @@
+---
+title: Remove CSS for nprogress removed
+merge_request: 12737
+author: Takuya Noguchi
diff --git a/changelogs/unreleased/replace_spinach_spec_browse_files.yml b/changelogs/unreleased/replace_spinach_spec_browse_files.yml
new file mode 100644
index 00000000000..7380d39fa9f
--- /dev/null
+++ b/changelogs/unreleased/replace_spinach_spec_browse_files.yml
@@ -0,0 +1,4 @@
+---
+title: Replace 'browse_files.feature' spinach test with an rspec analog
+merge_request: 12251
+author: @blackst0ne
diff --git a/changelogs/unreleased/sh-add-mr-simple-mode.yml b/changelogs/unreleased/sh-add-mr-simple-mode.yml
new file mode 100644
index 00000000000..0033ca28444
--- /dev/null
+++ b/changelogs/unreleased/sh-add-mr-simple-mode.yml
@@ -0,0 +1,4 @@
+---
+title: Add a simple mode to merge request API
+merge_request:
+author:
diff --git a/changelogs/unreleased/toggle-new-project-import-description.yml b/changelogs/unreleased/toggle-new-project-import-description.yml
new file mode 100644
index 00000000000..8f0d09e0540
--- /dev/null
+++ b/changelogs/unreleased/toggle-new-project-import-description.yml
@@ -0,0 +1,4 @@
+---
+title: Toggle import description with import_sources_enabled
+merge_request: 12691
+author: Brianna Kicia \ No newline at end of file
diff --git a/changelogs/unreleased/username-password-stripped-from-import-url-fix.yml b/changelogs/unreleased/username-password-stripped-from-import-url-fix.yml
deleted file mode 100644
index 571279d3dc7..00000000000
--- a/changelogs/unreleased/username-password-stripped-from-import-url-fix.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Username and password are no longer stripped from import url on mirror update
-merge_request: 12725
-author:
diff --git a/config/README.md b/config/README.md
index 0a5ea2424e0..2778d0d4f02 100644
--- a/config/README.md
+++ b/config/README.md
@@ -19,4 +19,132 @@ an ERB file and then loads the resulting YML as its configuration.
This file is called `resque.yml` for historical reasons. We are **NOT**
using Resque at the moment. It is used to specify Redis configuration
-values instead.
+values when a single database instance of Redis is desired.
+
+# Advanced Redis configuration files
+
+In more advanced configurations of Redis key-value storage, it is desirable
+to separate the keys by lifecycle and intended use to ease provisioning and
+management of scalable Redis clusters.
+
+These settings provide routing and other configuration data (such as sentinel,
+persistence policies, and other Redis customization) for connections
+to Redis single instances, Redis sentinel, and Redis clusters.
+
+If desired, the routing URL provided by these settings can be used with:
+1. Unix Socket
+ 1. named socket for each Redis instance desired.
+ 2. `database number` for each Redis instance desired.
+2. TCP Socket
+ 1. `host name` or IP for each Redis instance desired
+ 2. TCP port number for each Redis instance desired
+ 3. `database number` for each Redis instance desired
+
+## Example URL attribute formats for GitLab Redis `.yml` configuration files
+* Unix Socket, default Redis database (0)
+ * `url: unix:/path/to/redis.sock`
+ * `url: unix:/path/to/redis.sock?db=`
+* Unix Socket, Redis database 44
+ * `url: unix:/path/to/redis.sock?db=44`
+ * `url: unix:/path/to/redis.sock?extra=foo&db=44`
+* TCP Socket for Redis on localhost, port 6379, database 33
+ * `url: redis://:mynewpassword@localhost:6379/33`
+* TCP Socket for Redis on remote host `myserver`, port 6379, database 33
+ * `url: redis://:mynewpassword@myserver:6379/33`
+
+## redis.cache.yml
+
+If configured, `redis.cache.yml` overrides the
+`resque.yml` settings to configure the Redis database instance
+used for `Rails.cache` and other volatile non-persistent data which enhances
+the performance of GitLab.
+Settings here can be overridden by the environment variable
+`GITLAB_REDIS_CACHE_CONFIG_FILE` which provides
+an alternate location for configuration settings.
+
+The order of precedence for the URL used to connect to the Redis instance
+used for `cache` is:
+1. URL from a configuration file pointed to by the
+`GITLAB_REDIS_CACHE_CONFIG_FILE` environment variable
+2. URL from `redis.cache.yml`
+3. URL from a configuration file pointed to by the
+`GITLAB_REDIS_CONFIG_FILE` environment variable
+4. URL from `resque.yml`
+5. `redis://localhost:6380`
+
+The order of precedence for all other configuration settings for `cache`
+are selected from only the first of the following files found (if a setting
+is not provided in an earlier file, the remainder of the files are not
+searched):
+1. the configuration file pointed to by the
+`GITLAB_REDIS_CACHE_CONFIG_FILE` environment variable
+2. the configuration file `redis.cache.yml`
+3. the configuration file pointed to by the
+`GITLAB_REDIS_CONFIG_FILE` environment variable
+4. the configuration file `resque.yml`
+
+## redis.queues.yml
+
+If configured, `redis.queues.yml` overrides the
+`resque.yml` settings to configure the Redis database instance
+used for clients of `::Gitlab::Redis::Queues`.
+These queues are intended to be the foundation
+of reliable inter-process communication between modules, whether on the same
+host node, or within a cluster. The primary clients of the queues are
+SideKiq, Mailroom, CI Runner, Workhorse, and push services. Settings here can
+be overridden by the environment variable
+`GITLAB_REDIS_QUEUES_CONFIG_FILE` which provides an alternate location for
+configuration settings.
+
+The order of precedence for the URL used to connect to the Redis instance
+used for `queues` is:
+1. URL from a configuration file pointed to by the
+`GITLAB_REDIS_QUEUES_CONFIG_FILE` environment variable
+2. URL from `redis.queues.yml`
+3. URL from a configuration file pointed to by the
+`GITLAB_REDIS_CONFIG_FILE` environment variable
+4. URL from `resque.yml`
+5. `redis://localhost:6381`
+
+The order of precedence for all other configuration settings for `queues`
+are selected from only the first of the following files found (if a setting
+is not provided in an earlier file, the remainder of the files are not
+searched):
+1. the configuration file pointed to by the
+`GITLAB_REDIS_QUEUES_CONFIG_FILE` environment variable
+2. the configuration file `redis.queues.yml`
+3. the configuration file pointed to by the
+`GITLAB_REDIS_CONFIG_FILE` environment variable
+4. the configuration file `resque.yml`
+
+## redis.shared_state.yml
+
+If configured, `redis.shared_state.yml` overrides the
+`resque.yml` settings to configure the Redis database instance
+used for clients of `::Gitlab::Redis::SharedState` such as session state,
+and rate limiting.
+Settings here can be overridden by the environment variable
+`GITLAB_REDIS_SHARED_STATE_CONFIG_FILE` which provides
+an alternate location for configuration settings.
+
+The order of precedence for the URL used to connect to the Redis instance
+used for `shared_state` is:
+1. URL from a configuration file pointed to by the
+`GITLAB_REDIS_SHARED_STATE_CONFIG_FILE` environment variable
+2. URL from `redis.shared_state.yml`
+3. URL from a configuration file pointed to by the
+`GITLAB_REDIS_CONFIG_FILE` environment variable
+4. URL from `resque.yml`
+5. `redis://localhost:6382`
+
+The order of precedence for all other configuration settings for `shared_state`
+are selected from only the first of the following files found (if a setting
+is not provided in an earlier file, the remainder of the files are not
+searched):
+1. the configuration file pointed to by the
+`GITLAB_REDIS_SHARED_STATE_CONFIG_FILE` environment variable
+2. the configuration file `redis.shared_state.yml`
+3. the configuration file pointed to by the
+`GITLAB_REDIS_CONFIG_FILE` environment variable
+4. the configuration file `resque.yml`
+
diff --git a/config/application.rb b/config/application.rb
index 2f4e2624195..1c13cc81270 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -6,7 +6,9 @@ Bundler.require(:default, Rails.env)
module Gitlab
class Application < Rails::Application
- require_dependency Rails.root.join('lib/gitlab/redis')
+ require_dependency Rails.root.join('lib/gitlab/redis/cache')
+ require_dependency Rails.root.join('lib/gitlab/redis/queues')
+ require_dependency Rails.root.join('lib/gitlab/redis/shared_state')
require_dependency Rails.root.join('lib/gitlab/request_context')
# Settings in config/environments/* take precedence over those specified here.
@@ -142,15 +144,15 @@ module Gitlab
end
end
- # Use Redis caching across all environments
- redis_config_hash = Gitlab::Redis.params
- redis_config_hash[:namespace] = Gitlab::Redis::CACHE_NAMESPACE
- redis_config_hash[:expires_in] = 2.weeks # Cache should not grow forever
+ # Use caching across all environments
+ caching_config_hash = Gitlab::Redis::Cache.params
+ caching_config_hash[:namespace] = Gitlab::Redis::Cache::CACHE_NAMESPACE
+ caching_config_hash[:expires_in] = 2.weeks # Cache should not grow forever
if Sidekiq.server? # threaded context
- redis_config_hash[:pool_size] = Sidekiq.options[:concurrency] + 5
- redis_config_hash[:pool_timeout] = 1
+ caching_config_hash[:pool_size] = Sidekiq.options[:concurrency] + 5
+ caching_config_hash[:pool_timeout] = 1
end
- config.cache_store = :redis_store, redis_config_hash
+ config.cache_store = :redis_store, caching_config_hash
config.active_record.raise_in_transactional_callbacks = true
diff --git a/config/database.yml.mysql b/config/database.yml.mysql
index db1b712d3bc..eb71d3f5fe1 100644
--- a/config/database.yml.mysql
+++ b/config/database.yml.mysql
@@ -42,3 +42,4 @@ test: &test
password:
# host: localhost
# socket: /tmp/mysql.sock
+ prepared_statements: false
diff --git a/config/database.yml.postgresql b/config/database.yml.postgresql
index c517a4c0cb8..4b30982fe82 100644
--- a/config/database.yml.postgresql
+++ b/config/database.yml.postgresql
@@ -46,3 +46,4 @@ test: &test
username: postgres
password:
# host: localhost
+ prepared_statements: false
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 221e3d6e03b..d0ab2dab0af 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -539,10 +539,15 @@ production: &base
# enabled: true
# host: localhost
# port: 3808
- prometheus:
+
+ ## Monitoring
+ # Built in monitoring settings
+ monitoring:
# Time between sampling of unicorn socket metrics, in seconds
# unicorn_sampler_interval: 10
-
+ # IP whitelist to access monitoring endpoints
+ ip_whitelist:
+ - 127.0.0.0/8
#
# 5. Extra customization
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index fa33e602e93..eb4a1e390a9 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -494,10 +494,11 @@ Settings.webpack.dev_server['host'] ||= 'localhost'
Settings.webpack.dev_server['port'] ||= 3808
#
-# Prometheus metrics settings
+# Monitoring settings
#
-Settings['prometheus'] ||= Settingslogic.new({})
-Settings.prometheus['unicorn_sampler_interval'] ||= 10
+Settings['monitoring'] ||= Settingslogic.new({})
+Settings.monitoring['ip_whitelist'] ||= ['127.0.0.1/8']
+Settings.monitoring['unicorn_sampler_interval'] ||= 10
#
# Testing settings
diff --git a/config/initializers/7_redis.rb b/config/initializers/7_redis.rb
index ae2ca258df1..af4967521b8 100644
--- a/config/initializers/7_redis.rb
+++ b/config/initializers/7_redis.rb
@@ -1,3 +1,8 @@
-# Make sure we initialize a Redis connection pool before Sidekiq starts
-# multi-threaded execution.
-Gitlab::Redis.with { nil }
+# Make sure we initialize a Redis connection pool before multi-threaded
+# execution starts by
+# 1. Sidekiq
+# 2. Rails.cache
+# 3. HTTP clients
+Gitlab::Redis::Cache.with { nil }
+Gitlab::Redis::Queues.with { nil }
+Gitlab::Redis::SharedState.with { nil }
diff --git a/config/initializers/8_metrics.rb b/config/initializers/8_metrics.rb
index d56fd7a6cfa..5e34aac6527 100644
--- a/config/initializers/8_metrics.rb
+++ b/config/initializers/8_metrics.rb
@@ -119,7 +119,7 @@ def instrument_classes(instrumentation)
end
# rubocop:enable Metrics/AbcSize
-Gitlab::Metrics::UnicornSampler.initialize_instance(Settings.prometheus.unicorn_sampler_interval).start
+Gitlab::Metrics::UnicornSampler.initialize_instance(Settings.monitoring.unicorn_sampler_interval).start
Gitlab::Application.configure do |config|
# 0 should be Sentry to catch errors in this middleware
diff --git a/config/initializers/peek.rb b/config/initializers/peek.rb
index 65432caac2a..da8282ec924 100644
--- a/config/initializers/peek.rb
+++ b/config/initializers/peek.rb
@@ -1,4 +1,4 @@
-Rails.application.config.peek.adapter = :redis, { client: ::Redis.new(Gitlab::Redis.params) }
+Rails.application.config.peek.adapter = :redis, { client: ::Redis.new(Gitlab::Redis::Cache.params) }
Peek.into Peek::Views::Host
Peek.into Peek::Views::PerformanceBar
diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb
index 8919f7640fe..e8213ac8ba4 100644
--- a/config/initializers/session_store.rb
+++ b/config/initializers/session_store.rb
@@ -19,12 +19,12 @@ cookie_key = if Rails.env.development?
if Rails.env.test?
Gitlab::Application.config.session_store :cookie_store, key: "_gitlab_session"
else
- redis_config = Gitlab::Redis.params
- redis_config[:namespace] = Gitlab::Redis::SESSION_NAMESPACE
+ sessions_config = Gitlab::Redis::SharedState.params
+ sessions_config[:namespace] = Gitlab::Redis::SharedState::SESSION_NAMESPACE
Gitlab::Application.config.session_store(
:redis_store, # Using the cookie_store would enable session replay attacks.
- servers: redis_config,
+ servers: sessions_config,
key: cookie_key,
secure: Gitlab.config.gitlab.https,
httponly: true,
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index ecd73956488..a1cc9655319 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -1,12 +1,12 @@
-# Custom Redis configuration
-redis_config_hash = Gitlab::Redis.params
-redis_config_hash[:namespace] = Gitlab::Redis::SIDEKIQ_NAMESPACE
+# Custom Queues configuration
+queues_config_hash = Gitlab::Redis::Queues.params
+queues_config_hash[:namespace] = Gitlab::Redis::Queues::SIDEKIQ_NAMESPACE
# Default is to retry 25 times with exponential backoff. That's too much.
Sidekiq.default_worker_options = { retry: 3 }
Sidekiq.configure_server do |config|
- config.redis = redis_config_hash
+ config.redis = queues_config_hash
config.server_middleware do |chain|
chain.add Gitlab::SidekiqMiddleware::ArgumentsLogger if ENV['SIDEKIQ_LOG_ARGUMENTS']
@@ -54,7 +54,7 @@ Sidekiq.configure_server do |config|
end
Sidekiq.configure_client do |config|
- config.redis = redis_config_hash
+ config.redis = queues_config_hash
config.client_middleware do |chain|
chain.add Gitlab::SidekiqStatus::ClientMiddleware
@@ -74,5 +74,5 @@ begin
end
end
end
-rescue Redis::BaseError, SocketError, Errno::ENOENT, Errno::EAFNOSUPPORT, Errno::ECONNRESET, Errno::ECONNREFUSED
+rescue Redis::BaseError, SocketError, Errno::ENOENT, Errno::EADDRNOTAVAIL, Errno::EAFNOSUPPORT, Errno::ECONNRESET, Errno::ECONNREFUSED
end
diff --git a/config/mail_room.yml b/config/mail_room.yml
index 88d93d4bc6b..c3a5be8d38c 100644
--- a/config/mail_room.yml
+++ b/config/mail_room.yml
@@ -21,7 +21,7 @@
:delivery_method: sidekiq
:delivery_options:
:redis_url: <%= config[:redis_url].to_json %>
- :namespace: <%= Gitlab::Redis::SIDEKIQ_NAMESPACE %>
+ :namespace: <%= Gitlab::Redis::Queues::SIDEKIQ_NAMESPACE %>
:queue: email_receiver
:worker: EmailReceiverWorker
<% if config[:sentinels] %>
@@ -36,7 +36,7 @@
:arbitration_method: redis
:arbitration_options:
:redis_url: <%= config[:redis_url].to_json %>
- :namespace: <%= Gitlab::Redis::MAILROOM_NAMESPACE %>
+ :namespace: <%= Gitlab::Redis::Queues::MAILROOM_NAMESPACE %>
<% if config[:sentinels] %>
:sentinels:
<% config[:sentinels].each do |sentinel| %>
diff --git a/config/redis.cache.yml.example b/config/redis.cache.yml.example
new file mode 100644
index 00000000000..27478f0a93e
--- /dev/null
+++ b/config/redis.cache.yml.example
@@ -0,0 +1,38 @@
+# If you change this file in a Merge Request, please also create
+# a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
+#
+development:
+ url: redis://localhost:6379/10
+ #
+ # url: redis://localhost:6380
+ # sentinels:
+ # -
+ # host: localhost
+ # port: 26380 # point to sentinel, not to redis port
+ # -
+ # host: slave2
+ # port: 26380 # point to sentinel, not to redis port
+test:
+ url: redis://localhost:6379/10
+ #
+ # url: redis://localhost:6380
+production:
+ # Redis (single instance)
+ url: unix:/var/run/redis/redis.cache.sock
+ ##
+ # Redis + Sentinel (for HA)
+ #
+ # Please read instructions carefully before using it as you may lose data:
+ # http://redis.io/topics/sentinel
+ #
+ # You must specify a list of a few sentinels that will handle client connection
+ # please read here for more information: https://docs.gitlab.com/ce/administration/high_availability/redis.html
+ ##
+ # url: redis://master:6380
+ # sentinels:
+ # -
+ # host: slave1
+ # port: 26380 # point to sentinel, not to redis port
+ # -
+ # host: slave2
+ # port: 26380 # point to sentinel, not to redis port
diff --git a/config/redis.queues.yml.example b/config/redis.queues.yml.example
new file mode 100644
index 00000000000..dab1f26b096
--- /dev/null
+++ b/config/redis.queues.yml.example
@@ -0,0 +1,38 @@
+# If you change this file in a Merge Request, please also create
+# a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
+#
+development:
+ url: redis://localhost:6379/11
+ #
+ # url: redis://localhost:6381
+ # sentinels:
+ # -
+ # host: localhost
+ # port: 26381 # point to sentinel, not to redis port
+ # -
+ # host: slave2
+ # port: 26381 # point to sentinel, not to redis port
+test:
+ url: redis://localhost:6379/11
+ #
+ # url: redis://localhost:6381
+production:
+ # Redis (single instance)
+ url: unix:/var/run/redis/redis.queues.sock
+ ##
+ # Redis + Sentinel (for HA)
+ #
+ # Please read instructions carefully before using it as you may lose data:
+ # http://redis.io/topics/sentinel
+ #
+ # You must specify a list of a few sentinels that will handle client connection
+ # please read here for more information: https://docs.gitlab.com/ce/administration/high_availability/redis.html
+ ##
+ # url: redis://master:6381
+ # sentinels:
+ # -
+ # host: slave1
+ # port: 26381 # point to sentinel, not to redis port
+ # -
+ # host: slave2
+ # port: 26381 # point to sentinel, not to redis port
diff --git a/config/redis.shared_state.yml.example b/config/redis.shared_state.yml.example
new file mode 100644
index 00000000000..9371e3619b7
--- /dev/null
+++ b/config/redis.shared_state.yml.example
@@ -0,0 +1,38 @@
+# If you change this file in a Merge Request, please also create
+# a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
+#
+development:
+ url: redis://localhost:6379/12
+ #
+ # url: redis://localhost:6382
+ # sentinels:
+ # -
+ # host: localhost
+ # port: 26382 # point to sentinel, not to redis port
+ # -
+ # host: slave2
+ # port: 26382 # point to sentinel, not to redis port
+test:
+ url: redis://localhost:6379/12
+ #
+ # url: redis://localhost:6382
+production:
+ # Redis (single instance)
+ url: unix:/var/run/redis/redis.shared_state.sock
+ ##
+ # Redis + Sentinel (for HA)
+ #
+ # Please read instructions carefully before using it as you may lose data:
+ # http://redis.io/topics/sentinel
+ #
+ # You must specify a list of a few sentinels that will handle client connection
+ # please read here for more information: https://docs.gitlab.com/ce/administration/high_availability/redis.html
+ ##
+ # url: redis://master:6382
+ # sentinels:
+ # -
+ # host: slave1
+ # port: 26382 # point to sentinel, not to redis port
+ # -
+ # host: slave2
+ # port: 26382 # point to sentinel, not to redis port
diff --git a/db/post_migrate/20170324160416_migrate_user_activities_to_users_last_activity_on.rb b/db/post_migrate/20170324160416_migrate_user_activities_to_users_last_activity_on.rb
index 397a9a2d28e..cb1b4f1855d 100644
--- a/db/post_migrate/20170324160416_migrate_user_activities_to_users_last_activity_on.rb
+++ b/db/post_migrate/20170324160416_migrate_user_activities_to_users_last_activity_on.rb
@@ -56,7 +56,7 @@ class MigrateUserActivitiesToUsersLastActivityOn < ActiveRecord::Migration
end
def activities(from, to, page: 1)
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
redis.zrangebyscore(USER_ACTIVITY_SET_KEY, from.to_i, to.to_i,
with_scores: true,
limit: limit(page))
@@ -64,7 +64,7 @@ class MigrateUserActivitiesToUsersLastActivityOn < ActiveRecord::Migration
end
def activities_count(from, to)
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
redis.zcount(USER_ACTIVITY_SET_KEY, from.to_i, to.to_i)
end
end
diff --git a/doc/administration/high_availability/redis_source.md b/doc/administration/high_availability/redis_source.md
index fe982ea83c2..8b7a515a076 100644
--- a/doc/administration/high_availability/redis_source.md
+++ b/doc/administration/high_availability/redis_source.md
@@ -4,6 +4,11 @@ This is the documentation for configuring a Highly Available Redis setup when
you have installed Redis all by yourself and not using the bundled one that
comes with the Omnibus packages.
+Note also that you may elect to override all references to
+`/home/git/gitlab/config/resque.yml` in accordance with the advanced Redis
+settings outlined in
+[Configuration Files Documentation](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/README.md).
+
We cannot stress enough the importance of reading the
[Overview section](redis.md#overview) of the Omnibus Redis HA as it provides
some invaluable information to the configuration of Redis. Please proceed to
diff --git a/doc/administration/operations/cleaning_up_redis_sessions.md b/doc/administration/operations/cleaning_up_redis_sessions.md
index 93521e976d5..3a35aff8366 100644
--- a/doc/administration/operations/cleaning_up_redis_sessions.md
+++ b/doc/administration/operations/cleaning_up_redis_sessions.md
@@ -15,6 +15,12 @@ prefixed with 'session:gitlab:', so they would look like
'session:gitlab:976aa289e2189b17d7ef525a6702ace9'. Below we describe how to
remove the keys in the old format.
+**Note:** the instructions below must be modified in accordance with your
+configuration settings if you have used the advanced Redis
+settings outlined in
+[Configuration Files Documentation](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/README.md).
+
+
First we define a shell function with the proper Redis connection details.
```
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index 3dc808c196d..c90d95e4dd0 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -25,6 +25,7 @@ Parameters:
| `order_by`| string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` |
| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc` |
| `milestone` | string | no | Return merge requests for a specific milestone |
+| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request |
| `labels` | string | no | Return merge requests matching a comma separated list of labels |
| `created_after` | datetime | no | Return merge requests created after the given time (inclusive) |
| `created_before` | datetime | no | Return merge requests created before the given time (inclusive) |
diff --git a/doc/api/users.md b/doc/api/users.md
index 91170e79645..6e5ec3231c5 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -364,7 +364,7 @@ GET /user
Parameters:
-- `sudo` (required) - the ID of a user
+- `sudo` (optional) - the ID of a user to make the call in their place
```
GET /user
diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md
index a984bb6c94c..0742b202807 100644
--- a/doc/development/fe_guide/vue.md
+++ b/doc/development/fe_guide/vue.md
@@ -112,7 +112,50 @@ Vue Resource should only be imported in the service file.
Vue.use(VueResource);
```
-### CSRF token
+#### Vue-resource gotchas
+#### Headers
+Headers are being parsed into a plain object in an interceptor.
+In Vue-resource 1.x `headers` object was changed into an `Headers` object. In order to not change all old code, an interceptor was added.
+
+If you need to write a unit test that takes the headers in consideration, you need to include an interceptor to parse the headers after your test interceptor.
+You can see an example in `spec/javascripts/environments/environment_spec.js`:
+ ```javascript
+ import { headersInterceptor } from './helpers/vue_resource_helper';
+
+ beforeEach(() => {
+ Vue.http.interceptors.push(myInterceptor);
+ Vue.http.interceptors.push(headersInterceptor);
+ });
+
+ afterEach(() => {
+ Vue.http.interceptors = _.without(Vue.http.interceptors, myInterceptor);
+ Vue.http.interceptors = _.without(Vue.http.interceptors, headersInterceptor);
+ });
+ ```
+
+#### `.json()`
+When making a request to the server, you will most likely need to access the body of the response.
+Use `.json()` to convert. Because `.json()` returns a Promise the follwoing structure should be used:
+
+ ```javascript
+ service.get('url')
+ .then(resp => resp.json())
+ .then((data) => {
+ this.store.storeData(data);
+ })
+ .catch(() => new Flash('Something went wrong'));
+ ```
+
+When using `Poll` (`app/assets/javascripts/lib/utils/poll.js`), the `successCallback` needs to handle `.json()` as a Promise:
+ ```javascript
+ successCallback: (response) => {
+ return response.json().then((data) => {
+ // handle the response
+ });
+ }
+ ```
+
+#### CSRF token
We use a Vue Resource interceptor to manage the CSRF token.
`app/assets/javascripts/vue_shared/vue_resource_interceptor.js` holds all our common interceptors.
Note: You don't need to load `app/assets/javascripts/vue_shared/vue_resource_interceptor.js`
@@ -126,13 +169,13 @@ The following example shows an application:
// store.js
export default class Store {
- /**
+ /**
* This is where we will iniatialize the state of our data.
* Usually in a small SPA you don't need any options when starting the store. In the case you do
* need guarantee it's an Object and it's documented.
- *
- * @param {Object} options
- */
+ *
+ * @param {Object} options
+ */
constructor(options) {
this.options = options;
@@ -205,14 +248,14 @@ import Store from 'store';
import Service from 'service';
import TodoComponent from 'todoComponent';
export default {
- /**
+ /**
* Although most data belongs in the store, each component it's own state.
* We want to show a loading spinner while we are fetching the todos, this state belong
* in the component.
*
* We need to access the store methods through all methods of our component.
* We need to access the state of our store.
- */
+ */
data() {
const store = new Store();
@@ -396,42 +439,46 @@ need to test the rendered output. [Vue][vue-test] guide's to unit test show us e
[Vue Resource Interceptors][vue-resource-interceptor] allow us to add a interceptor with
the response we need:
-```javascript
- // Mock the service to return data
- const interceptor = (request, next) => {
- next(request.respondWith(JSON.stringify([{
- title: 'This is a todo',
- body: 'This is the text'
- }]), {
- status: 200,
- }));
- };
+ ```javascript
+ // Mock the service to return data
+ const interceptor = (request, next) => {
+ next(request.respondWith(JSON.stringify([{
+ title: 'This is a todo',
+ body: 'This is the text'
+ }]), {
+ status: 200,
+ }));
+ };
- beforeEach(() => {
- Vue.http.interceptors.push(interceptor);
- });
+ beforeEach(() => {
+ Vue.http.interceptors.push(interceptor);
+ });
- afterEach(() => {
- Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor);
- });
+ afterEach(() => {
+ Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor);
+ });
- it('should do something', (done) => {
- setTimeout(() => {
- // Test received data
- done();
- }, 0);
- });
-```
+ it('should do something', (done) => {
+ setTimeout(() => {
+ // Test received data
+ done();
+ }, 0);
+ });
+ ```
+
+1. Headers interceptor
+Refer to [this section](vue.md#headers)
1. Use `$.mount()` to mount the component
+
```javascript
- // bad
- new Component({
- el: document.createElement('div')
- });
+// bad
+new Component({
+ el: document.createElement('div')
+});
- // good
- new Component().$mount();
+// good
+new Component().$mount();
```
[vue-docs]: http://vuejs.org/guide/index.html
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 992ff162efb..5e981b0b3e7 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -294,9 +294,9 @@ sudo usermod -aG redis git
### Clone the Source
# Clone GitLab repository
- sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 9-3-stable gitlab
+ sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 9-4-stable gitlab
-**Note:** You can change `9-3-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
+**Note:** You can change `9-4-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
### Configure It
@@ -420,6 +420,12 @@ GitLab Shell is an SSH access and repository management software developed speci
**Note:** Make sure your hostname can be resolved on the machine itself by either a proper DNS record or an additional line in /etc/hosts ("127.0.0.1 hostname"). This might be necessary for example if you set up GitLab behind a reverse proxy. If the hostname cannot be resolved, the final installation check will fail with "Check GitLab API access: FAILED. code: 401" and pushing commits will be rejected with "[remote rejected] master -> master (hook declined)".
+**Note:** GitLab Shell application startup time can be greatly reduced by disabling RubyGems. This can be done in several manners:
+
+* Export `RUBYOPT=--disable-gems` environment variable for the processes
+* Compile Ruby with `configure --disable-rubygems` to disable RubyGems by default. Not recommened for system-wide Ruby.
+* Omnibus GitLab [replaces the *shebang* line of the `gitlab-shell/bin/*` scripts](https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/1707)
+
### Install gitlab-workhorse
GitLab-Workhorse uses [GNU Make](https://www.gnu.org/software/make/). The
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index a3d676433e6..141df55f6bc 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -69,7 +69,7 @@ so keep in mind that you need at least 4GB available before running GitLab. With
less memory GitLab will give strange errors during the reconfigure run and 500
errors during usage.
-- 1GB RAM + 3GB of swap is the absolute minimum but we strongly **advise against** this amount of memory. See the unicorn worker section below for more advice.
+- 1GB RAM + 3GB of swap is the absolute minimum but we strongly **advise against** this amount of memory. See the [unicorn worker section below](#unicorn-workers) for more advice.
- 2GB RAM + 2GB swap supports up to 100 users but it will be very slow
- **4GB RAM** is the **recommended** memory size for all installations and supports up to 100 users
- 8GB RAM supports up to 1,000 users
diff --git a/doc/update/9.3-to-9.4.md b/doc/update/9.3-to-9.4.md
index bbb7f4a8d48..6962d124c80 100644
--- a/doc/update/9.3-to-9.4.md
+++ b/doc/update/9.3-to-9.4.md
@@ -72,8 +72,8 @@ More information can be found on the [yarn website](https://yarnpkg.com/en/docs/
### 5. Update Go
-NOTE: GitLab 9.4 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
+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`.
@@ -117,7 +117,7 @@ cd /home/git/gitlab
sudo -u git -H git checkout 9-4-stable-ee
```
-### 5. Update gitlab-shell
+### 7. Update gitlab-shell
```bash
cd /home/git/gitlab-shell
@@ -127,11 +127,10 @@ sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
sudo -u git -H bin/compile
```
-### 6. Update gitlab-workhorse
+### 8. Update gitlab-workhorse
-Install and compile gitlab-workhorse. This requires
-[Go 1.8](https://golang.org/dl) which should already be on your system from
-GitLab 8.1. GitLab-Workhorse uses [GNU Make](https://www.gnu.org/software/make/).
+Install and compile gitlab-workhorse. GitLab-Workhorse uses
+[GNU Make](https://www.gnu.org/software/make/).
If you are not using Linux you may have to run `gmake` instead of
`make` below.
@@ -143,7 +142,7 @@ sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
sudo -u git -H make
```
-### 7. Update Gitaly
+### 9. Update Gitaly
If you have not yet set up Gitaly then follow [Gitaly section of the installation
guide](../install/installation.md#install-gitaly).
@@ -171,7 +170,29 @@ sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
sudo -u git -H make
```
-### 10. Update configuration files
+### 10. Update MySQL permissions
+
+If you are using MySQL you need to grant the GitLab user the necessary
+permissions on the database:
+
+```bash
+mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
+```
+
+If you use MySQL with replication, or just have MySQL configured with binary logging,
+you will need to also run the following on all of your MySQL servers:
+
+```bash
+mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
+```
+
+You can make this setting permanent by adding it to your `my.cnf`:
+
+```
+log_bin_trust_function_creators=1
+```
+
+### 11. Update configuration files
#### New configuration options for `gitlab.yml`
@@ -245,7 +266,7 @@ For Ubuntu 16.04.1 LTS:
sudo systemctl daemon-reload
```
-### 11. Install libs, migrations, etc.
+### 12. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
@@ -271,14 +292,14 @@ sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-### 12. Start application
+### 13. Start application
```bash
sudo service gitlab start
sudo service nginx restart
```
-### 13. Check application status
+### 14. Check application status
Check if GitLab and its environment are configured correctly:
diff --git a/doc/user/admin_area/monitoring/health_check.md b/doc/user/admin_area/monitoring/health_check.md
index a954840b8a6..69a9dfc3500 100644
--- a/doc/user/admin_area/monitoring/health_check.md
+++ b/doc/user/admin_area/monitoring/health_check.md
@@ -5,6 +5,8 @@
- The `health_check` endpoint was [introduced][ce-3888] in GitLab 8.8 and will
be deprecated in GitLab 9.1. Read more in the [old behavior](#old-behavior)
section.
+ - [Access token](#access-token) has been deprecated in GitLab 9.4
+ in favor of [IP Whitelist](#ip-whitelist)
GitLab provides liveness and readiness probes to indicate service health and
reachability to required services. These probes report on the status of the
@@ -12,7 +14,19 @@ database connection, Redis connection, and access to the filesystem. These
endpoints [can be provided to schedulers like Kubernetes][kubernetes] to hold
traffic until the system is ready or restart the container as needed.
-## Access Token
+## IP Whitelist
+
+To access monitoring resources the client IP needs to be included in the whitelist.
+To add or remove hosts or IP ranges from the list you can edit `gitlab.rb` or `gitlab.yml`.
+
+Example whitelist configuration:
+```yaml
+monitoring:
+ ip_whitelist:
+ - 127.0.0.0/8 # by default only local IPs are allowed to access monitoring resources
+```
+
+## Access Token (Deprecated)
An access token needs to be provided while accessing the probe endpoints. The current
accepted token can be found under the **Admin area ➔ Monitoring ➔ Health check**
@@ -47,10 +61,10 @@ which will then provide a report of system health in JSON format:
## Using the Endpoint
-Once you have the access token, the probes can be accessed:
+With default whitelist settings, the probes can be accessed from localhost:
-- `https://gitlab.example.com/-/readiness?token=ACCESS_TOKEN`
-- `https://gitlab.example.com/-/liveness?token=ACCESS_TOKEN`
+- `http://localhost/-/readiness`
+- `http://localhost/-/liveness`
## Status
@@ -71,8 +85,8 @@ the database connection, the state of the database migrations, and the ability t
and access the cache. This endpoint can be provided to uptime monitoring services like
[Pingdom][pingdom], [Nagios][nagios-health], and [NewRelic][newrelic-health].
-Once you have the [access token](#access-token), health information can be
-retrieved as plain text, JSON, or XML using the `health_check` endpoint:
+Once you have the [access token](#access-token) or your client IP is [whitelisted](#ip-whitelist),
+health information can be retrieved as plain text, JSON, or XML using the `health_check` endpoint:
- `https://gitlab.example.com/health_check?token=ACCESS_TOKEN`
- `https://gitlab.example.com/health_check.json?token=ACCESS_TOKEN`
diff --git a/features/project/source/browse_files.feature b/features/project/source/browse_files.feature
deleted file mode 100644
index 59a625056d6..00000000000
--- a/features/project/source/browse_files.feature
+++ /dev/null
@@ -1,323 +0,0 @@
-Feature: Project Source Browse Files
- Background:
- Given I sign in as a user
- And I own project "Shop"
- Given I visit project source page
-
- Scenario: I browse files from master branch
- Then I should see files from repository
-
- Scenario: I browse files for specific ref
- Given I visit project source page for "6d39438"
- Then I should see files from repository for "6d39438"
-
- @javascript
- Scenario: I browse file content
- Given I click on ".gitignore" file in repo
- Then I should see its content
-
- Scenario: I browse raw file
- Given I visit blob file from repo
- And I click link "Raw"
- Then I should see raw file content
-
- Scenario: I can create file
- Given I click on "New file" link in repo
- Then I can see new file page
-
- Scenario: I can create file when I don't have write access
- Given I don't have write access
- And I click on "New file" link in repo
- Then I should see a notice about a new fork having been created
- Then I can see new file page
-
- @javascript
- Scenario: I can create and commit file
- Given I click on "New file" link in repo
- And I edit code
- And I fill the new file name
- And I fill the commit message
- And I click on "Commit changes"
- Then I am redirected to the new file
- And I should see its new content
-
- @javascript
- Scenario: I can create and commit file when I don't have write access
- Given I don't have write access
- And I click on "New file" link in repo
- And I edit code
- And I fill the new file name
- And I fill the commit message
- And I click on "Commit changes"
- Then I am redirected to the fork's new merge request page
- And I can see the new commit message
-
- @javascript
- Scenario: I can create and commit file with new lines at the end of file
- Given I click on "New file" link in repo
- And I edit code with new lines at end of file
- And I fill the new file name
- And I fill the commit message
- And I click on "Commit changes"
- Then I am redirected to the new file
- And I click button "Edit"
- And I should see its content with new lines preserved at end of file
-
- @javascript
- Scenario: I can create and commit file and specify new branch
- Given I click on "New file" link in repo
- And I edit code
- And I fill the new file name
- And I fill the commit message
- And I fill the new branch name
- And I click on "Commit changes"
- Then I am redirected to the new merge request page
- When I click on "Changes" tab
- And I should see its new content
-
- @javascript
- Scenario: I can upload file and commit
- Given I click on "Upload file" link in repo
- And I upload a new text file
- And I fill the upload file commit message
- And I fill the new branch name
- And I click on "Upload file"
- Then I can see the new commit message
- And I am redirected to the new merge request page
- When I click on "Changes" tab
- Then I can see the new text file
-
- @javascript
- Scenario: I can upload file and commit when I don't have write access
- Given I don't have write access
- And I click on "Upload file" link in repo
- Then I should see a notice about a new fork having been created
- When I click on "Upload file" link in repo
- And I upload a new text file
- And I fill the upload file commit message
- And I click on "Upload file"
- Then I can see the new commit message
- And I am redirected to the fork's new merge request page
- When I click on "Changes" tab
- Then I can see the new text file
-
- @javascript
- Scenario: I can replace file and commit
- Given I click on ".gitignore" file in repo
- And I see the ".gitignore"
- And I click on "Replace"
- And I replace it with a text file
- And I fill the replace file commit message
- And I click on "Replace file"
- Then I can see the new text file
- And I can see the replacement commit message
-
- @javascript
- Scenario: I can replace file and commit when I don't have write access
- Given I don't have write access
- And I click on ".gitignore" file in repo
- And I see the ".gitignore"
- And I click on "Replace"
- Then I should see a Fork/Cancel combo
- And I click button "Fork"
- Then I should see a notice about a new fork having been created
- When I click on "Replace"
- And I replace it with a text file
- And I fill the replace file commit message
- And I click on "Replace file"
- And I can see the replacement commit message
- And I am redirected to the fork's new merge request page
- When I click on "Changes" tab
- Then I can see the new text file
-
- @javascript
- Scenario: I can create file with a directory name
- Given I click on "New file" link in repo
- And I fill the new file name with a new directory
- And I edit code
- And I fill the commit message
- And I click on "Commit changes"
- Then I am redirected to the new file with directory
- And I should see its new content
-
- @javascript
- Scenario: I can edit file
- Given I click on ".gitignore" file in repo
- And I click button "Edit"
- Then I can edit code
-
- @javascript
- Scenario: I can edit file when I don't have write access
- Given I don't have write access
- And I click on ".gitignore" file in repo
- And I click button "Edit"
- Then I should see a Fork/Cancel combo
- And I click button "Fork"
- Then I should see a notice about a new fork having been created
- And I can edit code
-
- Scenario: If the file is binary the edit link is hidden
- Given I visit a binary file in the repo
- Then I cannot see the edit button
-
- @javascript
- Scenario: I can edit and commit file
- Given I click on ".gitignore" file in repo
- And I click button "Edit"
- And I edit code
- And I fill the commit message
- And I click on "Commit changes"
- Then I am redirected to the ".gitignore"
- And I should see its new content
-
- @javascript
- Scenario: I can edit and commit file when I don't have write access
- Given I don't have write access
- And I click on ".gitignore" file in repo
- And I click button "Edit"
- Then I should see a Fork/Cancel combo
- And I click button "Fork"
- And I edit code
- And I fill the commit message
- And I click on "Commit changes"
- Then I am redirected to the fork's new merge request page
- And I can see the new commit message
-
- @javascript
- Scenario: I can edit and commit file to new branch
- Given I click on ".gitignore" file in repo
- And I click button "Edit"
- And I edit code
- And I fill the commit message
- And I fill the new branch name
- And I click on "Commit changes"
- Then I am redirected to the new merge request page
- Then I click on "Changes" tab
- And I should see its new content
-
- @javascript @wip
- Scenario: If I don't change the content of the file I see an error message
- Given I click on ".gitignore" file in repo
- And I click button "edit"
- And I fill the commit message
- And I click on "Commit changes"
- # Test fails because carriage returns are added to the file.
- Then I am on the ".gitignore" edit file page
- And I see a commit error message
-
- @javascript
- Scenario: I can create directory in repo
- When I click on "New directory" link in repo
- And I fill the new directory name
- And I fill the commit message
- And I fill the new branch name
- And I click on "Create directory"
- Then I am redirected to the new merge request page
-
- @javascript
- Scenario: I can create directory in repo when I don't have write access
- Given I don't have write access
- When I click on "New directory" link in repo
- Then I should see a notice about a new fork having been created
- When I click on "New directory" link in repo
- And I fill the new directory name
- And I fill the commit message
- And I click on "Create directory"
- Then I am redirected to the fork's new merge request page
-
- @javascript
- Scenario: I attempt to create an existing directory
- When I click on "New directory" link in repo
- And I fill an existing directory name
- And I fill the commit message
- And I click on "Create directory"
- Then I see "Unable to create directory"
- And I am redirected to the root directory
-
- @javascript
- Scenario: I can see editing preview
- Given I click on ".gitignore" file in repo
- And I click button "Edit"
- And I edit code
- And I click link "Diff"
- Then I see diff
-
- @javascript
- Scenario: I can delete file and commit
- Given I click on ".gitignore" file in repo
- And I see the ".gitignore"
- And I click on "Delete"
- And I fill the commit message
- And I click on "Delete file"
- Then I am redirected to the files URL
- And I don't see the ".gitignore"
-
- @javascript
- Scenario: I can delete file and commit when I don't have write access
- Given I don't have write access
- And I click on ".gitignore" file in repo
- And I see the ".gitignore"
- And I click on "Delete"
- Then I should see a Fork/Cancel combo
- And I click button "Fork"
- Then I should see a notice about a new fork having been created
- When I click on "Delete"
- And I fill the commit message
- And I click on "Delete file"
- Then I am redirected to the fork's new merge request page
- And I can see the new commit message
-
- Scenario: I can browse directory with Browse Dir
- Given I click on files directory
- And I click on History link
- Then I see Browse dir link
-
- Scenario: I can browse file with Browse File
- Given I click on readme file
- And I click on History link
- Then I see Browse file link
-
- Scenario: I can browse code with Browse Code
- Given I click on History link
- Then I see Browse code link
-
- # Permalink
-
- Scenario: I click on the permalink link from a branch ref
- Given I click on ".gitignore" file in repo
- And I click on Permalink
- Then I am redirected to the permalink URL
-
- Scenario: I don't see the permalink link from a SHA ref
- Given I visit project source page for "6d394385cf567f80a8fd85055db1ab4c5295806f"
- And I click on ".gitignore" file in repo
- Then I don't see the permalink link
-
- @javascript
- Scenario: I browse code with single quotes in the ref
- Given I switch ref to 'test'
- And I see the ref 'test' has been selected
- And I visit the 'test' tree
- Then I see the commit data
-
- @javascript
- Scenario: I browse code with a leading dot in the directory
- Given I switch ref to fix
- And I visit the fix tree
- Then I see the commit data for a directory with a leading dot
-
- Scenario: I browse LFS object
- Given I click on "files/lfs/lfs_object.iso" file in repo
- Then I should see download link and object size
- And I should not see lfs pointer details
- And I should see buttons for allowed commands
-
- @javascript
- Scenario: I preview an SVG file
- Given I click on "Upload file" link in repo
- And I upload a new SVG file
- And I fill the upload file commit message
- And I fill the new branch name
- And I click on "Upload file"
- Given I visit the SVG file
- Then I can see the new rendered SVG image
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 945f2821d72..47742a164fc 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -314,6 +314,13 @@ module API
expose :id
end
+ class MergeRequestSimple < ProjectEntity
+ expose :title
+ expose :web_url do |merge_request, options|
+ Gitlab::UrlBuilder.build(merge_request)
+ end
+ end
+
class MergeRequestBasic < ProjectEntity
expose :target_branch, :source_branch
expose :upvotes do |merge_request, options|
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 4ad1eef4ff1..ac33b2b801c 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -44,9 +44,14 @@ module API
args[:label_name] = args.delete(:labels)
merge_requests = MergeRequestsFinder.new(current_user, args).execute
- .preload(:notes, :target_project, :author, :assignee, :milestone, :merge_request_diff, :labels)
+ .reorder(args[:order_by] => args[:sort])
+ merge_requests = paginate(merge_requests)
+ .preload(:target_project)
- merge_requests.reorder(args[:order_by] => args[:sort])
+ return merge_requests if args[:view] == 'simple'
+
+ merge_requests
+ .preload(:notes, :author, :assignee, :milestone, :merge_request_diff, :labels)
end
params :optional_params_ce do
@@ -77,15 +82,25 @@ module API
optional :labels, type: String, desc: 'Comma-separated list of label names'
optional :created_after, type: DateTime, desc: 'Return merge requests created after the specified time'
optional :created_before, type: DateTime, desc: 'Return merge requests created before the specified time'
+ optional :view, type: String, values: %w[simple], desc: 'If simple, returns the `iid`, URL, title, description, and basic state of merge request'
use :pagination
end
get ":id/merge_requests" do
authorize! :read_merge_request, user_project
merge_requests = find_merge_requests(project_id: user_project.id)
- issuable_metadata = issuable_meta_data(merge_requests, 'MergeRequest')
- present paginate(merge_requests), with: Entities::MergeRequestBasic, current_user: current_user, project: user_project, issuable_metadata: issuable_metadata
+ options = { with: Entities::MergeRequestBasic,
+ current_user: current_user,
+ project: user_project }
+
+ if params[:view] == 'simple'
+ options[:with] = Entities::MergeRequestSimple
+ else
+ options[:issuable_metadata] = issuable_meta_data(merge_requests, 'MergeRequest')
+ end
+
+ present merge_requests, options
end
desc 'Create a merge request' do
diff --git a/lib/api/users.rb b/lib/api/users.rb
index c469751c31c..81c68ea2658 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -421,7 +421,16 @@ module API
success Entities::UserPublic
end
get do
- present current_user, with: sudo? ? Entities::UserWithPrivateDetails : Entities::UserPublic
+ entity =
+ if sudo?
+ Entities::UserWithPrivateDetails
+ elsif current_user.admin?
+ Entities::UserWithAdmin
+ else
+ Entities::UserPublic
+ end
+
+ present current_user, with: entity
end
desc "Get the currently authenticated user's SSH keys" do
diff --git a/lib/gitlab/auth/unique_ips_limiter.rb b/lib/gitlab/auth/unique_ips_limiter.rb
index bf2239ca150..baa1f802d8a 100644
--- a/lib/gitlab/auth/unique_ips_limiter.rb
+++ b/lib/gitlab/auth/unique_ips_limiter.rb
@@ -27,7 +27,7 @@ module Gitlab
time = Time.now.utc.to_i
key = "#{USER_UNIQUE_IPS_PREFIX}:#{user_id}"
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
unique_ips_count = nil
redis.multi do |r|
r.zadd(key, time, ip)
diff --git a/lib/gitlab/cache/ci/project_pipeline_status.rb b/lib/gitlab/cache/ci/project_pipeline_status.rb
index 9c2e09943b0..dba37892863 100644
--- a/lib/gitlab/cache/ci/project_pipeline_status.rb
+++ b/lib/gitlab/cache/ci/project_pipeline_status.rb
@@ -23,7 +23,7 @@ module Gitlab
end
def self.cached_results_for_projects(projects)
- result = Gitlab::Redis.with do |redis|
+ result = Gitlab::Redis::Cache.with do |redis|
redis.multi do
projects.each do |project|
cache_key = cache_key_for_project(project)
@@ -100,19 +100,19 @@ module Gitlab
end
def load_from_cache
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::Cache.with do |redis|
self.sha, self.status, self.ref = redis.hmget(cache_key, :sha, :status, :ref)
end
end
def store_in_cache
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::Cache.with do |redis|
redis.mapped_hmset(cache_key, { sha: sha, status: status, ref: ref })
end
end
def delete_from_cache
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::Cache.with do |redis|
redis.del(cache_key)
end
end
@@ -120,7 +120,7 @@ module Gitlab
def has_cache?
return self.loaded unless self.loaded.nil?
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::Cache.with do |redis|
redis.exists(cache_key)
end
end
diff --git a/lib/gitlab/chat_name_token.rb b/lib/gitlab/chat_name_token.rb
index 1b081aa9b1d..e63e5437331 100644
--- a/lib/gitlab/chat_name_token.rb
+++ b/lib/gitlab/chat_name_token.rb
@@ -12,23 +12,23 @@ module Gitlab
end
def get
- Gitlab::Redis.with do |redis|
- data = redis.get(redis_key)
+ Gitlab::Redis::SharedState.with do |redis|
+ data = redis.get(redis_shared_state_key)
JSON.parse(data, symbolize_names: true) if data
end
end
def store!(params)
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
params = params.to_json
- redis.set(redis_key, params, ex: EXPIRY_TIME)
+ redis.set(redis_shared_state_key, params, ex: EXPIRY_TIME)
token
end
end
def delete
- Gitlab::Redis.with do |redis|
- redis.del(redis_key)
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.del(redis_shared_state_key)
end
end
@@ -38,7 +38,7 @@ module Gitlab
Devise.friendly_token(TOKEN_LENGTH)
end
- def redis_key
+ def redis_shared_state_key
"gitlab:chat_names:#{token}"
end
end
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index 791a3c36476..7fa02f3d7b3 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -25,7 +25,7 @@ module Gitlab
def cached_application_settings
begin
::ApplicationSetting.cached
- rescue ::Redis::BaseError, ::Errno::ENOENT
+ rescue ::Redis::BaseError, ::Errno::ENOENT, ::Errno::EADDRNOTAVAIL
# In case Redis isn't running or the Redis UNIX socket file is not available
end
end
diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb
index 33f8939bc61..1a697396ff1 100644
--- a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb
+++ b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb
@@ -145,7 +145,7 @@ module Gitlab
def track_rename(type, old_path, new_path)
key = redis_key_for_type(type)
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
redis.lpush(key, [old_path, new_path].to_json)
redis.expire(key, 2.weeks.to_i)
end
@@ -155,7 +155,7 @@ module Gitlab
def reverts_for_type(type)
key = redis_key_for_type(type)
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
failed_reverts = []
while rename_info = redis.lpop(key)
diff --git a/lib/gitlab/etag_caching/store.rb b/lib/gitlab/etag_caching/store.rb
index 072fcfc65e6..21172ff8d93 100644
--- a/lib/gitlab/etag_caching/store.rb
+++ b/lib/gitlab/etag_caching/store.rb
@@ -2,17 +2,17 @@ module Gitlab
module EtagCaching
class Store
EXPIRY_TIME = 20.minutes
- REDIS_NAMESPACE = 'etag:'.freeze
+ SHARED_STATE_NAMESPACE = 'etag:'.freeze
def get(key)
- Gitlab::Redis.with { |redis| redis.get(redis_key(key)) }
+ Gitlab::Redis::SharedState.with { |redis| redis.get(redis_shared_state_key(key)) }
end
def touch(key, only_if_missing: false)
etag = generate_etag
- Gitlab::Redis.with do |redis|
- redis.set(redis_key(key), etag, ex: EXPIRY_TIME, nx: only_if_missing)
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.set(redis_shared_state_key(key), etag, ex: EXPIRY_TIME, nx: only_if_missing)
end
etag
@@ -24,10 +24,10 @@ module Gitlab
SecureRandom.hex
end
- def redis_key(key)
+ def redis_shared_state_key(key)
raise 'Invalid key' if !Rails.env.production? && !Gitlab::EtagCaching::Router.match(key)
- "#{REDIS_NAMESPACE}#{key}"
+ "#{SHARED_STATE_NAMESPACE}#{key}"
end
end
end
diff --git a/lib/gitlab/exclusive_lease.rb b/lib/gitlab/exclusive_lease.rb
index a0f46594eb1..3784f6c4947 100644
--- a/lib/gitlab/exclusive_lease.rb
+++ b/lib/gitlab/exclusive_lease.rb
@@ -26,17 +26,17 @@ module Gitlab
EOS
def self.cancel(key, uuid)
- Gitlab::Redis.with do |redis|
- redis.eval(LUA_CANCEL_SCRIPT, keys: [redis_key(key)], argv: [uuid])
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.eval(LUA_CANCEL_SCRIPT, keys: [redis_shared_state_key(key)], argv: [uuid])
end
end
- def self.redis_key(key)
+ def self.redis_shared_state_key(key)
"gitlab:exclusive_lease:#{key}"
end
def initialize(key, timeout:)
- @redis_key = self.class.redis_key(key)
+ @redis_shared_state_key = self.class.redis_shared_state_key(key)
@timeout = timeout
@uuid = SecureRandom.uuid
end
@@ -45,24 +45,24 @@ module Gitlab
# false if the lease is already taken.
def try_obtain
# Performing a single SET is atomic
- Gitlab::Redis.with do |redis|
- redis.set(@redis_key, @uuid, nx: true, ex: @timeout) && @uuid
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.set(@redis_shared_state_key, @uuid, nx: true, ex: @timeout) && @uuid
end
end
# Try to renew an existing lease. Return lease UUID on success,
# false if the lease is taken by a different UUID or inexistent.
def renew
- Gitlab::Redis.with do |redis|
- result = redis.eval(LUA_RENEW_SCRIPT, keys: [@redis_key], argv: [@uuid, @timeout])
+ Gitlab::Redis::SharedState.with do |redis|
+ result = redis.eval(LUA_RENEW_SCRIPT, keys: [@redis_shared_state_key], argv: [@uuid, @timeout])
result == @uuid
end
end
# Returns true if the key for this lease is set.
def exists?
- Gitlab::Redis.with do |redis|
- redis.exists(@redis_key)
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.exists(@redis_shared_state_key)
end
end
end
diff --git a/lib/gitlab/health_checks/redis/cache_check.rb b/lib/gitlab/health_checks/redis/cache_check.rb
new file mode 100644
index 00000000000..a28658d42d4
--- /dev/null
+++ b/lib/gitlab/health_checks/redis/cache_check.rb
@@ -0,0 +1,31 @@
+module Gitlab
+ module HealthChecks
+ module Redis
+ class CacheCheck
+ extend SimpleAbstractCheck
+
+ class << self
+ def check_up
+ check
+ end
+
+ private
+
+ def metric_prefix
+ 'redis_cache_ping'
+ end
+
+ def is_successful?(result)
+ result == 'PONG'
+ end
+
+ def check
+ catch_timeout 10.seconds do
+ Gitlab::Redis::Cache.with(&:ping)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/health_checks/redis/queues_check.rb b/lib/gitlab/health_checks/redis/queues_check.rb
new file mode 100644
index 00000000000..f97d50d3947
--- /dev/null
+++ b/lib/gitlab/health_checks/redis/queues_check.rb
@@ -0,0 +1,31 @@
+module Gitlab
+ module HealthChecks
+ module Redis
+ class QueuesCheck
+ extend SimpleAbstractCheck
+
+ class << self
+ def check_up
+ check
+ end
+
+ private
+
+ def metric_prefix
+ 'redis_queues_ping'
+ end
+
+ def is_successful?(result)
+ result == 'PONG'
+ end
+
+ def check
+ catch_timeout 10.seconds do
+ Gitlab::Redis::Queues.with(&:ping)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/health_checks/redis/redis_check.rb b/lib/gitlab/health_checks/redis/redis_check.rb
new file mode 100644
index 00000000000..fe4e3c4a3ab
--- /dev/null
+++ b/lib/gitlab/health_checks/redis/redis_check.rb
@@ -0,0 +1,27 @@
+module Gitlab
+ module HealthChecks
+ module Redis
+ class RedisCheck
+ extend SimpleAbstractCheck
+
+ class << self
+ private
+
+ def metric_prefix
+ 'redis_ping'
+ end
+
+ def is_successful?(result)
+ result == 'PONG'
+ end
+
+ def check
+ ::Gitlab::HealthChecks::Redis::CacheCheck.check_up &&
+ ::Gitlab::HealthChecks::Redis::QueuesCheck.check_up &&
+ ::Gitlab::HealthChecks::Redis::SharedStateCheck.check_up
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/health_checks/redis/shared_state_check.rb b/lib/gitlab/health_checks/redis/shared_state_check.rb
new file mode 100644
index 00000000000..e3244392902
--- /dev/null
+++ b/lib/gitlab/health_checks/redis/shared_state_check.rb
@@ -0,0 +1,31 @@
+module Gitlab
+ module HealthChecks
+ module Redis
+ class SharedStateCheck
+ extend SimpleAbstractCheck
+
+ class << self
+ def check_up
+ check
+ end
+
+ private
+
+ def metric_prefix
+ 'redis_shared_state_ping'
+ end
+
+ def is_successful?(result)
+ result == 'PONG'
+ end
+
+ def check
+ catch_timeout 10.seconds do
+ Gitlab::Redis::SharedState.with(&:ping)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/health_checks/redis_check.rb b/lib/gitlab/health_checks/redis_check.rb
deleted file mode 100644
index 57bbe5b3ad0..00000000000
--- a/lib/gitlab/health_checks/redis_check.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-module Gitlab
- module HealthChecks
- class RedisCheck
- extend SimpleAbstractCheck
-
- class << self
- private
-
- def metric_prefix
- 'redis_ping'
- end
-
- def is_successful?(result)
- result == 'PONG'
- end
-
- def check
- catch_timeout 10.seconds do
- Gitlab::Redis.with(&:ping)
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/lfs_token.rb b/lib/gitlab/lfs_token.rb
index 5f67e97fa2a..8e57ba831c5 100644
--- a/lib/gitlab/lfs_token.rb
+++ b/lib/gitlab/lfs_token.rb
@@ -18,10 +18,10 @@ module Gitlab
end
def token
- Gitlab::Redis.with do |redis|
- token = redis.get(redis_key)
+ Gitlab::Redis::SharedState.with do |redis|
+ token = redis.get(redis_shared_state_key)
token ||= Devise.friendly_token(TOKEN_LENGTH)
- redis.set(redis_key, token, ex: EXPIRY_TIME)
+ redis.set(redis_shared_state_key, token, ex: EXPIRY_TIME)
token
end
@@ -41,7 +41,7 @@ module Gitlab
private
- def redis_key
+ def redis_shared_state_key
"gitlab:lfs_token:#{actor.class.name.underscore}_#{actor.id}" if actor
end
end
diff --git a/lib/gitlab/mail_room.rb b/lib/gitlab/mail_room.rb
index 3503fac40e8..9f432673a6e 100644
--- a/lib/gitlab/mail_room.rb
+++ b/lib/gitlab/mail_room.rb
@@ -1,6 +1,6 @@
require 'yaml'
require 'json'
-require_relative 'redis' unless defined?(Gitlab::Redis)
+require_relative 'redis/queues' unless defined?(Gitlab::Redis::Queues)
module Gitlab
module MailRoom
@@ -34,11 +34,11 @@ module Gitlab
config[:idle_timeout] = 60 if config[:idle_timeout].nil?
if config[:enabled] && config[:address]
- gitlab_redis = Gitlab::Redis.new(rails_env)
- config[:redis_url] = gitlab_redis.url
+ gitlab_redis_queues = Gitlab::Redis::Queues.new(rails_env)
+ config[:redis_url] = gitlab_redis_queues.url
- if gitlab_redis.sentinels?
- config[:sentinels] = gitlab_redis.sentinels
+ if gitlab_redis_queues.sentinels?
+ config[:sentinels] = gitlab_redis_queues.sentinels
end
end
diff --git a/lib/gitlab/o_auth/user.rb b/lib/gitlab/o_auth/user.rb
index b3f453e506d..3f2bbd9f6a6 100644
--- a/lib/gitlab/o_auth/user.rb
+++ b/lib/gitlab/o_auth/user.rb
@@ -101,14 +101,18 @@ module Gitlab
# Look for a corresponding person with same uid in any of the configured LDAP providers
Gitlab::LDAP::Config.providers.each do |provider|
adapter = Gitlab::LDAP::Adapter.new(provider)
- @ldap_person = Gitlab::LDAP::Person.find_by_uid(auth_hash.uid, adapter)
- # The `uid` might actually be a DN. Try it next.
- @ldap_person ||= Gitlab::LDAP::Person.find_by_dn(auth_hash.uid, adapter)
+ @ldap_person = find_ldap_person(auth_hash, adapter)
break if @ldap_person
end
@ldap_person
end
+ def find_ldap_person(auth_hash, adapter)
+ by_uid = Gitlab::LDAP::Person.find_by_uid(auth_hash.uid, adapter)
+ # The `uid` might actually be a DN. Try it next.
+ by_uid || Gitlab::LDAP::Person.find_by_dn(auth_hash.uid, adapter)
+ end
+
def ldap_config
Gitlab::LDAP::Config.new(ldap_person.provider) if ldap_person
end
diff --git a/lib/gitlab/redis.rb b/lib/gitlab/redis.rb
deleted file mode 100644
index bc5370de32a..00000000000
--- a/lib/gitlab/redis.rb
+++ /dev/null
@@ -1,102 +0,0 @@
-# This file should not have any direct dependency on Rails environment
-# please require all dependencies below:
-require 'active_support/core_ext/hash/keys'
-require 'active_support/core_ext/module/delegation'
-
-module Gitlab
- class Redis
- CACHE_NAMESPACE = 'cache:gitlab'.freeze
- SESSION_NAMESPACE = 'session:gitlab'.freeze
- SIDEKIQ_NAMESPACE = 'resque:gitlab'.freeze
- MAILROOM_NAMESPACE = 'mail_room:gitlab'.freeze
- DEFAULT_REDIS_URL = 'redis://localhost:6379'.freeze
-
- class << self
- delegate :params, :url, to: :new
-
- def with
- @pool ||= ConnectionPool.new(size: pool_size) { ::Redis.new(params) }
- @pool.with { |redis| yield redis }
- end
-
- def pool_size
- if Sidekiq.server?
- # the pool will be used in a multi-threaded context
- Sidekiq.options[:concurrency] + 5
- else
- # probably this is a Unicorn process, so single threaded
- 5
- end
- end
-
- def _raw_config
- return @_raw_config if defined?(@_raw_config)
-
- begin
- @_raw_config = ERB.new(File.read(config_file)).result.freeze
- rescue Errno::ENOENT
- @_raw_config = false
- end
-
- @_raw_config
- end
-
- def config_file
- ENV['GITLAB_REDIS_CONFIG_FILE'] || File.expand_path('../../config/resque.yml', __dir__)
- end
- end
-
- def initialize(rails_env = nil)
- @rails_env = rails_env || ::Rails.env
- end
-
- def params
- redis_store_options
- end
-
- def url
- raw_config_hash[:url]
- end
-
- def sentinels
- raw_config_hash[:sentinels]
- end
-
- def sentinels?
- sentinels && !sentinels.empty?
- end
-
- private
-
- def redis_store_options
- config = raw_config_hash
- redis_url = config.delete(:url)
- redis_uri = URI.parse(redis_url)
-
- if redis_uri.scheme == 'unix'
- # Redis::Store does not handle Unix sockets well, so let's do it for them
- config[:path] = redis_uri.path
- config
- else
- redis_hash = ::Redis::Store::Factory.extract_host_options_from_uri(redis_url)
- # order is important here, sentinels must be after the connection keys.
- # {url: ..., port: ..., sentinels: [...]}
- redis_hash.merge(config)
- end
- end
-
- def raw_config_hash
- config_data = fetch_config
-
- if config_data
- config_data.is_a?(String) ? { url: config_data } : config_data.deep_symbolize_keys
- else
- { url: DEFAULT_REDIS_URL }
- end
- end
-
- def fetch_config
- self.class._raw_config ? YAML.load(self.class._raw_config)[@rails_env] : false
- end
- end
-end
diff --git a/lib/gitlab/redis/cache.rb b/lib/gitlab/redis/cache.rb
new file mode 100644
index 00000000000..b0da516ff83
--- /dev/null
+++ b/lib/gitlab/redis/cache.rb
@@ -0,0 +1,34 @@
+# please require all dependencies below:
+require_relative 'wrapper' unless defined?(::Gitlab::Redis::Wrapper)
+
+module Gitlab
+ module Redis
+ class Cache < ::Gitlab::Redis::Wrapper
+ CACHE_NAMESPACE = 'cache:gitlab'.freeze
+ DEFAULT_REDIS_CACHE_URL = 'redis://localhost:6380'.freeze
+ REDIS_CACHE_CONFIG_ENV_VAR_NAME = 'GITLAB_REDIS_CACHE_CONFIG_FILE'.freeze
+ if defined?(::Rails) && ::Rails.root.present?
+ DEFAULT_REDIS_CACHE_CONFIG_FILE_NAME = ::Rails.root.join('config', 'redis.cache.yml').freeze
+ end
+
+ class << self
+ def default_url
+ DEFAULT_REDIS_CACHE_URL
+ end
+
+ def config_file_name
+ # if ENV set for this class, use it even if it points to a file does not exist
+ file_name = ENV[REDIS_CACHE_CONFIG_ENV_VAR_NAME]
+ return file_name unless file_name.nil?
+
+ # otherwise, if config files exists for this class, use it
+ file_name = File.expand_path(DEFAULT_REDIS_CACHE_CONFIG_FILE_NAME, __dir__)
+ return file_name if File.file?(file_name)
+
+ # this will force use of DEFAULT_REDIS_QUEUES_URL when config file is absent
+ super
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/redis/queues.rb b/lib/gitlab/redis/queues.rb
new file mode 100644
index 00000000000..f9249d05565
--- /dev/null
+++ b/lib/gitlab/redis/queues.rb
@@ -0,0 +1,35 @@
+# please require all dependencies below:
+require_relative 'wrapper' unless defined?(::Gitlab::Redis::Wrapper)
+
+module Gitlab
+ module Redis
+ class Queues < ::Gitlab::Redis::Wrapper
+ SIDEKIQ_NAMESPACE = 'resque:gitlab'.freeze
+ MAILROOM_NAMESPACE = 'mail_room:gitlab'.freeze
+ DEFAULT_REDIS_QUEUES_URL = 'redis://localhost:6381'.freeze
+ REDIS_QUEUES_CONFIG_ENV_VAR_NAME = 'GITLAB_REDIS_QUEUES_CONFIG_FILE'.freeze
+ if defined?(::Rails) && ::Rails.root.present?
+ DEFAULT_REDIS_QUEUES_CONFIG_FILE_NAME = ::Rails.root.join('config', 'redis.queues.yml').freeze
+ end
+
+ class << self
+ def default_url
+ DEFAULT_REDIS_QUEUES_URL
+ end
+
+ def config_file_name
+ # if ENV set for this class, use it even if it points to a file does not exist
+ file_name = ENV[REDIS_QUEUES_CONFIG_ENV_VAR_NAME]
+ return file_name if file_name
+
+ # otherwise, if config files exists for this class, use it
+ file_name = File.expand_path(DEFAULT_REDIS_QUEUES_CONFIG_FILE_NAME, __dir__)
+ return file_name if File.file?(file_name)
+
+ # this will force use of DEFAULT_REDIS_QUEUES_URL when config file is absent
+ super
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/redis/shared_state.rb b/lib/gitlab/redis/shared_state.rb
new file mode 100644
index 00000000000..395dcf082da
--- /dev/null
+++ b/lib/gitlab/redis/shared_state.rb
@@ -0,0 +1,34 @@
+# please require all dependencies below:
+require_relative 'wrapper' unless defined?(::Gitlab::Redis::Wrapper)
+
+module Gitlab
+ module Redis
+ class SharedState < ::Gitlab::Redis::Wrapper
+ SESSION_NAMESPACE = 'session:gitlab'.freeze
+ DEFAULT_REDIS_SHARED_STATE_URL = 'redis://localhost:6382'.freeze
+ REDIS_SHARED_STATE_CONFIG_ENV_VAR_NAME = 'GITLAB_REDIS_SHARED_STATE_CONFIG_FILE'.freeze
+ if defined?(::Rails) && ::Rails.root.present?
+ DEFAULT_REDIS_SHARED_STATE_CONFIG_FILE_NAME = ::Rails.root.join('config', 'redis.shared_state.yml').freeze
+ end
+
+ class << self
+ def default_url
+ DEFAULT_REDIS_SHARED_STATE_URL
+ end
+
+ def config_file_name
+ # if ENV set for this class, use it even if it points to a file does not exist
+ file_name = ENV[REDIS_SHARED_STATE_CONFIG_ENV_VAR_NAME]
+ return file_name if file_name
+
+ # otherwise, if config files exists for this class, use it
+ file_name = File.expand_path(DEFAULT_REDIS_SHARED_STATE_CONFIG_FILE_NAME, __dir__)
+ return file_name if File.file?(file_name)
+
+ # this will force use of DEFAULT_REDIS_SHARED_STATE_URL when config file is absent
+ super
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/redis/wrapper.rb b/lib/gitlab/redis/wrapper.rb
new file mode 100644
index 00000000000..c43b37dde74
--- /dev/null
+++ b/lib/gitlab/redis/wrapper.rb
@@ -0,0 +1,135 @@
+# This file should only be used by sub-classes, not directly by any clients of the sub-classes
+# please require all dependencies below:
+require 'active_support/core_ext/hash/keys'
+require 'active_support/core_ext/module/delegation'
+
+module Gitlab
+ module Redis
+ class Wrapper
+ DEFAULT_REDIS_URL = 'redis://localhost:6379'.freeze
+ REDIS_CONFIG_ENV_VAR_NAME = 'GITLAB_REDIS_CONFIG_FILE'.freeze
+ if defined?(::Rails) && ::Rails.root.present?
+ DEFAULT_REDIS_CONFIG_FILE_NAME = ::Rails.root.join('config', 'resque.yml').freeze
+ end
+
+ class << self
+ delegate :params, :url, to: :new
+
+ def with
+ @pool ||= ConnectionPool.new(size: pool_size) { ::Redis.new(params) }
+ @pool.with { |redis| yield redis }
+ end
+
+ def pool_size
+ # heuristic constant 5 should be a config setting somewhere -- related to CPU count?
+ size = 5
+ if Sidekiq.server?
+ # the pool will be used in a multi-threaded context
+ size += Sidekiq.options[:concurrency]
+ end
+ size
+ end
+
+ def _raw_config
+ return @_raw_config if defined?(@_raw_config)
+
+ @_raw_config =
+ begin
+ if filename = config_file_name
+ ERB.new(File.read(filename)).result.freeze
+ else
+ false
+ end
+ rescue Errno::ENOENT
+ false
+ end
+ end
+
+ def default_url
+ DEFAULT_REDIS_URL
+ end
+
+ def config_file_name
+ # if ENV set for wrapper class, use it even if it points to a file does not exist
+ file_name = ENV[REDIS_CONFIG_ENV_VAR_NAME]
+ return file_name unless file_name.nil?
+
+ # otherwise, if config files exists for wrapper class, use it
+ file_name = File.expand_path(DEFAULT_REDIS_CONFIG_FILE_NAME, __dir__)
+ return file_name if File.file?(file_name)
+
+ # nil will force use of DEFAULT_REDIS_URL when config file is absent
+ nil
+ end
+ end
+
+ def initialize(rails_env = nil)
+ @rails_env = rails_env || ::Rails.env
+ end
+
+ def params
+ redis_store_options
+ end
+
+ def url
+ raw_config_hash[:url]
+ end
+
+ def sentinels
+ raw_config_hash[:sentinels]
+ end
+
+ def sentinels?
+ sentinels && !sentinels.empty?
+ end
+
+ private
+
+ def redis_store_options
+ config = raw_config_hash
+ redis_url = config.delete(:url)
+ redis_uri = URI.parse(redis_url)
+
+ if redis_uri.scheme == 'unix'
+ # Redis::Store does not handle Unix sockets well, so let's do it for them
+ config[:path] = redis_uri.path
+ query = redis_uri.query
+ unless query.nil?
+ queries = CGI.parse(redis_uri.query)
+ db_numbers = queries["db"] if queries.key?("db")
+ config[:db] = db_numbers[0].to_i if db_numbers.any?
+ end
+ config
+ else
+ redis_hash = ::Redis::Store::Factory.extract_host_options_from_uri(redis_url)
+ # order is important here, sentinels must be after the connection keys.
+ # {url: ..., port: ..., sentinels: [...]}
+ redis_hash.merge(config)
+ end
+ end
+
+ def raw_config_hash
+ config_data = fetch_config
+
+ if config_data
+ config_data.is_a?(String) ? { url: config_data } : config_data.deep_symbolize_keys
+ else
+ { url: self.class.default_url }
+ end
+ end
+
+ def fetch_config
+ return false unless self.class._raw_config
+
+ yaml = YAML.load(self.class._raw_config)
+
+ # If the file has content but it's invalid YAML, `load` returns false
+ if yaml
+ yaml.fetch(@rails_env, false)
+ else
+ false
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/url_builder.rb b/lib/gitlab/url_builder.rb
index 35792d2d67f..824e2d7251f 100644
--- a/lib/gitlab/url_builder.rb
+++ b/lib/gitlab/url_builder.rb
@@ -52,15 +52,13 @@ module Gitlab
commit_url(id: object.commit_id, anchor: dom_id(object))
elsif object.for_issue?
- issue = Issue.find(object.noteable_id)
- issue_url(issue, anchor: dom_id(object))
+ issue_url(object.noteable, anchor: dom_id(object))
elsif object.for_merge_request?
- merge_request = MergeRequest.find(object.noteable_id)
- merge_request_url(merge_request, anchor: dom_id(object))
+ merge_request_url(object.noteable, anchor: dom_id(object))
elsif object.for_snippet?
- snippet = Snippet.find(object.noteable_id)
+ snippet = object.noteable
if snippet.is_a?(PersonalSnippet)
snippet_url(snippet, anchor: dom_id(object))
diff --git a/lib/gitlab/user_activities.rb b/lib/gitlab/user_activities.rb
index eb36ab9fded..125488536e1 100644
--- a/lib/gitlab/user_activities.rb
+++ b/lib/gitlab/user_activities.rb
@@ -6,13 +6,13 @@ module Gitlab
BATCH_SIZE = 500
def self.record(key, time = Time.now)
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
redis.hset(KEY, key, time.to_i)
end
end
def delete(*keys)
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
redis.hdel(KEY, keys)
end
end
@@ -21,7 +21,7 @@ module Gitlab
cursor = 0
loop do
cursor, pairs =
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
redis.hscan(KEY, cursor, count: BATCH_SIZE)
end
diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb
index 4aef23b6aee..ee4f2b773ea 100644
--- a/lib/gitlab/workhorse.rb
+++ b/lib/gitlab/workhorse.rb
@@ -176,7 +176,7 @@ module Gitlab
end
def set_key_and_notify(key, value, expire: nil, overwrite: true)
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::Queues.with do |redis|
result = redis.set(key, value, ex: expire, nx: !overwrite)
if result
redis.publish(NOTIFICATION_CHANNEL, "#{key}=#{value}")
diff --git a/lib/tasks/cache.rake b/lib/tasks/cache.rake
index 125a3d560d6..564aa141952 100644
--- a/lib/tasks/cache.rake
+++ b/lib/tasks/cache.rake
@@ -5,12 +5,12 @@ namespace :cache do
desc "GitLab | Clear redis cache"
task redis: :environment do
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::Cache.with do |redis|
cursor = REDIS_SCAN_START_STOP
loop do
cursor, keys = redis.scan(
cursor,
- match: "#{Gitlab::Redis::CACHE_NAMESPACE}*",
+ match: "#{Gitlab::Redis::Cache::CACHE_NAMESPACE}*",
count: REDIS_CLEAR_BATCH_SIZE
)
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
index db4dc9a02da..7406629ef9d 100644
--- a/locale/bg/gitlab.po
+++ b/locale/bg/gitlab.po
@@ -4,11 +4,11 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-06-19 15:50-0500\n"
+"POT-Creation-Date: 2017-06-28 13:32+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"PO-Revision-Date: 2017-06-23 04:07-0400\n"
+"PO-Revision-Date: 2017-07-05 08:18-0400\n"
"Last-Translator: Lyubomir Vasilev <lyubomirv@abv.bg>\n"
"Language-Team: Bulgarian (https://translate.zanata.org/project/view/GitLab)\n"
"Language: bg\n"
@@ -29,6 +29,14 @@ msgstr[1] "%d подавания"
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr "%{commit_author_link} подаде %{commit_timeago}"
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] "1 схема"
+msgstr[1] "%d схеми"
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr "Набор от графики относно непрекъснатата интеграция"
+
msgid "About auto deploy"
msgstr "Относно автоматичното внедряване"
@@ -191,6 +199,9 @@ msgid_plural "Commits"
msgstr[0] "Подаване"
msgstr[1] "Подавания"
+msgid "Commit duration in minutes for last 30 commits"
+msgstr "Времетраене на подаванията в минути за последните 30 подавания"
+
msgid "Commit message"
msgstr "Съобщение за подаването"
@@ -230,6 +241,13 @@ msgstr "Копиране на идентификатора на подаване
msgid "Create New Directory"
msgstr "Създаване на нова папка"
+msgid ""
+"Create a personal access token on your account to pull or push via "
+"%{protocol}."
+msgstr ""
+"Създайте си личен жетон за достъп в профила си, за да можете да изтегляте и "
+"изпращате промени чрез %{protocol}."
+
msgid "Create directory"
msgstr "Създаване на папка"
@@ -248,6 +266,9 @@ msgstr "Разклоняване"
msgid "CreateTag|Tag"
msgstr "Етикет"
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr "си създадете личен жетон за достъп"
+
msgid "Cron Timezone"
msgstr "Часова зона за „Cron“"
@@ -419,6 +440,15 @@ msgstr "Шаблон за интервала"
msgid "Introducing Cycle Analytics"
msgstr "Представяме Ви анализа на циклите"
+msgid "Jobs for last month"
+msgstr "Задачи за последния месец"
+
+msgid "Jobs for last week"
+msgstr "Задачи за последната седмица"
+
+msgid "Jobs for last year"
+msgstr "Задачи за последната година"
+
msgid "LFSStatus|Disabled"
msgstr "Изключено"
@@ -584,6 +614,21 @@ msgstr "План за схема"
msgid "Pipeline Schedules"
msgstr "Планове за схема"
+msgid "PipelineCharts|Failed:"
+msgstr "Неуспешни:"
+
+msgid "PipelineCharts|Overall statistics"
+msgstr "Обща статистика"
+
+msgid "PipelineCharts|Success ratio:"
+msgstr "Коефициент на успех:"
+
+msgid "PipelineCharts|Successful:"
+msgstr "Успешни:"
+
+msgid "PipelineCharts|Total:"
+msgstr "Общо:"
+
msgid "PipelineSchedules|Activated"
msgstr "Включено"
@@ -614,6 +659,18 @@ msgstr "Цел"
msgid "PipelineSheduleIntervalPattern|Custom"
msgstr "собствен"
+msgid "Pipelines"
+msgstr "Схеми"
+
+msgid "Pipelines charts"
+msgstr "Графики за схемите"
+
+msgid "Pipeline|all"
+msgstr "всички"
+
+msgid "Pipeline|success"
+msgstr "успешни"
+
msgid "Pipeline|with stage"
msgstr "с етап"
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
index 0ca8dfca266..015d96d6e53 100644
--- a/locale/eo/gitlab.po
+++ b/locale/eo/gitlab.po
@@ -4,11 +4,11 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-06-19 15:50-0500\n"
+"POT-Creation-Date: 2017-06-28 13:32+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"PO-Revision-Date: 2017-07-05 02:56-0400\n"
+"PO-Revision-Date: 2017-07-05 08:18-0400\n"
"Last-Translator: Lyubomir Vasilev <lyubomirv@abv.bg>\n"
"Language-Team: Esperanto (https://translate.zanata.org/project/view/GitLab)\n"
"Language: eo\n"
@@ -29,6 +29,14 @@ msgstr[1] "%d enmetadoj"
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr "%{commit_author_link} enmetis %{commit_timeago}"
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] "1 ĉenstablo"
+msgstr[1] "%d ĉenstabloj"
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr "Aro da diagramoj pri la seninterrompa integrado"
+
msgid "About auto deploy"
msgstr "Pri la aŭtomata disponigado"
@@ -191,6 +199,9 @@ msgid_plural "Commits"
msgstr[0] "Enmetado"
msgstr[1] "Enmetadoj"
+msgid "Commit duration in minutes for last 30 commits"
+msgstr "Daŭro de la enmetadoj por la lastaj 30 enmetadoj"
+
msgid "Commit message"
msgstr "Mesaĝo pri la enmetado"
@@ -230,6 +241,13 @@ msgstr "Kopii la identigilon de la enmetado"
msgid "Create New Directory"
msgstr "Krei novan dosierujon"
+msgid ""
+"Create a personal access token on your account to pull or push via "
+"%{protocol}."
+msgstr ""
+"Kreu propran atingoĵetonon en via konto por ebligi al vi eltiri kaj alpuŝi "
+"per %{protocol}."
+
msgid "Create directory"
msgstr "Krei dosierujon"
@@ -248,6 +266,9 @@ msgstr "Disbranĉigi"
msgid "CreateTag|Tag"
msgstr "Etikedo"
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr "kreos propran atingoĵetonon"
+
msgid "Cron Timezone"
msgstr "Horzono por Cron"
@@ -420,6 +441,15 @@ msgstr "Intervala ŝablono"
msgid "Introducing Cycle Analytics"
msgstr "Ni prezentas al vi la ciklan analizon"
+msgid "Jobs for last month"
+msgstr "Taskoj po la lasta monato"
+
+msgid "Jobs for last week"
+msgstr "Taskoj po la lasta semajno"
+
+msgid "Jobs for last year"
+msgstr "Taskoj po la lasta jaro"
+
msgid "LFSStatus|Disabled"
msgstr "Malŝaltita"
@@ -585,6 +615,21 @@ msgstr "Ĉenstabla plano"
msgid "Pipeline Schedules"
msgstr "Ĉenstablaj planoj"
+msgid "PipelineCharts|Failed:"
+msgstr "Malsukcesaj:"
+
+msgid "PipelineCharts|Overall statistics"
+msgstr "Ĝenerala statistiko"
+
+msgid "PipelineCharts|Success ratio:"
+msgstr "Proporcio de sukceso:"
+
+msgid "PipelineCharts|Successful:"
+msgstr "Sukcesaj:"
+
+msgid "PipelineCharts|Total:"
+msgstr "Totalo:"
+
msgid "PipelineSchedules|Activated"
msgstr "Ŝaltita"
@@ -615,6 +660,18 @@ msgstr "Celo"
msgid "PipelineSheduleIntervalPattern|Custom"
msgstr "Propra"
+msgid "Pipelines"
+msgstr "Ĉenstabloj"
+
+msgid "Pipelines charts"
+msgstr "Ĉenstablaj diagramoj"
+
+msgid "Pipeline|all"
+msgstr "ĉiuj"
+
+msgid "Pipeline|success"
+msgstr "sukcesaj"
+
msgid "Pipeline|with stage"
msgstr "kun etapo"
diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po
index db992021403..c5600721d49 100644
--- a/locale/it/gitlab.po
+++ b/locale/it/gitlab.po
@@ -4,13 +4,13 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-06-19 15:50-0500\n"
+"POT-Creation-Date: 2017-06-28 13:32+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"PO-Revision-Date: 2017-07-02 10:32-0400\n"
+"PO-Revision-Date: 2017-07-12 05:45-0400\n"
"Last-Translator: Paolo Falomo <info@paolofalomo.it>\n"
-"Language-Team: Italian\n"
+"Language-Team: Italian (https://translate.zanata.org/project/view/GitLab)\n"
"Language: it\n"
"X-Generator: Zanata 3.9.6\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
@@ -33,6 +33,14 @@ msgstr[1] "%d commit"
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr "%{commit_author_link} ha committato %{commit_timeago}"
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] "1 pipeline"
+msgstr[1] "%d pipeline"
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr "Un insieme di grafici riguardo la Continuous Integration"
+
msgid "About auto deploy"
msgstr "Riguardo il rilascio automatico"
@@ -196,6 +204,9 @@ msgid_plural "Commits"
msgstr[0] "Commit"
msgstr[1] "Commits"
+msgid "Commit duration in minutes for last 30 commits"
+msgstr "Durata del commit (in minuti) per gli ultimi 30 commit"
+
msgid "Commit message"
msgstr "Messaggio del commit"
@@ -235,6 +246,13 @@ msgstr "Copia l'SHA del commit negli appunti"
msgid "Create New Directory"
msgstr "Crea una nuova cartella"
+msgid ""
+"Create a personal access token on your account to pull or push via "
+"%{protocol}."
+msgstr ""
+"Creare un token di accesso sul tuo account per eseguire pull o push tramite "
+"%{protocol}"
+
msgid "Create directory"
msgstr "Crea cartella"
@@ -253,6 +271,9 @@ msgstr "Fork"
msgid "CreateTag|Tag"
msgstr "Tag"
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr "Crea token d'accesso personale"
+
msgid "Cron Timezone"
msgstr "Cron Timezone"
@@ -425,6 +446,15 @@ msgstr "Intervallo di Pattern"
msgid "Introducing Cycle Analytics"
msgstr "Introduzione delle Analisi Cicliche"
+msgid "Jobs for last month"
+msgstr "Jobs dell'ultimo mese"
+
+msgid "Jobs for last week"
+msgstr "Jobs dell'ultima settimana"
+
+msgid "Jobs for last year"
+msgstr "Jobs dell'ultimo anno"
+
msgid "LFSStatus|Disabled"
msgstr "Disabilitato"
@@ -590,6 +620,21 @@ msgstr "Pianificazione Pipeline"
msgid "Pipeline Schedules"
msgstr "Pianificazione multipla Pipeline"
+msgid "PipelineCharts|Failed:"
+msgstr "Fallita:"
+
+msgid "PipelineCharts|Overall statistics"
+msgstr "Statistiche riassuntive"
+
+msgid "PipelineCharts|Success ratio:"
+msgstr "Percentuale di successo"
+
+msgid "PipelineCharts|Successful:"
+msgstr "Completata:"
+
+msgid "PipelineCharts|Total:"
+msgstr "Totale:"
+
msgid "PipelineSchedules|Activated"
msgstr "Attivata"
@@ -620,6 +665,18 @@ msgstr "Target"
msgid "PipelineSheduleIntervalPattern|Custom"
msgstr "Personalizzato"
+msgid "Pipelines"
+msgstr "Pipeline"
+
+msgid "Pipelines charts"
+msgstr "Grafici pipeline"
+
+msgid "Pipeline|all"
+msgstr "tutto"
+
+msgid "Pipeline|success"
+msgstr "successo"
+
msgid "Pipeline|with stage"
msgstr "con stadio"
@@ -684,7 +741,7 @@ msgid "ProjectNetworkGraph|Graph"
msgstr "Grafico"
msgid "Read more"
-msgstr "Continua..."
+msgstr "Vedi altro"
msgid "Readme"
msgstr "Leggimi"
@@ -751,7 +808,7 @@ msgstr "Seleziona una branch di destinazione"
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
-"Imposta una password sul tuo account per eseguire pull o push tramite "
+"Establezca una contraseña en su cuenta para actualizar o enviar a través de "
"%{protocol}."
msgid "Set up CI"
@@ -814,9 +871,9 @@ msgid ""
"the issue to a milestone, or add the issue to a list on your Issue Board. "
"Begin creating issues to see data for this stage."
msgstr ""
-"Questo stadio di issue mostra il tempo che ci vuole dal creare un issue "
-"all'assegnarli una milestone, o ad aggiungere un issue alla tua board. Crea "
-"un issue per vedere questo stadio."
+"Lo stadio di Issue mostra il tempo che impiega un issue ad esser correlato "
+"ad una Milestone, o ad esser aggiunto ad una tua Lavagna. Inizia la "
+"creazione di problemi per visualizzare i dati in questo stadio."
msgid "The phase of the development lifecycle."
msgstr "Il ciclo vitale della fase di sviluppo."
diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po
index 2f21aae2899..8a76121e0c1 100644
--- a/locale/zh_CN/gitlab.po
+++ b/locale/zh_CN/gitlab.po
@@ -4,11 +4,11 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-06-19 15:50-0500\n"
+"POT-Creation-Date: 2017-06-28 13:32+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"PO-Revision-Date: 2017-06-27 03:18-0400\n"
+"PO-Revision-Date: 2017-07-10 09:58-0400\n"
"Last-Translator: Huang Tao <htve@outlook.com>\n"
"Language-Team: Chinese (China) (https://translate.zanata.org/project/view/GitLab)\n"
"Language: zh-CN\n"
@@ -27,6 +27,13 @@ msgstr[0] "%d 次提交"
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr "由 %{commit_author_link} 提交于 %{commit_timeago}"
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] "%d 条流水线"
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr "持续集成数据图"
+
msgid "About auto deploy"
msgstr "关于自动部署"
@@ -184,6 +191,9 @@ msgid "Commit"
msgid_plural "Commits"
msgstr[0] "提交"
+msgid "Commit duration in minutes for last 30 commits"
+msgstr "最近30次提交相应持续集成花费的时间(分钟)"
+
msgid "Commit message"
msgstr "提交信息"
@@ -223,6 +233,11 @@ msgstr "复制提交 SHA 的值到剪贴板"
msgid "Create New Directory"
msgstr "创建新目录"
+msgid ""
+"Create a personal access token on your account to pull or push via "
+"%{protocol}."
+msgstr "在帐户上创建个人访问令牌,以通过%{protocol}来拉取或推送。"
+
msgid "Create directory"
msgstr "创建目录"
@@ -241,6 +256,9 @@ msgstr "派生"
msgid "CreateTag|Tag"
msgstr "标签"
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr "创建个人访问令牌"
+
msgid "Cron Timezone"
msgstr "Cron 时区"
@@ -405,6 +423,15 @@ msgstr "循环周期"
msgid "Introducing Cycle Analytics"
msgstr "周期分析简介"
+msgid "Jobs for last month"
+msgstr "上个月的作业"
+
+msgid "Jobs for last week"
+msgstr "上个星期的作业"
+
+msgid "Jobs for last year"
+msgstr "去年的作业"
+
msgid "LFSStatus|Disabled"
msgstr "停用"
@@ -567,6 +594,21 @@ msgstr "流水线计划"
msgid "Pipeline Schedules"
msgstr "流水线计划"
+msgid "PipelineCharts|Failed:"
+msgstr "失败:"
+
+msgid "PipelineCharts|Overall statistics"
+msgstr "总体统计数据"
+
+msgid "PipelineCharts|Success ratio:"
+msgstr "成功率:"
+
+msgid "PipelineCharts|Successful:"
+msgstr "成功:"
+
+msgid "PipelineCharts|Total:"
+msgstr "总计:"
+
msgid "PipelineSchedules|Activated"
msgstr "是否启用"
@@ -597,6 +639,18 @@ msgstr "目标"
msgid "PipelineSheduleIntervalPattern|Custom"
msgstr "自定义"
+msgid "Pipelines"
+msgstr "流水线"
+
+msgid "Pipelines charts"
+msgstr "流水线统计图"
+
+msgid "Pipeline|all"
+msgstr "所有"
+
+msgid "Pipeline|success"
+msgstr "成功"
+
msgid "Pipeline|with stage"
msgstr "于阶段"
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index afdbd01b7d7..b679ed3f26b 100644
--- a/locale/zh_HK/gitlab.po
+++ b/locale/zh_HK/gitlab.po
@@ -1,17 +1,15 @@
# Huang Tao <htve@outlook.com>, 2017. #zanata
-# Victor Wu <anonymous@domain.com>, 2017.
-# Hazel Yang <anonymous@domain.com>, 2017.
msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-06-15 21:59-0500\n"
+"POT-Creation-Date: 2017-06-28 13:32+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"PO-Revision-Date: 2017-06-23 01:23-0400\n"
+"PO-Revision-Date: 2017-07-06 11:26-0400\n"
"Last-Translator: Huang Tao <htve@outlook.com>\n"
-"Language-Team: Chinese (Hong Kong) (https://translate.zanata.org/project/view/GitLab)\n"
+"Language-Team: Chinese (Hong Kong SAR China)\n"
"Language: zh-HK\n"
"X-Generator: Zanata 3.9.6\n"
"Plural-Forms: nplurals=1; plural=0\n"
@@ -28,6 +26,13 @@ msgstr[0] " %d 次提交"
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr "由 %{commit_author_link} 提交於 %{commit_timeago}"
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] "%d 條流水線"
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr "相關持續集成的圖像集合"
+
msgid "About auto deploy"
msgstr "關於自動部署"
@@ -185,6 +190,9 @@ msgid "Commit"
msgid_plural "Commits"
msgstr[0] "提交"
+msgid "Commit duration in minutes for last 30 commits"
+msgstr "最近30次提交花費的時間(分鐘)"
+
msgid "Commit message"
msgstr "提交信息"
@@ -224,6 +232,11 @@ msgstr "複製提交 SHA 到剪貼板"
msgid "Create New Directory"
msgstr "創建新目錄"
+msgid ""
+"Create a personal access token on your account to pull or push via "
+"%{protocol}."
+msgstr "在帳戶上創建個人訪問令牌,以通過 %{protocol} 來拉取或推送。"
+
msgid "Create directory"
msgstr "創建目錄"
@@ -242,6 +255,9 @@ msgstr "派生"
msgid "CreateTag|Tag"
msgstr "標籤"
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr "創建個人訪問令牌"
+
msgid "Cron Timezone"
msgstr "Cron 時區"
@@ -406,6 +422,15 @@ msgstr "循環週期"
msgid "Introducing Cycle Analytics"
msgstr "週期分析簡介"
+msgid "Jobs for last month"
+msgstr "上個月的作業"
+
+msgid "Jobs for last week"
+msgstr "上個星期的作業"
+
+msgid "Jobs for last year"
+msgstr "去年的作業"
+
msgid "LFSStatus|Disabled"
msgstr "停用"
@@ -568,6 +593,21 @@ msgstr "流水線計劃"
msgid "Pipeline Schedules"
msgstr "流水線計劃"
+msgid "PipelineCharts|Failed:"
+msgstr "失敗:"
+
+msgid "PipelineCharts|Overall statistics"
+msgstr "總體統計"
+
+msgid "PipelineCharts|Success ratio:"
+msgstr "成功率:"
+
+msgid "PipelineCharts|Successful:"
+msgstr "成功:"
+
+msgid "PipelineCharts|Total:"
+msgstr "總計:"
+
msgid "PipelineSchedules|Activated"
msgstr "是否啟用"
@@ -598,6 +638,18 @@ msgstr "目標"
msgid "PipelineSheduleIntervalPattern|Custom"
msgstr "自定義"
+msgid "Pipelines"
+msgstr "流水線"
+
+msgid "Pipelines charts"
+msgstr "流水線圖表"
+
+msgid "Pipeline|all"
+msgstr "所有"
+
+msgid "Pipeline|success"
+msgstr "成功"
+
msgid "Pipeline|with stage"
msgstr "於階段"
diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po
index fa0b3b339fa..d5a3c5ea0b9 100644
--- a/locale/zh_TW/gitlab.po
+++ b/locale/zh_TW/gitlab.po
@@ -1,18 +1,18 @@
# Huang Tao <htve@outlook.com>, 2017. #zanata
-# Lin Jen-Shin <anonymous@domain.com>, 2017.
# Hazel Yang <anonymous@domain.com>, 2017.
# TzeKei Lee <anonymous@domain.com>, 2017.
# Jerry Ho <a29988122@gmail.com>, 2017.
+# Lin Jen-Shin <godfat@godfat.org>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-06-19 15:50-0500\n"
+"POT-Creation-Date: 2017-06-28 13:32+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"PO-Revision-Date: 2017-06-28 11:13-0400\n"
-"Last-Translator: Huang Tao <htve@outlook.com>\n"
+"PO-Revision-Date: 2017-07-11 09:10-0400\n"
+"Last-Translator: Lin Jen-Shin <godfat@godfat.org>\n"
"Language-Team: Chinese (Taiwan) (https://translate.zanata.org/project/view/GitLab)\n"
"Language: zh-TW\n"
"X-Generator: Zanata 3.9.6\n"
@@ -30,6 +30,13 @@ msgstr[0] "%d 個更動 (commit)"
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr "%{commit_author_link} 在 %{commit_timeago} 送交"
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] "%d 條流水線"
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr "持續整合 (CI) 相關的圖表"
+
msgid "About auto deploy"
msgstr "關於自動部署"
@@ -187,6 +194,9 @@ msgid "Commit"
msgid_plural "Commits"
msgstr[0] "更動記錄 (commit) "
+msgid "Commit duration in minutes for last 30 commits"
+msgstr "最近 30 次更動花費的時間(分鐘)"
+
msgid "Commit message"
msgstr "更動說明 (commit) "
@@ -226,6 +236,11 @@ msgstr "複製更動記錄 (commit) 的 SHA 值到剪貼簿"
msgid "Create New Directory"
msgstr "建立新目錄"
+msgid ""
+"Create a personal access token on your account to pull or push via "
+"%{protocol}."
+msgstr "建立個人存取憑證 (access token) 以使用 %{protocol} 來上傳 (push) 或下載 (pull) 。"
+
msgid "Create directory"
msgstr "建立目錄"
@@ -244,6 +259,9 @@ msgstr "分支 (fork) "
msgid "CreateTag|Tag"
msgstr "建立標籤"
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr "建立個人存取憑證 (access token)"
+
msgid "Cron Timezone"
msgstr "Cron 時區"
@@ -408,6 +426,15 @@ msgstr "循環週期"
msgid "Introducing Cycle Analytics"
msgstr "週期分析簡介"
+msgid "Jobs for last month"
+msgstr "上個月的任務 (job) "
+
+msgid "Jobs for last week"
+msgstr "上個星期的任務 (job) "
+
+msgid "Jobs for last year"
+msgstr "去年的任務 (job) "
+
msgid "LFSStatus|Disabled"
msgstr "停用"
@@ -570,6 +597,21 @@ msgstr "流水線 (pipeline) 排程"
msgid "Pipeline Schedules"
msgstr "流水線 (pipeline) 排程"
+msgid "PipelineCharts|Failed:"
+msgstr "失敗:"
+
+msgid "PipelineCharts|Overall statistics"
+msgstr "總體統計"
+
+msgid "PipelineCharts|Success ratio:"
+msgstr "成功比率:"
+
+msgid "PipelineCharts|Successful:"
+msgstr "成功:"
+
+msgid "PipelineCharts|Total:"
+msgstr "總計:"
+
msgid "PipelineSchedules|Activated"
msgstr "是否啟用"
@@ -600,6 +642,18 @@ msgstr "目標"
msgid "PipelineSheduleIntervalPattern|Custom"
msgstr "自訂"
+msgid "Pipelines"
+msgstr "流水線 (pipeline) "
+
+msgid "Pipelines charts"
+msgstr "流水線 (pipeline) 圖表"
+
+msgid "Pipeline|all"
+msgstr "所有"
+
+msgid "Pipeline|success"
+msgstr "成功"
+
msgid "Pipeline|with stage"
msgstr "於階段"
diff --git a/package.json b/package.json
index 5a997e813f8..fd944531a6a 100644
--- a/package.json
+++ b/package.json
@@ -58,7 +58,7 @@
"visibilityjs": "^1.2.4",
"vue": "^2.2.6",
"vue-loader": "^11.3.4",
- "vue-resource": "^0.9.3",
+ "vue-resource": "^1.3.4",
"vue-template-compiler": "^2.2.6",
"webpack": "^2.6.1",
"webpack-bundle-analyzer": "^2.8.2"
diff --git a/public/ci/favicon.ico b/public/ci/favicon.ico
deleted file mode 100644
index 9663d4d00b9..00000000000
--- a/public/ci/favicon.ico
+++ /dev/null
Binary files differ
diff --git a/scripts/prepare_build.sh b/scripts/prepare_build.sh
index 03de59f27ad..68114d149c4 100644
--- a/scripts/prepare_build.sh
+++ b/scripts/prepare_build.sh
@@ -12,9 +12,6 @@ fi
# gems could not be found under some circumstance. No idea why, hours wasted.
retry gem install knapsack fog-aws mime-types
-cp config/resque.yml.example config/resque.yml
-sed -i 's/localhost/redis/g' config/resque.yml
-
cp config/gitlab.yml.example config/gitlab.yml
# Determine the database by looking at the job name.
@@ -37,6 +34,18 @@ else # Assume it's mysql
sed -i 's/# host:.*/host: mysql/g' config/database.yml
fi
+cp config/resque.yml.example config/resque.yml
+sed -i 's/localhost/redis/g' config/resque.yml
+
+cp config/redis.cache.yml.example config/redis.cache.yml
+sed -i 's/localhost/redis/g' config/redis.cache.yml
+
+cp config/redis.queues.yml.example config/redis.queues.yml
+sed -i 's/localhost/redis/g' config/redis.queues.yml
+
+cp config/redis.shared_state.yml.example config/redis.shared_state.yml
+sed -i 's/localhost/redis/g' config/redis.shared_state.yml
+
if [ "$SETUP_DB" != "false" ]; then
bundle exec rake db:drop db:create db:schema:load db:migrate
diff --git a/spec/config/mail_room_spec.rb b/spec/config/mail_room_spec.rb
index 092048a6259..a31e44fa928 100644
--- a/spec/config/mail_room_spec.rb
+++ b/spec/config/mail_room_spec.rb
@@ -5,12 +5,12 @@ describe 'mail_room.yml' do
let(:mailroom_config_path) { 'config/mail_room.yml' }
let(:gitlab_config_path) { 'config/mail_room.yml' }
- let(:redis_config_path) { 'config/resque.yml' }
+ let(:queues_config_path) { 'config/redis.queues.yml' }
let(:configuration) do
vars = {
'MAIL_ROOM_GITLAB_CONFIG_FILE' => absolute_path(gitlab_config_path),
- 'GITLAB_REDIS_CONFIG_FILE' => absolute_path(redis_config_path)
+ 'GITLAB_REDIS_QUEUES_CONFIG_FILE' => absolute_path(queues_config_path)
}
cmd = "puts ERB.new(File.read(#{absolute_path(mailroom_config_path).inspect})).result"
@@ -21,12 +21,12 @@ describe 'mail_room.yml' do
end
before(:each) do
- stub_env('GITLAB_REDIS_CONFIG_FILE', absolute_path(redis_config_path))
- clear_redis_raw_config
+ stub_env('GITLAB_REDIS_QUEUES_CONFIG_FILE', absolute_path(queues_config_path))
+ clear_queues_raw_config
end
after(:each) do
- clear_redis_raw_config
+ clear_queues_raw_config
end
context 'when incoming email is disabled' do
@@ -39,9 +39,9 @@ describe 'mail_room.yml' do
context 'when incoming email is enabled' do
let(:gitlab_config_path) { 'spec/fixtures/config/mail_room_enabled.yml' }
- let(:redis_config_path) { 'spec/fixtures/config/redis_new_format_host.yml' }
+ let(:queues_config_path) { 'spec/fixtures/config/redis_queues_new_format_host.yml' }
- let(:gitlab_redis) { Gitlab::Redis.new(Rails.env) }
+ let(:gitlab_redis_queues) { Gitlab::Redis::Queues.new(Rails.env) }
it 'contains the intended configuration' do
expect(configuration[:mailboxes].length).to eq(1)
@@ -56,8 +56,8 @@ describe 'mail_room.yml' do
expect(mailbox[:name]).to eq('inbox')
expect(mailbox[:idle_timeout]).to eq(60)
- redis_url = gitlab_redis.url
- sentinels = gitlab_redis.sentinels
+ redis_url = gitlab_redis_queues.url
+ sentinels = gitlab_redis_queues.sentinels
expect(mailbox[:delivery_options][:redis_url]).to be_present
expect(mailbox[:delivery_options][:redis_url]).to eq(redis_url)
@@ -73,8 +73,8 @@ describe 'mail_room.yml' do
end
end
- def clear_redis_raw_config
- Gitlab::Redis.remove_instance_variable(:@_raw_config)
+ def clear_queues_raw_config
+ Gitlab::Redis::Queues.remove_instance_variable(:@_raw_config)
rescue NameError
# raised if @_raw_config was not set; ignore
end
diff --git a/spec/controllers/health_check_controller_spec.rb b/spec/controllers/health_check_controller_spec.rb
index 58c16cc57e6..03da6287774 100644
--- a/spec/controllers/health_check_controller_spec.rb
+++ b/spec/controllers/health_check_controller_spec.rb
@@ -3,52 +3,79 @@ require 'spec_helper'
describe HealthCheckController do
include StubENV
- let(:token) { current_application_settings.health_check_access_token }
let(:json_response) { JSON.parse(response.body) }
let(:xml_response) { Hash.from_xml(response.body)['hash'] }
+ let(:token) { current_application_settings.health_check_access_token }
+ let(:whitelisted_ip) { '127.0.0.1' }
+ let(:not_whitelisted_ip) { '127.0.0.2' }
before do
+ allow(Settings.monitoring).to receive(:ip_whitelist).and_return([whitelisted_ip])
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
end
describe 'GET #index' do
- context 'when services are up but NO access token' do
+ context 'when services are up but accessed from outside whitelisted ips' do
+ before do
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(not_whitelisted_ip)
+ end
+
it 'returns a not found page' do
get :index
+
expect(response).to be_not_found
end
+
+ context 'when services are accessed with token' do
+ it 'supports passing the token in the header' do
+ request.headers['TOKEN'] = token
+
+ get :index
+
+ expect(response).to be_success
+ expect(response.content_type).to eq 'text/plain'
+ end
+
+ it 'supports passing the token in query params' do
+ get :index, token: token
+
+ expect(response).to be_success
+ expect(response.content_type).to eq 'text/plain'
+ end
+ end
end
- context 'when services are up and an access token is provided' do
- it 'supports passing the token in the header' do
- request.headers['TOKEN'] = token
- get :index
- expect(response).to be_success
- expect(response.content_type).to eq 'text/plain'
+ context 'when services are up and accessed from whitelisted ips' do
+ before do
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(whitelisted_ip)
end
- it 'supports successful plaintest response' do
- get :index, token: token
+ it 'supports successful plaintext response' do
+ get :index
+
expect(response).to be_success
expect(response.content_type).to eq 'text/plain'
end
it 'supports successful json response' do
- get :index, token: token, format: :json
+ get :index, format: :json
+
expect(response).to be_success
expect(response.content_type).to eq 'application/json'
expect(json_response['healthy']).to be true
end
it 'supports successful xml response' do
- get :index, token: token, format: :xml
+ get :index, format: :xml
+
expect(response).to be_success
expect(response.content_type).to eq 'application/xml'
expect(xml_response['healthy']).to be true
end
it 'supports successful responses for specific checks' do
- get :index, token: token, checks: 'email', format: :json
+ get :index, checks: 'email', format: :json
+
expect(response).to be_success
expect(response.content_type).to eq 'application/json'
expect(json_response['healthy']).to be true
@@ -58,33 +85,29 @@ describe HealthCheckController do
context 'when a service is down but NO access token' do
it 'returns a not found page' do
get :index
+
expect(response).to be_not_found
end
end
- context 'when a service is down and an access token is provided' do
+ context 'when a service is down and an endpoint is accessed from whitelisted ip' do
before do
allow(HealthCheck::Utils).to receive(:process_checks).with(['standard']).and_return('The server is on fire')
allow(HealthCheck::Utils).to receive(:process_checks).with(['email']).and_return('Email is on fire')
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(whitelisted_ip)
end
- it 'supports passing the token in the header' do
- request.headers['TOKEN'] = token
+ it 'supports failure plaintext response' do
get :index
- expect(response).to have_http_status(500)
- expect(response.content_type).to eq 'text/plain'
- expect(response.body).to include('The server is on fire')
- end
- it 'supports failure plaintest response' do
- get :index, token: token
expect(response).to have_http_status(500)
expect(response.content_type).to eq 'text/plain'
expect(response.body).to include('The server is on fire')
end
it 'supports failure json response' do
- get :index, token: token, format: :json
+ get :index, format: :json
+
expect(response).to have_http_status(500)
expect(response.content_type).to eq 'application/json'
expect(json_response['healthy']).to be false
@@ -92,7 +115,8 @@ describe HealthCheckController do
end
it 'supports failure xml response' do
- get :index, token: token, format: :xml
+ get :index, format: :xml
+
expect(response).to have_http_status(500)
expect(response.content_type).to eq 'application/xml'
expect(xml_response['healthy']).to be false
@@ -100,7 +124,8 @@ describe HealthCheckController do
end
it 'supports failure responses for specific checks' do
- get :index, token: token, checks: 'email', format: :json
+ get :index, checks: 'email', format: :json
+
expect(response).to have_http_status(500)
expect(response.content_type).to eq 'application/json'
expect(json_response['healthy']).to be false
diff --git a/spec/controllers/health_controller_spec.rb b/spec/controllers/health_controller_spec.rb
index e7c19b47a6a..cc389e554ad 100644
--- a/spec/controllers/health_controller_spec.rb
+++ b/spec/controllers/health_controller_spec.rb
@@ -3,55 +3,120 @@ require 'spec_helper'
describe HealthController do
include StubENV
- let(:token) { current_application_settings.health_check_access_token }
let(:json_response) { JSON.parse(response.body) }
+ let(:token) { current_application_settings.health_check_access_token }
+ let(:whitelisted_ip) { '127.0.0.1' }
+ let(:not_whitelisted_ip) { '127.0.0.2' }
before do
+ allow(Settings.monitoring).to receive(:ip_whitelist).and_return([whitelisted_ip])
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
end
describe '#readiness' do
- context 'authorization token provided' do
- before do
- request.headers['TOKEN'] = token
- end
+ shared_context 'endpoint responding with readiness data' do
+ let(:request_params) { {} }
+
+ subject { get :readiness, request_params }
+
+ it 'responds with readiness checks data' do
+ subject
- it 'returns proper response' do
- get :readiness
expect(json_response['db_check']['status']).to eq('ok')
- expect(json_response['redis_check']['status']).to eq('ok')
+ expect(json_response['cache_check']['status']).to eq('ok')
+ expect(json_response['queues_check']['status']).to eq('ok')
+ expect(json_response['shared_state_check']['status']).to eq('ok')
expect(json_response['fs_shards_check']['status']).to eq('ok')
expect(json_response['fs_shards_check']['labels']['shard']).to eq('default')
end
end
- context 'without authorization token' do
- it 'returns proper response' do
+ context 'accessed from whitelisted ip' do
+ before do
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(whitelisted_ip)
+ end
+
+ it_behaves_like 'endpoint responding with readiness data'
+ end
+
+ context 'accessed from not whitelisted ip' do
+ before do
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(not_whitelisted_ip)
+ end
+
+ it 'responds with resource not found' do
get :readiness
+
expect(response.status).to eq(404)
end
+
+ context 'accessed with valid token' do
+ context 'token passed in request header' do
+ before do
+ request.headers['TOKEN'] = token
+ end
+
+ it_behaves_like 'endpoint responding with readiness data'
+ end
+ end
+
+ context 'token passed as URL param' do
+ it_behaves_like 'endpoint responding with readiness data' do
+ let(:request_params) { { token: token } }
+ end
+ end
end
end
describe '#liveness' do
- context 'authorization token provided' do
- before do
- request.headers['TOKEN'] = token
- end
+ shared_context 'endpoint responding with liveness data' do
+ subject { get :liveness }
+
+ it 'responds with liveness checks data' do
+ subject
- it 'returns proper response' do
- get :liveness
expect(json_response['db_check']['status']).to eq('ok')
- expect(json_response['redis_check']['status']).to eq('ok')
+ expect(json_response['cache_check']['status']).to eq('ok')
+ expect(json_response['queues_check']['status']).to eq('ok')
+ expect(json_response['shared_state_check']['status']).to eq('ok')
expect(json_response['fs_shards_check']['status']).to eq('ok')
end
end
- context 'without authorization token' do
- it 'returns proper response' do
+ context 'accessed from whitelisted ip' do
+ before do
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(whitelisted_ip)
+ end
+
+ it_behaves_like 'endpoint responding with liveness data'
+ end
+
+ context 'accessed from not whitelisted ip' do
+ before do
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(not_whitelisted_ip)
+ end
+
+ it 'responds with resource not found' do
get :liveness
+
expect(response.status).to eq(404)
end
+
+ context 'accessed with valid token' do
+ context 'token passed in request header' do
+ before do
+ request.headers['TOKEN'] = token
+ end
+
+ it_behaves_like 'endpoint responding with liveness data'
+ end
+
+ context 'token passed as URL param' do
+ it_behaves_like 'endpoint responding with liveness data' do
+ subject { get :liveness, token: token }
+ end
+ end
+ end
end
end
end
diff --git a/spec/controllers/metrics_controller_spec.rb b/spec/controllers/metrics_controller_spec.rb
index 044c9f179ed..86847c07c09 100644
--- a/spec/controllers/metrics_controller_spec.rb
+++ b/spec/controllers/metrics_controller_spec.rb
@@ -3,22 +3,22 @@ require 'spec_helper'
describe MetricsController do
include StubENV
- let(:token) { current_application_settings.health_check_access_token }
let(:json_response) { JSON.parse(response.body) }
let(:metrics_multiproc_dir) { Dir.mktmpdir }
+ let(:whitelisted_ip) { '127.0.0.1' }
+ let(:whitelisted_ip_range) { '10.0.0.0/24' }
+ let(:ip_in_whitelisted_range) { '10.0.0.1' }
+ let(:not_whitelisted_ip) { '10.0.1.1' }
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
stub_env('prometheus_multiproc_dir', metrics_multiproc_dir)
allow(Gitlab::Metrics).to receive(:prometheus_metrics_enabled?).and_return(true)
+ allow(Settings.monitoring).to receive(:ip_whitelist).and_return([whitelisted_ip, whitelisted_ip_range])
end
describe '#index' do
- context 'authorization token provided' do
- before do
- request.headers['TOKEN'] = token
- end
-
+ shared_examples_for 'endpoint providing metrics' do
it 'returns DB ping metrics' do
get :index
@@ -35,6 +35,30 @@ describe MetricsController do
expect(response.body).to match(/^redis_ping_latency [0-9\.]+$/)
end
+ it 'returns Caching ping metrics' do
+ get :index
+
+ expect(response.body).to match(/^redis_cache_ping_timeout 0$/)
+ expect(response.body).to match(/^redis_cache_ping_success 1$/)
+ expect(response.body).to match(/^redis_cache_ping_latency [0-9\.]+$/)
+ end
+
+ it 'returns Queues ping metrics' do
+ get :index
+
+ expect(response.body).to match(/^redis_queues_ping_timeout 0$/)
+ expect(response.body).to match(/^redis_queues_ping_success 1$/)
+ expect(response.body).to match(/^redis_queues_ping_latency [0-9\.]+$/)
+ end
+
+ it 'returns SharedState ping metrics' do
+ get :index
+
+ expect(response.body).to match(/^redis_shared_state_ping_timeout 0$/)
+ expect(response.body).to match(/^redis_shared_state_ping_success 1$/)
+ expect(response.body).to match(/^redis_shared_state_ping_latency [0-9\.]+$/)
+ end
+
it 'returns file system check metrics' do
get :index
@@ -59,7 +83,27 @@ describe MetricsController do
end
end
- context 'without authorization token' do
+ context 'accessed from whitelisted ip' do
+ before do
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(whitelisted_ip)
+ end
+
+ it_behaves_like 'endpoint providing metrics'
+ end
+
+ context 'accessed from ip in whitelisted range' do
+ before do
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(ip_in_whitelisted_range)
+ end
+
+ it_behaves_like 'endpoint providing metrics'
+ end
+
+ context 'accessed from not whitelisted ip' do
+ before do
+ allow(Gitlab::RequestContext).to receive(:client_ip).and_return(not_whitelisted_ip)
+ end
+
it 'returns proper response' do
get :index
diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb
index bf922260b2f..2b4e8723b48 100644
--- a/spec/controllers/sessions_controller_spec.rb
+++ b/spec/controllers/sessions_controller_spec.rb
@@ -47,7 +47,7 @@ describe SessionsController do
end
end
- context 'when using valid password', :redis do
+ context 'when using valid password', :clean_gitlab_redis_shared_state do
include UserActivitiesHelpers
let(:user) { create(:user) }
diff --git a/spec/features/dashboard/issuables_counter_spec.rb b/spec/features/dashboard/issuables_counter_spec.rb
index 285724f4b48..6b666934563 100644
--- a/spec/features/dashboard/issuables_counter_spec.rb
+++ b/spec/features/dashboard/issuables_counter_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe 'Navigation bar counter', feature: true, caching: true do
+describe 'Navigation bar counter', :use_clean_rails_memory_store_caching, feature: true do
let(:user) { create(:user) }
let(:project) { create(:empty_project, namespace: user.namespace) }
let(:issue) { create(:issue, project: project) }
diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb
index 7ca002fc821..bdba22fe9a9 100644
--- a/spec/features/dashboard/projects_spec.rb
+++ b/spec/features/dashboard/projects_spec.rb
@@ -61,7 +61,7 @@ feature 'Dashboard Projects' do
end
end
- describe 'with a pipeline', redis: true do
+ describe "with a pipeline", clean_gitlab_redis_shared_state: true do
let(:pipeline) { create(:ci_pipeline, project: project, sha: project.commit.sha) }
before do
diff --git a/spec/features/groups/members/sort_members_spec.rb b/spec/features/groups/members/sort_members_spec.rb
index 169827f5d0d..92ff45e0cdc 100644
--- a/spec/features/groups/members/sort_members_spec.rb
+++ b/spec/features/groups/members/sort_members_spec.rb
@@ -68,7 +68,7 @@ feature 'Groups > Members > Sort members', feature: true do
expect(page).to have_css('.member-sort-dropdown .dropdown-toggle-text', text: 'Name, descending')
end
- scenario 'sorts by recent sign in', :redis do
+ scenario 'sorts by recent sign in', :clean_gitlab_redis_shared_state do
visit_members_list(sort: :recent_sign_in)
expect(first_member).to include(owner.name)
@@ -76,7 +76,7 @@ feature 'Groups > Members > Sort members', feature: true do
expect(page).to have_css('.member-sort-dropdown .dropdown-toggle-text', text: 'Recent sign in')
end
- scenario 'sorts by oldest sign in', :redis do
+ scenario 'sorts by oldest sign in', :clean_gitlab_redis_shared_state do
visit_members_list(sort: :oldest_sign_in)
expect(first_member).to include(developer.name)
diff --git a/spec/features/login_spec.rb b/spec/features/login_spec.rb
index a8055b21cee..2a2213b67ed 100644
--- a/spec/features/login_spec.rb
+++ b/spec/features/login_spec.rb
@@ -41,7 +41,7 @@ feature 'Login', feature: true do
expect(page).to have_content('Your account has been blocked.')
end
- it 'does not update Devise trackable attributes', :redis do
+ it 'does not update Devise trackable attributes', :clean_gitlab_redis_shared_state do
user = create(:user, :blocked)
expect { gitlab_sign_in(user) }.not_to change { user.reload.sign_in_count }
@@ -55,7 +55,7 @@ feature 'Login', feature: true do
expect(page).to have_content('Invalid Login or password.')
end
- it 'does not update Devise trackable attributes', :redis do
+ it 'does not update Devise trackable attributes', :clean_gitlab_redis_shared_state do
expect { gitlab_sign_in(User.ghost) }.not_to change { User.ghost.reload.sign_in_count }
end
end
diff --git a/spec/features/projects/members/sorting_spec.rb b/spec/features/projects/members/sorting_spec.rb
index afb613f034e..dc7236fa120 100644
--- a/spec/features/projects/members/sorting_spec.rb
+++ b/spec/features/projects/members/sorting_spec.rb
@@ -67,7 +67,7 @@ feature 'Projects > Members > Sorting', feature: true do
expect(page).to have_css('.member-sort-dropdown .dropdown-toggle-text', text: 'Name, descending')
end
- scenario 'sorts by recent sign in', :redis do
+ scenario 'sorts by recent sign in', :clean_gitlab_redis_shared_state do
visit_members_list(sort: :recent_sign_in)
expect(first_member).to include(master.name)
@@ -75,7 +75,7 @@ feature 'Projects > Members > Sorting', feature: true do
expect(page).to have_css('.member-sort-dropdown .dropdown-toggle-text', text: 'Recent sign in')
end
- scenario 'sorts by oldest sign in', :redis do
+ scenario 'sorts by oldest sign in', :clean_gitlab_redis_shared_state do
visit_members_list(sort: :oldest_sign_in)
expect(first_member).to include(developer.name)
diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb
index 992a68b25a5..033ccf06124 100644
--- a/spec/features/projects/pipeline_schedules_spec.rb
+++ b/spec/features/projects/pipeline_schedules_spec.rb
@@ -9,188 +9,222 @@ feature 'Pipeline Schedules', :feature, js: true do
let(:scope) { nil }
let!(:user) { create(:user) }
- before do
- project.add_master(user)
- sign_in(user)
- end
-
- describe 'GET /projects/pipeline_schedules' do
+ context 'logged in as master' do
before do
- visit_pipelines_schedules
+ project.add_master(user)
+ gitlab_sign_in(user)
end
- describe 'The view' do
- it 'displays the required information description' do
- page.within('.pipeline-schedule-table-row') do
- expect(page).to have_content('pipeline schedule')
- expect(find(".next-run-cell time")['data-original-title'])
- .to include(pipeline_schedule.real_next_run.strftime('%b %-d, %Y'))
- expect(page).to have_link('master')
- expect(page).to have_link("##{pipeline.id}")
- end
+ describe 'GET /projects/pipeline_schedules' do
+ before do
+ visit_pipelines_schedules
end
- it 'creates a new scheduled pipeline' do
- click_link 'New schedule'
+ describe 'The view' do
+ it 'displays the required information description' do
+ page.within('.pipeline-schedule-table-row') do
+ expect(page).to have_content('pipeline schedule')
+ expect(find(".next-run-cell time")['data-original-title'])
+ .to include(pipeline_schedule.real_next_run.strftime('%b %-d, %Y'))
+ expect(page).to have_link('master')
+ expect(page).to have_link("##{pipeline.id}")
+ end
+ end
- expect(page).to have_content('Schedule a new pipeline')
- end
+ it 'creates a new scheduled pipeline' do
+ click_link 'New schedule'
- it 'changes ownership of the pipeline' do
- click_link 'Take ownership'
- page.within('.pipeline-schedule-table-row') do
- expect(page).not_to have_content('No owner')
- expect(page).to have_link('John Doe')
+ expect(page).to have_content('Schedule a new pipeline')
end
- end
- it 'edits the pipeline' do
- page.within('.pipeline-schedule-table-row') do
- click_link 'Edit'
+ it 'changes ownership of the pipeline' do
+ click_link 'Take ownership'
+ page.within('.pipeline-schedule-table-row') do
+ expect(page).not_to have_content('No owner')
+ expect(page).to have_link('John Doe')
+ end
end
- expect(page).to have_content('Edit Pipeline Schedule')
+ it 'edits the pipeline' do
+ page.within('.pipeline-schedule-table-row') do
+ click_link 'Edit'
+ end
+
+ expect(page).to have_content('Edit Pipeline Schedule')
+ end
+
+ it 'deletes the pipeline' do
+ click_link 'Delete'
+
+ expect(page).not_to have_css(".pipeline-schedule-table-row")
+ end
end
- it 'deletes the pipeline' do
- click_link 'Delete'
+ context 'when ref is nil' do
+ before do
+ pipeline_schedule.update_attribute(:ref, nil)
+ visit_pipelines_schedules
+ end
- expect(page).not_to have_css(".pipeline-schedule-table-row")
+ it 'shows a list of the pipeline schedules with empty ref column' do
+ expect(first('.branch-name-cell').text).to eq('')
+ end
end
end
- context 'when ref is nil' do
+ describe 'POST /projects/pipeline_schedules/new' do
before do
- pipeline_schedule.update_attribute(:ref, nil)
- visit_pipelines_schedules
+ visit_new_pipeline_schedule
end
- it 'shows a list of the pipeline schedules with empty ref column' do
- expect(first('.branch-name-cell').text).to eq('')
+ it 'sets defaults for timezone and target branch' do
+ expect(page).to have_button('master')
+ expect(page).to have_button('UTC')
end
- end
- end
- describe 'POST /projects/pipeline_schedules/new' do
- before do
- visit_new_pipeline_schedule
- end
+ it 'it creates a new scheduled pipeline' do
+ fill_in_schedule_form
+ save_pipeline_schedule
- it 'sets defaults for timezone and target branch' do
- expect(page).to have_button('master')
- expect(page).to have_button('UTC')
- end
+ expect(page).to have_content('my fancy description')
+ end
- it 'it creates a new scheduled pipeline' do
- fill_in_schedule_form
- save_pipeline_schedule
+ it 'it prevents an invalid form from being submitted' do
+ save_pipeline_schedule
- expect(page).to have_content('my fancy description')
+ expect(page).to have_content('This field is required')
+ end
end
- it 'it prevents an invalid form from being submitted' do
- save_pipeline_schedule
+ describe 'PATCH /projects/pipelines_schedules/:id/edit' do
+ before do
+ edit_pipeline_schedule
+ end
- expect(page).to have_content('This field is required')
- end
- end
+ it 'it displays existing properties' do
+ description = find_field('schedule_description').value
+ expect(description).to eq('pipeline schedule')
+ expect(page).to have_button('master')
+ expect(page).to have_button('UTC')
+ end
- describe 'PATCH /projects/pipelines_schedules/:id/edit' do
- before do
- edit_pipeline_schedule
- end
+ it 'edits the scheduled pipeline' do
+ fill_in 'schedule_description', with: 'my brand new description'
- it 'it displays existing properties' do
- description = find_field('schedule_description').value
- expect(description).to eq('pipeline schedule')
- expect(page).to have_button('master')
- expect(page).to have_button('UTC')
- end
+ save_pipeline_schedule
- it 'edits the scheduled pipeline' do
- fill_in 'schedule_description', with: 'my brand new description'
+ expect(page).to have_content('my brand new description')
+ end
- save_pipeline_schedule
+ context 'when ref is nil' do
+ before do
+ pipeline_schedule.update_attribute(:ref, nil)
+ edit_pipeline_schedule
+ end
- expect(page).to have_content('my brand new description')
+ it 'shows the pipeline schedule with default ref' do
+ page.within('.js-target-branch-dropdown') do
+ expect(first('.dropdown-toggle-text').text).to eq('master')
+ end
+ end
+ end
end
- context 'when ref is nil' do
- before do
- pipeline_schedule.update_attribute(:ref, nil)
- edit_pipeline_schedule
+ context 'when user creates a new pipeline schedule with variables' do
+ background do
+ visit_pipelines_schedules
+ click_link 'New schedule'
+ fill_in_schedule_form
+ all('[name="schedule[variables_attributes][][key]"]')[0].set('AAA')
+ all('[name="schedule[variables_attributes][][value]"]')[0].set('AAA123')
+ all('[name="schedule[variables_attributes][][key]"]')[1].set('BBB')
+ all('[name="schedule[variables_attributes][][value]"]')[1].set('BBB123')
+ save_pipeline_schedule
end
- it 'shows the pipeline schedule with default ref' do
- page.within('.js-target-branch-dropdown') do
- expect(first('.dropdown-toggle-text').text).to eq('master')
+ scenario 'user sees the new variable in edit window' do
+ find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click
+ page.within('.pipeline-variable-list') do
+ expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-key-input").value).to eq('AAA')
+ expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-value-input").value).to eq('AAA123')
+ expect(find(".pipeline-variable-row:nth-child(2) .pipeline-variable-key-input").value).to eq('BBB')
+ expect(find(".pipeline-variable-row:nth-child(2) .pipeline-variable-value-input").value).to eq('BBB123')
end
end
end
- end
- context 'when user creates a new pipeline schedule with variables' do
- background do
- visit_pipelines_schedules
- click_link 'New schedule'
- fill_in_schedule_form
- all('[name="schedule[variables_attributes][][key]"]')[0].set('AAA')
- all('[name="schedule[variables_attributes][][value]"]')[0].set('AAA123')
- all('[name="schedule[variables_attributes][][key]"]')[1].set('BBB')
- all('[name="schedule[variables_attributes][][value]"]')[1].set('BBB123')
- save_pipeline_schedule
- end
+ context 'when user edits a variable of a pipeline schedule' do
+ background do
+ create(:ci_pipeline_schedule, project: project, owner: user).tap do |pipeline_schedule|
+ create(:ci_pipeline_schedule_variable, key: 'AAA', value: 'AAA123', pipeline_schedule: pipeline_schedule)
+ end
- scenario 'user sees the new variable in edit window' do
- find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click
- page.within('.pipeline-variable-list') do
- expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-key-input").value).to eq('AAA')
- expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-value-input").value).to eq('AAA123')
- expect(find(".pipeline-variable-row:nth-child(2) .pipeline-variable-key-input").value).to eq('BBB')
- expect(find(".pipeline-variable-row:nth-child(2) .pipeline-variable-value-input").value).to eq('BBB123')
+ visit_pipelines_schedules
+ find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click
+ all('[name="schedule[variables_attributes][][key]"]')[0].set('foo')
+ all('[name="schedule[variables_attributes][][value]"]')[0].set('bar')
+ click_button 'Save pipeline schedule'
end
- end
- end
- context 'when user edits a variable of a pipeline schedule' do
- background do
- create(:ci_pipeline_schedule, project: project, owner: user).tap do |pipeline_schedule|
- create(:ci_pipeline_schedule_variable, key: 'AAA', value: 'AAA123', pipeline_schedule: pipeline_schedule)
+ scenario 'user sees the updated variable in edit window' do
+ find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click
+ page.within('.pipeline-variable-list') do
+ expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-key-input").value).to eq('foo')
+ expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-value-input").value).to eq('bar')
+ end
end
-
- visit_pipelines_schedules
- find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click
- all('[name="schedule[variables_attributes][][key]"]')[0].set('foo')
- all('[name="schedule[variables_attributes][][value]"]')[0].set('bar')
- click_button 'Save pipeline schedule'
end
- scenario 'user sees the updated variable in edit window' do
- find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click
- page.within('.pipeline-variable-list') do
- expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-key-input").value).to eq('foo')
- expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-value-input").value).to eq('bar')
+ context 'when user removes a variable of a pipeline schedule' do
+ background do
+ create(:ci_pipeline_schedule, project: project, owner: user).tap do |pipeline_schedule|
+ create(:ci_pipeline_schedule_variable, key: 'AAA', value: 'AAA123', pipeline_schedule: pipeline_schedule)
+ end
+
+ visit_pipelines_schedules
+ find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click
+ find('.pipeline-variable-list .pipeline-variable-row-remove-button').click
+ click_button 'Save pipeline schedule'
+ end
+
+ scenario 'user does not see the removed variable in edit window' do
+ find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click
+ page.within('.pipeline-variable-list') do
+ expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-key-input").value).to eq('')
+ expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-value-input").value).to eq('')
+ end
end
end
end
- context 'when user removes a variable of a pipeline schedule' do
- background do
- create(:ci_pipeline_schedule, project: project, owner: user).tap do |pipeline_schedule|
- create(:ci_pipeline_schedule_variable, key: 'AAA', value: 'AAA123', pipeline_schedule: pipeline_schedule)
+ context 'logged in as non-member' do
+ before do
+ gitlab_sign_in(user)
+ end
+
+ describe 'GET /projects/pipeline_schedules' do
+ before do
+ visit_pipelines_schedules
end
- visit_pipelines_schedules
- find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click
- find('.pipeline-variable-list .pipeline-variable-row-remove-button').click
- click_button 'Save pipeline schedule'
+ describe 'The view' do
+ it 'does not show create schedule button' do
+ expect(page).not_to have_link('New schedule')
+ end
+ end
end
+ end
+
+ context 'not logged in' do
+ describe 'GET /projects/pipeline_schedules' do
+ before do
+ visit_pipelines_schedules
+ end
- scenario 'user does not see the removed variable in edit window' do
- find(".content-list .pipeline-schedule-table-row:nth-child(1) .btn-group a[title='Edit']").click
- page.within('.pipeline-variable-list') do
- expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-key-input").value).to eq('')
- expect(find(".pipeline-variable-row:nth-child(1) .pipeline-variable-value-input").value).to eq('')
+ describe 'The view' do
+ it 'does not show create schedule button' do
+ expect(page).not_to have_link('New schedule')
+ end
end
end
end
diff --git a/spec/features/projects/user_browses_files_spec.rb b/spec/features/projects/user_browses_files_spec.rb
new file mode 100644
index 00000000000..263a3a29a66
--- /dev/null
+++ b/spec/features/projects/user_browses_files_spec.rb
@@ -0,0 +1,188 @@
+require 'spec_helper'
+
+describe 'User browses files' do
+ include DropzoneHelper
+
+ let(:fork_message) do
+ "You're not allowed to make changes to this project directly. "\
+ "A fork of this project has been created that you can make changes in, so you can submit a merge request."
+ end
+ let(:project) { create(:project, name: 'Shop') }
+ let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') }
+ let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) }
+ let(:tree_path_ref_6d39438) { project_tree_path(project, '6d39438') }
+ let(:tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) }
+ let(:user) { create(:user) }
+
+ before do
+ project.team << [user, :master]
+ sign_in(user)
+ end
+
+ context 'when browsing the master branch' do
+ before do
+ visit(tree_path_root_ref)
+ end
+
+ it 'shows files from a repository' do
+ expect(page).to have_content('VERSION')
+ expect(page).to have_content('.gitignore')
+ expect(page).to have_content('LICENSE')
+ end
+
+ it 'shows the "Browse Directory" link' do
+ click_link('files')
+ click_link('History')
+
+ expect(page).to have_link('Browse Directory')
+ expect(page).not_to have_link('Browse Code')
+ end
+
+ it 'shows the "Browse File" link' do
+ page.within('.tree-table') do
+ click_link('README.md')
+ end
+ click_link('History')
+
+ expect(page).to have_link('Browse File')
+ expect(page).not_to have_link('Browse Files')
+ end
+
+ it 'shows the "Browse Code" link' do
+ click_link('History')
+
+ expect(page).to have_link('Browse Files')
+ expect(page).not_to have_link('Browse Directory')
+ end
+
+ it 'redirects to the permalink URL' do
+ click_link('.gitignore')
+ click_link('Permalink')
+
+ permalink_path = project_blob_path(project, "#{project.repository.commit.sha}/.gitignore")
+
+ expect(current_path).to eq(permalink_path)
+ end
+ end
+
+ context 'when browsing a specific ref' do
+ before do
+ visit(tree_path_ref_6d39438)
+ end
+
+ it 'shows files from a repository for "6d39438"' do
+ expect(current_path).to eq(tree_path_ref_6d39438)
+ expect(page).to have_content('.gitignore')
+ expect(page).to have_content('LICENSE')
+ end
+
+ it 'shows files from a repository with apostroph in its name', js: true do
+ first('.js-project-refs-dropdown').click
+
+ page.within('.project-refs-form') do
+ click_link("'test'")
+ end
+
+ expect(page).to have_selector('.dropdown-toggle-text', text: "'test'")
+
+ visit(project_tree_path(project, "'test'"))
+
+ expect(page).to have_css('.tree-commit-link', visible: true)
+ expect(page).not_to have_content('Loading commit data...')
+ end
+
+ it 'shows the code with a leading dot in the directory', js: true do
+ first('.js-project-refs-dropdown').click
+
+ page.within('.project-refs-form') do
+ click_link('fix')
+ end
+
+ visit(project_tree_path(project, 'fix/.testdir'))
+
+ expect(page).to have_css('.tree-commit-link', visible: true)
+ expect(page).not_to have_content('Loading commit data...')
+ end
+
+ it 'does not show the permalink link' do
+ click_link('.gitignore')
+
+ expect(page).not_to have_link('permalink')
+ end
+ end
+
+ context 'when browsing a file content' do
+ before do
+ visit(tree_path_root_ref)
+ click_link('.gitignore')
+ end
+
+ it 'shows a file content', js: true do
+ wait_for_requests
+ expect(page).to have_content('*.rbc')
+ end
+ end
+
+ context 'when browsing a raw file' do
+ before do
+ visit(project_blob_path(project, File.join(RepoHelpers.sample_commit.id, RepoHelpers.sample_blob.path)))
+ end
+
+ it 'shows a raw file content' do
+ click_link('Open raw')
+ expect(source).to eq('') # Body is filled in by gitlab-workhorse
+ end
+ end
+
+ context 'when browsing an LFS object' do
+ before do
+ allow_any_instance_of(Project).to receive(:lfs_enabled?).and_return(true)
+ visit(project_tree_path(project, 'lfs'))
+ end
+
+ it 'shows an LFS object' do
+ click_link('files')
+ click_link('lfs')
+ click_link('lfs_object.iso')
+
+ expect(page).to have_content('Download (1.5 MB)')
+ expect(page).not_to have_content('version https://git-lfs.github.com/spec/v1')
+ expect(page).not_to have_content('oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897')
+ expect(page).not_to have_content('size 1575078')
+
+ page.within('.content') do
+ expect(page).to have_content('Delete')
+ expect(page).to have_content('History')
+ expect(page).to have_content('Permalink')
+ expect(page).to have_content('Replace')
+ expect(page).not_to have_content('Annotate')
+ expect(page).not_to have_content('Blame')
+ expect(page).not_to have_content('Edit')
+ expect(page).to have_link('Download')
+ end
+ end
+ end
+
+ context 'when previewing a file content' do
+ before do
+ visit(tree_path_root_ref)
+ end
+
+ it 'shows a preview of a file content', js: true do
+ find('.add-to-tree').click
+ click_link('Upload file')
+ drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'logo_sample.svg'))
+
+ page.within('#modal-upload-blob') do
+ fill_in(:commit_message, with: 'New commit message')
+ end
+
+ fill_in(:branch_name, with: 'new_branch_name', visible: true)
+ click_button('Upload file')
+
+ visit(project_blob_path(project, 'new_branch_name/logo_sample.svg'))
+
+ expect(page).to have_css('.file-content img')
+ end
+ end
+end
diff --git a/spec/features/projects/user_create_dir_spec.rb b/spec/features/projects/user_create_dir_spec.rb
deleted file mode 100644
index 5e302da8a63..00000000000
--- a/spec/features/projects/user_create_dir_spec.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-require 'spec_helper'
-
-feature 'New directory creation', feature: true, js: true do
- given(:user) { create(:user) }
- given(:role) { :developer }
- given(:project) { create(:project) }
-
- background do
- sign_in(user)
- project.team << [user, role]
- visit project_tree_path(project, 'master')
- open_new_directory_modal
- fill_in 'dir_name', with: 'new_directory'
- end
-
- def open_new_directory_modal
- first('.add-to-tree').click
- click_link 'New directory'
- end
-
- def create_directory
- click_button 'Create directory'
- end
-
- context 'with default target branch' do
- background do
- create_directory
- end
-
- scenario 'creates the directory in the default branch' do
- expect(page).to have_content 'master'
- expect(page).to have_content 'The directory has been successfully created'
- expect(page).to have_content 'new_directory'
- end
- end
-
- context 'with a new target branch' do
- given(:new_branch_name) { 'new-feature' }
-
- background do
- fill_in :branch_name, with: new_branch_name
- create_directory
- end
-
- scenario 'creates the directory in the new branch' do
- expect(page).to have_content new_branch_name
- expect(page).to have_content 'The directory has been successfully created'
- end
-
- scenario 'redirects to the merge request' do
- expect(page).to have_content 'New Merge Request'
- expect(page).to have_content "From #{new_branch_name} into master"
- expect(page).to have_content 'Add new directory'
- expect(current_path).to eq(project_new_merge_request_path(project))
- end
- end
-end
diff --git a/spec/features/projects/user_creates_directory_spec.rb b/spec/features/projects/user_creates_directory_spec.rb
new file mode 100644
index 00000000000..635bd4493dd
--- /dev/null
+++ b/spec/features/projects/user_creates_directory_spec.rb
@@ -0,0 +1,87 @@
+require 'spec_helper'
+
+feature 'User creates a directory', js: true do
+ let(:fork_message) do
+ "You're not allowed to make changes to this project directly. "\
+ "A fork of this project has been created that you can make changes in, so you can submit a merge request."
+ end
+ let(:project) { create(:project) }
+ let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') }
+ let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) }
+ let(:user) { create(:user) }
+
+ before do
+ project.team << [user, :developer]
+ sign_in(user)
+ visit project_tree_path(project, 'master')
+ end
+
+ context 'with default target branch' do
+ before do
+ first('.add-to-tree').click
+ click_link('New directory')
+ end
+
+ it 'creates the directory in the default branch' do
+ fill_in(:dir_name, with: 'new_directory')
+ click_button('Create directory')
+
+ expect(page).to have_content('master')
+ expect(page).to have_content('The directory has been successfully created')
+ expect(page).to have_content('new_directory')
+ end
+
+ it 'does not create a directory with a name of already existed directory' do
+ fill_in(:dir_name, with: 'files')
+ fill_in(:commit_message, with: 'New commit message', visible: true)
+ click_button('Create directory')
+
+ expect(page).to have_content('A directory with this name already exists')
+ expect(current_path).to eq(project_tree_path(project, 'master'))
+ end
+ end
+
+ context 'with a new target branch' do
+ before do
+ first('.add-to-tree').click
+ click_link('New directory')
+ fill_in(:dir_name, with: 'new_directory')
+ fill_in(:branch_name, with: 'new-feature')
+ click_button('Create directory')
+ end
+
+ it 'creates the directory in the new branch and redirect to the merge request' do
+ expect(page).to have_content('new-feature')
+ expect(page).to have_content('The directory has been successfully created')
+ expect(page).to have_content('New Merge Request')
+ expect(page).to have_content('From new-feature into master')
+ expect(page).to have_content('Add new directory')
+
+ expect(current_path).to eq(project_new_merge_request_path(project))
+ end
+ end
+
+ context 'when an user does not have write access' do
+ before do
+ project2.team << [user, :reporter]
+ visit(project2_tree_path_root_ref)
+ end
+
+ it 'creates a directory in a forked project' do
+ find('.add-to-tree').click
+ click_link('New directory')
+
+ expect(page).to have_content(fork_message)
+
+ find('.add-to-tree').click
+ click_link('New directory')
+ fill_in(:dir_name, with: 'new_directory')
+ fill_in(:commit_message, with: 'New commit message', visible: true)
+ click_button('Create directory')
+
+ fork = user.fork_of(project2)
+
+ expect(current_path).to eq(project_new_merge_request_path(fork))
+ end
+ end
+end
diff --git a/spec/features/projects/user_creates_files_spec.rb b/spec/features/projects/user_creates_files_spec.rb
new file mode 100644
index 00000000000..0c7f1a775c1
--- /dev/null
+++ b/spec/features/projects/user_creates_files_spec.rb
@@ -0,0 +1,153 @@
+require 'spec_helper'
+
+describe 'User creates files' do
+ let(:fork_message) do
+ "You're not allowed to make changes to this project directly. "\
+ "A fork of this project has been created that you can make changes in, so you can submit a merge request."
+ end
+ let(:project) { create(:project, name: 'Shop') }
+ let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') }
+ let(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) }
+ let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) }
+ let(:user) { create(:user) }
+
+ before do
+ project.team << [user, :master]
+ sign_in(user)
+ end
+
+ context 'without commiting a new file' do
+ context 'when an user has write access' do
+ before do
+ visit(project_tree_path_root_ref)
+ end
+
+ it 'opens new file page' do
+ find('.add-to-tree').click
+ click_link('New file')
+
+ expect(page).to have_content('New file')
+ expect(page).to have_content('Commit message')
+ end
+ end
+
+ context 'when an user does not have write access' do
+ before do
+ project2.team << [user, :reporter]
+ visit(project2_tree_path_root_ref)
+ end
+
+ it 'opens new file page on a forked project' do
+ find('.add-to-tree').click
+ click_link('New file')
+
+ expect(page).to have_selector('.file-editor')
+ expect(page).to have_content(fork_message)
+ expect(page).to have_content('New file')
+ expect(page).to have_content('Commit message')
+ end
+ end
+ end
+
+ context 'with commiting a new file' do
+ context 'when an user has write access' do
+ before do
+ visit(project_tree_path_root_ref)
+
+ find('.add-to-tree').click
+ click_link('New file')
+ end
+
+ it 'creates and commit a new file', js: true do
+ expect(page).to have_selector('.file-editor')
+
+ execute_script("ace.edit('editor').setValue('*.rbca')")
+ fill_in(:file_name, with: 'not_a_file.md')
+ fill_in(:commit_message, with: 'New commit message', visible: true)
+ click_button('Commit changes')
+
+ new_file_path = project_blob_path(project, 'master/not_a_file.md')
+
+ expect(current_path).to eq(new_file_path)
+
+ wait_for_requests
+
+ expect(page).to have_content('*.rbca')
+ end
+
+ it 'creates and commit a new file with new lines at the end of file', js: true do
+ execute_script('ace.edit("editor").setValue("Sample\n\n\n")')
+ fill_in(:file_name, with: 'not_a_file.md')
+ fill_in(:commit_message, with: 'New commit message', visible: true)
+ click_button('Commit changes')
+
+ new_file_path = project_blob_path(project, 'master/not_a_file.md')
+
+ expect(current_path).to eq(new_file_path)
+
+ find('.js-edit-blob').click
+
+ expect(evaluate_script('ace.edit("editor").getValue()')).to eq("Sample\n\n\n")
+ end
+
+ it 'creates and commit a new file with a directory name', js: true do
+ fill_in(:file_name, with: 'foo/bar/baz.txt')
+
+ expect(page).to have_selector('.file-editor')
+
+ execute_script("ace.edit('editor').setValue('*.rbca')")
+ fill_in(:commit_message, with: 'New commit message', visible: true)
+ click_button('Commit changes')
+
+ expect(current_path).to eq(project_blob_path(project, 'master/foo/bar/baz.txt'))
+
+ wait_for_requests
+
+ expect(page).to have_content('*.rbca')
+ end
+
+ it 'creates and commit a new file specifying a new branch', js: true do
+ expect(page).to have_selector('.file-editor')
+
+ execute_script("ace.edit('editor').setValue('*.rbca')")
+ fill_in(:file_name, with: 'not_a_file.md')
+ fill_in(:commit_message, with: 'New commit message', visible: true)
+ fill_in(:branch_name, with: 'new_branch_name', visible: true)
+ click_button('Commit changes')
+
+ expect(current_path).to eq(project_new_merge_request_path(project))
+
+ click_link('Changes')
+
+ wait_for_requests
+
+ expect(page).to have_content('*.rbca')
+ end
+ end
+
+ context 'when an user does not have write access' do
+ before do
+ project2.team << [user, :reporter]
+ visit(project2_tree_path_root_ref)
+ end
+
+ it 'creates and commit new file in forked project', js: true do
+ find('.add-to-tree').click
+ click_link('New file')
+
+ expect(page).to have_selector('.file-editor')
+
+ execute_script("ace.edit('editor').setValue('*.rbca')")
+
+ fill_in(:file_name, with: 'not_a_file.md')
+ fill_in(:commit_message, with: 'New commit message', visible: true)
+ click_button('Commit changes')
+
+ fork = user.fork_of(project2)
+
+ expect(current_path).to eq(project_new_merge_request_path(fork))
+ expect(page).to have_content('New commit message')
+ end
+ end
+ end
+end
diff --git a/spec/features/projects/user_deletes_files_spec.rb b/spec/features/projects/user_deletes_files_spec.rb
new file mode 100644
index 00000000000..97e60862b4f
--- /dev/null
+++ b/spec/features/projects/user_deletes_files_spec.rb
@@ -0,0 +1,68 @@
+require 'spec_helper'
+
+describe 'User deletes files' do
+ let(:fork_message) do
+ "You're not allowed to make changes to this project directly. "\
+ "A fork of this project has been created that you can make changes in, so you can submit a merge request."
+ end
+ let(:project) { create(:project, name: 'Shop') }
+ let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') }
+ let(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) }
+ let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) }
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ end
+
+ context 'when an user has write access' do
+ before do
+ project.team << [user, :master]
+ visit(project_tree_path_root_ref)
+ end
+
+ it 'deletes the file', js: true do
+ click_link('.gitignore')
+
+ expect(page).to have_content('.gitignore')
+
+ click_on('Delete')
+ fill_in(:commit_message, with: 'New commit message', visible: true)
+ click_button('Delete file')
+
+ expect(current_path).to eq(project_tree_path(project, 'master'))
+ expect(page).not_to have_content('.gitignore')
+ end
+ end
+
+ context 'when an user does not have write access' do
+ before do
+ project2.team << [user, :reporter]
+ visit(project2_tree_path_root_ref)
+ end
+
+ it 'deletes the file in a forked project', js: true do
+ click_link('.gitignore')
+
+ expect(page).to have_content('.gitignore')
+
+ click_on('Delete')
+
+ expect(page).to have_link('Fork')
+ expect(page).to have_button('Cancel')
+
+ click_link('Fork')
+
+ expect(page).to have_content(fork_message)
+
+ click_on('Delete')
+ fill_in(:commit_message, with: 'New commit message', visible: true)
+ click_button('Delete file')
+
+ fork = user.fork_of(project2)
+
+ expect(current_path).to eq(project_new_merge_request_path(fork))
+ expect(page).to have_content('New commit message')
+ end
+ end
+end
diff --git a/spec/features/projects/user_edits_files_spec.rb b/spec/features/projects/user_edits_files_spec.rb
new file mode 100644
index 00000000000..eb26f1bc123
--- /dev/null
+++ b/spec/features/projects/user_edits_files_spec.rb
@@ -0,0 +1,122 @@
+require 'spec_helper'
+
+describe 'User edits files' do
+ let(:fork_message) do
+ "You're not allowed to make changes to this project directly. "\
+ "A fork of this project has been created that you can make changes in, so you can submit a merge request."
+ end
+ let(:project) { create(:project, name: 'Shop') }
+ let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') }
+ let(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) }
+ let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) }
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ end
+
+ context 'when an user has write access' do
+ before do
+ project.team << [user, :master]
+ visit(project_tree_path_root_ref)
+ end
+
+ it 'inserts a content of a file', js: true do
+ click_link('.gitignore')
+ find('.js-edit-blob').click
+ execute_script("ace.edit('editor').setValue('*.rbca')")
+
+ expect(evaluate_script('ace.edit("editor").getValue()')).to eq('*.rbca')
+ end
+
+ it 'does not show the edit link if a file is binary' do
+ binary_file = File.join(project.repository.root_ref, 'files/images/logo-black.png')
+ visit(project_blob_path(project, binary_file))
+
+ expect(page).not_to have_link('edit')
+ end
+
+ it 'commits an edited file', js: true do
+ click_link('.gitignore')
+ find('.js-edit-blob').click
+ execute_script("ace.edit('editor').setValue('*.rbca')")
+ fill_in(:commit_message, with: 'New commit message', visible: true)
+ click_button('Commit changes')
+
+ expect(current_path).to eq(project_blob_path(project, 'master/.gitignore'))
+
+ wait_for_requests
+
+ expect(page).to have_content('*.rbca')
+ end
+
+ it 'commits an edited file to a new branch', js: true do
+ click_link('.gitignore')
+ find('.js-edit-blob').click
+ execute_script("ace.edit('editor').setValue('*.rbca')")
+ fill_in(:commit_message, with: 'New commit message', visible: true)
+ fill_in(:branch_name, with: 'new_branch_name', visible: true)
+ click_button('Commit changes')
+
+ expect(current_path).to eq(project_new_merge_request_path(project))
+
+ click_link('Changes')
+
+ wait_for_requests
+ expect(page).to have_content('*.rbca')
+ end
+
+ it 'shows the diff of an edited file', js: true do
+ click_link('.gitignore')
+ find('.js-edit-blob').click
+ execute_script("ace.edit('editor').setValue('*.rbca')")
+ click_link('Preview changes')
+
+ expect(page).to have_css('.line_holder.new')
+ end
+ end
+
+ context 'when an user does not have write access' do
+ before do
+ project2.team << [user, :reporter]
+ visit(project2_tree_path_root_ref)
+ end
+
+ it 'inserts a content of a file in a forked project', js: true do
+ click_link('.gitignore')
+ find('.js-edit-blob').click
+
+ expect(page).to have_link('Fork')
+ expect(page).to have_button('Cancel')
+
+ click_link('Fork')
+
+ expect(page).to have_content(fork_message)
+
+ execute_script("ace.edit('editor').setValue('*.rbca')")
+
+ expect(evaluate_script('ace.edit("editor").getValue()')).to eq('*.rbca')
+ end
+
+ it 'commits an edited file in a forked project', js: true do
+ click_link('.gitignore')
+ find('.js-edit-blob').click
+
+ expect(page).to have_link('Fork')
+ expect(page).to have_button('Cancel')
+
+ click_link('Fork')
+ execute_script("ace.edit('editor').setValue('*.rbca')")
+ fill_in(:commit_message, with: 'New commit message', visible: true)
+ click_button('Commit changes')
+
+ fork = user.fork_of(project2)
+
+ expect(current_path).to eq(project_new_merge_request_path(fork))
+
+ wait_for_requests
+
+ expect(page).to have_content('New commit message')
+ end
+ end
+end
diff --git a/spec/features/projects/user_replaces_files_spec.rb b/spec/features/projects/user_replaces_files_spec.rb
new file mode 100644
index 00000000000..50f2ffc4bbf
--- /dev/null
+++ b/spec/features/projects/user_replaces_files_spec.rb
@@ -0,0 +1,87 @@
+require 'spec_helper'
+
+describe 'User replaces files' do
+ include DropzoneHelper
+
+ let(:fork_message) do
+ "You're not allowed to make changes to this project directly. "\
+ "A fork of this project has been created that you can make changes in, so you can submit a merge request."
+ end
+ let(:project) { create(:project, name: 'Shop') }
+ let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') }
+ let(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) }
+ let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) }
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ end
+
+ context 'when an user has write access' do
+ before do
+ project.team << [user, :master]
+ visit(project_tree_path_root_ref)
+ end
+
+ it 'replaces an existed file with a new one', js: true do
+ click_link('.gitignore')
+
+ expect(page).to have_content('.gitignore')
+
+ click_on('Replace')
+ drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'))
+
+ page.within('#modal-upload-blob') do
+ fill_in(:commit_message, with: 'Replacement file commit message')
+ end
+
+ click_button('Replace file')
+
+ expect(page).to have_content('Lorem ipsum dolor sit amet')
+ expect(page).to have_content('Sed ut perspiciatis unde omnis')
+ expect(page).to have_content('Replacement file commit message')
+ end
+ end
+
+ context 'when an user does not have write access' do
+ before do
+ project2.team << [user, :reporter]
+ visit(project2_tree_path_root_ref)
+ end
+
+ it 'replaces an existed file with a new one in a forked project', js: true do
+ click_link('.gitignore')
+
+ expect(page).to have_content('.gitignore')
+
+ click_on('Replace')
+
+ expect(page).to have_link('Fork')
+ expect(page).to have_button('Cancel')
+
+ click_link('Fork')
+
+ expect(page).to have_content(fork_message)
+
+ click_on('Replace')
+ drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'))
+
+ page.within('#modal-upload-blob') do
+ fill_in(:commit_message, with: 'Replacement file commit message')
+ end
+
+ click_button('Replace file')
+
+ expect(page).to have_content('Replacement file commit message')
+
+ fork = user.fork_of(project2)
+
+ expect(current_path).to eq(project_new_merge_request_path(fork))
+
+ click_link('Changes')
+
+ expect(page).to have_content('Lorem ipsum dolor sit amet')
+ expect(page).to have_content('Sed ut perspiciatis unde omnis')
+ end
+ end
+end
diff --git a/spec/features/projects/user_uploads_files_spec.rb b/spec/features/projects/user_uploads_files_spec.rb
new file mode 100644
index 00000000000..64a1439badd
--- /dev/null
+++ b/spec/features/projects/user_uploads_files_spec.rb
@@ -0,0 +1,82 @@
+require 'spec_helper'
+
+describe 'User uploads files' do
+ include DropzoneHelper
+
+ let(:fork_message) do
+ "You're not allowed to make changes to this project directly. "\
+ "A fork of this project has been created that you can make changes in, so you can submit a merge request."
+ end
+ let(:project) { create(:project, name: 'Shop') }
+ let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') }
+ let(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) }
+ let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) }
+ let(:user) { create(:user) }
+
+ before do
+ project.team << [user, :master]
+ sign_in(user)
+ end
+
+ context 'when an user has write access' do
+ before do
+ visit(project_tree_path_root_ref)
+ end
+
+ it 'uploads and commit a new file', js: true do
+ find('.add-to-tree').click
+ click_link('Upload file')
+ drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'))
+
+ page.within('#modal-upload-blob') do
+ fill_in(:commit_message, with: 'New commit message')
+ end
+
+ fill_in(:branch_name, with: 'new_branch_name', visible: true)
+ click_button('Upload file')
+
+ expect(page).to have_content('New commit message')
+ expect(current_path).to eq(project_new_merge_request_path(project))
+
+ click_link('Changes')
+
+ expect(page).to have_content('Lorem ipsum dolor sit amet')
+ expect(page).to have_content('Sed ut perspiciatis unde omnis')
+ end
+ end
+
+ context 'when an user does not have write access' do
+ before do
+ project2.team << [user, :reporter]
+ visit(project2_tree_path_root_ref)
+ end
+
+ it 'uploads and commit a new fileto a forked project', js: true do
+ find('.add-to-tree').click
+ click_link('Upload file')
+
+ expect(page).to have_content(fork_message)
+
+ find('.add-to-tree').click
+ click_link('Upload file')
+ drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'))
+
+ page.within('#modal-upload-blob') do
+ fill_in(:commit_message, with: 'New commit message')
+ end
+
+ click_button('Upload file')
+
+ expect(page).to have_content('New commit message')
+
+ fork = user.fork_of(project2)
+
+ expect(current_path).to eq(project_new_merge_request_path(fork))
+
+ click_link('Changes')
+
+ expect(page).to have_content('Lorem ipsum dolor sit amet')
+ expect(page).to have_content('Sed ut perspiciatis unde omnis')
+ end
+ end
+end
diff --git a/spec/fixtures/api/schemas/public_api/v4/user/admin.json b/spec/fixtures/api/schemas/public_api/v4/user/admin.json
new file mode 100644
index 00000000000..f733914fbf8
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/user/admin.json
@@ -0,0 +1,34 @@
+{
+ "type": "object",
+ "required": [
+ "id",
+ "username",
+ "email",
+ "name",
+ "state",
+ "avatar_url",
+ "web_url",
+ "created_at",
+ "is_admin",
+ "bio",
+ "location",
+ "skype",
+ "linkedin",
+ "twitter",
+ "website_url",
+ "organization",
+ "last_sign_in_at",
+ "confirmed_at",
+ "color_scheme_id",
+ "projects_limit",
+ "current_sign_in_at",
+ "identities",
+ "can_create_group",
+ "can_create_project",
+ "two_factor_enabled",
+ "external"
+ ],
+ "properties": {
+ "$ref": "full.json"
+ }
+}
diff --git a/spec/fixtures/config/redis_cache_config_with_env.yml b/spec/fixtures/config/redis_cache_config_with_env.yml
new file mode 100644
index 00000000000..52fd5a06460
--- /dev/null
+++ b/spec/fixtures/config/redis_cache_config_with_env.yml
@@ -0,0 +1,2 @@
+test:
+ url: <%= ENV['TEST_GITLAB_REDIS_CACHE_URL'] %>
diff --git a/spec/fixtures/config/redis_cache_new_format_host.yml b/spec/fixtures/config/redis_cache_new_format_host.yml
new file mode 100644
index 00000000000..a24f3716391
--- /dev/null
+++ b/spec/fixtures/config/redis_cache_new_format_host.yml
@@ -0,0 +1,29 @@
+# redis://[:password@]host[:port][/db-number][?option=value]
+# more details: http://www.iana.org/assignments/uri-schemes/prov/redis
+development:
+ url: redis://:mynewpassword@localhost:6380/10
+ sentinels:
+ -
+ host: localhost
+ port: 26380 # point to sentinel, not to redis port
+ -
+ host: slave2
+ port: 26380 # point to sentinel, not to redis port
+test:
+ url: redis://:mynewpassword@localhost:6380/10
+ sentinels:
+ -
+ host: localhost
+ port: 26380 # point to sentinel, not to redis port
+ -
+ host: slave2
+ port: 26380 # point to sentinel, not to redis port
+production:
+ url: redis://:mynewpassword@localhost:6380/10
+ sentinels:
+ -
+ host: slave1
+ port: 26380 # point to sentinel, not to redis port
+ -
+ host: slave2
+ port: 26380 # point to sentinel, not to redis port
diff --git a/spec/fixtures/config/redis_cache_new_format_socket.yml b/spec/fixtures/config/redis_cache_new_format_socket.yml
new file mode 100644
index 00000000000..3634c550163
--- /dev/null
+++ b/spec/fixtures/config/redis_cache_new_format_socket.yml
@@ -0,0 +1,6 @@
+development:
+ url: unix:/path/to/redis.cache.sock
+test:
+ url: unix:/path/to/redis.cache.sock
+production:
+ url: unix:/path/to/redis.cache.sock
diff --git a/spec/fixtures/config/redis_cache_old_format_host.yml b/spec/fixtures/config/redis_cache_old_format_host.yml
new file mode 100644
index 00000000000..3609dcd022e
--- /dev/null
+++ b/spec/fixtures/config/redis_cache_old_format_host.yml
@@ -0,0 +1,5 @@
+# redis://[:password@]host[:port][/db-number][?option=value]
+# more details: http://www.iana.org/assignments/uri-schemes/prov/redis
+development: redis://:mypassword@localhost:6380/10
+test: redis://:mypassword@localhost:6380/10
+production: redis://:mypassword@localhost:6380/10
diff --git a/spec/fixtures/config/redis_cache_old_format_socket.yml b/spec/fixtures/config/redis_cache_old_format_socket.yml
new file mode 100644
index 00000000000..26fa0eda245
--- /dev/null
+++ b/spec/fixtures/config/redis_cache_old_format_socket.yml
@@ -0,0 +1,3 @@
+development: unix:/path/to/old/redis.cache.sock
+test: unix:/path/to/old/redis.cache.sock
+production: unix:/path/to/old/redis.cache.sock
diff --git a/spec/fixtures/config/redis_new_format_host.yml b/spec/fixtures/config/redis_new_format_host.yml
index 13772677a45..8d134d467e9 100644
--- a/spec/fixtures/config/redis_new_format_host.yml
+++ b/spec/fixtures/config/redis_new_format_host.yml
@@ -5,25 +5,25 @@ development:
sentinels:
-
host: localhost
- port: 26380 # point to sentinel, not to redis port
+ port: 26379 # point to sentinel, not to redis port
-
host: slave2
- port: 26381 # point to sentinel, not to redis port
+ port: 26379 # point to sentinel, not to redis port
test:
url: redis://:mynewpassword@localhost:6379/99
sentinels:
-
host: localhost
- port: 26380 # point to sentinel, not to redis port
+ port: 26379 # point to sentinel, not to redis port
-
host: slave2
- port: 26381 # point to sentinel, not to redis port
+ port: 26379 # point to sentinel, not to redis port
production:
url: redis://:mynewpassword@localhost:6379/99
sentinels:
-
host: slave1
- port: 26380 # point to sentinel, not to redis port
+ port: 26379 # point to sentinel, not to redis port
-
host: slave2
- port: 26381 # point to sentinel, not to redis port
+ port: 26379 # point to sentinel, not to redis port
diff --git a/spec/fixtures/config/redis_queues_config_with_env.yml b/spec/fixtures/config/redis_queues_config_with_env.yml
new file mode 100644
index 00000000000..d16a9d8a7f8
--- /dev/null
+++ b/spec/fixtures/config/redis_queues_config_with_env.yml
@@ -0,0 +1,2 @@
+test:
+ url: <%= ENV['TEST_GITLAB_REDIS_QUEUES_URL'] %>
diff --git a/spec/fixtures/config/redis_queues_new_format_host.yml b/spec/fixtures/config/redis_queues_new_format_host.yml
new file mode 100644
index 00000000000..1535584d779
--- /dev/null
+++ b/spec/fixtures/config/redis_queues_new_format_host.yml
@@ -0,0 +1,29 @@
+# redis://[:password@]host[:port][/db-number][?option=value]
+# more details: http://www.iana.org/assignments/uri-schemes/prov/redis
+development:
+ url: redis://:mynewpassword@localhost:6381/11
+ sentinels:
+ -
+ host: localhost
+ port: 26381 # point to sentinel, not to redis port
+ -
+ host: slave2
+ port: 26381 # point to sentinel, not to redis port
+test:
+ url: redis://:mynewpassword@localhost:6381/11
+ sentinels:
+ -
+ host: localhost
+ port: 26381 # point to sentinel, not to redis port
+ -
+ host: slave2
+ port: 26381 # point to sentinel, not to redis port
+production:
+ url: redis://:mynewpassword@localhost:6381/11
+ sentinels:
+ -
+ host: slave1
+ port: 26381 # point to sentinel, not to redis port
+ -
+ host: slave2
+ port: 26381 # point to sentinel, not to redis port
diff --git a/spec/fixtures/config/redis_queues_new_format_socket.yml b/spec/fixtures/config/redis_queues_new_format_socket.yml
new file mode 100644
index 00000000000..b488d84d022
--- /dev/null
+++ b/spec/fixtures/config/redis_queues_new_format_socket.yml
@@ -0,0 +1,6 @@
+development:
+ url: unix:/path/to/redis.queues.sock
+test:
+ url: unix:/path/to/redis.queues.sock
+production:
+ url: unix:/path/to/redis.queues.sock
diff --git a/spec/fixtures/config/redis_queues_old_format_host.yml b/spec/fixtures/config/redis_queues_old_format_host.yml
new file mode 100644
index 00000000000..6531748a8d7
--- /dev/null
+++ b/spec/fixtures/config/redis_queues_old_format_host.yml
@@ -0,0 +1,5 @@
+# redis://[:password@]host[:port][/db-number][?option=value]
+# more details: http://www.iana.org/assignments/uri-schemes/prov/redis
+development: redis://:mypassword@localhost:6381/11
+test: redis://:mypassword@localhost:6381/11
+production: redis://:mypassword@localhost:6381/11
diff --git a/spec/fixtures/config/redis_queues_old_format_socket.yml b/spec/fixtures/config/redis_queues_old_format_socket.yml
new file mode 100644
index 00000000000..53f5db72758
--- /dev/null
+++ b/spec/fixtures/config/redis_queues_old_format_socket.yml
@@ -0,0 +1,3 @@
+development: unix:/path/to/old/redis.queues.sock
+test: unix:/path/to/old/redis.queues.sock
+production: unix:/path/to/old/redis.queues.sock
diff --git a/spec/fixtures/config/redis_shared_state_config_with_env.yml b/spec/fixtures/config/redis_shared_state_config_with_env.yml
new file mode 100644
index 00000000000..eab7203d0de
--- /dev/null
+++ b/spec/fixtures/config/redis_shared_state_config_with_env.yml
@@ -0,0 +1,2 @@
+test:
+ url: <%= ENV['TEST_GITLAB_REDIS_SHARED_STATE_URL'] %>
diff --git a/spec/fixtures/config/redis_shared_state_new_format_host.yml b/spec/fixtures/config/redis_shared_state_new_format_host.yml
new file mode 100644
index 00000000000..1180b2b4a82
--- /dev/null
+++ b/spec/fixtures/config/redis_shared_state_new_format_host.yml
@@ -0,0 +1,29 @@
+# redis://[:password@]host[:port][/db-number][?option=value]
+# more details: http://www.iana.org/assignments/uri-schemes/prov/redis
+development:
+ url: redis://:mynewpassword@localhost:6382/12
+ sentinels:
+ -
+ host: localhost
+ port: 26382 # point to sentinel, not to redis port
+ -
+ host: slave2
+ port: 26382 # point to sentinel, not to redis port
+test:
+ url: redis://:mynewpassword@localhost:6382/12
+ sentinels:
+ -
+ host: localhost
+ port: 26382 # point to sentinel, not to redis port
+ -
+ host: slave2
+ port: 26382 # point to sentinel, not to redis port
+production:
+ url: redis://:mynewpassword@localhost:6382/12
+ sentinels:
+ -
+ host: slave1
+ port: 26382 # point to sentinel, not to redis port
+ -
+ host: slave2
+ port: 26382 # point to sentinel, not to redis port
diff --git a/spec/fixtures/config/redis_shared_state_new_format_socket.yml b/spec/fixtures/config/redis_shared_state_new_format_socket.yml
new file mode 100644
index 00000000000..1b0e699729e
--- /dev/null
+++ b/spec/fixtures/config/redis_shared_state_new_format_socket.yml
@@ -0,0 +1,6 @@
+development:
+ url: unix:/path/to/redis.shared_state.sock
+test:
+ url: unix:/path/to/redis.shared_state.sock
+production:
+ url: unix:/path/to/redis.shared_state.sock
diff --git a/spec/fixtures/config/redis_shared_state_old_format_host.yml b/spec/fixtures/config/redis_shared_state_old_format_host.yml
new file mode 100644
index 00000000000..fef5e768c5d
--- /dev/null
+++ b/spec/fixtures/config/redis_shared_state_old_format_host.yml
@@ -0,0 +1,5 @@
+# redis://[:password@]host[:port][/db-number][?option=value]
+# more details: http://www.iana.org/assignments/uri-schemes/prov/redis
+development: redis://:mypassword@localhost:6382/12
+test: redis://:mypassword@localhost:6382/12
+production: redis://:mypassword@localhost:6382/12
diff --git a/spec/fixtures/config/redis_shared_state_old_format_socket.yml b/spec/fixtures/config/redis_shared_state_old_format_socket.yml
new file mode 100644
index 00000000000..4746afbb5ef
--- /dev/null
+++ b/spec/fixtures/config/redis_shared_state_old_format_socket.yml
@@ -0,0 +1,3 @@
+development: unix:/path/to/old/redis.shared_state.sock
+test: unix:/path/to/old/redis.shared_state.sock
+production: unix:/path/to/old/redis.shared_state.sock
diff --git a/spec/helpers/award_emoji_helper_spec.rb b/spec/helpers/award_emoji_helper_spec.rb
index 7dfd6a3f6b4..035960ed96e 100644
--- a/spec/helpers/award_emoji_helper_spec.rb
+++ b/spec/helpers/award_emoji_helper_spec.rb
@@ -40,7 +40,7 @@ describe AwardEmojiHelper do
it 'returns correct url' do
@project = merge_request.project
- expected_url = "/#{@project.namespace.path}/#{@project.path}/merge_requests/#{merge_request.id}/toggle_award_emoji"
+ expected_url = "/#{@project.namespace.path}/#{@project.path}/merge_requests/#{merge_request.iid}/toggle_award_emoji"
expect(helper.toggle_award_url(merge_request)).to eq(expected_url)
end
@@ -52,7 +52,7 @@ describe AwardEmojiHelper do
it 'returns correct url' do
@project = issue.project
- expected_url = "/#{@project.namespace.path}/#{@project.path}/issues/#{issue.id}/toggle_award_emoji"
+ expected_url = "/#{@project.namespace.path}/#{@project.path}/issues/#{issue.iid}/toggle_award_emoji"
expect(helper.toggle_award_url(issue)).to eq(expected_url)
end
diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb
index d2e918ef014..b423a09873b 100644
--- a/spec/helpers/issuables_helper_spec.rb
+++ b/spec/helpers/issuables_helper_spec.rb
@@ -60,7 +60,7 @@ describe IssuablesHelper do
end
end
- describe 'counter caching based on issuable type and params', :caching do
+ describe 'counter caching based on issuable type and params', :use_clean_rails_memory_store_caching do
let(:params) do
{
scope: 'created-by-me',
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index 487d9800707..c462d9006ea 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -63,7 +63,7 @@ describe ProjectsHelper do
end
end
- describe "#project_list_cache_key", redis: true do
+ describe "#project_list_cache_key", clean_gitlab_redis_shared_state: true do
let(:project) { create(:project) }
it "includes the route" do
diff --git a/spec/javascripts/environments/environment_spec.js b/spec/javascripts/environments/environment_spec.js
index 6639a6b5e7b..0c8817a8148 100644
--- a/spec/javascripts/environments/environment_spec.js
+++ b/spec/javascripts/environments/environment_spec.js
@@ -2,6 +2,7 @@ import Vue from 'vue';
import '~/flash';
import environmentsComponent from '~/environments/components/environment.vue';
import { environment, folder } from './mock_data';
+import { headersInterceptor } from '../helpers/vue_resource_helper';
describe('Environment', () => {
preloadFixtures('static/environments/environments.html.raw');
@@ -25,12 +26,14 @@ describe('Environment', () => {
beforeEach(() => {
Vue.http.interceptors.push(environmentsEmptyResponseInterceptor);
+ Vue.http.interceptors.push(headersInterceptor);
});
afterEach(() => {
Vue.http.interceptors = _.without(
Vue.http.interceptors, environmentsEmptyResponseInterceptor,
);
+ Vue.http.interceptors = _.without(Vue.http.interceptors, headersInterceptor);
});
it('should render the empty state', (done) => {
@@ -54,6 +57,10 @@ describe('Environment', () => {
describe('with paginated environments', () => {
const environmentsResponseInterceptor = (request, next) => {
+ next((response) => {
+ response.headers.set('X-nExt-pAge', '2');
+ });
+
next(request.respondWith(JSON.stringify({
environments: [environment],
stopped_count: 1,
@@ -73,6 +80,7 @@ describe('Environment', () => {
beforeEach(() => {
Vue.http.interceptors.push(environmentsResponseInterceptor);
+ Vue.http.interceptors.push(headersInterceptor);
component = new EnvironmentsComponent({
el: document.querySelector('#environments-list-view'),
});
@@ -82,6 +90,7 @@ describe('Environment', () => {
Vue.http.interceptors = _.without(
Vue.http.interceptors, environmentsResponseInterceptor,
);
+ Vue.http.interceptors = _.without(Vue.http.interceptors, headersInterceptor);
});
it('should render a table with environments', (done) => {
diff --git a/spec/javascripts/environments/folder/environments_folder_view_spec.js b/spec/javascripts/environments/folder/environments_folder_view_spec.js
index 350078ad5f5..fdaea5c0b0c 100644
--- a/spec/javascripts/environments/folder/environments_folder_view_spec.js
+++ b/spec/javascripts/environments/folder/environments_folder_view_spec.js
@@ -2,6 +2,7 @@ import Vue from 'vue';
import '~/flash';
import environmentsFolderViewComponent from '~/environments/folder/environments_folder_view.vue';
import { environmentsList } from '../mock_data';
+import { headersInterceptor } from '../../helpers/vue_resource_helper';
describe('Environments Folder View', () => {
preloadFixtures('static/environments/environments_folder_view.html.raw');
@@ -36,6 +37,8 @@ describe('Environments Folder View', () => {
beforeEach(() => {
Vue.http.interceptors.push(environmentsResponseInterceptor);
+ Vue.http.interceptors.push(headersInterceptor);
+
component = new EnvironmentsFolderViewComponent({
el: document.querySelector('#environments-folder-list-view'),
});
@@ -45,6 +48,7 @@ describe('Environments Folder View', () => {
Vue.http.interceptors = _.without(
Vue.http.interceptors, environmentsResponseInterceptor,
);
+ Vue.http.interceptors = _.without(Vue.http.interceptors, headersInterceptor);
});
it('should render a table with environments', (done) => {
diff --git a/spec/javascripts/helpers/vue_resource_helper.js b/spec/javascripts/helpers/vue_resource_helper.js
new file mode 100644
index 00000000000..0d1bf5e2e80
--- /dev/null
+++ b/spec/javascripts/helpers/vue_resource_helper.js
@@ -0,0 +1,11 @@
+// eslint-disable-next-line import/prefer-default-export
+export const headersInterceptor = (request, next) => {
+ next((response) => {
+ const headers = {};
+ response.headers.forEach((value, key) => {
+ headers[key] = value;
+ });
+ // eslint-disable-next-line no-param-reassign
+ response.headers = headers;
+ });
+};
diff --git a/spec/javascripts/issue_show/components/app_spec.js b/spec/javascripts/issue_show/components/app_spec.js
index bc13373a27e..81ce18bf2fb 100644
--- a/spec/javascripts/issue_show/components/app_spec.js
+++ b/spec/javascripts/issue_show/components/app_spec.js
@@ -3,7 +3,6 @@ import '~/render_math';
import '~/render_gfm';
import issuableApp from '~/issue_show/components/app.vue';
import eventHub from '~/issue_show/event_hub';
-import Poll from '~/lib/utils/poll';
import issueShowData from '../mock_data';
function formatText(text) {
@@ -11,16 +10,26 @@ function formatText(text) {
}
describe('Issuable output', () => {
+ let requestData = issueShowData.initialRequest;
+
document.body.innerHTML = '<span id="task_status"></span>';
+ const interceptor = (request, next) => {
+ next(request.respondWith(JSON.stringify(requestData), {
+ status: 200,
+ }));
+ };
+
let vm;
- beforeEach(() => {
+ beforeEach((done) => {
spyOn(eventHub, '$emit');
- spyOn(Poll.prototype, 'makeRequest');
const IssuableDescriptionComponent = Vue.extend(issuableApp);
+ requestData = issueShowData.initialRequest;
+ Vue.http.interceptors.push(interceptor);
+
vm = new IssuableDescriptionComponent({
propsData: {
canUpdate: true,
@@ -40,15 +49,17 @@ describe('Issuable output', () => {
projectPath: '/',
},
}).$mount();
+
+ setTimeout(done);
});
- it('should render a title/description/edited and update title/description/edited on update', (done) => {
- vm.poll.options.successCallback({
- json() {
- return issueShowData.initialRequest;
- },
- });
+ afterEach(() => {
+ Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor);
+ vm.poll.stop();
+ });
+
+ it('should render a title/description/edited and update title/description/edited on update', (done) => {
let editedText;
Vue.nextTick()
.then(() => {
@@ -64,13 +75,10 @@ describe('Issuable output', () => {
expect(editedText.querySelector('time')).toBeTruthy();
})
.then(() => {
- vm.poll.options.successCallback({
- json() {
- return issueShowData.secondRequest;
- },
- });
+ requestData = issueShowData.secondRequest;
+ vm.poll.makeRequest();
})
- .then(Vue.nextTick)
+ .then(() => new Promise(resolve => setTimeout(resolve)))
.then(() => {
expect(document.querySelector('title').innerText).toContain('2 (#1)');
expect(vm.$el.querySelector('.title').innerHTML).toContain('<p>2</p>');
@@ -304,7 +312,7 @@ describe('Issuable output', () => {
it('stops polling when deleting', (done) => {
spyOn(gl.utils, 'visitUrl');
- spyOn(vm.poll, 'stop');
+ spyOn(vm.poll, 'stop').and.callThrough();
spyOn(vm.service, 'deleteIssuable').and.callFake(() => new Promise((resolve) => {
resolve({
json() {
@@ -347,23 +355,14 @@ describe('Issuable output', () => {
describe('open form', () => {
it('shows locked warning if form is open & data is different', (done) => {
- vm.poll.options.successCallback({
- json() {
- return issueShowData.initialRequest;
- },
- });
-
Vue.nextTick()
.then(() => {
vm.openForm();
- vm.poll.options.successCallback({
- json() {
- return issueShowData.secondRequest;
- },
- });
+ requestData = issueShowData.secondRequest;
+ vm.poll.makeRequest();
})
- .then(Vue.nextTick)
+ .then(() => new Promise(resolve => setTimeout(resolve)))
.then(() => {
expect(
vm.formState.lockedWarningVisible,
diff --git a/spec/lib/gitlab/auth/unique_ips_limiter_spec.rb b/spec/lib/gitlab/auth/unique_ips_limiter_spec.rb
index fc72df575be..15b3db0ed3d 100644
--- a/spec/lib/gitlab/auth/unique_ips_limiter_spec.rb
+++ b/spec/lib/gitlab/auth/unique_ips_limiter_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe Gitlab::Auth::UniqueIpsLimiter, :redis, lib: true do
+describe Gitlab::Auth::UniqueIpsLimiter, :clean_gitlab_redis_shared_state, lib: true do
include_context 'unique ips sign in limit'
let(:user) { create(:user) }
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 07db6c3a640..0daf41a7c86 100644
--- a/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb
+++ b/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe Gitlab::Cache::Ci::ProjectPipelineStatus, :redis do
+describe Gitlab::Cache::Ci::ProjectPipelineStatus, :clean_gitlab_redis_cache do
let!(:project) { create(:project) }
let(:pipeline_status) { described_class.new(project) }
let(:cache_key) { "projects/#{project.id}/pipeline_status" }
@@ -28,8 +28,8 @@ describe Gitlab::Cache::Ci::ProjectPipelineStatus, :redis do
expect(project.instance_variable_get('@pipeline_status')).to be_a(described_class)
end
- describe 'without a status in redis' do
- it 'loads the status from a commit when it was not in redis' do
+ describe 'without a status in redis_cache' do
+ it 'loads the status from a commit when it was not in redis_cache' do
empty_status = { sha: nil, status: nil, ref: nil }
fake_pipeline = described_class.new(
project_without_status,
@@ -48,9 +48,9 @@ describe Gitlab::Cache::Ci::ProjectPipelineStatus, :redis do
described_class.load_in_batch_for_projects([project_without_status])
end
- it 'only connects to redis twice' do
+ it 'only connects to redis_cache twice' do
# Once to load, once to store in the cache
- expect(Gitlab::Redis).to receive(:with).exactly(2).and_call_original
+ expect(Gitlab::Redis::Cache).to receive(:with).exactly(2).and_call_original
described_class.load_in_batch_for_projects([project_without_status])
@@ -58,9 +58,9 @@ describe Gitlab::Cache::Ci::ProjectPipelineStatus, :redis do
end
end
- describe 'when a status was cached in redis' do
+ describe 'when a status was cached in redis_cache' do
before do
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::Cache.with do |redis|
redis.mapped_hmset(cache_key,
{ sha: sha, status: status, ref: ref })
end
@@ -76,8 +76,8 @@ describe Gitlab::Cache::Ci::ProjectPipelineStatus, :redis do
expect(pipeline_status.ref).to eq(ref)
end
- it 'only connects to redis once' do
- expect(Gitlab::Redis).to receive(:with).exactly(1).and_call_original
+ it 'only connects to redis_cache once' do
+ expect(Gitlab::Redis::Cache).to receive(:with).exactly(1).and_call_original
described_class.load_in_batch_for_projects([project])
@@ -94,8 +94,8 @@ describe Gitlab::Cache::Ci::ProjectPipelineStatus, :redis do
end
describe '.cached_results_for_projects' do
- it 'loads a status from redis for all projects' do
- Gitlab::Redis.with do |redis|
+ it 'loads a status from caching for all projects' do
+ Gitlab::Redis::Cache.with do |redis|
redis.mapped_hmset(cache_key, { sha: sha, status: status, ref: ref })
end
@@ -183,7 +183,7 @@ describe Gitlab::Cache::Ci::ProjectPipelineStatus, :redis do
end
end
- describe "#load_from_project" do
+ describe "#load_from_project", :clean_gitlab_redis_cache do
let!(:pipeline) { create(:ci_pipeline, :success, project: project, sha: project.commit.sha) }
it 'reads the status from the pipeline for the commit' do
@@ -203,40 +203,40 @@ describe Gitlab::Cache::Ci::ProjectPipelineStatus, :redis do
end
end
- describe "#store_in_cache", :redis do
- it "sets the object in redis" do
+ describe "#store_in_cache", :clean_gitlab_redis_cache do
+ it "sets the object in caching" do
pipeline_status.sha = '123456'
pipeline_status.status = 'failed'
pipeline_status.store_in_cache
- read_sha, read_status = Gitlab::Redis.with { |redis| redis.hmget(cache_key, :sha, :status) }
+ read_sha, read_status = Gitlab::Redis::Cache.with { |redis| redis.hmget(cache_key, :sha, :status) }
expect(read_sha).to eq('123456')
expect(read_status).to eq('failed')
end
end
- describe '#store_in_cache_if_needed', :redis do
+ describe '#store_in_cache_if_needed', :clean_gitlab_redis_cache do
it 'stores the state in the cache when the sha is the HEAD of the project' do
create(:ci_pipeline, :success, project: project, sha: project.commit.sha)
pipeline_status = described_class.load_for_project(project)
pipeline_status.store_in_cache_if_needed
- sha, status, ref = Gitlab::Redis.with { |redis| redis.hmget(cache_key, :sha, :status, :ref) }
+ sha, status, ref = Gitlab::Redis::Cache.with { |redis| redis.hmget(cache_key, :sha, :status, :ref) }
expect(sha).not_to be_nil
expect(status).not_to be_nil
expect(ref).not_to be_nil
end
- it "doesn't store the status in redis when the sha is not the head of the project" do
+ it "doesn't store the status in redis_cache when the sha is not the head of the project" do
other_status = described_class.new(
project,
pipeline_info: { sha: "123456", status: "failed" }
)
other_status.store_in_cache_if_needed
- sha, status = Gitlab::Redis.with { |redis| redis.hmget(cache_key, :sha, :status) }
+ sha, status = Gitlab::Redis::Cache.with { |redis| redis.hmget(cache_key, :sha, :status) }
expect(sha).to be_nil
expect(status).to be_nil
@@ -244,7 +244,7 @@ describe Gitlab::Cache::Ci::ProjectPipelineStatus, :redis do
it "deletes the cache if the repository doesn't have a head commit" do
empty_project = create(:empty_project)
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::Cache.with do |redis|
redis.mapped_hmset(cache_key,
{ sha: 'sha', status: 'pending', ref: 'master' })
end
@@ -255,7 +255,7 @@ describe Gitlab::Cache::Ci::ProjectPipelineStatus, :redis do
})
other_status.store_in_cache_if_needed
- sha, status, ref = Gitlab::Redis.with { |redis| redis.hmget("projects/#{empty_project.id}/pipeline_status", :sha, :status, :ref) }
+ sha, status, ref = Gitlab::Redis::Cache.with { |redis| redis.hmget("projects/#{empty_project.id}/pipeline_status", :sha, :status, :ref) }
expect(sha).to be_nil
expect(status).to be_nil
@@ -263,20 +263,20 @@ describe Gitlab::Cache::Ci::ProjectPipelineStatus, :redis do
end
end
- describe "with a status in redis", :redis do
+ describe "with a status in caching", :clean_gitlab_redis_cache do
let(:status) { 'success' }
let(:sha) { '424d1b73bc0d3cb726eb7dc4ce17a4d48552f8c6' }
let(:ref) { 'master' }
before do
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::Cache.with do |redis|
redis.mapped_hmset(cache_key,
{ sha: sha, status: status, ref: ref })
end
end
describe '#load_from_cache' do
- it 'reads the status from redis' do
+ it 'reads the status from redis_cache' do
pipeline_status.load_from_cache
expect(pipeline_status.sha).to eq(sha)
@@ -292,10 +292,10 @@ describe Gitlab::Cache::Ci::ProjectPipelineStatus, :redis do
end
describe '#delete_from_cache' do
- it 'deletes values from redis' do
+ it 'deletes values from redis_cache' do
pipeline_status.delete_from_cache
- key_exists = Gitlab::Redis.with { |redis| redis.exists(cache_key) }
+ key_exists = Gitlab::Redis::Cache.with { |redis| redis.exists(cache_key) }
expect(key_exists).to be_falsy
end
diff --git a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb
index 8813f129ef5..df7d1b5d27a 100644
--- a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb
+++ b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb
@@ -236,7 +236,7 @@ describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameBase, :trunca
subject.track_rename('namespace', 'path/to/namespace', 'path/to/renamed')
old_path, new_path = [nil, nil]
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
rename_info = redis.lpop(key)
old_path, new_path = JSON.parse(rename_info)
end
@@ -268,7 +268,7 @@ describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameBase, :trunca
key = 'rename:FakeRenameReservedPathMigrationV1:project'
stored_renames = nil
rename_count = 0
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
stored_renames = redis.lrange(key, 0, 1)
rename_count = redis.llen(key)
end
diff --git a/spec/lib/gitlab/exclusive_lease_spec.rb b/spec/lib/gitlab/exclusive_lease_spec.rb
index 81bbd70ffb8..590d6da4113 100644
--- a/spec/lib/gitlab/exclusive_lease_spec.rb
+++ b/spec/lib/gitlab/exclusive_lease_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe Gitlab::ExclusiveLease, type: :redis do
+describe Gitlab::ExclusiveLease, type: :clean_gitlab_redis_shared_state do
let(:unique_key) { SecureRandom.hex(10) }
describe '#try_obtain' do
diff --git a/spec/lib/gitlab/git/hook_spec.rb b/spec/lib/gitlab/git/hook_spec.rb
index 73518656bde..19f45ea1cb2 100644
--- a/spec/lib/gitlab/git/hook_spec.rb
+++ b/spec/lib/gitlab/git/hook_spec.rb
@@ -2,6 +2,12 @@ require 'spec_helper'
require 'fileutils'
describe Gitlab::Git::Hook, lib: true do
+ before do
+ # We need this because in the spec/spec_helper.rb we define it like this:
+ # allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([true, nil])
+ allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_call_original
+ end
+
describe "#trigger" do
let(:project) { create(:project, :repository) }
let(:repo_path) { project.repository.path }
diff --git a/spec/lib/gitlab/health_checks/redis/cache_check_spec.rb b/spec/lib/gitlab/health_checks/redis/cache_check_spec.rb
new file mode 100644
index 00000000000..3693f52b51b
--- /dev/null
+++ b/spec/lib/gitlab/health_checks/redis/cache_check_spec.rb
@@ -0,0 +1,6 @@
+require 'spec_helper'
+require_relative '../simple_check_shared'
+
+describe Gitlab::HealthChecks::Redis::CacheCheck do
+ include_examples 'simple_check', 'redis_cache_ping', 'RedisCache', 'PONG'
+end
diff --git a/spec/lib/gitlab/health_checks/redis/queues_check_spec.rb b/spec/lib/gitlab/health_checks/redis/queues_check_spec.rb
new file mode 100644
index 00000000000..c69443d205d
--- /dev/null
+++ b/spec/lib/gitlab/health_checks/redis/queues_check_spec.rb
@@ -0,0 +1,6 @@
+require 'spec_helper'
+require_relative '../simple_check_shared'
+
+describe Gitlab::HealthChecks::Redis::QueuesCheck do
+ include_examples 'simple_check', 'redis_queues_ping', 'RedisQueues', 'PONG'
+end
diff --git a/spec/lib/gitlab/health_checks/redis/redis_check_spec.rb b/spec/lib/gitlab/health_checks/redis/redis_check_spec.rb
new file mode 100644
index 00000000000..03afc1cd761
--- /dev/null
+++ b/spec/lib/gitlab/health_checks/redis/redis_check_spec.rb
@@ -0,0 +1,6 @@
+require 'spec_helper'
+require_relative '../simple_check_shared'
+
+describe Gitlab::HealthChecks::Redis::RedisCheck do
+ include_examples 'simple_check', 'redis_ping', 'Redis', 'PONG'
+end
diff --git a/spec/lib/gitlab/health_checks/redis/shared_state_check_spec.rb b/spec/lib/gitlab/health_checks/redis/shared_state_check_spec.rb
new file mode 100644
index 00000000000..b72e152bbe2
--- /dev/null
+++ b/spec/lib/gitlab/health_checks/redis/shared_state_check_spec.rb
@@ -0,0 +1,6 @@
+require 'spec_helper'
+require_relative '../simple_check_shared'
+
+describe Gitlab::HealthChecks::Redis::SharedStateCheck do
+ include_examples 'simple_check', 'redis_shared_state_ping', 'RedisSharedState', 'PONG'
+end
diff --git a/spec/lib/gitlab/health_checks/redis_check_spec.rb b/spec/lib/gitlab/health_checks/redis_check_spec.rb
deleted file mode 100644
index 734cdcb893e..00000000000
--- a/spec/lib/gitlab/health_checks/redis_check_spec.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-require 'spec_helper'
-require_relative './simple_check_shared'
-
-describe Gitlab::HealthChecks::RedisCheck do
- include_examples 'simple_check', 'redis_ping', 'Redis', 'PONG'
-end
diff --git a/spec/lib/gitlab/health_checks/simple_check_shared.rb b/spec/lib/gitlab/health_checks/simple_check_shared.rb
index 3f871d66034..1abebeac4dd 100644
--- a/spec/lib/gitlab/health_checks/simple_check_shared.rb
+++ b/spec/lib/gitlab/health_checks/simple_check_shared.rb
@@ -47,7 +47,7 @@ shared_context 'simple_check' do |metrics_prefix, check_name, success_result|
allow(described_class).to receive(:check).and_return 'error!'
end
- it { is_expected.to have_attributes(success: false, message: "unexpected #{check_name} check result: error!") }
+ it { is_expected.to have_attributes(success: false, message: "unexpected #{described_class.human_name} check result: error!") }
end
context 'Check is timeouting' do
@@ -55,7 +55,7 @@ shared_context 'simple_check' do |metrics_prefix, check_name, success_result|
allow(described_class).to receive(:check ).and_return Timeout::Error.new
end
- it { is_expected.to have_attributes(success: false, message: "#{check_name} check timed out") }
+ it { is_expected.to have_attributes(success: false, message: "#{described_class.human_name} check timed out") }
end
end
diff --git a/spec/lib/gitlab/performance_bar_spec.rb b/spec/lib/gitlab/performance_bar_spec.rb
index 8a586bdbf63..b8a2267f1a4 100644
--- a/spec/lib/gitlab/performance_bar_spec.rb
+++ b/spec/lib/gitlab/performance_bar_spec.rb
@@ -7,7 +7,7 @@ describe Gitlab::PerformanceBar do
described_class.enabled?(user)
end
- it 'caches the allowed user IDs in cache', :caching do
+ it 'caches the allowed user IDs in cache', :use_clean_rails_memory_store_caching do
expect do
expect(described_class.enabled?(user)).to be_truthy
end.not_to exceed_query_limit(0)
diff --git a/spec/lib/gitlab/redis/cache_spec.rb b/spec/lib/gitlab/redis/cache_spec.rb
new file mode 100644
index 00000000000..5a4f17cfcf6
--- /dev/null
+++ b/spec/lib/gitlab/redis/cache_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe Gitlab::Redis::Cache do
+ let(:config_file_name) { "config/redis.cache.yml" }
+ let(:environment_config_file_name) { "GITLAB_REDIS_CACHE_CONFIG_FILE" }
+ let(:config_old_format_socket) { "spec/fixtures/config/redis_cache_old_format_socket.yml" }
+ let(:config_new_format_socket) { "spec/fixtures/config/redis_cache_new_format_socket.yml" }
+ let(:old_socket_path) {"/path/to/old/redis.cache.sock" }
+ let(:new_socket_path) {"/path/to/redis.cache.sock" }
+ let(:config_old_format_host) { "spec/fixtures/config/redis_cache_old_format_host.yml" }
+ let(:config_new_format_host) { "spec/fixtures/config/redis_cache_new_format_host.yml" }
+ let(:redis_port) { 6380 }
+ let(:redis_database) { 10 }
+ let(:sentinel_port) { redis_port + 20000 }
+ let(:config_with_environment_variable_inside) { "spec/fixtures/config/redis_cache_config_with_env.yml"}
+ let(:config_env_variable_url) {"TEST_GITLAB_REDIS_CACHE_URL"}
+ let(:class_redis_url) { Gitlab::Redis::Cache::DEFAULT_REDIS_CACHE_URL }
+
+ include_examples "redis_shared_examples"
+end
diff --git a/spec/lib/gitlab/redis/queues_spec.rb b/spec/lib/gitlab/redis/queues_spec.rb
new file mode 100644
index 00000000000..01ca25635a9
--- /dev/null
+++ b/spec/lib/gitlab/redis/queues_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe Gitlab::Redis::Queues do
+ let(:config_file_name) { "config/redis.queues.yml" }
+ let(:environment_config_file_name) { "GITLAB_REDIS_QUEUES_CONFIG_FILE" }
+ let(:config_old_format_socket) { "spec/fixtures/config/redis_queues_old_format_socket.yml" }
+ let(:config_new_format_socket) { "spec/fixtures/config/redis_queues_new_format_socket.yml" }
+ let(:old_socket_path) {"/path/to/old/redis.queues.sock" }
+ let(:new_socket_path) {"/path/to/redis.queues.sock" }
+ let(:config_old_format_host) { "spec/fixtures/config/redis_queues_old_format_host.yml" }
+ let(:config_new_format_host) { "spec/fixtures/config/redis_queues_new_format_host.yml" }
+ let(:redis_port) { 6381 }
+ let(:redis_database) { 11 }
+ let(:sentinel_port) { redis_port + 20000 }
+ let(:config_with_environment_variable_inside) { "spec/fixtures/config/redis_queues_config_with_env.yml"}
+ let(:config_env_variable_url) {"TEST_GITLAB_REDIS_QUEUES_URL"}
+ let(:class_redis_url) { Gitlab::Redis::Queues::DEFAULT_REDIS_QUEUES_URL }
+
+ include_examples "redis_shared_examples"
+end
diff --git a/spec/lib/gitlab/redis/shared_state_spec.rb b/spec/lib/gitlab/redis/shared_state_spec.rb
new file mode 100644
index 00000000000..24b73745dc5
--- /dev/null
+++ b/spec/lib/gitlab/redis/shared_state_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe Gitlab::Redis::SharedState do
+ let(:config_file_name) { "config/redis.shared_state.yml" }
+ let(:environment_config_file_name) { "GITLAB_REDIS_SHARED_STATE_CONFIG_FILE" }
+ let(:config_old_format_socket) { "spec/fixtures/config/redis_shared_state_old_format_socket.yml" }
+ let(:config_new_format_socket) { "spec/fixtures/config/redis_shared_state_new_format_socket.yml" }
+ let(:old_socket_path) {"/path/to/old/redis.shared_state.sock" }
+ let(:new_socket_path) {"/path/to/redis.shared_state.sock" }
+ let(:config_old_format_host) { "spec/fixtures/config/redis_shared_state_old_format_host.yml" }
+ let(:config_new_format_host) { "spec/fixtures/config/redis_shared_state_new_format_host.yml" }
+ let(:redis_port) { 6382 }
+ let(:redis_database) { 12 }
+ let(:sentinel_port) { redis_port + 20000 }
+ let(:config_with_environment_variable_inside) { "spec/fixtures/config/redis_shared_state_config_with_env.yml"}
+ let(:config_env_variable_url) {"TEST_GITLAB_REDIS_SHARED_STATE_URL"}
+ let(:class_redis_url) { Gitlab::Redis::SharedState::DEFAULT_REDIS_SHARED_STATE_URL }
+
+ include_examples "redis_shared_examples"
+end
diff --git a/spec/lib/gitlab/redis/wrapper_spec.rb b/spec/lib/gitlab/redis/wrapper_spec.rb
new file mode 100644
index 00000000000..e1becd0a614
--- /dev/null
+++ b/spec/lib/gitlab/redis/wrapper_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe Gitlab::Redis::Wrapper do
+ let(:config_file_name) { "config/resque.yml" }
+ let(:environment_config_file_name) { "GITLAB_REDIS_CONFIG_FILE" }
+ let(:config_old_format_socket) { "spec/fixtures/config/redis_old_format_socket.yml" }
+ let(:config_new_format_socket) { "spec/fixtures/config/redis_new_format_socket.yml" }
+ let(:old_socket_path) {"/path/to/old/redis.sock" }
+ let(:new_socket_path) {"/path/to/redis.sock" }
+ let(:config_old_format_host) { "spec/fixtures/config/redis_old_format_host.yml" }
+ let(:config_new_format_host) { "spec/fixtures/config/redis_new_format_host.yml" }
+ let(:redis_port) { 6379 }
+ let(:redis_database) { 99 }
+ let(:sentinel_port) { redis_port + 20000 }
+ let(:config_with_environment_variable_inside) { "spec/fixtures/config/redis_config_with_env.yml"}
+ let(:config_env_variable_url) {"TEST_GITLAB_REDIS_URL"}
+ let(:class_redis_url) { Gitlab::Redis::Wrapper::DEFAULT_REDIS_URL }
+
+ include_examples "redis_shared_examples"
+end
diff --git a/spec/lib/gitlab/sidekiq_status_spec.rb b/spec/lib/gitlab/sidekiq_status_spec.rb
index 496e50fbae4..c2e77ef6b6c 100644
--- a/spec/lib/gitlab/sidekiq_status_spec.rb
+++ b/spec/lib/gitlab/sidekiq_status_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Gitlab::SidekiqStatus do
- describe '.set', :redis do
+ describe '.set', :clean_gitlab_redis_shared_state do
it 'stores the job ID' do
described_class.set('123')
@@ -14,7 +14,7 @@ describe Gitlab::SidekiqStatus do
end
end
- describe '.unset', :redis do
+ describe '.unset', :clean_gitlab_redis_shared_state do
it 'removes the job ID' do
described_class.set('123')
described_class.unset('123')
@@ -27,7 +27,7 @@ describe Gitlab::SidekiqStatus do
end
end
- describe '.all_completed?', :redis do
+ describe '.all_completed?', :clean_gitlab_redis_shared_state do
it 'returns true if all jobs have been completed' do
expect(described_class.all_completed?(%w(123))).to eq(true)
end
@@ -39,7 +39,7 @@ describe Gitlab::SidekiqStatus do
end
end
- describe '.num_running', :redis do
+ describe '.num_running', :clean_gitlab_redis_shared_state do
it 'returns 0 if all jobs have been completed' do
expect(described_class.num_running(%w(123))).to eq(0)
end
@@ -52,7 +52,7 @@ describe Gitlab::SidekiqStatus do
end
end
- describe '.num_completed', :redis do
+ describe '.num_completed', :clean_gitlab_redis_shared_state do
it 'returns 1 if all jobs have been completed' do
expect(described_class.num_completed(%w(123))).to eq(1)
end
@@ -74,7 +74,7 @@ describe Gitlab::SidekiqStatus do
end
end
- describe 'completed', :redis do
+ describe 'completed', :clean_gitlab_redis_shared_state do
it 'returns the completed job' do
expect(described_class.completed_jids(%w(123))).to eq(['123'])
end
diff --git a/spec/lib/gitlab/user_activities_spec.rb b/spec/lib/gitlab/user_activities_spec.rb
index 187d88c8c58..a4ea0ac59e9 100644
--- a/spec/lib/gitlab/user_activities_spec.rb
+++ b/spec/lib/gitlab/user_activities_spec.rb
@@ -1,27 +1,27 @@
require 'spec_helper'
-describe Gitlab::UserActivities, :redis, lib: true do
+describe Gitlab::UserActivities, :clean_gitlab_redis_shared_state, lib: true do
let(:now) { Time.now }
describe '.record' do
context 'with no time given' do
- it 'uses Time.now and records an activity in Redis' do
+ it 'uses Time.now and records an activity in SharedState' do
Timecop.freeze do
now # eager-load now
described_class.record(42)
end
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
expect(redis.hscan(described_class::KEY, 0)).to eq(['0', [['42', now.to_i.to_s]]])
end
end
end
context 'with a time given' do
- it 'uses the given time and records an activity in Redis' do
+ it 'uses the given time and records an activity in SharedState' do
described_class.record(42, now)
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
expect(redis.hscan(described_class::KEY, 0)).to eq(['0', [['42', now.to_i.to_s]]])
end
end
@@ -31,30 +31,30 @@ describe Gitlab::UserActivities, :redis, lib: true do
describe '.delete' do
context 'with a single key' do
context 'and key exists' do
- it 'removes the pair from Redis' do
+ it 'removes the pair from SharedState' do
described_class.record(42, now)
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
expect(redis.hscan(described_class::KEY, 0)).to eq(['0', [['42', now.to_i.to_s]]])
end
subject.delete(42)
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
expect(redis.hscan(described_class::KEY, 0)).to eq(['0', []])
end
end
end
context 'and key does not exist' do
- it 'removes the pair from Redis' do
- Gitlab::Redis.with do |redis|
+ it 'removes the pair from SharedState' do
+ Gitlab::Redis::SharedState.with do |redis|
expect(redis.hscan(described_class::KEY, 0)).to eq(['0', []])
end
subject.delete(42)
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
expect(redis.hscan(described_class::KEY, 0)).to eq(['0', []])
end
end
@@ -63,33 +63,33 @@ describe Gitlab::UserActivities, :redis, lib: true do
context 'with multiple keys' do
context 'and all keys exist' do
- it 'removes the pair from Redis' do
+ it 'removes the pair from SharedState' do
described_class.record(41, now)
described_class.record(42, now)
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
expect(redis.hscan(described_class::KEY, 0)).to eq(['0', [['41', now.to_i.to_s], ['42', now.to_i.to_s]]])
end
subject.delete(41, 42)
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
expect(redis.hscan(described_class::KEY, 0)).to eq(['0', []])
end
end
end
context 'and some keys does not exist' do
- it 'removes the existing pair from Redis' do
+ it 'removes the existing pair from SharedState' do
described_class.record(42, now)
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
expect(redis.hscan(described_class::KEY, 0)).to eq(['0', [['42', now.to_i.to_s]]])
end
subject.delete(41, 42)
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
expect(redis.hscan(described_class::KEY, 0)).to eq(['0', []])
end
end
diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb
index 493ff3bb5fb..efff0a152a8 100644
--- a/spec/lib/gitlab/workhorse_spec.rb
+++ b/spec/lib/gitlab/workhorse_spec.rb
@@ -276,7 +276,7 @@ describe Gitlab::Workhorse, lib: true do
end
it 'set and notify' do
- expect_any_instance_of(Redis).to receive(:publish)
+ expect_any_instance_of(::Redis).to receive(:publish)
.with(described_class::NOTIFICATION_CHANNEL, "test-key=test-value")
subject
@@ -310,7 +310,7 @@ describe Gitlab::Workhorse, lib: true do
end
it 'does not notify' do
- expect_any_instance_of(Redis).not_to receive(:publish)
+ expect_any_instance_of(::Redis).not_to receive(:publish)
subject
end
diff --git a/spec/migrations/migrate_process_commit_worker_jobs_spec.rb b/spec/migrations/migrate_process_commit_worker_jobs_spec.rb
index 4223d2337a8..5b633dd349b 100644
--- a/spec/migrations/migrate_process_commit_worker_jobs_spec.rb
+++ b/spec/migrations/migrate_process_commit_worker_jobs_spec.rb
@@ -54,7 +54,7 @@ describe MigrateProcessCommitWorkerJobs do
end
end
- describe '#up', :redis do
+ describe '#up', :clean_gitlab_redis_shared_state do
let(:migration) { described_class.new }
def job_count
@@ -172,7 +172,7 @@ describe MigrateProcessCommitWorkerJobs do
end
end
- describe '#down', :redis do
+ describe '#down', :clean_gitlab_redis_shared_state do
let(:migration) { described_class.new }
def job_count
diff --git a/spec/migrations/migrate_user_activities_to_users_last_activity_on_spec.rb b/spec/migrations/migrate_user_activities_to_users_last_activity_on_spec.rb
index e3b42b5eac8..063829be546 100644
--- a/spec/migrations/migrate_user_activities_to_users_last_activity_on_spec.rb
+++ b/spec/migrations/migrate_user_activities_to_users_last_activity_on_spec.rb
@@ -3,13 +3,13 @@
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170324160416_migrate_user_activities_to_users_last_activity_on.rb')
-describe MigrateUserActivitiesToUsersLastActivityOn, :redis, :truncate do
+describe MigrateUserActivitiesToUsersLastActivityOn, :clean_gitlab_redis_shared_state, :truncate do
let(:migration) { described_class.new }
let!(:user_active_1) { create(:user) }
let!(:user_active_2) { create(:user) }
def record_activity(user, time)
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::SharedState.with do |redis|
redis.zadd(described_class::USER_ACTIVITY_SET_KEY, time.to_i, user.username)
end
end
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index 76ce558eea0..4b9cce28e0e 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -276,14 +276,14 @@ describe Ci::Runner, models: true do
it 'sets a new last_update value when it is called the first time' do
last_update = runner.ensure_runner_queue_value
- expect_value_in_redis.to eq(last_update)
+ expect_value_in_queues.to eq(last_update)
end
it 'does not change if it is not expired and called again' do
last_update = runner.ensure_runner_queue_value
expect(runner.ensure_runner_queue_value).to eq(last_update)
- expect_value_in_redis.to eq(last_update)
+ expect_value_in_queues.to eq(last_update)
end
context 'updates runner queue after changing editable value' do
@@ -294,7 +294,7 @@ describe Ci::Runner, models: true do
end
it 'sets a new last_update value' do
- expect_value_in_redis.not_to eq(last_update)
+ expect_value_in_queues.not_to eq(last_update)
end
end
@@ -306,12 +306,12 @@ describe Ci::Runner, models: true do
end
it 'has an old last_update value' do
- expect_value_in_redis.to eq(last_update)
+ expect_value_in_queues.to eq(last_update)
end
end
- def expect_value_in_redis
- Gitlab::Redis.with do |redis|
+ def expect_value_in_queues
+ Gitlab::Redis::Queues.with do |redis|
runner_queue_key = runner.send(:runner_queue_key)
expect(redis.get(runner_queue_key))
end
@@ -330,7 +330,7 @@ describe Ci::Runner, models: true do
end
it 'cleans up the queue' do
- Gitlab::Redis.with do |redis|
+ Gitlab::Redis::Queues.with do |redis|
expect(redis.get(queue_key)).to be_nil
end
end
diff --git a/spec/models/concerns/reactive_caching_spec.rb b/spec/models/concerns/reactive_caching_spec.rb
index 808247ebfd5..5f9b7e0a367 100644
--- a/spec/models/concerns/reactive_caching_spec.rb
+++ b/spec/models/concerns/reactive_caching_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe ReactiveCaching, caching: true do
+describe ReactiveCaching, :use_clean_rails_memory_store_caching do
include ReactiveCachingHelpers
class CacheTest
diff --git a/spec/models/project_services/bamboo_service_spec.rb b/spec/models/project_services/bamboo_service_spec.rb
index 7b1a554d1fb..99190d763f2 100644
--- a/spec/models/project_services/bamboo_service_spec.rb
+++ b/spec/models/project_services/bamboo_service_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe BambooService, models: true, caching: true do
+describe BambooService, :use_clean_rails_memory_store_caching, models: true do
include ReactiveCachingHelpers
let(:bamboo_url) { 'http://gitlab.com/bamboo' }
diff --git a/spec/models/project_services/buildkite_service_spec.rb b/spec/models/project_services/buildkite_service_spec.rb
index dd529597067..b4ee6691e67 100644
--- a/spec/models/project_services/buildkite_service_spec.rb
+++ b/spec/models/project_services/buildkite_service_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe BuildkiteService, models: true, caching: true do
+describe BuildkiteService, :use_clean_rails_memory_store_caching, models: true do
include ReactiveCachingHelpers
let(:project) { create(:empty_project) }
diff --git a/spec/models/project_services/drone_ci_service_spec.rb b/spec/models/project_services/drone_ci_service_spec.rb
index 1400175427f..c9ac256ff38 100644
--- a/spec/models/project_services/drone_ci_service_spec.rb
+++ b/spec/models/project_services/drone_ci_service_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe DroneCiService, models: true, caching: true do
+describe DroneCiService, :use_clean_rails_memory_store_caching, models: true do
include ReactiveCachingHelpers
describe 'associations' do
diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb
index 5ba523a478a..b66bb5321ab 100644
--- a/spec/models/project_services/kubernetes_service_spec.rb
+++ b/spec/models/project_services/kubernetes_service_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe KubernetesService, models: true, caching: true do
+describe KubernetesService, :use_clean_rails_memory_store_caching, models: true do
include KubernetesHelpers
include ReactiveCachingHelpers
diff --git a/spec/models/project_services/prometheus_service_spec.rb b/spec/models/project_services/prometheus_service_spec.rb
index 37f23b1243c..3fb134ec3b7 100644
--- a/spec/models/project_services/prometheus_service_spec.rb
+++ b/spec/models/project_services/prometheus_service_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe PrometheusService, models: true, caching: true do
+describe PrometheusService, :use_clean_rails_memory_store_caching, models: true do
include PrometheusHelpers
include ReactiveCachingHelpers
diff --git a/spec/models/project_services/teamcity_service_spec.rb b/spec/models/project_services/teamcity_service_spec.rb
index 6b004098510..3f3a74d0f96 100644
--- a/spec/models/project_services/teamcity_service_spec.rb
+++ b/spec/models/project_services/teamcity_service_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe TeamcityService, models: true, caching: true do
+describe TeamcityService, :use_clean_rails_memory_store_caching, models: true do
include ReactiveCachingHelpers
let(:teamcity_url) { 'http://gitlab.com/teamcity' }
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 99bfab70088..c4bc129dd37 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -899,7 +899,7 @@ describe Project, models: true do
end
end
- describe '.cached_count', caching: true do
+ describe '.cached_count', :use_clean_rails_memory_store_caching do
let(:group) { create(:group, :public) }
let!(:project1) { create(:empty_project, :public, group: group) }
let!(:project2) { create(:empty_project, :public, group: group) }
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index af305e9b234..7635b0868e7 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -561,7 +561,7 @@ describe Repository, models: true do
end
end
- describe "#changelog", caching: true do
+ describe "#changelog", :use_clean_rails_memory_store_caching do
it 'accepts changelog' do
expect(repository.tree).to receive(:blobs).and_return([TestBlob.new('changelog')])
@@ -593,7 +593,7 @@ describe Repository, models: true do
end
end
- describe "#license_blob", caching: true do
+ describe "#license_blob", :use_clean_rails_memory_store_caching do
before do
repository.delete_file(
user, 'LICENSE', message: 'Remove LICENSE', branch_name: 'master')
@@ -638,7 +638,7 @@ describe Repository, models: true do
end
end
- describe '#license_key', caching: true do
+ describe '#license_key', :use_clean_rails_memory_store_caching do
before do
repository.delete_file(user, 'LICENSE',
message: 'Remove LICENSE', branch_name: 'master')
@@ -703,7 +703,7 @@ describe Repository, models: true do
end
end
- describe "#gitlab_ci_yml", caching: true do
+ describe "#gitlab_ci_yml", :use_clean_rails_memory_store_caching do
it 'returns valid file' do
files = [TestBlob.new('file'), TestBlob.new('.gitlab-ci.yml'), TestBlob.new('copying')]
expect(repository.tree).to receive(:blobs).and_return(files)
@@ -1611,7 +1611,7 @@ describe Repository, models: true do
end
end
- describe '#contribution_guide', caching: true do
+ describe '#contribution_guide', :use_clean_rails_memory_store_caching do
it 'returns and caches the output' do
expect(repository).to receive(:file_on_head)
.with(:contributing)
@@ -1625,7 +1625,7 @@ describe Repository, models: true do
end
end
- describe '#gitignore', caching: true do
+ describe '#gitignore', :use_clean_rails_memory_store_caching do
it 'returns and caches the output' do
expect(repository).to receive(:file_on_head)
.with(:gitignore)
@@ -1638,7 +1638,7 @@ describe Repository, models: true do
end
end
- describe '#koding_yml', caching: true do
+ describe '#koding_yml', :use_clean_rails_memory_store_caching do
it 'returns and caches the output' do
expect(repository).to receive(:file_on_head)
.with(:koding)
@@ -1651,7 +1651,7 @@ describe Repository, models: true do
end
end
- describe '#readme', caching: true do
+ describe '#readme', :use_clean_rails_memory_store_caching do
context 'with a non-existing repository' do
it 'returns nil' do
allow(repository).to receive(:tree).with(:head).and_return(nil)
@@ -1822,7 +1822,7 @@ describe Repository, models: true do
end
end
- describe '#cache_method_output', caching: true do
+ describe '#cache_method_output', :use_clean_rails_memory_store_caching do
context 'with a non-existing repository' do
let(:value) do
repository.cache_method_output(:cats, fallback: 10) do
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 448555d2190..c70f916a8bd 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -348,7 +348,7 @@ describe User, models: true do
end
end
- describe '#update_tracked_fields!', :redis do
+ describe '#update_tracked_fields!', :clean_gitlab_redis_shared_state do
let(:request) { OpenStruct.new(remote_ip: "127.0.0.1") }
let(:user) { create(:user) }
@@ -1159,6 +1159,18 @@ describe User, models: true do
end
end
+ describe '#sanitize_attrs' do
+ let(:user) { build(:user, name: 'test & user', skype: 'test&user') }
+
+ it 'encodes HTML entities in the Skype attribute' do
+ expect { user.sanitize_attrs }.to change { user.skype }.to('test&amp;user')
+ end
+
+ it 'does not encode HTML entities in the name attribute' do
+ expect { user.sanitize_attrs }.not_to change { user.name }
+ end
+ end
+
describe '#starred?' do
it 'determines if user starred a project' do
user = create :user
@@ -1684,7 +1696,7 @@ describe User, models: true do
end
end
- describe '#refresh_authorized_projects', redis: true do
+ describe '#refresh_authorized_projects', clean_gitlab_redis_shared_state: true do
let(:project1) { create(:empty_project) }
let(:project2) { create(:empty_project) }
let(:user) { create(:user) }
diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb
index cde4fa888a0..453eb4683a0 100644
--- a/spec/requests/api/internal_spec.rb
+++ b/spec/requests/api/internal_spec.rb
@@ -168,7 +168,7 @@ describe API::Internal do
end
end
- describe "POST /internal/allowed", :redis do
+ describe "POST /internal/allowed", :clean_gitlab_redis_shared_state do
context "access granted" do
before do
project.team << [user, :developer]
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 360a82196a8..9098ae6bcda 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -69,6 +69,22 @@ describe API::MergeRequests do
expect(json_response.first['merge_commit_sha']).to eq(merge_request_merged.merge_commit_sha)
end
+ it "returns an array of all merge_requests using simple mode" do
+ get api("/projects/#{project.id}/merge_requests?view=simple", user)
+
+ expect(response).to have_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response.last.keys).to match_array(%w(id iid title web_url created_at description project_id state updated_at))
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(3)
+ expect(json_response.last['iid']).to eq(merge_request.iid)
+ expect(json_response.last['title']).to eq(merge_request.title)
+ expect(json_response.last).to have_key('web_url')
+ expect(json_response.first['iid']).to eq(merge_request_merged.iid)
+ expect(json_response.first['title']).to eq(merge_request_merged.title)
+ expect(json_response.first).to have_key('web_url')
+ end
+
it "returns an array of all merge_requests" do
get api("/projects/#{project.id}/merge_requests?state", user)
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index c34b88f0741..877bde3b9a6 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -943,11 +943,11 @@ describe API::Users do
expect(response).to have_http_status(403)
end
- it 'returns initial current user without private token when sudo not defined' do
+ it 'returns initial current user without private token but with is_admin when sudo not defined' do
get api("/user?private_token=#{admin_personal_access_token}")
expect(response).to have_http_status(200)
- expect(response).to match_response_schema('public_api/v4/user/public')
+ expect(response).to match_response_schema('public_api/v4/user/admin')
expect(json_response['id']).to eq(admin.id)
end
end
@@ -961,11 +961,11 @@ describe API::Users do
expect(json_response['id']).to eq(user.id)
end
- it 'returns initial current user without private token when sudo not defined' do
+ it 'returns initial current user without private token but with is_admin when sudo not defined' do
get api("/user?private_token=#{admin.private_token}")
expect(response).to have_http_status(200)
- expect(response).to match_response_schema('public_api/v4/user/public')
+ expect(response).to match_response_schema('public_api/v4/user/admin')
expect(json_response['id']).to eq(admin.id)
end
end
@@ -1313,7 +1313,7 @@ describe API::Users do
end
end
- context "user activities", :redis do
+ context "user activities", :clean_gitlab_redis_shared_state do
let!(:old_active_user) { create(:user, last_activity_on: Time.utc(2000, 1, 1)) }
let!(:newly_active_user) { create(:user, last_activity_on: 2.days.ago.midday) }
diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb
index 185679e1a0f..d0443a450a2 100644
--- a/spec/requests/git_http_spec.rb
+++ b/spec/requests/git_http_spec.rb
@@ -406,7 +406,7 @@ describe 'Git HTTP requests', lib: true do
end
end
- it 'updates the user last activity', :redis do
+ it 'updates the user last activity', :clean_gitlab_redis_shared_state do
expect(user_activity(user)).to be_nil
download(path, env) do |response|
diff --git a/spec/requests/openid_connect_spec.rb b/spec/requests/openid_connect_spec.rb
index 6d1f0b24196..ebba28ba8ce 100644
--- a/spec/requests/openid_connect_spec.rb
+++ b/spec/requests/openid_connect_spec.rb
@@ -98,7 +98,7 @@ describe 'OpenID Connect requests' do
expect(@payload['sub']).to eq hashed_subject
end
- it 'includes the time of the last authentication', :redis do
+ it 'includes the time of the last authentication', :clean_gitlab_redis_shared_state do
expect(@payload['auth_time']).to eq user.current_sign_in_at.to_i
end
diff --git a/spec/services/event_create_service_spec.rb b/spec/services/event_create_service_spec.rb
index b06cefe071d..8d067c194cc 100644
--- a/spec/services/event_create_service_spec.rb
+++ b/spec/services/event_create_service_spec.rb
@@ -113,7 +113,7 @@ describe EventCreateService, services: true do
end
end
- describe '#push', :redis do
+ describe '#push', :clean_gitlab_redis_shared_state do
let(:project) { create(:empty_project) }
let(:user) { create(:user) }
diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb
index 8e8816870e1..3f77ed10069 100644
--- a/spec/services/git_push_service_spec.rb
+++ b/spec/services/git_push_service_spec.rb
@@ -527,14 +527,18 @@ describe GitPushService, services: true do
let(:housekeeping) { Projects::HousekeepingService.new(project) }
before do
- # Flush any raw Redis data stored by the housekeeping code.
- Gitlab::Redis.with { |conn| conn.flushall }
+ # Flush any raw key-value data stored by the housekeeping code.
+ Gitlab::Redis::Cache.with { |conn| conn.flushall }
+ Gitlab::Redis::Queues.with { |conn| conn.flushall }
+ Gitlab::Redis::SharedState.with { |conn| conn.flushall }
allow(Projects::HousekeepingService).to receive(:new).and_return(housekeeping)
end
after do
- Gitlab::Redis.with { |conn| conn.flushall }
+ Gitlab::Redis::Cache.with { |conn| conn.flushall }
+ Gitlab::Redis::Queues.with { |conn| conn.flushall }
+ Gitlab::Redis::SharedState.with { |conn| conn.flushall }
end
it 'does not perform housekeeping when not needed' do
diff --git a/spec/services/milestones/destroy_service_spec.rb b/spec/services/milestones/destroy_service_spec.rb
new file mode 100644
index 00000000000..8d1fe3ae2c1
--- /dev/null
+++ b/spec/services/milestones/destroy_service_spec.rb
@@ -0,0 +1,51 @@
+require 'spec_helper'
+
+describe Milestones::DestroyService, services: true do
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+ let(:milestone) { create(:milestone, title: 'Milestone v1.0', project: project) }
+ let(:issue) { create(:issue, project: project, milestone: milestone) }
+ let(:merge_request) { create(:merge_request, source_project: project, milestone: milestone) }
+
+ before do
+ project.team << [user, :master]
+ end
+
+ def service
+ described_class.new(project, user, {})
+ end
+
+ describe '#execute' do
+ it 'deletes milestone' do
+ service.execute(milestone)
+
+ expect { milestone.reload }.to raise_error ActiveRecord::RecordNotFound
+ end
+
+ it 'deletes milestone id from issuables' do
+ service.execute(milestone)
+
+ expect(issue.reload.milestone).to be_nil
+ expect(merge_request.reload.milestone).to be_nil
+ end
+
+ context 'group milestones' do
+ let(:group) { create(:group) }
+ let(:group_milestone) { create(:milestone, group: group) }
+
+ before do
+ project.update(namespace: group)
+ group.add_developer(user)
+ end
+
+ it { expect(service.execute(group_milestone)).to be_nil }
+
+ it 'does not update milestone issuables' do
+ expect(MergeRequests::UpdateService).not_to receive(:new)
+ expect(Issues::UpdateService).not_to receive(:new)
+
+ service.execute(group_milestone)
+ end
+ end
+ end
+end
diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb
index 697dc18feb0..b399d3402fd 100644
--- a/spec/services/projects/destroy_service_spec.rb
+++ b/spec/services/projects/destroy_service_spec.rb
@@ -60,14 +60,14 @@ describe Projects::DestroyService, services: true do
before do
new_user = create(:user)
project.team.add_user(new_user, Gitlab::Access::DEVELOPER)
- allow_any_instance_of(Projects::DestroyService).to receive(:flush_caches).and_raise(Redis::CannotConnectError)
+ allow_any_instance_of(Projects::DestroyService).to receive(:flush_caches).and_raise(::Redis::CannotConnectError)
end
it 'keeps project team intact upon an error' do
Sidekiq::Testing.inline! do
begin
destroy_project(project, user, {})
- rescue Redis::CannotConnectError
+ rescue ::Redis::CannotConnectError
end
end
diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb
index 175a42a32d9..de41cbab14c 100644
--- a/spec/services/todo_service_spec.rb
+++ b/spec/services/todo_service_spec.rb
@@ -908,7 +908,7 @@ describe TodoService, services: true do
end
end
- it 'caches the number of todos of a user', :caching do
+ 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)
TodoService.new.mark_todos_as_done([todo], john_doe)
diff --git a/spec/services/users/activity_service_spec.rb b/spec/services/users/activity_service_spec.rb
index 2e009d4ce1c..e5330d1d3e4 100644
--- a/spec/services/users/activity_service_spec.rb
+++ b/spec/services/users/activity_service_spec.rb
@@ -7,7 +7,7 @@ describe Users::ActivityService, services: true do
subject(:service) { described_class.new(user, 'type') }
- describe '#execute', :redis do
+ describe '#execute', :clean_gitlab_redis_shared_state do
context 'when last activity is nil' do
before do
service.execute
diff --git a/spec/services/users/refresh_authorized_projects_service_spec.rb b/spec/services/users/refresh_authorized_projects_service_spec.rb
index b65cadbb2f5..1c0f55d2965 100644
--- a/spec/services/users/refresh_authorized_projects_service_spec.rb
+++ b/spec/services/users/refresh_authorized_projects_service_spec.rb
@@ -8,7 +8,7 @@ describe Users::RefreshAuthorizedProjectsService do
let(:user) { project.namespace.owner }
let(:service) { described_class.new(user) }
- describe '#execute', :redis do
+ describe '#execute', :clean_gitlab_redis_shared_state do
it 'refreshes the authorizations using a lease' do
expect_any_instance_of(Gitlab::ExclusiveLease).to receive(:try_obtain)
.and_return('foo')
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index a497b8613bb..3c142764e28 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -76,6 +76,11 @@ RSpec.configure do |config|
TestEnv.cleanup
end
+ config.before(:example) do
+ # Skip pre-receive hook check so we can use the web editor and merge.
+ allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([true, nil])
+ end
+
config.before(:example, :request_store) do
RequestStore.begin!
end
@@ -91,20 +96,30 @@ RSpec.configure do |config|
end
end
- config.around(:each, :caching) do |example|
+ config.around(:each, :use_clean_rails_memory_store_caching) do |example|
caching_store = Rails.cache
- Rails.cache = ActiveSupport::Cache::MemoryStore.new if example.metadata[:caching]
+ Rails.cache = ActiveSupport::Cache::MemoryStore.new
+
example.run
+
Rails.cache = caching_store
end
- config.around(:each, :redis) do |example|
- Gitlab::Redis.with(&:flushall)
+ config.around(:each, :clean_gitlab_redis_cache) do |example|
+ Gitlab::Redis::Cache.with(&:flushall)
+
+ example.run
+
+ Gitlab::Redis::Cache.with(&:flushall)
+ end
+
+ config.around(:each, :clean_gitlab_redis_shared_state) do |example|
+ Gitlab::Redis::SharedState.with(&:flushall)
Sidekiq.redis(&:flushall)
example.run
- Gitlab::Redis.with(&:flushall)
+ Gitlab::Redis::SharedState.with(&:flushall)
Sidekiq.redis(&:flushall)
end
diff --git a/spec/support/dropzone_helper.rb b/spec/support/dropzone_helper.rb
index 02fdeb08afe..fe72d320fcf 100644
--- a/spec/support/dropzone_helper.rb
+++ b/spec/support/dropzone_helper.rb
@@ -54,4 +54,23 @@ module DropzoneHelper
loop until page.evaluate_script('window._dropzoneComplete === true')
end
end
+
+ def drop_in_dropzone(file_path)
+ # Generate a fake input selector
+ page.execute_script <<-JS
+ var fakeFileInput = window.$('<input/>').attr(
+ {id: 'fakeFileInput', type: 'file'}
+ ).appendTo('body');
+ JS
+
+ # Attach the file to the fake input selector with Capybara
+ attach_file('fakeFileInput', file_path)
+
+ # Add the file to a fileList array and trigger the fake drop event
+ page.execute_script <<-JS
+ var fileList = [$('#fakeFileInput')[0].files[0]];
+ var e = jQuery.Event('drop', { dataTransfer : { files : fileList } });
+ $('.dropzone')[0].dropzone.listeners[0].events.drop(e);
+ JS
+ end
end
diff --git a/spec/lib/gitlab/redis_spec.rb b/spec/support/redis/redis_shared_examples.rb
index 593aa5038ad..f9552e41894 100644
--- a/spec/lib/gitlab/redis_spec.rb
+++ b/spec/support/redis/redis_shared_examples.rb
@@ -1,12 +1,10 @@
-require 'spec_helper'
-
-describe Gitlab::Redis do
+RSpec.shared_examples "redis_shared_examples" do
include StubENV
- let(:config) { 'config/resque.yml' }
+ let(:test_redis_url) { "redis://redishost:#{redis_port}"}
before(:each) do
- stub_env('GITLAB_REDIS_CONFIG_FILE', Rails.root.join(config).to_s)
+ stub_env(environment_config_file_name, Rails.root.join(config_file_name))
clear_raw_config
end
@@ -26,46 +24,40 @@ describe Gitlab::Redis do
end
context 'when url contains unix socket reference' do
- let(:config_old) { 'spec/fixtures/config/redis_old_format_socket.yml' }
- let(:config_new) { 'spec/fixtures/config/redis_new_format_socket.yml' }
-
context 'with old format' do
- let(:config) { config_old }
+ let(:config_file_name) { config_old_format_socket }
it 'returns path key instead' do
- is_expected.to include(path: '/path/to/old/redis.sock')
+ is_expected.to include(path: old_socket_path)
is_expected.not_to have_key(:url)
end
end
context 'with new format' do
- let(:config) { config_new }
+ let(:config_file_name) { config_new_format_socket }
it 'returns path key instead' do
- is_expected.to include(path: '/path/to/redis.sock')
+ is_expected.to include(path: new_socket_path)
is_expected.not_to have_key(:url)
end
end
end
context 'when url is host based' do
- let(:config_old) { 'spec/fixtures/config/redis_old_format_host.yml' }
- let(:config_new) { 'spec/fixtures/config/redis_new_format_host.yml' }
-
context 'with old format' do
- let(:config) { config_old }
+ let(:config_file_name) { config_old_format_host }
it 'returns hash with host, port, db, and password' do
- is_expected.to include(host: 'localhost', password: 'mypassword', port: 6379, db: 99)
+ is_expected.to include(host: 'localhost', password: 'mypassword', port: redis_port, db: redis_database)
is_expected.not_to have_key(:url)
end
end
context 'with new format' do
- let(:config) { config_new }
+ let(:config_file_name) { config_new_format_host }
it 'returns hash with host, port, db, and password' do
- is_expected.to include(host: 'localhost', password: 'mynewpassword', port: 6379, db: 99)
+ is_expected.to include(host: 'localhost', password: 'mynewpassword', port: redis_port, db: redis_database)
is_expected.not_to have_key(:url)
end
end
@@ -73,30 +65,22 @@ describe Gitlab::Redis do
end
describe '.url' do
- it 'withstands mutation' do
- url1 = described_class.url
- url2 = described_class.url
- url1 << 'foobar'
-
- expect(url2).not_to end_with('foobar')
- end
-
context 'when yml file with env variable' do
- let(:config) { 'spec/fixtures/config/redis_config_with_env.yml' }
+ let(:config_file_name) { config_with_environment_variable_inside }
before do
- stub_env('TEST_GITLAB_REDIS_URL', 'redis://redishost:6379')
+ stub_env(config_env_variable_url, test_redis_url)
end
it 'reads redis url from env variable' do
- expect(described_class.url).to eq 'redis://redishost:6379'
+ expect(described_class.url).to eq test_redis_url
end
end
end
describe '._raw_config' do
subject { described_class._raw_config }
- let(:config) { '/var/empty/doesnotexist' }
+ let(:config_file_name) { '/var/empty/doesnotexist' }
it 'should be frozen' do
expect(subject).to be_frozen
@@ -105,6 +89,12 @@ describe Gitlab::Redis do
it 'returns false when the file does not exist' do
expect(subject).to eq(false)
end
+
+ it "returns false when the filename can't be determined" do
+ expect(described_class).to receive(:config_file_name).and_return(nil)
+
+ expect(subject).to eq(false)
+ end
end
describe '.with' do
@@ -124,7 +114,7 @@ describe Gitlab::Redis do
it 'instantiates a connection pool with size 5' do
expect(ConnectionPool).to receive(:new).with(size: 5).and_call_original
- described_class.with { |_redis| true }
+ described_class.with { |_redis_shared_example| true }
end
end
@@ -137,7 +127,7 @@ describe Gitlab::Redis do
it 'instantiates a connection pool with a size based on the concurrency of the worker' do
expect(ConnectionPool).to receive(:new).with(size: 18 + 5).and_call_original
- described_class.with { |_redis| true }
+ described_class.with { |_redis_shared_example| true }
end
end
end
@@ -146,16 +136,16 @@ describe Gitlab::Redis do
subject { described_class.new(Rails.env).sentinels }
context 'when sentinels are defined' do
- let(:config) { 'spec/fixtures/config/redis_new_format_host.yml' }
+ let(:config_file_name) { config_new_format_host }
it 'returns an array of hashes with host and port keys' do
- is_expected.to include(host: 'localhost', port: 26380)
- is_expected.to include(host: 'slave2', port: 26381)
+ is_expected.to include(host: 'localhost', port: sentinel_port)
+ is_expected.to include(host: 'slave2', port: sentinel_port)
end
end
context 'when sentinels are not defined' do
- let(:config) { 'spec/fixtures/config/redis_old_format_host.yml' }
+ let(:config_file_name) { config_old_format_host }
it 'returns nil' do
is_expected.to be_nil
@@ -167,7 +157,7 @@ describe Gitlab::Redis do
subject { described_class.new(Rails.env).sentinels? }
context 'when sentinels are defined' do
- let(:config) { 'spec/fixtures/config/redis_new_format_host.yml' }
+ let(:config_file_name) { config_new_format_host }
it 'returns true' do
is_expected.to be_truthy
@@ -175,7 +165,7 @@ describe Gitlab::Redis do
end
context 'when sentinels are not defined' do
- let(:config) { 'spec/fixtures/config/redis_old_format_host.yml' }
+ let(:config_file_name) { config_old_format_host }
it 'returns false' do
is_expected.to be_falsey
@@ -187,12 +177,12 @@ describe Gitlab::Redis do
it 'returns default redis url when no config file is present' do
expect(subject).to receive(:fetch_config) { false }
- expect(subject.send(:raw_config_hash)).to eq(url: Gitlab::Redis::DEFAULT_REDIS_URL)
+ expect(subject.send(:raw_config_hash)).to eq(url: class_redis_url )
end
it 'returns old-style single url config in a hash' do
- expect(subject).to receive(:fetch_config) { 'redis://myredis:6379' }
- expect(subject.send(:raw_config_hash)).to eq(url: 'redis://myredis:6379')
+ expect(subject).to receive(:fetch_config) { test_redis_url }
+ expect(subject.send(:raw_config_hash)).to eq(url: test_redis_url)
end
end
@@ -200,7 +190,13 @@ describe Gitlab::Redis do
it 'returns false when no config file is present' do
allow(described_class).to receive(:_raw_config) { false }
- expect(subject.send(:fetch_config)).to be_falsey
+ expect(subject.send(:fetch_config)).to eq false
+ end
+
+ it 'returns false when config file is present but has invalid YAML' do
+ allow(described_class).to receive(:_raw_config) { "# development: true" }
+
+ expect(subject.send(:fetch_config)).to eq false
end
end
diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb
index 0cae5620920..0a194ca4c90 100644
--- a/spec/support/test_env.rb
+++ b/spec/support/test_env.rb
@@ -206,6 +206,7 @@ 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..."
diff --git a/spec/support/unique_ip_check_shared_examples.rb b/spec/support/unique_ip_check_shared_examples.rb
index 1986d202c4a..ff0b47899f5 100644
--- a/spec/support/unique_ip_check_shared_examples.rb
+++ b/spec/support/unique_ip_check_shared_examples.rb
@@ -1,7 +1,9 @@
shared_context 'unique ips sign in limit' do
include StubENV
before(:each) do
- Gitlab::Redis.with(&:flushall)
+ Gitlab::Redis::Cache.with(&:flushall)
+ Gitlab::Redis::Queues.with(&:flushall)
+ Gitlab::Redis::SharedState.with(&:flushall)
end
before do
diff --git a/spec/workers/schedule_update_user_activity_worker_spec.rb b/spec/workers/schedule_update_user_activity_worker_spec.rb
index e583c3203aa..32c59381b01 100644
--- a/spec/workers/schedule_update_user_activity_worker_spec.rb
+++ b/spec/workers/schedule_update_user_activity_worker_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe ScheduleUpdateUserActivityWorker, :redis do
+describe ScheduleUpdateUserActivityWorker, :clean_gitlab_redis_shared_state do
let(:now) { Time.now }
before do
diff --git a/spec/workers/update_user_activity_worker_spec.rb b/spec/workers/update_user_activity_worker_spec.rb
index 43e9511f116..268ca1d81f2 100644
--- a/spec/workers/update_user_activity_worker_spec.rb
+++ b/spec/workers/update_user_activity_worker_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe UpdateUserActivityWorker, :redis do
+describe UpdateUserActivityWorker, :clean_gitlab_redis_shared_state do
let(:user_active_2_days_ago) { create(:user, current_sign_in_at: 10.months.ago) }
let(:user_active_yesterday_1) { create(:user) }
let(:user_active_yesterday_2) { create(:user) }
@@ -25,7 +25,7 @@ describe UpdateUserActivityWorker, :redis do
end
end
- it 'deletes the pairs from Redis' do
+ it 'deletes the pairs from SharedState' do
data.each { |id, time| Gitlab::UserActivities.record(id, time) }
subject.perform(data)
diff --git a/vendor/gitlab-ci-yml/Docker.gitlab-ci.yml b/vendor/gitlab-ci-yml/Docker.gitlab-ci.yml
index 5b6af7be8c4..eeefadaa019 100644
--- a/vendor/gitlab-ci-yml/Docker.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Docker.gitlab-ci.yml
@@ -4,10 +4,21 @@ image: docker:latest
services:
- docker:dind
+before_script:
+ - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
+
+build-master:
+ stage: build
+ script:
+ - docker build --pull -t "$CI_REGISTRY_IMAGE" .
+ - docker push "$CI_REGISTRY_IMAGE"
+ only:
+ - master
+
build:
stage: build
- before_script:
- - docker login -u "$CI_REGISTRY_USER" -p "CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- - docker build --pull -t "$CI_REGISTRY_IMAGE:CI_COMMIT_REF_SLUG" .
- - docker push "$CI_REGISTRY_IMAGE:CI_COMMIT_REF_SLUG"
+ - docker build --pull -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" .
+ - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG"
+ except:
+ - master
diff --git a/vendor/gitlab-ci-yml/autodeploy/Kubernetes-with-canary.gitlab-ci.yml b/vendor/gitlab-ci-yml/autodeploy/Kubernetes-with-canary.gitlab-ci.yml
index 555a51d35b9..06b0c84e516 100644
--- a/vendor/gitlab-ci-yml/autodeploy/Kubernetes-with-canary.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/autodeploy/Kubernetes-with-canary.gitlab-ci.yml
@@ -28,7 +28,7 @@ canary:
- command canary
environment:
name: production
- url: http://$CI_PROJECT_NAME.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG.$KUBE_DOMAIN
when: manual
only:
- master
@@ -39,7 +39,7 @@ production:
- command deploy
environment:
name: production
- url: http://$CI_PROJECT_NAME.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG.$KUBE_DOMAIN
when: manual
only:
- master
@@ -50,7 +50,7 @@ staging:
- command deploy
environment:
name: staging
- url: http://$CI_PROJECT_NAME-staging.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG-staging.$KUBE_DOMAIN
only:
- master
@@ -60,7 +60,7 @@ review:
- command deploy
environment:
name: review/$CI_COMMIT_REF_NAME
- url: http://$CI_PROJECT_NAME-$CI_ENVIRONMENT_SLUG.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG-$CI_ENVIRONMENT_SLUG.$KUBE_DOMAIN
on_stop: stop_review
only:
- branches
diff --git a/vendor/gitlab-ci-yml/autodeploy/Kubernetes.gitlab-ci.yml b/vendor/gitlab-ci-yml/autodeploy/Kubernetes.gitlab-ci.yml
index ee830ec2eb0..722934b7981 100644
--- a/vendor/gitlab-ci-yml/autodeploy/Kubernetes.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/autodeploy/Kubernetes.gitlab-ci.yml
@@ -27,7 +27,7 @@ production:
- command deploy
environment:
name: production
- url: http://$CI_PROJECT_NAME.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG.$KUBE_DOMAIN
when: manual
only:
- master
@@ -38,7 +38,7 @@ staging:
- command deploy
environment:
name: staging
- url: http://$CI_PROJECT_NAME-staging.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG-staging.$KUBE_DOMAIN
only:
- master
@@ -48,7 +48,7 @@ review:
- command deploy
environment:
name: review/$CI_COMMIT_REF_NAME
- url: http://$CI_PROJECT_NAME-$CI_ENVIRONMENT_SLUG.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG-$CI_ENVIRONMENT_SLUG.$KUBE_DOMAIN
on_stop: stop_review
only:
- branches
diff --git a/vendor/gitlab-ci-yml/autodeploy/OpenShift.gitlab-ci.yml b/vendor/gitlab-ci-yml/autodeploy/OpenShift.gitlab-ci.yml
index 27c9107e0d7..acba718ebe4 100644
--- a/vendor/gitlab-ci-yml/autodeploy/OpenShift.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/autodeploy/OpenShift.gitlab-ci.yml
@@ -23,38 +23,32 @@ build:
production:
stage: production
- variables:
- CI_ENVIRONMENT_URL: http://$CI_PROJECT_NAME.$KUBE_DOMAIN
script:
- command deploy
environment:
name: production
- url: http://$CI_PROJECT_NAME.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG.$KUBE_DOMAIN
when: manual
only:
- master
staging:
stage: staging
- variables:
- CI_ENVIRONMENT_URL: http://$CI_PROJECT_NAME-staging.$KUBE_DOMAIN
script:
- command deploy
environment:
name: staging
- url: http://$CI_PROJECT_NAME-staging.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG-staging.$KUBE_DOMAIN
only:
- master
review:
stage: review
- variables:
- CI_ENVIRONMENT_URL: http://$CI_PROJECT_NAME-$CI_ENVIRONMENT_SLUG.$KUBE_DOMAIN
script:
- command deploy
environment:
name: review/$CI_COMMIT_REF_NAME
- url: http://$CI_PROJECT_NAME-$CI_ENVIRONMENT_SLUG.$KUBE_DOMAIN
+ url: http://$CI_PROJECT_PATH_SLUG-$CI_ENVIRONMENT_SLUG.$KUBE_DOMAIN
on_stop: stop_review
only:
- branches
diff --git a/vendor/licenses.csv b/vendor/licenses.csv
index 5dcac5947a1..5beb3e5e9bf 100644
--- a/vendor/licenses.csv
+++ b/vendor/licenses.csv
@@ -1,9 +1,9 @@
RedCloth,4.3.2,MIT
-abbrev,1.0.9,ISC
+abbrev,1.1.0,ISC
accepts,1.3.3,MIT
ace-rails-ap,4.1.2,MIT
-acorn,5.0.3,MIT
-acorn-dynamic-import,2.0.1,MIT
+acorn,5.1.1,MIT
+acorn-dynamic-import,2.0.2,MIT
acorn-jsx,3.0.1,MIT
actionmailer,4.2.8,MIT
actionpack,4.2.8,MIT
@@ -16,7 +16,7 @@ acts-as-taggable-on,4.0.0,MIT
addressable,2.3.8,Apache 2.0
after,0.8.2,MIT
after_commit_queue,1.3.0,MIT
-ajv,4.11.2,MIT
+ajv,4.11.8,MIT
ajv-keywords,1.5.1,MIT
akismet,2.0.0,MIT
align-text,0.1.4,MIT
@@ -26,16 +26,17 @@ amdefine,1.0.1,BSD-3-Clause OR MIT
ansi-escapes,1.4.0,MIT
ansi-html,0.0.5,"Apache, Version 2.0"
ansi-regex,2.1.1,MIT
-ansi-styles,2.2.1,MIT
+ansi-styles,3.1.0,MIT
anymatch,1.3.0,ISC
append-transform,0.4.0,MIT
-aproba,1.1.0,ISC
-are-we-there-yet,1.1.2,ISC
+aproba,1.1.2,ISC
+are-we-there-yet,1.1.4,ISC
arel,6.0.4,MIT
argparse,1.0.9,MIT
arr-diff,2.0.0,MIT
-arr-flatten,1.0.1,MIT
+arr-flatten,1.1.0,MIT
array-find,1.0.0,MIT
+array-find-index,1.0.2,MIT
array-flatten,1.1.1,MIT
array-slice,0.2.3,MIT
array-union,1.0.2,MIT
@@ -63,26 +64,27 @@ aws-sign2,0.6.0,Apache 2.0
aws4,1.6.0,MIT
axiom-types,0.1.1,MIT
babel-code-frame,6.22.0,MIT
-babel-core,6.23.1,MIT
-babel-generator,6.23.0,MIT
-babel-helper-bindify-decorators,6.22.0,MIT
-babel-helper-builder-binary-assignment-operator-visitor,6.22.0,MIT
-babel-helper-call-delegate,6.22.0,MIT
-babel-helper-define-map,6.23.0,MIT
-babel-helper-explode-assignable-expression,6.22.0,MIT
-babel-helper-explode-class,6.22.0,MIT
-babel-helper-function-name,6.23.0,MIT
-babel-helper-get-function-arity,6.22.0,MIT
-babel-helper-hoist-variables,6.22.0,MIT
-babel-helper-optimise-call-expression,6.23.0,MIT
-babel-helper-regex,6.22.0,MIT
-babel-helper-remap-async-to-generator,6.22.0,MIT
-babel-helper-replace-supers,6.23.0,MIT
-babel-helpers,6.23.0,MIT
-babel-loader,6.2.10,MIT
+babel-core,6.25.0,MIT
+babel-eslint,7.2.3,MIT
+babel-generator,6.25.0,MIT
+babel-helper-bindify-decorators,6.24.1,MIT
+babel-helper-builder-binary-assignment-operator-visitor,6.24.1,MIT
+babel-helper-call-delegate,6.24.1,MIT
+babel-helper-define-map,6.24.1,MIT
+babel-helper-explode-assignable-expression,6.24.1,MIT
+babel-helper-explode-class,6.24.1,MIT
+babel-helper-function-name,6.24.1,MIT
+babel-helper-get-function-arity,6.24.1,MIT
+babel-helper-hoist-variables,6.24.1,MIT
+babel-helper-optimise-call-expression,6.24.1,MIT
+babel-helper-regex,6.24.1,MIT
+babel-helper-remap-async-to-generator,6.24.1,MIT
+babel-helper-replace-supers,6.24.1,MIT
+babel-helpers,6.24.1,MIT
+babel-loader,6.4.1,MIT
babel-messages,6.23.0,MIT
babel-plugin-check-es2015-constants,6.22.0,MIT
-babel-plugin-istanbul,4.0.0,New BSD
+babel-plugin-istanbul,4.1.4,New BSD
babel-plugin-syntax-async-functions,6.13.0,MIT
babel-plugin-syntax-async-generators,6.13.0,MIT
babel-plugin-syntax-class-properties,6.13.0,MIT
@@ -91,57 +93,57 @@ babel-plugin-syntax-dynamic-import,6.18.0,MIT
babel-plugin-syntax-exponentiation-operator,6.13.0,MIT
babel-plugin-syntax-object-rest-spread,6.13.0,MIT
babel-plugin-syntax-trailing-function-commas,6.22.0,MIT
-babel-plugin-transform-async-generator-functions,6.22.0,MIT
-babel-plugin-transform-async-to-generator,6.22.0,MIT
-babel-plugin-transform-class-properties,6.23.0,MIT
-babel-plugin-transform-decorators,6.22.0,MIT
-babel-plugin-transform-define,1.2.0,MIT
+babel-plugin-transform-async-generator-functions,6.24.1,MIT
+babel-plugin-transform-async-to-generator,6.24.1,MIT
+babel-plugin-transform-class-properties,6.24.1,MIT
+babel-plugin-transform-decorators,6.24.1,MIT
+babel-plugin-transform-define,1.3.0,MIT
babel-plugin-transform-es2015-arrow-functions,6.22.0,MIT
babel-plugin-transform-es2015-block-scoped-functions,6.22.0,MIT
-babel-plugin-transform-es2015-block-scoping,6.23.0,MIT
-babel-plugin-transform-es2015-classes,6.23.0,MIT
-babel-plugin-transform-es2015-computed-properties,6.22.0,MIT
+babel-plugin-transform-es2015-block-scoping,6.24.1,MIT
+babel-plugin-transform-es2015-classes,6.24.1,MIT
+babel-plugin-transform-es2015-computed-properties,6.24.1,MIT
babel-plugin-transform-es2015-destructuring,6.23.0,MIT
-babel-plugin-transform-es2015-duplicate-keys,6.22.0,MIT
+babel-plugin-transform-es2015-duplicate-keys,6.24.1,MIT
babel-plugin-transform-es2015-for-of,6.23.0,MIT
-babel-plugin-transform-es2015-function-name,6.22.0,MIT
+babel-plugin-transform-es2015-function-name,6.24.1,MIT
babel-plugin-transform-es2015-literals,6.22.0,MIT
-babel-plugin-transform-es2015-modules-amd,6.24.0,MIT
-babel-plugin-transform-es2015-modules-commonjs,6.24.0,MIT
-babel-plugin-transform-es2015-modules-systemjs,6.23.0,MIT
-babel-plugin-transform-es2015-modules-umd,6.24.0,MIT
-babel-plugin-transform-es2015-object-super,6.22.0,MIT
-babel-plugin-transform-es2015-parameters,6.23.0,MIT
-babel-plugin-transform-es2015-shorthand-properties,6.22.0,MIT
+babel-plugin-transform-es2015-modules-amd,6.24.1,MIT
+babel-plugin-transform-es2015-modules-commonjs,6.24.1,MIT
+babel-plugin-transform-es2015-modules-systemjs,6.24.1,MIT
+babel-plugin-transform-es2015-modules-umd,6.24.1,MIT
+babel-plugin-transform-es2015-object-super,6.24.1,MIT
+babel-plugin-transform-es2015-parameters,6.24.1,MIT
+babel-plugin-transform-es2015-shorthand-properties,6.24.1,MIT
babel-plugin-transform-es2015-spread,6.22.0,MIT
-babel-plugin-transform-es2015-sticky-regex,6.22.0,MIT
+babel-plugin-transform-es2015-sticky-regex,6.24.1,MIT
babel-plugin-transform-es2015-template-literals,6.22.0,MIT
babel-plugin-transform-es2015-typeof-symbol,6.23.0,MIT
-babel-plugin-transform-es2015-unicode-regex,6.22.0,MIT
-babel-plugin-transform-exponentiation-operator,6.22.0,MIT
+babel-plugin-transform-es2015-unicode-regex,6.24.1,MIT
+babel-plugin-transform-exponentiation-operator,6.24.1,MIT
babel-plugin-transform-object-rest-spread,6.23.0,MIT
-babel-plugin-transform-regenerator,6.22.0,MIT
-babel-plugin-transform-strict-mode,6.22.0,MIT
-babel-preset-es2015,6.24.0,MIT
-babel-preset-es2016,6.22.0,MIT
-babel-preset-es2017,6.22.0,MIT
-babel-preset-latest,6.24.0,MIT
-babel-preset-stage-2,6.22.0,MIT
-babel-preset-stage-3,6.22.0,MIT
-babel-register,6.23.0,MIT
-babel-runtime,6.22.0,MIT
-babel-template,6.23.0,MIT
-babel-traverse,6.23.1,MIT
-babel-types,6.23.0,MIT
+babel-plugin-transform-regenerator,6.24.1,MIT
+babel-plugin-transform-strict-mode,6.24.1,MIT
+babel-preset-es2015,6.24.1,MIT
+babel-preset-es2016,6.24.1,MIT
+babel-preset-es2017,6.24.1,MIT
+babel-preset-latest,6.24.1,MIT
+babel-preset-stage-2,6.24.1,MIT
+babel-preset-stage-3,6.24.1,MIT
+babel-register,6.24.1,MIT
+babel-runtime,6.23.0,MIT
+babel-template,6.25.0,MIT
+babel-traverse,6.25.0,MIT
+babel-types,6.25.0,MIT
babosa,1.0.2,MIT
-babylon,6.15.0,MIT
+babylon,6.17.4,MIT
backo2,1.0.2,MIT
-balanced-match,0.4.2,MIT
+balanced-match,1.0.0,MIT
base32,0.3.2,MIT
base64-arraybuffer,0.1.5,MIT
-base64-js,1.2.0,MIT
+base64-js,1.2.1,MIT
base64id,1.0.0,MIT
-batch,0.5.3,MIT
+batch,0.6.1,MIT
bcrypt,3.1.11,MIT
bcrypt-pbkdf,1.0.1,New BSD
better-assert,1.0.2,MIT
@@ -150,24 +152,28 @@ binary-extensions,1.8.0,MIT
bindata,2.3.5,ruby
blob,0.0.4,unknown
block-stream,0.0.9,ISC
-bluebird,3.4.7,MIT
-bn.js,4.11.6,MIT
+bluebird,3.5.0,MIT
+bn.js,4.11.7,MIT
body-parser,1.17.2,MIT
+bonjour,3.5.0,MIT
boom,2.10.1,New BSD
-bootsnap,1.0.0,MIT
+bootsnap,1.1.1,MIT
bootstrap-sass,3.3.6,MIT
-brace-expansion,1.1.6,MIT
+bootstrap-sass,3.3.7,MIT
+bootstrap_form,2.7.0,MIT
+brace-expansion,1.1.8,MIT
braces,1.8.5,MIT
-brorand,1.0.7,MIT
+brorand,1.1.0,MIT
browser,2.2.0,MIT
browserify-aes,1.0.6,MIT
browserify-cipher,1.0.0,MIT
browserify-des,1.0.0,MIT
browserify-rsa,4.0.1,MIT
-browserify-sign,4.0.0,ISC
+browserify-sign,4.0.4,ISC
browserify-zlib,0.1.4,MIT
browserslist,1.7.7,MIT
buffer,4.9.1,MIT
+buffer-indexof,1.1.0,MIT
buffer-shims,1.0.0,MIT
buffer-xor,1.0.3,MIT
builder,3.2.3,MIT
@@ -178,29 +184,30 @@ caller-path,0.1.0,MIT
callsite,1.0.0,unknown
callsites,0.2.0,MIT
camelcase,1.2.1,MIT
+camelcase-keys,2.1.0,MIT
caniuse-api,1.6.1,MIT
-caniuse-db,1.0.30000649,CC-BY-4.0
-carrierwave,1.0.0,MIT
-caseless,0.11.0,Apache 2.0
+caniuse-db,1.0.30000699,CC-BY-4.0
+carrierwave,1.1.0,MIT
+caseless,0.12.0,Apache 2.0
cause,0.1,MIT
center-align,0.1.3,MIT
chalk,1.1.3,MIT
charlock_holmes,0.7.3,MIT
-chokidar,1.6.1,MIT
+chokidar,1.7.0,MIT
chronic,0.10.2,MIT
chronic_duration,0.10.6,MIT
chunky_png,1.3.5,MIT
-cipher-base,1.0.3,MIT
+cipher-base,1.0.4,MIT
circular-json,0.3.1,MIT
citrus,3.0.2,MIT
-clap,1.1.3,MIT
+clap,1.2.0,MIT
cli-cursor,1.0.2,MIT
cli-width,2.1.0,ISC
-clipboard,1.6.1,MIT
+clipboard,1.7.1,MIT
cliui,2.1.0,ISC
clone,1.0.2,MIT
co,4.6.0,MIT
-coa,1.0.1,MIT
+coa,1.0.4,MIT
code-point-at,1.1.0,MIT
coercible,1.0.0,MIT
coffee-rails,4.1.1,MIT
@@ -214,13 +221,13 @@ colormin,1.1.2,MIT
colors,1.1.2,MIT
combine-lists,1.0.1,MIT
combined-stream,1.0.5,MIT
-commander,2.9.0,MIT
+commander,2.11.0,MIT
commondir,1.0.1,MIT
component-bind,1.0.0,unknown
component-emitter,1.2.1,MIT
component-inherit,0.0.3,unknown
-compressible,2.0.9,MIT
-compression,1.6.2,MIT
+compressible,2.0.10,MIT
+compression,1.7.0,MIT
compression-webpack-plugin,0.3.2,MIT
concat-map,0.0.1,MIT
concat-stream,1.6.0,MIT
@@ -237,38 +244,40 @@ constants-browserify,1.0.0,MIT
contains-path,0.1.0,MIT
content-disposition,0.5.2,MIT
content-type,1.0.2,MIT
-convert-source-map,1.3.0,MIT
+convert-source-map,1.5.0,MIT
cookie,0.3.1,MIT
cookie-signature,1.0.6,MIT
core-js,2.4.1,MIT
core-util-is,1.0.2,MIT
-cosmiconfig,2.1.1,MIT
+cosmiconfig,2.1.3,MIT
crack,0.4.3,MIT
create-ecdh,4.0.0,MIT
-create-hash,1.1.2,MIT
-create-hmac,1.1.4,MIT
+create-hash,1.1.3,MIT
+create-hmac,1.1.6,MIT
creole,0.5.0,ruby
cryptiles,2.0.5,New BSD
crypto-browserify,3.11.0,MIT
css-color-names,0.0.4,MIT
-css-loader,0.28.0,MIT
-css-selector-tokenizer,0.7.0,MIT
-css_parser,1.4.1,MIT
+css-loader,0.28.4,MIT
+css-selector-tokenizer,"",unknown
+css_parser,1.5.0,MIT
cssesc,0.1.0,MIT
cssnano,3.10.0,MIT
csso,2.3.2,MIT
+currently-unhandled,0.4.1,MIT
custom-event,1.0.1,MIT
-d,0.1.1,MIT
-d3,3.5.11,New BSD
+d,1.0.0,MIT
+d3,3.5.17,New BSD
d3_rails,3.5.11,MIT
dashdash,1.14.1,MIT
date-now,0.1.4,MIT
de-indent,1.0.2,MIT
-debug,2.6.0,MIT
+debug,2.6.8,MIT
debugger-ruby_core_source,1.3.8,MIT
decamelize,1.2.0,MIT
deckar01-task_list,2.0.0,MIT
-deep-extend,0.4.1,MIT
+deep-equal,1.0.1,MIT
+deep-extend,0.4.2,MIT
deep-is,0.1.3,MIT
default-require-extensions,1.0.0,MIT
default_value_for,3.0.2,MIT
@@ -276,31 +285,35 @@ defaults,1.0.3,MIT
defined,1.0.0,MIT
del,2.2.2,MIT
delayed-stream,1.0.0,MIT
-delegate,3.1.2,MIT
+delegate,3.1.3,MIT
delegates,1.0.0,MIT
depd,1.1.0,MIT
des.js,1.0.0,MIT
descendants_tracker,0.0.4,MIT
destroy,1.0.4,MIT
detect-indent,4.0.0,MIT
+detect-node,2.0.3,ISC
devise,4.2.0,MIT
devise-two-factor,3.0.0,MIT
di,0.0.1,MIT
diff-lcs,1.2.5,"MIT,Perl Artistic v2,GNU GPL v2"
diffie-hellman,5.0.2,MIT
diffy,3.1.0,MIT
-doctrine,1.5.0,BSD
-document-register-element,1.3.0,MIT
+dns-equal,1.0.0,MIT
+dns-packet,1.1.1,MIT
+dns-txt,2.0.2,MIT
+doctrine,2.0.0,Apache 2.0
+document-register-element,1.5.0,MIT
dom-serialize,2.2.1,MIT
dom-serializer,0.1.0,MIT
domain-browser,1.1.7,MIT
domain_name,0.5.20161021,"Simplified BSD,New BSD,Mozilla Public License 2.0"
domelementtype,1.3.0,unknown
-domhandler,2.3.0,unknown
-domutils,1.5.1,unknown
+domhandler,2.4.1,Simplified BSD
+domutils,1.6.2,Simplified BSD
doorkeeper,4.2.0,MIT
doorkeeper-openid_connect,1.1.2,MIT
-dropzone,4.2.0,MIT
+dropzone,4.3.0,MIT
dropzonejs-rails,0.7.2,MIT
duplexer,0.1.1,MIT
duplexify,3.5.0,MIT
@@ -308,8 +321,8 @@ ecc-jsbn,0.1.1,MIT
editorconfig,0.13.2,MIT
ee-first,1.1.1,MIT
ejs,2.5.6,Apache 2.0
-electron-to-chromium,1.3.3,ISC
-elliptic,6.3.3,MIT
+electron-to-chromium,1.3.15,ISC
+elliptic,6.4.0,MIT
email_reply_trimmer,0.1.6,MIT
emoji-unicode-version,0.2.1,MIT
emojis-list,2.1.0,MIT
@@ -319,44 +332,45 @@ end-of-stream,1.0.0,MIT
engine.io,1.8.3,MIT
engine.io-client,1.8.3,MIT
engine.io-parser,1.3.2,MIT
-enhanced-resolve,3.1.0,MIT
+enhanced-resolve,3.3.0,MIT
ent,2.2.0,MIT
entities,1.1.1,BSD-like
equalizer,0.0.11,MIT
errno,0.1.4,MIT
-error-ex,1.3.0,MIT
+error-ex,1.3.1,MIT
erubis,2.7.0,MIT
-es5-ext,0.10.12,MIT
-es6-iterator,2.0.0,MIT
-es6-map,0.1.4,MIT
+es5-ext,0.10.24,MIT
+es6-iterator,2.0.1,MIT
+es6-map,0.1.5,MIT
es6-promise,3.0.2,MIT
-es6-set,0.1.4,MIT
-es6-symbol,3.1.0,MIT
-es6-weak-map,2.0.1,MIT
+es6-set,0.1.5,MIT
+es6-symbol,3.1.1,MIT
+es6-weak-map,2.0.2,MIT
escape-html,1.0.3,MIT
escape-string-regexp,1.0.5,MIT
escape_utils,1.1.1,MIT
escodegen,1.8.1,Simplified BSD
escope,3.6.0,Simplified BSD
-eslint,3.15.0,MIT
+eslint,3.19.0,MIT
eslint-config-airbnb-base,10.0.1,MIT
-eslint-import-resolver-node,0.2.3,MIT
-eslint-import-resolver-webpack,0.8.1,MIT
-eslint-module-utils,2.0.0,MIT
-eslint-plugin-filenames,1.1.0,MIT
-eslint-plugin-html,2.0.1,ISC
-eslint-plugin-import,2.2.0,MIT
-eslint-plugin-jasmine,2.2.0,MIT
+eslint-import-resolver-node,0.3.1,MIT
+eslint-import-resolver-webpack,0.8.3,MIT
+eslint-module-utils,2.1.1,MIT
+eslint-plugin-filenames,1.2.0,MIT
+eslint-plugin-html,2.0.3,ISC
+eslint-plugin-import,2.7.0,MIT
+eslint-plugin-jasmine,2.7.1,MIT
eslint-plugin-promise,3.5.0,ISC
-espree,3.4.0,Simplified BSD
-esprima,3.1.3,Simplified BSD
-esrecurse,4.1.0,Simplified BSD
-estraverse,4.1.1,Simplified BSD
+espree,3.4.3,Simplified BSD
+esprima,2.7.3,Simplified BSD
+esquery,1.0.0,BSD
+esrecurse,4.2.0,Simplified BSD
+estraverse,4.2.0,Simplified BSD
esutils,2.0.2,BSD
et-orbi,1.0.3,MIT
etag,1.8.0,MIT
eve-raphael,0.5.0,Apache 2.0
-event-emitter,0.3.4,MIT
+event-emitter,0.3.5,MIT
event-stream,3.3.4,MIT
eventemitter3,1.2.0,MIT
events,1.1.1,MIT
@@ -371,13 +385,14 @@ expand-range,1.8.2,MIT
exports-loader,0.6.4,MIT
express,4.15.3,MIT
expression_parser,0.9.0,MIT
-extend,3.0.0,MIT
+extend,3.0.1,MIT
extglob,0.3.2,MIT
extlib,0.9.16,MIT
extsprintf,1.0.2,MIT
-faraday,0.11.0,MIT
+faraday,0.12.1,MIT
faraday_middleware,0.11.0.1,MIT
faraday_middleware-multi_json,0.0.6,MIT
+fast-deep-equal,1.0.0,MIT
fast-levenshtein,2.0.6,MIT
fast_gettext,1.4.0,"MIT,ruby"
fastparse,1.1.1,MIT
@@ -385,15 +400,15 @@ faye-websocket,0.7.3,MIT
ffi,1.9.10,BSD
figures,1.7.0,MIT
file-entry-cache,2.0.0,MIT
-file-loader,0.11.1,MIT
-filename-regex,2.0.0,MIT
+file-loader,0.11.2,MIT
+filename-regex,2.0.1,MIT
fileset,2.0.3,MIT
filesize,3.3.0,New BSD
fill-range,2.2.3,MIT
finalhandler,1.0.3,MIT
find-cache-dir,0.1.1,MIT
find-root,0.1.2,MIT
-find-up,2.1.0,MIT
+find-up,1.1.2,MIT
flat-cache,1.2.2,MIT
flatten,1.0.2,MIT
flipper,0.10.2,MIT
@@ -409,41 +424,43 @@ fog-openstack,0.1.6,MIT
fog-rackspace,0.1.1,MIT
fog-xml,0.1.3,MIT
font-awesome-rails,4.7.0.1,"MIT,SIL Open Font License"
-for-in,0.1.6,MIT
-for-own,0.1.4,MIT
+for-in,1.0.2,MIT
+for-own,0.1.5,MIT
forever-agent,0.6.1,Apache 2.0
-form-data,2.1.2,MIT
+form-data,2.1.4,MIT
formatador,0.2.5,MIT
forwarded,0.1.0,MIT
fresh,0.5.0,MIT
from,0.1.7,MIT
+fs-access,1.0.1,MIT
fs.realpath,1.0.0,ISC
-fsevents,,unknown
-fstream,1.0.10,ISC
+fsevents,1.1.2,MIT
+fstream,1.0.11,ISC
fstream-ignore,1.0.5,ISC
function-bind,1.1.0,MIT
-gauge,2.7.2,ISC
+gauge,2.7.4,ISC
gemnasium-gitlab-service,0.2.6,MIT
gemojione,3.0.1,MIT
generate-function,2.0.0,MIT
generate-object-property,1.2.0,MIT
get-caller-file,1.0.2,ISC
+get-stdin,4.0.1,MIT
get_process_mem,0.2.0,MIT
-getpass,0.1.6,MIT
+getpass,0.1.7,MIT
gettext_i18n_rails,1.8.0,MIT
gettext_i18n_rails_js,1.2.0,MIT
-gitaly,0.8.0,MIT
+gitaly,0.14.0,MIT
github-linguist,4.7.6,MIT
github-markup,1.4.0,MIT
gitlab-flowdock-git-hook,1.0.1,MIT
gitlab-grit,2.8.1,MIT
gitlab-markup,1.5.1,MIT
gitlab_omniauth-ldap,1.2.1,MIT
-glob,7.1.1,ISC
+glob,7.1.2,ISC
glob-base,0.3.0,MIT
glob-parent,2.0.0,ISC
globalid,0.3.7,MIT
-globals,9.14.0,MIT
+globals,9.18.0,MIT
globby,5.0.0,MIT
gollum-grit_adapter,1.0.1,MIT
gollum-lib,4.2.1,MIT
@@ -455,32 +472,34 @@ google-protobuf,3.2.0.2,New BSD
googleauth,0.5.1,Apache 2.0
got,3.3.1,MIT
graceful-fs,4.1.11,ISC
-graceful-readlink,1.0.1,MIT
grape,0.19.1,MIT
grape-entity,0.6.0,MIT
-grpc,1.2.5,New BSD
+grpc,1.4.0,New BSD
gzip-size,3.0.0,MIT
hamlit,2.6.1,MIT
handle-thing,1.2.5,MIT
-handlebars,4.0.6,MIT
-har-validator,2.0.6,ISC
+handlebars,4.0.10,MIT
+har-schema,1.0.5,ISC
+har-validator,4.2.1,ISC
has,1.0.1,MIT
has-ansi,2.0.0,MIT
has-binary,0.1.7,MIT
has-cors,1.1.0,MIT
-has-flag,1.0.0,MIT
+has-flag,2.0.0,MIT
has-unicode,2.0.1,ISC
+hash-base,2.0.2,MIT
hash-sum,1.0.2,MIT
-hash.js,1.0.3,MIT
+hash.js,1.1.3,MIT
hashie,3.5.5,MIT
hashie-forbidden_attributes,0.1.1,MIT
hawk,3.1.3,New BSD
he,1.1.1,MIT
health_check,2.6.0,MIT
hipchat,1.5.2,MIT
+hmac-drbg,1.0.1,MIT
hoek,2.16.3,New BSD
home-or-tmp,2.0.0,MIT
-hosted-git-info,2.2.0,ISC
+hosted-git-info,2.5.0,ISC
hpack.js,2.1.6,MIT
html-comment-regex,1.1.1,MIT
html-entities,1.2.0,MIT
@@ -503,12 +522,14 @@ https-browserify,0.0.1,MIT
i18n,0.8.1,MIT
ice_nine,0.11.2,MIT
iconv-lite,0.4.15,MIT
-icss-replace-symbols,1.0.2,ISC
+icss-replace-symbols,1.1.0,ISC
+icss-utils,2.1.0,ISC
ieee754,1.1.8,New BSD
-ignore,3.2.2,MIT
+ignore,3.3.3,MIT
ignore-by-default,1.0.1,ISC
immediate,3.0.6,MIT
imurmurhash,0.1.4,MIT
+indent-string,2.1.0,MIT
indexes-of,1.0.1,MIT
indexof,0.0.1,unknown
infinity-agent,2.0.3,MIT
@@ -517,25 +538,28 @@ influxdb,0.2.3,MIT
inherits,2.0.3,ISC
ini,1.3.4,ISC
inquirer,0.12.0,MIT
-interpret,1.0.1,MIT
+internal-ip,1.2.0,MIT
+interpret,1.0.3,MIT
invariant,2.2.2,New BSD
invert-kv,1.0.0,MIT
+ip,1.1.5,MIT
ipaddr.js,1.3.0,MIT
ipaddress,0.8.3,MIT
is-absolute,0.2.6,MIT
is-absolute-url,2.1.0,MIT
is-arrayish,0.2.1,MIT
is-binary-path,1.0.1,MIT
-is-buffer,1.1.4,MIT
+is-buffer,1.1.5,MIT
is-builtin-module,1.0.0,MIT
-is-dotfile,1.0.2,MIT
+is-directory,0.3.1,MIT
+is-dotfile,1.0.3,MIT
is-equal-shallow,0.1.3,MIT
is-extendable,0.1.1,MIT
is-extglob,1.0.0,MIT
is-finite,1.0.2,MIT
is-fullwidth-code-point,1.0.0,MIT
is-glob,2.0.1,MIT
-is-my-json-valid,2.15.0,MIT
+is-my-json-valid,2.16.0,MIT
is-npm,1.0.0,MIT
is-number,2.1.0,MIT
is-path-cwd,1.0.0,MIT
@@ -556,56 +580,58 @@ is-utf8,0.2.1,MIT
is-windows,0.2.0,MIT
isarray,1.0.0,MIT
isbinaryfile,3.0.2,MIT
-isexe,1.1.2,ISC
+isexe,2.0.0,ISC
isobject,2.1.0,MIT
isstream,0.1.2,MIT
istanbul,0.4.5,New BSD
-istanbul-api,1.1.1,New BSD
-istanbul-lib-coverage,1.0.1,New BSD
-istanbul-lib-hook,1.0.0,New BSD
-istanbul-lib-instrument,1.4.2,New BSD
-istanbul-lib-report,1.0.0-alpha.3,New BSD
-istanbul-lib-source-maps,1.1.0,New BSD
-istanbul-reports,1.0.1,New BSD
-jasmine-core,2.6.3,MIT
+istanbul-api,1.1.10,New BSD
+istanbul-lib-coverage,1.1.1,New BSD
+istanbul-lib-hook,1.0.7,New BSD
+istanbul-lib-instrument,1.7.3,New BSD
+istanbul-lib-report,1.1.1,New BSD
+istanbul-lib-source-maps,1.2.1,New BSD
+istanbul-reports,1.1.1,New BSD
+jasmine-core,2.6.4,MIT
jasmine-jquery,2.1.1,MIT
jed,1.1.1,MIT
jira-ruby,1.1.2,MIT
jodid25519,1.0.2,MIT
-jquery,2.2.1,MIT
+jquery,2.2.4,MIT
jquery-atwho-rails,1.3.2,MIT
jquery-rails,4.1.1,MIT
-jquery-ujs,1.2.1,MIT
+jquery-ujs,1.2.2,MIT
js-base64,2.1.9,BSD
-js-beautify,1.6.12,MIT
-js-cookie,2.1.3,MIT
-js-tokens,3.0.1,MIT
-js-yaml,3.7.0,MIT
-jsbn,0.1.0,BSD
+js-beautify,1.6.14,MIT
+js-cookie,2.1.4,MIT
+js-tokens,3.0.2,MIT
+js-yaml,"",unknown
+jsbn,0.1.1,MIT
jsesc,1.3.0,MIT
json,1.8.6,ruby
json-jwt,1.7.1,MIT
json-loader,0.5.4,MIT
json-schema,0.2.3,"AFLv2.1,BSD"
+json-schema-traverse,0.3.1,MIT
json-stable-stringify,1.0.1,MIT
json-stringify-safe,5.0.1,ISC
json3,3.3.2,MIT
json5,0.5.1,MIT
jsonify,0.0.0,Public Domain
jsonpointer,4.0.1,MIT
-jsprim,1.3.1,MIT
+jsprim,1.4.0,MIT
jszip,3.1.3,(MIT OR GPL-3.0)
jszip-utils,0.0.2,MIT or GPLv3
jwt,1.5.6,MIT
kaminari,0.17.0,MIT
karma,1.7.0,MIT
-karma-coverage-istanbul-reporter,0.2.0,MIT
+karma-chrome-launcher,2.2.0,MIT
+karma-coverage-istanbul-reporter,0.2.3,MIT
karma-jasmine,1.1.0,MIT
-karma-mocha-reporter,2.2.2,MIT
+karma-mocha-reporter,2.2.3,MIT
karma-sourcemap-loader,0.3.7,MIT
-karma-webpack,2.0.2,MIT
+karma-webpack,2.0.4,MIT
kgio,2.10.0,LGPL-2.1+
-kind-of,3.1.0,MIT
+kind-of,3.2.2,MIT
kubeclient,2.2.0,MIT
latest-version,1.0.1,MIT
launchy,2.4.3,ISC
@@ -617,7 +643,7 @@ lie,3.1.1,MIT
little-plugger,1.1.4,MIT
load-json-file,1.1.0,MIT
loader-runner,2.3.0,MIT
-loader-utils,0.2.16,MIT
+loader-utils,"",unknown
locale,2.1.2,"ruby,LGPLv3+"
locate-path,2.0.0,MIT
lodash,4.17.4,MIT
@@ -631,65 +657,69 @@ lodash._isiterateecall,3.0.9,MIT
lodash._topath,3.8.1,MIT
lodash.assign,3.2.0,MIT
lodash.camelcase,4.3.0,MIT
-lodash.capitalize,4.2.1,MIT
lodash.cond,4.5.2,MIT
-lodash.deburr,4.1.0,MIT
lodash.defaults,3.1.2,MIT
-lodash.get,4.4.2,MIT
+lodash.get,3.7.0,MIT
lodash.isarguments,3.1.0,MIT
lodash.isarray,3.0.4,MIT
-lodash.kebabcase,4.0.1,MIT
+lodash.kebabcase,4.1.1,MIT
lodash.keys,3.1.2,MIT
lodash.memoize,4.1.2,MIT
lodash.restparam,3.6.1,MIT
-lodash.snakecase,4.0.1,MIT
+lodash.snakecase,4.1.1,MIT
lodash.uniq,4.5.0,MIT
-lodash.words,4.2.0,MIT
+lodash.upperfirst,4.3.1,MIT
log4js,0.6.38,Apache 2.0
logging,2.2.2,MIT
longest,1.0.1,MIT
loofah,2.0.3,MIT
loose-envify,1.3.1,MIT
+loud-rejection,1.6.0,MIT
lowercase-keys,1.0.0,MIT
lru-cache,3.2.0,ISC
macaddress,0.2.8,MIT
mail,2.6.5,MIT
mail_room,0.9.1,MIT
+map-obj,1.0.1,MIT
map-stream,0.1.0,unknown
marked,0.3.6,MIT
-math-expression-evaluator,1.2.16,MIT
+math-expression-evaluator,1.2.17,MIT
media-typer,0.3.0,MIT
memoist,0.15.0,MIT
memory-fs,0.4.1,MIT
+meow,3.7.0,MIT
merge-descriptors,1.0.1,MIT
method_source,0.8.2,MIT
methods,1.1.2,MIT
micromatch,2.3.11,MIT
miller-rabin,4.0.0,MIT
-mime,1.3.4,MIT
+mime,1.3.6,MIT
mime-db,1.27.0,MIT
+mime-types,2.1.15,MIT
mime-types,2.99.3,"MIT,Artistic-2.0,GPL-2.0"
mimemagic,0.3.0,MIT
mini_portile2,2.1.0,MIT
minimalistic-assert,1.0.0,ISC
-minimatch,3.0.3,ISC
+minimalistic-crypto-utils,1.0.1,MIT
+minimatch,3.0.4,ISC
minimist,0.0.8,MIT
mkdirp,0.5.1,MIT
-mmap2,2.2.6,ruby
-moment,2.17.1,MIT
-mousetrap,1.4.6,Apache 2.0
+mmap2,2.2.7,ruby
+moment,2.18.1,MIT
+mousetrap,1.6.1,Apache 2.0
mousetrap-rails,1.4.6,"MIT,Apache"
-ms,0.7.2,MIT
+ms,2.0.0,MIT
msgpack,1.1.0,Apache 2.0
multi_json,1.12.1,MIT
multi_xml,0.6.0,MIT
+multicast-dns,6.1.1,MIT
+multicast-dns-service-types,1.1.0,MIT
multipart-post,2.0.0,MIT
mustermann,0.4.0,MIT
mustermann-grape,0.4.0,MIT
mute-stream,0.0.5,ISC
-mysql2,0.3.20,MIT
name-all-modules-plugin,1.0.1,MIT
-nan,2.5.1,MIT
+nan,2.6.2,MIT
natural-compare,1.4.0,MIT
negotiator,0.6.1,MIT
nested-error-stacks,1.0.2,MIT
@@ -697,23 +727,25 @@ net-ldap,0.12.1,MIT
net-ssh,3.0.1,MIT
netrc,0.11.0,MIT
node-ensure,0.0.0,MIT
+node-forge,0.6.33,BSD
node-libs-browser,2.0.0,MIT
-node-pre-gyp,0.6.33,New BSD
+node-pre-gyp,0.6.36,New BSD
node-zopfli,2.0.2,MIT
nodemon,1.11.0,MIT
nokogiri,1.6.8.1,MIT
-nopt,3.0.6,ISC
-normalize-package-data,2.3.5,Simplified BSD
-normalize-path,2.0.1,MIT
+nopt,4.0.1,ISC
+normalize-package-data,2.4.0,Simplified BSD
+normalize-path,2.1.1,MIT
normalize-range,0.1.2,MIT
normalize-url,1.9.1,MIT
-npmlog,4.0.2,ISC
+npmlog,4.1.2,ISC
+null-check,1.0.0,MIT
num2fraction,1.2.2,MIT
number-is-nan,1.0.1,MIT
numerizer,0.1.1,MIT
oauth,0.5.1,MIT
oauth-sign,0.8.2,Apache 2.0
-oauth2,1.3.1,MIT
+oauth2,1.4.0,MIT
object-assign,4.1.1,MIT
object-component,0.0.3,unknown
object.omit,2.0.1,MIT
@@ -740,7 +772,7 @@ omniauth-twitter,1.2.1,MIT
omniauth_crowd,2.2.3,MIT
on-finished,2.3.0,MIT
on-headers,1.0.1,MIT
-once,1.3.3,ISC
+once,1.4.0,ISC
onetime,1.1.0,MIT
opener,1.4.3,(WTFPL OR MIT)
opn,4.0.2,MIT
@@ -758,10 +790,11 @@ os-tmpdir,1.0.2,MIT
osenv,0.1.4,ISC
p-limit,1.1.0,MIT
p-locate,2.0.0,MIT
+p-map,1.1.1,MIT
package-json,1.2.0,MIT
pako,1.0.5,(MIT AND Zlib)
-paranoia,2.2.0,MIT
-parse-asn1,5.0.0,ISC
+paranoia,2.3.1,MIT
+parse-asn1,5.1.0,ISC
parse-glob,3.0.4,MIT
parse-json,2.2.0,MIT
parsejson,0.0.3,MIT
@@ -769,36 +802,35 @@ parseqs,0.0.5,MIT
parseuri,0.0.5,MIT
parseurl,1.3.1,MIT
path-browserify,0.0.0,MIT
-path-exists,3.0.0,MIT
+path-exists,2.1.0,MIT
path-is-absolute,1.0.1,MIT
path-is-inside,1.0.2,(WTFPL OR MIT)
path-parse,1.0.5,MIT
path-to-regexp,0.1.7,MIT
path-type,1.1.0,MIT
pause-stream,0.0.11,"MIT,Apache2"
-pbkdf2,3.0.9,MIT
-pdfjs-dist,1.8.252,Apache 2.0
+pbkdf2,3.0.12,MIT
+pdfjs-dist,1.8.527,Apache 2.0
peek,1.0.1,MIT
peek-gc,0.0.2,MIT
peek-host,1.0.0,MIT
-peek-mysql2,1.1.0,MIT
peek-performance_bar,1.2.1,MIT
peek-pg,1.3.0,MIT
peek-rblineprof,0.2.0,MIT
peek-redis,1.2.0,MIT
peek-sidekiq,1.0.3,MIT
+performance-now,0.2.0,MIT
pg,0.18.4,"BSD,ruby,GPL"
pify,2.3.0,MIT
-pikaday,1.5.1,"BSD,MIT"
+pikaday,1.6.1,(0BSD OR MIT)
pinkie,2.0.4,MIT
pinkie-promise,2.0.1,MIT
pkg-dir,1.0.0,MIT
-pkg-up,1.0.0,MIT
pluralize,1.2.1,MIT
po_to_json,1.0.1,MIT
portfinder,1.0.13,MIT
posix-spawn,0.3.11,"MIT,LGPL"
-postcss,5.2.16,MIT
+postcss,5.2.17,MIT
postcss-calc,5.3.1,MIT
postcss-colormin,2.2.2,MIT
postcss-convert-values,2.6.1,MIT
@@ -819,10 +851,10 @@ postcss-minify-font-values,1.0.5,MIT
postcss-minify-gradients,1.0.5,MIT
postcss-minify-params,1.2.2,MIT
postcss-minify-selectors,2.1.1,MIT
-postcss-modules-extract-imports,1.0.1,ISC
-postcss-modules-local-by-default,1.1.1,MIT
-postcss-modules-scope,1.0.2,ISC
-postcss-modules-values,1.2.2,ISC
+postcss-modules-extract-imports,1.1.0,ISC
+postcss-modules-local-by-default,1.2.0,MIT
+postcss-modules-scope,1.1.0,ISC
+postcss-modules-values,1.3.0,ISC
postcss-normalize-charset,1.1.1,MIT
postcss-normalize-url,3.0.8,MIT
postcss-ordered-values,2.2.3,MIT
@@ -835,16 +867,16 @@ postcss-unique-selectors,2.0.2,MIT
postcss-value-parser,3.3.0,MIT
postcss-zindex,2.2.0,MIT
prelude-ls,1.1.2,MIT
-premailer,1.8.6,New BSD
-premailer-rails,1.9.2,MIT
+premailer,1.10.4,New BSD
+premailer-rails,1.9.7,MIT
prepend-http,1.0.4,MIT
preserve,0.2.0,MIT
prismjs,1.6.0,MIT
private,0.1.7,MIT
-process,0.11.9,MIT
+process,0.11.10,MIT
process-nextick-args,1.0.7,MIT
progress,1.1.8,MIT
-prometheus-client-mmap,0.7.0.beta5,Apache 2.0
+prometheus-client-mmap,0.7.0.beta8,Apache 2.0
proto-list,1.2.4,ISC
proxy-addr,1.1.4,MIT
prr,0.0.0,MIT
@@ -855,8 +887,8 @@ punycode,1.4.1,MIT
pyu-ruby-sasl,0.0.3.3,MIT
q,1.5.0,MIT
qjobs,1.1.5,MIT
-qs,6.3.0,New BSD
-query-string,4.3.2,MIT
+qs,6.4.0,New BSD
+query-string,4.3.4,MIT
querystring,0.2.0,MIT
querystring-es3,0.2.1,MIT
querystringify,0.0.4,MIT
@@ -872,24 +904,25 @@ rails,4.2.8,MIT
rails-deprecated_sanitizer,1.0.3,MIT
rails-dom-testing,1.0.8,MIT
rails-html-sanitizer,1.0.3,MIT
+rails-i18n,4.0.9,MIT
railties,4.2.8,MIT
-rainbow,2.1.0,MIT
-raindrops,0.17.0,LGPL-2.1+
+rainbow,2.2.2,MIT
+raindrops,0.18.0,LGPL-2.1+
rake,10.5.0,MIT
-randomatic,1.1.6,MIT
-randombytes,2.0.3,MIT
+randomatic,1.1.7,MIT
+randombytes,2.0.5,MIT
range-parser,1.2.0,MIT
raphael,2.2.7,MIT
-raven-js,3.14.0,Simplified BSD
+raven-js,3.16.1,Simplified BSD
raw-body,2.2.0,MIT
raw-loader,0.5.1,MIT
-rc,1.1.6,(BSD-2-Clause OR MIT OR Apache-2.0)
+rc,1.2.1,(BSD-2-Clause OR MIT OR Apache-2.0)
rdoc,4.2.2,ruby
react-dev-utils,0.5.2,New BSD
read-all-stream,3.1.0,MIT
read-pkg,1.1.0,MIT
read-pkg-up,1.0.1,MIT
-readable-stream,2.2.2,MIT
+readable-stream,2.3.3,MIT
readdirp,2.1.0,MIT
readline2,1.0.1,MIT
recaptcha,3.0.0,MIT
@@ -897,6 +930,7 @@ rechoir,0.6.2,MIT
recursive-open-struct,1.0.0,MIT
recursive-readdir,2.1.1,MIT
redcarpet,3.4.0,MIT
+redent,1.0.0,MIT
redis,3.3.3,MIT
redis-actionpack,5.0.1,MIT
redis-activesupport,5.0.1,MIT
@@ -907,33 +941,34 @@ redis-store,1.2.0,MIT
reduce-css-calc,1.3.0,MIT
reduce-function-call,1.0.2,MIT
regenerate,1.3.2,MIT
-regenerator-runtime,0.10.1,MIT
-regenerator-transform,0.9.8,BSD
+regenerator-runtime,0.10.5,MIT
+regenerator-transform,0.9.11,BSD
regex-cache,0.4.3,MIT
-regexpu-core,2.0.0,MIT
+regexpu-core,"",unknown
registry-url,3.1.0,MIT
regjsgen,0.2.0,MIT
regjsparser,0.1.5,BSD
+remove-trailing-separator,1.0.2,ISC
repeat-element,1.1.2,MIT
repeat-string,1.6.1,MIT
repeating,2.0.1,MIT
-request,2.79.0,Apache 2.0
+request,2.81.0,Apache 2.0
request_store,1.3.1,MIT
require-directory,2.1.1,MIT
require-from-string,1.2.1,MIT
require-main-filename,1.0.1,ISC
require-uncached,1.0.3,MIT
requires-port,1.0.0,MIT
-resolve,1.2.0,MIT
+resolve,1.3.3,MIT
resolve-from,1.0.1,MIT
responders,2.3.0,MIT
rest-client,2.0.0,MIT
restore-cursor,1.0.1,MIT
retriable,1.4.1,MIT
right-align,0.1.3,MIT
-rimraf,2.5.4,ISC
+rimraf,2.6.1,ISC
rinku,2.0.0,ISC
-ripemd160,1.0.1,New BSD
+ripemd160,2.0.1,MIT
rotp,2.1.2,MIT
rouge,2.1.0,MIT
rqrcode,0.7.0,MIT
@@ -941,40 +976,42 @@ rqrcode-rails3,0.1.7,MIT
ruby-fogbugz,0.2.1,MIT
ruby-prof,0.16.2,Simplified BSD
ruby-saml,1.4.1,MIT
-ruby_parser,3.8.4,MIT
+ruby_parser,3.9.0,MIT
rubyntlm,0.5.2,MIT
rubypants,0.2.0,BSD
rufus-scheduler,3.4.0,MIT
rugged,0.25.1.1,MIT
run-async,0.1.0,MIT
rx-lite,3.1.2,Apache 2.0
-safe-buffer,5.0.1,MIT
+safe-buffer,5.1.1,MIT
safe_yaml,1.0.4,MIT
sanitize,2.1.0,MIT
sass,3.4.22,MIT
sass-rails,5.0.6,MIT
sawyer,0.8.1,MIT
-sax,1.2.2,ISC
+sax,1.2.4,ISC
+schema-utils,0.3.0,MIT
securecompare,1.0.0,MIT
seed-fu,2.3.6,MIT
select,1.1.2,MIT
select-hose,2.0.0,MIT
select2,3.5.2-browserify,unknown
select2-rails,3.5.9.3,MIT
+selfsigned,1.9.1,MIT
semver,5.3.0,ISC
semver-diff,2.1.0,MIT
send,0.15.3,MIT
-sentry-raven,2.4.0,Apache 2.0
-serve-index,1.8.0,MIT
+sentry-raven,2.5.3,Apache 2.0
+serve-index,1.9.0,MIT
serve-static,1.12.3,MIT
set-blocking,2.0.0,ISC
set-immediate-shim,1.0.1,MIT
setimmediate,1.0.5,MIT
setprototypeof,1.0.3,ISC
settingslogic,2.0.9,MIT
-sexp_processor,4.8.0,MIT
+sexp_processor,4.9.0,MIT
sha.js,2.4.8,MIT
-shelljs,0.7.6,New BSD
+shelljs,0.7.8,New BSD
sidekiq,5.0.0,LGPL
sidekiq-cron,0.6.0,MIT
sidekiq-limit_fetch,3.4.0,MIT
@@ -995,18 +1032,18 @@ sockjs-client,1.0.1,MIT
sort-keys,1.1.2,MIT
source-list-map,0.1.8,MIT
source-map,0.5.6,New BSD
-source-map-support,0.4.11,MIT
+source-map-support,0.4.15,MIT
spdx-correct,1.0.2,Apache 2.0
spdx-expression-parse,1.0.4,(MIT AND CC-BY-3.0)
spdx-license-ids,1.2.2,Unlicense
-spdy,3.4.4,MIT
-spdy-transport,2.0.18,MIT
+spdy,3.4.7,MIT
+spdy-transport,2.0.20,MIT
split,0.3.3,MIT
sprintf-js,1.0.3,New BSD
sprockets,3.7.1,MIT
sprockets-rails,3.2.0,MIT
sql.js,0.4.0,MIT
-sshpk,1.10.2,MIT
+sshpk,1.13.1,MIT
state_machines,0.4.0,MIT
state_machines-activemodel,0.4.0,MIT
state_machines-activerecord,0.4.0,MIT
@@ -1014,7 +1051,7 @@ stats-webpack-plugin,0.4.3,MIT
statuses,1.3.1,MIT
stream-browserify,2.0.1,MIT
stream-combiner,0.0.4,MIT
-stream-http,2.6.3,MIT
+stream-http,2.7.2,MIT
stream-shift,1.0.0,MIT
strict-uri-encode,1.1.0,MIT
string-length,1.0.1,MIT
@@ -1024,44 +1061,47 @@ stringex,2.5.2,MIT
stringstream,0.0.5,MIT
strip-ansi,3.0.1,MIT
strip-bom,2.0.0,MIT
-strip-json-comments,1.0.4,MIT
-supports-color,0.2.0,MIT
+strip-indent,1.0.1,MIT
+strip-json-comments,2.0.1,MIT
+supports-color,4.2.0,MIT
svgo,0.7.2,MIT
sys-filesystem,1.1.6,Artistic 2.0
table,3.8.3,New BSD
tapable,0.2.6,MIT
tar,2.2.1,ISC
-tar-pack,3.3.0,Simplified BSD
+tar-pack,3.4.0,Simplified BSD
temple,0.7.7,MIT
-test-exclude,4.0.0,ISC
+test-exclude,4.1.1,ISC
text,1.3.1,MIT
text-table,0.2.0,MIT
thor,0.19.4,MIT
thread_safe,0.3.6,Apache 2.0
three,0.84.0,MIT
three-orbit-controls,82.1.0,MIT
-three-stl-loader,1.0.4,MIT
+three-stl-loader,1.0.5,MIT
through,2.3.8,MIT
+thunky,0.1.0,unknown
tilt,2.0.6,MIT
timeago.js,2.0.5,MIT
timed-out,2.0.0,MIT
timers-browserify,2.0.2,MIT
timfel-krb5-auth,0.8.3,LGPL
-tiny-emitter,1.1.0,MIT
+tiny-emitter,2.0.1,MIT
tmp,0.0.31,MIT
to-array,0.1.4,MIT
to-arraybuffer,1.0.1,MIT
-to-fast-properties,1.0.2,MIT
+to-fast-properties,1.0.3,MIT
toml-rb,0.3.15,MIT
tool,0.2.3,MIT
touch,1.0.0,ISC
tough-cookie,2.3.2,New BSD
traverse,0.6.6,MIT
+trim-newlines,1.0.0,MIT
trim-right,1.0.1,MIT
truncato,0.7.8,MIT
tryit,1.0.3,MIT
tty-browserify,0.0.0,MIT
-tunnel-agent,0.4.3,Apache 2.0
+tunnel-agent,0.6.0,Apache 2.0
tweetnacl,0.14.5,Unlicense
type-check,0.3.2,MIT
type-is,1.6.15,MIT
@@ -1069,7 +1109,7 @@ typedarray,0.0.6,MIT
tzinfo,1.2.2,MIT
u2f,0.2.1,MIT
uglifier,2.7.2,MIT
-uglify-js,2.8.27,Simplified BSD
+uglify-js,2.8.29,Simplified BSD
uglify-to-browserify,1.0.2,MIT
uid-number,0.0.6,ISC
ultron,1.1.0,MIT
@@ -1087,15 +1127,15 @@ uniqs,2.0.0,MIT
unpipe,1.0.0,MIT
update-notifier,0.5.0,Simplified BSD
url,0.11.0,MIT
-url-loader,0.5.8,MIT
+url-loader,0.5.9,MIT
url-parse,1.0.5,MIT
url_safe_base64,0.2.2,MIT
user-home,2.0.0,MIT
-useragent,2.1.13,MIT
+useragent,2.2.0,MIT
util,0.10.3,MIT
util-deprecate,1.0.2,MIT
utils-merge,1.0.0,MIT
-uuid,3.0.1,MIT
+uuid,3.1.0,MIT
validate-npm-package-license,3.0.1,Apache 2.0
validates_hostname,1.0.6,MIT
vary,1.1.1,MIT
@@ -1107,36 +1147,36 @@ visibilityjs,1.2.4,MIT
vm-browserify,0.0.4,MIT
vmstat,2.3.0,MIT
void-elements,2.0.1,MIT
-vue,2.2.6,MIT
-vue-hot-reload-api,2.0.11,MIT
+vue,2.3.4,MIT
+vue-hot-reload-api,2.1.0,MIT
vue-loader,11.3.4,MIT
vue-resource,0.9.3,MIT
vue-style-loader,2.0.5,MIT
-vue-template-compiler,2.2.6,MIT
-vue-template-es2015-compiler,1.5.1,MIT
+vue-template-compiler,2.3.4,MIT
+vue-template-es2015-compiler,1.5.3,MIT
warden,1.2.6,MIT
watchpack,1.3.1,MIT
wbuf,1.7.2,MIT
webpack,2.6.1,MIT
webpack-bundle-analyzer,2.8.2,MIT
-webpack-dev-middleware,1.10.0,MIT
-webpack-dev-server,2.4.2,MIT
+webpack-dev-middleware,1.11.0,MIT
+webpack-dev-server,2.5.1,MIT
webpack-rails,0.9.10,MIT
-webpack-sources,0.1.4,MIT
+webpack-sources,0.1.5,MIT
websocket-driver,0.6.5,MIT
websocket-extensions,0.1.1,MIT
whet.extend,0.9.9,MIT
-which,1.2.12,ISC
+which,1.2.14,ISC
which-module,1.0.0,ISC
-wide-align,1.1.0,ISC
+wide-align,1.1.2,ISC
wikicloth,0.8.1,MIT
window-size,0.1.0,MIT
wordwrap,0.0.2,MIT/X11
-worker-loader,0.8.0,MIT
+worker-loader,0.8.1,MIT
wrap-ansi,2.1.0,MIT
wrappy,1.0.2,ISC
write,0.2.1,MIT
-write-file-atomic,1.3.1,ISC
+write-file-atomic,1.3.4,ISC
ws,2.3.1,MIT
wtf-8,1.0.0,MIT
xdg-basedir,2.0.0,MIT
diff --git a/yarn.lock b/yarn.lock
index b04eebe60af..98da6a984d1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1575,6 +1575,12 @@ deckar01-task_list@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/deckar01-task_list/-/deckar01-task_list-2.0.0.tgz#7f7a595430d21b3036ed5dfbf97d6b65de18e2c9"
+decompress-response@^3.2.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3"
+ dependencies:
+ mimic-response "^1.0.0"
+
deep-extend@~0.4.0:
version "0.4.1"
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.1.tgz#efe4113d08085f4e6f9687759810f807469e2253"
@@ -1712,6 +1718,10 @@ dropzone@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/dropzone/-/dropzone-4.2.0.tgz#fbe7acbb9918e0706489072ef663effeef8a79f3"
+duplexer3@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
+
duplexer@^0.1.1, duplexer@~0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
@@ -2445,6 +2455,10 @@ get-caller-file@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
+get-stream@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
+
getpass@^0.1.1:
version "0.1.6"
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6"
@@ -2521,6 +2535,25 @@ got@^3.2.0:
read-all-stream "^3.0.0"
timed-out "^2.0.0"
+got@^7.0.0:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a"
+ dependencies:
+ decompress-response "^3.2.0"
+ duplexer3 "^0.1.4"
+ get-stream "^3.0.0"
+ is-plain-obj "^1.1.0"
+ is-retry-allowed "^1.0.0"
+ is-stream "^1.0.0"
+ isurl "^1.0.0-alpha5"
+ lowercase-keys "^1.0.0"
+ p-cancelable "^0.3.0"
+ p-timeout "^1.1.1"
+ safe-buffer "^5.0.1"
+ timed-out "^4.0.0"
+ url-parse-lax "^1.0.0"
+ url-to-options "^1.0.1"
+
graceful-fs@^4.1.11, graceful-fs@^4.1.2:
version "4.1.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
@@ -2578,6 +2611,16 @@ has-flag@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
+has-symbol-support-x@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.3.0.tgz#588bd6927eaa0e296afae24160659167fc2be4f8"
+
+has-to-string-tag-x@^1.2.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.3.0.tgz#78e3d98c3c0ec9413e970eb8d766249a1e13058f"
+ dependencies:
+ has-symbol-support-x "^1.3.0"
+
has-unicode@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
@@ -2902,6 +2945,10 @@ is-number@^2.0.2, is-number@^2.1.0:
dependencies:
kind-of "^3.0.2"
+is-object@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470"
+
is-path-cwd@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
@@ -2918,7 +2965,7 @@ is-path-inside@^1.0.0:
dependencies:
path-is-inside "^1.0.1"
-is-plain-obj@^1.0.0:
+is-plain-obj@^1.0.0, is-plain-obj@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
@@ -2950,6 +2997,10 @@ is-resolvable@^1.0.0:
dependencies:
tryit "^1.0.1"
+is-retry-allowed@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34"
+
is-stream@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
@@ -3087,6 +3138,13 @@ istanbul@^0.4.5:
which "^1.1.1"
wordwrap "^1.0.0"
+isurl@^1.0.0-alpha5:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67"
+ dependencies:
+ has-to-string-tag-x "^1.2.0"
+ is-object "^1.0.1"
+
jasmine-core@^2.6.3:
version "2.6.3"
resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.6.3.tgz#45072950e4a42b1e322fe55c001100a465d77815"
@@ -3633,6 +3691,10 @@ mime@1.3.4, mime@1.3.x, mime@^1.3.4:
version "1.3.4"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53"
+mimic-response@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.0.tgz#df3d3652a73fded6b9b0b24146e6fd052353458e"
+
minimalistic-assert@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3"
@@ -3981,6 +4043,14 @@ osenv@^0.1.0:
os-homedir "^1.0.0"
os-tmpdir "^1.0.0"
+p-cancelable@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa"
+
+p-finally@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
+
p-limit@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc"
@@ -3991,6 +4061,12 @@ p-locate@^2.0.0:
dependencies:
p-limit "^1.1.0"
+p-timeout@^1.1.1:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.0.tgz#9820f99434c5817868b4f34809ee5291660d5b6c"
+ dependencies:
+ p-finally "^1.0.0"
+
package-json@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/package-json/-/package-json-1.2.0.tgz#c8ecac094227cdf76a316874ed05e27cc939a0e0"
@@ -4419,7 +4495,7 @@ prelude-ls@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
-prepend-http@^1.0.0:
+prepend-http@^1.0.0, prepend-http@^1.0.1:
version "1.0.4"
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
@@ -5384,6 +5460,10 @@ timed-out@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-2.0.0.tgz#f38b0ae81d3747d628001f41dafc652ace671c0a"
+timed-out@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f"
+
timers-browserify@^1.4.2:
version "1.4.2"
resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d"
@@ -5545,6 +5625,12 @@ url-loader@^0.5.8:
loader-utils "^1.0.2"
mime "1.3.x"
+url-parse-lax@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73"
+ dependencies:
+ prepend-http "^1.0.1"
+
url-parse@1.0.x:
version "1.0.5"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.0.5.tgz#0854860422afdcfefeb6c965c662d4800169927b"
@@ -5559,6 +5645,10 @@ url-parse@^1.0.1, url-parse@^1.1.1:
querystringify "0.0.x"
requires-port "1.0.x"
+url-to-options@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9"
+
url@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
@@ -5657,9 +5747,11 @@ vue-loader@^11.3.4:
vue-style-loader "^2.0.0"
vue-template-es2015-compiler "^1.2.2"
-vue-resource@^0.9.3:
- version "0.9.3"
- resolved "https://registry.yarnpkg.com/vue-resource/-/vue-resource-0.9.3.tgz#ab46e1c44ea219142dcc28ae4043b3b04c80959d"
+vue-resource@^1.3.4:
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/vue-resource/-/vue-resource-1.3.4.tgz#9fc0bdf6a2f5cab430129fc99d347b3deae7b099"
+ dependencies:
+ got "^7.0.0"
vue-style-loader@^2.0.0:
version "2.0.5"